Skip to main content

Shared infrastructure (typed exceptions, central config, structured logging + tracing) for MGF projects

Project description

mgf-common

PyPI version Python versions License: MIT Typed: PEP 561

The cornerstone library for the MGF project family. One typed, tested, opt-in observability stack — typed exceptions, central configuration, structured logging, OpenTelemetry tracing — so every project in the family inherits the same shape instead of re-inventing it.

Status: v0.1.0 on PyPI (released 2026-04-22). The API is "lifted-from-VManager-shaped" and may evolve up to v1.0 as more consumers arrive — see FEEDBACK.md for the early-consumer feedback pipeline that shapes that evolution. Reference consumer: VManager.


Two things in one repository

This repository serves a dual role; both halves move together.

  1. The library (src/mgf/common/) — battle-tested infrastructure, lifted from VManager and packaged for reuse. Ships with a PEP 561 py.typed marker so consumers' mypy --strict accepts inline annotations. Three subpackages:

    • mgf.common.exceptions — typed exception hierarchy (1 base + 7 categories + 7 generic concretes)
    • mgf.common.configBaseAppSettings (pydantic-settings) + make_settings_config + atomic loader/saver + cross-OS path helpers
    • mgf.common.observabilitysetup_logging, setup_otel, operation_span, Redactor, crash reporter, sys/threading excepthooks (OpenTelemetry deps live behind the [observability] extra; the package is fully usable without it)
  2. The standards (docs/standards/) — the single source of truth for the cross-project engineering bar every MGF project commits to. Five topic docs covering design principles, error handling, logging, configuration, and the common-component catalogue, with conformance levels (L0 / L1 / L2) every project declares against. Grounded in code that ships in this repository, illustrated with real VManager call sites.


Install

# Default — slim install, no optional sinks pulled in
pip install mgf-common

# Tier C observability — adds OpenTelemetry SDK + Sentry SDK + httpx instrumentation
pip install 'mgf-common[observability]'

Requires Python 3.11+. No system-package dependencies — installs cleanly into any virtualenv.

Quick start

import mgf.common

# Once at startup — establishes app identity for log paths,
# env-var prefixes, OTel service name, and crash report `app` field.
# MUST come before any observability function.
mgf.common.configure(app_name="myapp", app_version="1.0.0")

# ── Logging ──────────────────────────────────────────────────────
from mgf.common.observability import setup_logging, setup_otel

# Console + rotating file by default; opt-in journald/OTLP/syslog/HTTP via env.
setup_logging(level="INFO")

# No-op unless OTEL_EXPORTER_OTLP_ENDPOINT is set.
setup_otel()

# ── Typed configuration ──────────────────────────────────────────
from mgf.common.config import BaseAppSettings, load_settings, make_settings_config

class Settings(BaseAppSettings):
    # IMPORTANT: subclass model_config via the helper. The naïve
    # `**BaseAppSettings.model_config` spread does NOT work
    # (pydantic-settings raises TypeError on duplicate keys).
    model_config = make_settings_config(env_prefix="MYAPP_")
    backend_uri: str = "qemu:///system"
    timeout_seconds: int = 30

settings = load_settings(Settings, path=None)  # uses default OS-aware path

# ── Typed exceptions ─────────────────────────────────────────────
from mgf.common.exceptions import AppError, ResourceNotFoundError

class MyAppError(AppError):
    """Base for myapp-specific errors."""

class VMNotFoundError(ResourceNotFoundError):
    """Extends a generic concrete with project-specific phrasing."""

# ── Crash reporting + excepthooks ────────────────────────────────
from mgf.common.observability import (
    install_excepthook,
    install_threading_excepthook,
    report_now,
)

install_excepthook()
install_threading_excepthook()

A consumer entry point in ~10 lines is the goal. See docs/standards/COMMON_COMPONENTS.md §"How to bootstrap a new project from this catalogue" for the full recipe.

Examples

Eighteen runnable examples under examples/ — six topics, three layers each (simple → practical → advanced):

examples/
├── 01_exceptions/         typed hierarchy + subclassing + translation seam
├── 02_config/             BaseAppSettings + make_settings_config + load/save
├── 03_logging/            setup_logging + Redactor + structured fields
├── 04_observability/      setup_otel + operation_span + trace correlation
├── 05_crash_reporting/    report_now + sys/threading excepthooks
└── 06_full_app/           a complete tiny CLI tying everything together

