Skip to content

fix(typing): stop 3.14 DI wire NameError in MySQL session manager - #121

Merged
HosseinNejatiJavaremi merged 1 commit into
SyntaxArc:masterfrom
alip990:fix/mysql-uuid-annotation-pep649
Sep 13, 2026
Merged

HosseinNejatiJavaremi merged 1 commit into
SyntaxArc:masterfrom
alip990:fix/mysql-uuid-annotation-pep649

Conversation

@alip990

@alip990 alip990 commented Sep 13, 2026

Copy link
Copy Markdown

Description

Completes the Python 3.14 / PEP 649 annotation fix from 5.2.3 for the one module that release missed: archipy/adapters/mysql/sqlalchemy/session_managers.py.

The bug

On Python 3.14 (PEP 649), annotations are no longer evaluated at definition time; they compile into an __annotate__ function that does a real global name lookup the first time __annotations__ is read. inspect.signature() reads it. In session_managers.py, PostgresUUID is imported only under if TYPE_CHECKING: but is used in the runtime-visible annotation of the visit_UUID function that the module monkeypatches onto SQLAlchemy's MySQLTypeCompiler. The module has no from __future__ import annotations, so any signature inspection of MySQLTypeCompiler.visit_UUID raises NameError: name 'PostgresUUID' is not defined.

dependency_injector's container.wire() calls inspect.signature() on every class member it finds in the wired modules, so this aborts wiring (and therefore service startup) whenever a wired namespace contains MySQLTypeCompiler. Because the patch is installed on SQLAlchemy's own class at import time, the broken annotation leaks to any other runtime introspection of MySQLTypeCompiler in a process that imports the MySQL adapter.

Relation to 5.2.3

5.2.3 (352ff45b, "fix(typing): stop 3.14 DI wire NameError") fixed exactly this class of bug by adding from __future__ import annotations across errors, adapters, helpers, decorators, gRPC interceptors and FastAPIErrorResponseDTO. Its "SQLAlchemy" entry covers archipy/adapters/base/sqlalchemy/{adapters,ports,session_manager_ports}.py. None of the dialect session managers were touched. Postgres and SQLite do not use TYPE_CHECKING imports, and StarRocks already had the future import around an identical visit_UUID patch. The MySQL session manager was left behind.

I ran a sweep that imports every archipy module (207 modules, all importable with all extras) and calls inspect.signature() on every function and class member defined in them:

Version Callables checked Unresolvable signatures (NameError)
5.2.2 2797 232
5.2.3 / master (87140177) 2770 1archipy.adapters.mysql.sqlalchemy.session_managers :: MySQLTypeCompiler.visit_UUID (NameError: name 'PostgresUUID' is not defined)
this PR 2770 0

Reproduction (Python 3.14.6, archipy 5.2.3)

import inspect
from archipy.adapters.mysql.sqlalchemy.session_managers import MySQLTypeCompiler

inspect.signature(MySQLTypeCompiler.visit_UUID)
  File ".../archipy/adapters/mysql/sqlalchemy/session_managers.py", line 30, in __annotate__
    def visit_UUID(self: MySQLTypeCompiler, type_: PostgresUUID, **kw: object) -> str:  # noqa: ARG001
                                                   ^^^^^^^^^^^^
NameError: name 'PostgresUUID' is not defined

Through dependency_injector (4.x) on 5.2.3:

from dependency_injector import containers
import archipy.adapters.mysql.sqlalchemy as mysql_sqlalchemy

class Container(containers.DeclarativeContainer): ...

Container().wire(packages=[mysql_sqlalchemy])
# NameError: name 'PostgresUUID' is not defined

The same happens with wire(modules=[...]) on the session_managers module, on any app module that does from sqlalchemy.dialects.mysql.base import MySQLTypeCompiler, and with wire(packages=[archipy]).

The fix

One line, mirroring the 5.2.3 remedy and the StarRocks session manager next to it:

 """MySQL SQLAlchemy session manager implementations."""

+from __future__ import annotations
+
 from typing import TYPE_CHECKING, override

No other code changes.

Fixes # (no issue filed)

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

