From: Shamil Abdulaev Date: Thu, 16 Apr 2026 18:56:23 +0000 (-0400) Subject: Add mypy ignore comments for Python 3.14 module imports X-Git-Tag: rel_2_1_0b2~2^2 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=77c91b8df51c5a00d6940a9b63b2ba5bd01d9ceb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add mypy ignore comments for Python 3.14 module imports Fixes #13240 Use `sys.version_info >= (3, 14)` instead of the `py314` variable for the py314-only imports block (`annotationlib`, `string.templatelib`). mypy has built-in support for `sys.version_info` guards and only type-checks the reachable branch, while a plain variable like `py314` causes mypy to check both branches — leading to `import-not-found` on <3.14 and `unused-ignore` on 3.14 if `type: ignore` comments are added. Closes: #13239 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13239 Pull-request-sha: f58bfc11694c71020b98ed69d8400a0173be096b Change-Id: Ib5e2361e849a3f14f90d0da34800c1d31f8bf201 --- diff --git a/lib/sqlalchemy/sql/_elements_constructors.py b/lib/sqlalchemy/sql/_elements_constructors.py index 7567896979..5d596525d1 100644 --- a/lib/sqlalchemy/sql/_elements_constructors.py +++ b/lib/sqlalchemy/sql/_elements_constructors.py @@ -53,8 +53,6 @@ from .elements import WithinGroup from .functions import FunctionElement if typing.TYPE_CHECKING: - from string.templatelib import Template - from ._typing import _ByArgument from ._typing import _ColumnExpressionArgument from ._typing import _ColumnExpressionOrLiteralArgument @@ -66,6 +64,7 @@ if typing.TYPE_CHECKING: from .elements import FrameClause from .selectable import FromClause from .type_api import TypeEngine + from ..util.compat import Template _T = TypeVar("_T") diff --git a/lib/sqlalchemy/util/compat.py b/lib/sqlalchemy/util/compat.py index ddf042a474..38ff365628 100644 --- a/lib/sqlalchemy/util/compat.py +++ b/lib/sqlalchemy/util/compat.py @@ -31,7 +31,6 @@ from typing import Sequence from typing import Set from typing import Tuple from typing import Type -from typing import TYPE_CHECKING py314b1 = sys.version_info >= (3, 14, 0, "beta", 1) py314 = sys.version_info >= (3, 14) @@ -51,11 +50,24 @@ has_refcount_gc = bool(cpython) dottedgetter = operator.attrgetter -if py314 or TYPE_CHECKING: + +# use sys.version_info to enable mypy version narrowing +if sys.version_info >= (3, 14): + + import annotationlib from string.templatelib import Template as Template + + def get_annotations(obj: Any) -> Mapping[str, Any]: + return annotationlib.get_annotations( + obj, format=annotationlib.Format.FORWARDREF + ) + else: - class Template: # type: ignore[no-redef] + def get_annotations(obj: Any) -> Mapping[str, Any]: + return inspect.get_annotations(obj) + + class Template: """Minimal Template for Python < 3.14 (test usage only).""" def __init__(self, *parts: Any): @@ -73,21 +85,6 @@ else: return iter(self._parts) -if py314: - - import annotationlib - - def get_annotations(obj: Any) -> Mapping[str, Any]: - return annotationlib.get_annotations( - obj, format=annotationlib.Format.FORWARDREF - ) - -else: - - def get_annotations(obj: Any) -> Mapping[str, Any]: - return inspect.get_annotations(obj) - - class FullArgSpec(typing.NamedTuple): args: List[str] varargs: Optional[str]