Every script is self-contained (uses tempfile.TemporaryDirectory for disk side-effects), runs in under a second, and is smoke-tested in CI so the examples never drift from the API. Run any of them with python examples/<topic>/<layer>.py or browse examples/README.md for the index.


Standards

The docs/standards/ folder is the cross-project engineering bar. Every MGF project declares its conformance level against it.

Doc What it covers
README.md Master index, RFC 2119 keywords, L0/L1/L2 levels, sortable index of every MUST
DESIGN_PRINCIPLES.md Layering (DP-01..13), provider ABC pattern, frozen domain types, GUI threading, async + time + resource discipline, mechanical enforcement matrix
ERROR_HANDLING.md Exception hierarchy (EH-01..10), translation seams, top-level handlers, crash reporter, async error handling, error-message style guide
LOGGING.md Stdlib + JSON, OTel correlation, redaction, sinks (LG-01..14), volume control (rate-limit / sample / dedup), contextvars correlation
CONFIGURATION.md pydantic-settings, layered precedence, schema versioning, atomic writes (CF-01..12), discriminated unions, env-tier layering, alias renames
SECURITY.md Cross-project security standard (SC-01..18): secrets, subprocess, deserialization, crypto, TLS, input validation, dependency scanning, vulnerability response, threat model template
TESTING.md Cross-project testing standard (TS-01..18): layout, fixtures, mock provider, property tests, GUI / async testing, performance benchmarks, security pins
API_DESIGN.md Cross-project API-design standard (AP-01..15): __all__ discipline, semver rigor, deprecation cycle, type stability, stability tiers, PUBLIC_API.md contract, CHANGELOG migration recipes
COMMON_COMPONENTS.md Catalogue of every common component + lift instructions + cornerstone-rhythm guidance

Standards version: v2.0 (released 2026-04-25 — introduced SECURITY.md, TESTING.md, and API_DESIGN.md, plus new MUSTs across the existing docs; see What's new in v2.0). Versioning policy: MAJOR for a MUST change, MINOR for SHOULD/template change, PATCH for wording. Independent of the package version.

Conformance levels

Every project that adopts these standards declares its target level in its top-level README:

Level What you commit to Typical use
L0 — Bootstrap Hierarchical logging, base exception class, env-driven config (no schema). MUST NOT log secrets. MUST NOT swallow exceptions silently. Spike, prototype, throwaway tool
L1 — Production-Ready Full typed exception hierarchy, JSON-capable structured logging with correlation IDs, pydantic-settings config with schema versioning, top-level error handlers wired (CLI + GUI/threading/asyncio as applicable), local crash reporter. Any tool a real user will run
L2 — Observability-Native Everything in L1 + OpenTelemetry traces/metrics/logs (OTLP exporter, off by default but flip-able via env), optional Sentry/GlitchTip handler, log redaction on by default, GUI log viewer dialog, remote log shipping handler available. Any tool that runs unattended, in production, on a user's machine, or as a service

mgf-common ships at L2. Consumers that depend on it are L1 by default; they reach L2 by installing the [observability] extra and calling mgf.common.observability.setup_otel().


Quality gates

Gate Today Tooling
Tests 176 passing in <1.5s on a warm machine; no external services, no network. 19 of those are example-smoke tests verifying every script in examples/ runs cleanly pytest (see [tool.pytest.ini_options])
Type checking mypy --strict clean on 18 source files mypy with the [dev,observability] install
Lint clean ruff check src tests
Layering mgf-common-is-a-leaf contract enforced (forbids any upward import on consumer projects) import-linter
Coverage ~85% (gate at 80%) — lazy-imported sink code inflates the unreachable-without-real-backends surface pytest --cov

CI is in .woodpecker.yml and runs on every push / PR / tag once active. ci.codeberg.org access is allow-list gated; apply at https://codeberg.org/Codeberg-CI/request-access.


Layout

mgf_common/
├── pyproject.toml                 hatchling, packages = ["src/mgf"]
├── README.md                      (this file)
├── PUBLIC_API.md                  public-API contract per AP-10 (every public name + tier)
├── COMMON.md                      Round 5 extraction plan + path-to-PyPI roadmap
├── FEEDBACK.md                    early-consumer feedback + roadmap input
├── CONTRIBUTING.md                dev setup, four green gates, PR process, communication channels
├── CHANGELOG.md                   Keep-a-Changelog
├── SECURITY.md                    vulnerability reporting policy (per SC-12)
├── LICENSE                        MIT
├── .importlinter                  single contract: mgf-common-is-a-leaf
├── .woodpecker.yml                lint + typecheck + test matrix + build (CI pending)
├── examples/                      runnable layered examples (6 topics × 3 layers, smoke-tested in CI)
├── docs/
│   ├── CLAUDE.md                  dense lookup for AI agents + maintainers
│   └── standards/                 cross-project engineering standards (7 topic docs + master README)
└── src/mgf/                       PEP 420 namespace package (no __init__.py at src/mgf/)
    └── common/
        ├── __init__.py            re-exports configure / app_name / app_version + __version__
        ├── _identity.py           process-wide identity cache + configure()
        ├── py.typed               PEP 561 marker
        ├── exceptions/            AppError + 7 categories + 7 generic concretes
        ├── config/                BaseAppSettings + make_settings_config + load/save + paths
        └── observability/         setup_logging + setup_otel + crash reporter + redactor + excepthooks

Documentation

File Purpose
README.md This file — install, quick-start, standards links, conformance levels, project layout
PUBLIC_API.md The public-API contract list — every public name with its stability tier, per AP-10
CHANGELOG.md Per-release notes (Keep a Changelog)
COMMON.md Round 5 extraction plan + PyPI roadmap (history + forward)
FEEDBACK.md Living document for early-consumer feedback + roadmap input
CONTRIBUTING.md How to set up dev, the four green gates, the PR process, the design-discussion channels
SECURITY.md Vulnerability reporting policy (per SC-12)
examples/ Eighteen runnable examples (6 topics × 3 layers); smoke-tested in CI
docs/standards/ Cross-project engineering standards (7 topic docs + master README)
docs/CLAUDE.md Dense lookup for AI agents and maintainers (gotchas, invariants, phase-by-phase critical facts)

Reference consumer

VManager — VM-management desktop application built on top of mgf-common. The standards docs are grounded in real VManager code throughout; "AS-IS in VManager" sections show the canonical real-world example for each pattern.

The two repos act as a federation:


Feedback from consumers

FEEDBACK.md is the living interface for opinionated, brutally-honest feedback from real consumers BEFORE the API locks at v1.0. The stakes are asymmetric: a 🔴 Blocker concern raised now is a minor commit; the same concern after v1.0 ships with N consumers becomes a breaking-change coordination exercise across the ecosystem.

If your project is about to adopt mgf-common, read FEEDBACK.md first — an early consumer may already have surfaced a concern that shapes your integration.

If your project is already using mgf-common, add your own feedback section. The submission process is documented in FEEDBACK.md §10.


Development

git clone ssh://git@codeberg.org/magogi-admin/mgf_common.git
cd mgf_common
uv venv
uv sync --extra dev --extra observability

# Quality gates — same set the future CI runs
uv run pytest --tb=short -q
uv run ruff check src tests
uv run mypy src
uv run lint-imports

For local development against a consumer, depend on a path source instead of the PyPI pin:

# In a consumer project's pyproject.toml:
dependencies = ["mgf-common"]

[tool.uv.sources]
mgf-common = { path = "../mgf_common", editable = true }

The release workflow (manual twine upload until PyPI adds Codeberg as an OIDC issuer) is documented in docs/CLAUDE.md §"Build and release".


Versioning

The package follows Semantic Versioning. The 0.x series exists to make API churn possible while VManager and other early consumers shape the surface — see COMMON.md §8.5 for the version-bump policy.

Standards docs (docs/standards/) version independently of the package — see docs/standards/README.md §Versioning.


License

MIT — see LICENSE.


Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mgf_common-0.3.0.tar.gz (560.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mgf_common-0.3.0-py3-none-any.whl (122.0 kB view details)

Uploaded Python 3

File details

Details for the file mgf_common-0.3.0.tar.gz.

File metadata

  • Download URL: mgf_common-0.3.0.tar.gz
  • Upload date:
  • Size: 560.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mgf_common-0.3.0.tar.gz
Algorithm Hash digest
SHA256 39ec459f093287d55472f82e116fcf74486e12836ebad1a2554b697909f77280
MD5 07139be6525238d1d1b96537bce27884
BLAKE2b-256 52d5ace976748af81eee499735cf4631cf89223af68a00655c8805b4ddf8404e

See more details on using hashes here.

File details

Details for the file mgf_common-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: mgf_common-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 122.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for mgf_common-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8789196fc57bb356294265a485954c9f8cb896918368f66f13cfc86620716e96
MD5 e7f8817800e32b347c2abbd8c311be5d
BLAKE2b-256 61fc146f6c3a4d1156b65cddc7943afe925de251d8845e68dca9bc3ec60a3403

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page