All on Python 3.14.6 with uv sync --all-extras --all-groups against the locked dependencies.

  • New BDD regression scenario in features/atomic_transactions.feature (steps in features/steps/atomic_transaction_steps.py), modelled on the 5.2.3 "Public error constructors stay inspectable at runtime" scenario:
    @unit
    Scenario Outline: SQLAlchemy session manager callables stay inspectable at runtime
      When I inspect callables of the <db_type> SQLAlchemy session manager module
      Then all session manager callable signatures resolve without NameError
    
      Examples:
        | db_type   |
        | postgres  |
        | sqlite    |
        | mysql     |
        | starrocks |
    The step imports archipy.adapters.<db_type>.sqlalchemy.session_managers and calls inspect.signature on every function and class member in its namespace, which is the same walk container.wire() performs. That includes the patched MySQLTypeCompiler.visit_UUID.
    • Red, with the fix reverted: mysql fails with MySQLTypeCompiler.visit_UUID: name 'PostgresUUID' is not defined, and postgres, sqlite and starrocks pass.
    • Green, with the fix: 4 scenarios passed, 8 steps passed.
    • Note: atomic_transactions.feature has feature-level @needs-postgres @needs-mysql @needs-starrocks tags. The Postgres 18.6-alpine and StarRocks all-in-one images could not be pulled in my environment, so I ran the new outline through behave from a temporary copy without those feature tags (same steps, not committed). behave --dry-run features/atomic_transactions.feature shows no undefined steps, and the untested count goes from 58 to 62 scenarios, as expected. I did not run the container-backed scenarios of that feature.
  • Full sweep described above: 0 unresolvable signatures on this branch.
  • dependency_injector wiring of archipy.adapters.mysql.sqlalchemy.session_managers, and of a module importing MySQLTypeCompiler: NameError on 5.2.3, wires cleanly on this branch.
  • make format: 208 files left unchanged
  • make lint: ruff All checks passed!, ty All checks passed!
  • make security: no findings in the changed file (the only finding is a pre-existing medium elsewhere)
  • pre-commit hooks on the changed files: all passed (codespell, ruff-format, ruff, add-trailing-comma, validate-pyproject, ty)
  • uv run --extra behave behave features/error_handling.feature (includes the 5.2.3 inspectability scenario): 59 scenarios passed, 0 failed
  • Full make behave: not run, because the container images listed in .env.test were not available in my environment

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • I have checked my code and corrected any misspellings

Additional context

Impact

  • Only affects consumers on Python 3.14 that import the MySQL SQLAlchemy adapter and whose wiring or introspection reaches MySQLTypeCompiler. Postgres, SQLite and StarRocks users are unaffected. In local checks, wiring app modules that only import MySQLSQLAlchemyAdapter, MySQLSQlAlchemySessionManager or mysql_sqlalchemy_atomic_decorator already worked on 5.2.3.
  • This is the same crash that kept a production service from starting on Python 3.14 with archipy 5.2.2. That service uses Postgres, so upgrading to 5.2.3 fixed it. A MySQL consumer whose wiring reaches the patched compiler would still hit it on 5.2.3.
  • No behavior change: visit_UUID still maps UUID to VARCHAR(36); only annotation evaluation becomes lazy (string).

Changelog

Per .cursor/rules/contributing.mdc, I have not edited docs/community/changelog/ because it is written at release time. Suggested entry in the 5.2.3 format:

## Fixed

### Adapters - Annotations

- **Same 3.14 inspect.signature crash on MySQL session manager** - The
  `MySQLTypeCompiler.visit_UUID` patch no longer raises
  `NameError: name 'PostgresUUID' is not defined` during `container.wire()`.
    - Added `from __future__ import annotations` to
      `archipy/adapters/mysql/sqlalchemy/session_managers.py`, the one module
      the 5.2.3 sweep missed

## Tests

### Tests - Adapters

- **Session manager inspectability BDD** - Postgres, SQLite, MySQL, and
  StarRocks SQLAlchemy session manager callables are asserted to resolve
  `inspect.signature` without `NameError`.

PEP 649 evaluates the TYPE_CHECKING-only PostgresUUID annotation on the
visit_UUID patch that is installed on MySQLTypeCompiler, so
inspect.signature() and container.wire() raise NameError. Stringify
annotations, as 5.2.3 did for the other adapters and helpers.
@HosseinNejatiJavaremi
HosseinNejatiJavaremi merged commit 0e9f321 into SyntaxArc:master Sep 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants