From 732698427e822b6ba81f1214864685903cdc13a4 Mon Sep 17 00:00:00 2001 From: Federico Caselli Date: Wed, 30 Oct 2024 21:17:45 +0100 Subject: [PATCH] Improve mutable typing. References: #12046 Change-Id: If950f7e2090a0f637c2c28cf21a40dc345acc89a --- lib/sqlalchemy/ext/mutable.py | 3 ++- lib/sqlalchemy/sql/elements.py | 4 +++- lib/sqlalchemy/sql/type_api.py | 5 ++--- test/typing/plain_files/ext/misc_ext.py | 17 +++++++++++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 test/typing/plain_files/ext/misc_ext.py diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index fc53981c1b..8f58749f94 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -392,6 +392,7 @@ from ..orm.context import QueryContext from ..orm.decl_api import DeclarativeAttributeIntercept from ..orm.state import InstanceState from ..orm.unitofwork import UOWTransaction +from ..sql._typing import _TypeEngineArgument from ..sql.base import SchemaEventTarget from ..sql.schema import Column from ..sql.type_api import TypeEngine @@ -638,7 +639,7 @@ class Mutable(MutableBase): event.listen(Mapper, "mapper_configured", listen_for_type) @classmethod - def as_mutable(cls, sqltype: TypeEngine[_T]) -> TypeEngine[_T]: + def as_mutable(cls, sqltype: _TypeEngineArgument[_T]) -> TypeEngine[_T]: """Associate a SQL type with this mutable Python type. This establishes listeners that will detect ORM mappings against diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 2b6835a6a2..70c27ef5a8 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -2441,7 +2441,9 @@ class TextClause( @util.preload_module("sqlalchemy.sql.selectable") def columns( - self, *cols: _ColumnExpressionArgument[Any], **types: TypeEngine[Any] + self, + *cols: _ColumnExpressionArgument[Any], + **types: _TypeEngineArgument[Any], ) -> TextualSelect: r"""Turn this :class:`_expression.TextClause` object into a :class:`_expression.TextualSelect` diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index 9f40905fa6..228020ec20 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -2315,11 +2315,10 @@ def to_instance( def adapt_type( - typeobj: TypeEngine[Any], + typeobj: _TypeEngineArgument[Any], colspecs: Mapping[Type[Any], Type[TypeEngine[Any]]], ) -> TypeEngine[Any]: - if isinstance(typeobj, type): - typeobj = typeobj() + typeobj = to_instance(typeobj) for t in typeobj.__class__.__mro__[0:-1]: try: impltype = colspecs[t] diff --git a/test/typing/plain_files/ext/misc_ext.py b/test/typing/plain_files/ext/misc_ext.py new file mode 100644 index 0000000000..c44d09bb3e --- /dev/null +++ b/test/typing/plain_files/ext/misc_ext.py @@ -0,0 +1,17 @@ +from typing import Any + +from sqlalchemy import JSON +from sqlalchemy import Select +from sqlalchemy.ext.compiler import compiles +from sqlalchemy.ext.mutable import MutableDict +from sqlalchemy.ext.mutable import MutableList +from sqlalchemy.sql.compiler import SQLCompiler + + +@compiles(Select[Any], "my_cool_driver") +def go(sel: Select[Any], compiler: SQLCompiler, **kw: Any) -> str: + return "select 42" + + +MutableList.as_mutable(JSON) +MutableDict.as_mutable(JSON()) -- 2.47.3