Skip to content

v1.0.6

Choose a tag to compare

@kidoz kidoz released this 25 Aug 17:47
· 191 commits to main since this release

structguru v1.0.6

A stdlib-bridge control release. The bridge and Django's config builder gain a disable_existing_loggers policy with dictConfig semantics — but reversible — every bridge option can now be configured from environment variables at an explicit call site, and the managed installer refuses to stack a second bridge instead of silently duplicating every record. No changes to correct existing usage; upgrade in place from any v1.0.x.

Features

  • disable_existing_loggers on install_stdlib_bridge(). True disables named loggers that already exist at installation time, False re-enables them — the same policy logging.config.dictConfig applies, except reversible: uninstall_stdlib_bridge() restores the states the bridge changed, unless application code changed them again in the meantime. The root logger, and loggers created after installation, are never touched.

    bridge = install_stdlib_bridge(level="INFO", disable_existing_loggers=True)
    # ... existing named loggers are silenced while the bridge runs ...
    uninstall_stdlib_bridge(bridge)  # their previous states come back

    When the option is omitted, the installer reads STRUCTGURU_STDLIB_DISABLE_EXISTING_LOGGERS; when that is unset too, existing states are preserved. An explicit Python value always wins over the environment.

  • install_stdlib_bridge_from_env() — configure every bridge option from STRUCTGURU_STDLIB_* variables at a controlled point in application startup. Importing structguru still never touches the root logger; only the explicit call reads the environment.

    Variable Default
    STRUCTGURU_STDLIB_LEVEL LOG_LEVEL, then INFO
    STRUCTGURU_STDLIB_CLEAR_HANDLERS true
    STRUCTGURU_STDLIB_DISABLE_EXISTING_LOGGERS preserve existing states
    STRUCTGURU_STDLIB_SUPPRESS_LOGGERS empty comma-separated list
    STRUCTGURU_STDLIB_SUPPRESS_LEVEL WARNING

    Booleans accept 1/0, true/false, yes/no, and on/off; an invalid value raises ValueError before any logging state is changed.

  • Django's build_logging_config() accepts disable_existing_loggers. When omitted it reads the same environment variable and falls back to the previous hard-coded False, so existing settings modules keep their behavior.

  • A runnable example. examples/stdlib_existing_loggers/main.py demonstrates the policy from code and from the environment, and runs as part of the test suite so it cannot rot.

Changed

  • Only one managed bridge can be active. A second install_stdlib_bridge() call now raises RuntimeError instead of stacking a second handler that delivered every third-party record twice. A bridge whose handler was detached by hand is cleaned up — its logger-state snapshot restored — before a replacement installs.

Packaging & CI

  • Cargo dependencies refreshed: fancy-regex 0.18 → 0.19, pyo3 0.29.2, plus compatible serde, serde_json, regex, and time updates.
  • The internal path dependency is exempted from the cargo-deny wildcard ban, so cargo deny enforces the ban for real dependencies without failing on the workspace-internal crate link.

Docs

  • The README and the integrations guide document the existing-logger policy, the full environment-variable table, and the precedence rules (explicit value → environment → preserve).

Test coverage

  • 40 new tests pin the policy semantics: preserve/disable/re-enable and restore-on-uninstall (including the "application changed it since" case), placeholder and root/later-logger exclusions, environment precedence and validation-before-mutation, duplicate-install rejection, and the example smoke paths — 451 Python tests and 66 Rust tests in total.