[codex] Format object logging messages before interpolation

Draft
PY
1d ago
+123-0

Valid standard-library logging calls can start raising TypeError after adding LogfireLoggingHandler: when a message object's __str__ returns a percent template, the handler applies % to the object instead of its string representation. For example, logger.error(message_object, 'gemini') fails for an object rendering as model %s finished, interrupting the logging call and subsequent handlers.

Convert the local message to str before interpolation, following the Python logging contract. Keep the existing no-arguments early return so Logfire's minimum-level filtering remains lazy. The original record, grouping template, structured positional/mapping arguments and extra attributes remain intact.

Validation:

  • Three public logging regressions fail with genuine TypeErrors on unchanged main and pass with the fix. All 28 stdlib/Loguru tests pass, including filtering and invalid-template guards.
  • An independent Sol review replayed those regressions, passed 12 additional public API probes, and verified 100% coverage of the changed logging module (45 statements / 8 branches).
  • Full locally available suite: original 2,932 passed, fixed 2,944 passed, both with 13 skipped / 2 expected failures. Only eight Docker-dependent cases were excluded because the local Docker daemon is unavailable. The unmodified full-suite attempt confirms that limitation; normal warning checks were retained.
  • All-files precommit passed, including repository-wide Ruff formatting/lint and Pyright, without source rewrites.

Local checks used macOS arm64 / Python 3.12.10 with locked dependencies. Docker-backed integrations, the full Python/OS matrix and the globally combined 100% coverage gate are left to upstream CI; the module coverage above is not a whole-project claim. No configuration, dependency, API or documentation changes.

Upstream CI status: attempt 1 has 15 successful jobs, including Python 3.11–3.14, Pydantic 2.4, OTel 1.39, install/upgrade checks and Pyodide. The Python 3.10 job failed when a documentation example collected an unclosed event loop and Unix sockets (PytestUnraisableExceptionWarning); its allocation root cause has not been established. The aggregate gate therefore failed and combined coverage was skipped. GitHub rejected both retry requests because rerunning requires repository admin rights. This draft remains pending that CI result; no warning suppression or unrelated code change was added.

Additional Python 3.10 diagnosis (October 18): with CPython 3.10.20 on macOS arm64, the documentation/logging selection passed 277 tests; the available original and patched full suites passed 2,927 / 2,939 tests, respectively, each with 18 skipped / 2 expected failures. The same eight Docker cases were excluded and repository warning filters remained enabled. These runs did not reproduce the warning. Linux CI, which also uses coverage tracing and different host setup, remains failed with its allocation cause unresolved; combined coverage remains skipped.

AI-assisted implementation and independent review using Codex Sol agents.