MCPcopy
hub / github.com/sqlalchemy/sqlalchemy / de_stringify_annotation

Function de_stringify_annotation

lib/sqlalchemy/util/typing.py:117–185  ·  view source on GitHub ↗

Resolve annotations that may be string based into real objects. This is particularly important if a module defines "from __future__ import annotations", as everything inside of __annotations__ is a string. We want to at least have generic containers like ``Mapped``, ``Union``, ``List``,

(
    cls: Type[Any],
    annotation: _AnnotationScanType,
    originating_module: str,
    locals_: Mapping[str, Any],
    *,
    str_cleanup_fn: Optional[Callable[[str, str], str]] = None,
    include_generic: bool = False,
    _already_seen: Optional[Set[Any]] = None,
)

Source from the content-addressed store, hash-verified

115
116
117def de_stringify_annotation(
118 cls: Type[Any],
119 annotation: _AnnotationScanType,
120 originating_module: str,
121 locals_: Mapping[str, Any],
122 *,
123 str_cleanup_fn: Optional[Callable[[str, str], str]] = None,
124 include_generic: bool = False,
125 _already_seen: Optional[Set[Any]] = None,
126) -> Type[Any]:
127 """Resolve annotations that may be string based into real objects.
128
129 This is particularly important if a module defines "from __future__ import
130 annotations", as everything inside of __annotations__ is a string. We want
131 to at least have generic containers like ``Mapped``, ``Union``, ``List``,
132 etc.
133
134 """
135 # looked at typing.get_type_hints(), looked at pydantic. We need much
136 # less here, and we here try to not use any private typing internals
137 # or construct ForwardRef objects which is documented as something
138 # that should be avoided.
139
140 original_annotation = annotation
141
142 if is_fwd_ref(annotation):
143 annotation = annotation.__forward_arg__
144
145 if isinstance(annotation, str):
146 if str_cleanup_fn:
147 annotation = str_cleanup_fn(annotation, originating_module)
148
149 annotation = eval_expression(
150 annotation, originating_module, locals_=locals_, in_class=cls
151 )
152
153 if (
154 include_generic
155 and is_generic(annotation)
156 and not is_literal(annotation)
157 ):
158 if _already_seen is None:
159 _already_seen = set()
160
161 if annotation in _already_seen:
162 # only occurs recursively. outermost return type
163 # will always be Type.
164 # the element here will be either ForwardRef or
165 # Optional[ForwardRef]
166 return original_annotation # type: ignore
167 else:
168 _already_seen.add(annotation)
169
170 elements = tuple(
171 de_stringify_annotation(
172 cls,
173 elem,
174 originating_module,

Callers 7

check_argsMethod · 0.90
check_argsMethod · 0.90
declarative_scanMethod · 0.85
_is_mapped_annotationFunction · 0.85
_extract_mapped_subtypeFunction · 0.85
_collect_annotationMethod · 0.85

Calls 6

is_fwd_refFunction · 0.85
eval_expressionFunction · 0.85
is_genericFunction · 0.85
is_literalFunction · 0.85
addMethod · 0.45

Tested by 2

check_argsMethod · 0.72
check_argsMethod · 0.72