summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/util/typing.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/util/typing.py')
-rw-r--r--lib/sqlalchemy/util/typing.py21
1 files changed, 18 insertions, 3 deletions
diff --git a/lib/sqlalchemy/util/typing.py b/lib/sqlalchemy/util/typing.py
index b1ef87db1..e1670ed21 100644
--- a/lib/sqlalchemy/util/typing.py
+++ b/lib/sqlalchemy/util/typing.py
@@ -97,8 +97,12 @@ class GenericProtocol(Protocol[_T]):
__args__: Tuple[_AnnotationScanType, ...]
__origin__: Type[_T]
- def copy_with(self, params: Tuple[_AnnotationScanType, ...]) -> Type[_T]:
- ...
+ # Python's builtin _GenericAlias has this method, however builtins like
+ # list, dict, etc. do not, even though they have ``__origin__`` and
+ # ``__args__``
+ #
+ # def copy_with(self, params: Tuple[_AnnotationScanType, ...]) -> Type[_T]:
+ # ...
class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]):
@@ -158,10 +162,21 @@ def de_stringify_annotation(
for elem in annotation.__args__
)
- return annotation.copy_with(elements)
+ return _copy_generic_annotation_with(annotation, elements)
return annotation # type: ignore
+def _copy_generic_annotation_with(
+ annotation: GenericProtocol[_T], elements: Tuple[_AnnotationScanType, ...]
+) -> Type[_T]:
+ if hasattr(annotation, "copy_with"):
+ # List, Dict, etc. real generics
+ return annotation.copy_with(elements) # type: ignore
+ else:
+ # Python builtins list, dict, etc.
+ return annotation.__origin__[elements] # type: ignore
+
+
def eval_expression(expression: str, module_name: str) -> Any:
try:
base_globals: Dict[str, Any] = sys.modules[module_name].__dict__