ducktools-classbuilder 0.5.0__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ducktools-classbuilder might be problematic. Click here for more details.
- ducktools/classbuilder/__init__.py +493 -179
- ducktools/classbuilder/__init__.pyi +143 -39
- ducktools/classbuilder/annotations.py +173 -0
- ducktools/classbuilder/annotations.pyi +26 -0
- ducktools/classbuilder/prefab.py +120 -230
- ducktools/classbuilder/prefab.pyi +28 -22
- ducktools_classbuilder-0.6.0.dist-info/METADATA +318 -0
- ducktools_classbuilder-0.6.0.dist-info/RECORD +12 -0
- ducktools_classbuilder-0.5.0.dist-info/METADATA +0 -270
- ducktools_classbuilder-0.5.0.dist-info/RECORD +0 -10
- {ducktools_classbuilder-0.5.0.dist-info → ducktools_classbuilder-0.6.0.dist-info}/LICENSE.md +0 -0
- {ducktools_classbuilder-0.5.0.dist-info → ducktools_classbuilder-0.6.0.dist-info}/WHEEL +0 -0
- {ducktools_classbuilder-0.5.0.dist-info → ducktools_classbuilder-0.6.0.dist-info}/top_level.txt +0 -0
|
@@ -1,43 +1,70 @@
|
|
|
1
|
+
import types
|
|
1
2
|
import typing
|
|
3
|
+
|
|
2
4
|
from collections.abc import Callable
|
|
5
|
+
from types import MappingProxyType
|
|
6
|
+
from typing_extensions import dataclass_transform
|
|
3
7
|
|
|
4
|
-
_py_type = type # Alias for type
|
|
8
|
+
_py_type = type | str # Alias for type hint values
|
|
9
|
+
_CopiableMappings = dict[str, typing.Any] | MappingProxyType[str, typing.Any]
|
|
5
10
|
|
|
6
11
|
__version__: str
|
|
7
12
|
INTERNALS_DICT: str
|
|
13
|
+
META_GATHERER_NAME: str
|
|
8
14
|
|
|
9
15
|
def get_fields(cls: type, *, local: bool = False) -> dict[str, Field]: ...
|
|
10
16
|
|
|
11
|
-
def get_flags(cls:type) -> dict[str, bool]: ...
|
|
17
|
+
def get_flags(cls: type) -> dict[str, bool]: ...
|
|
18
|
+
|
|
19
|
+
def get_methods(cls: type) -> types.MappingProxyType[str, MethodMaker]: ...
|
|
12
20
|
|
|
13
21
|
def _get_inst_fields(inst: typing.Any) -> dict[str, typing.Any]: ...
|
|
14
22
|
|
|
15
23
|
class _NothingType:
|
|
16
|
-
...
|
|
24
|
+
def __repr__(self) -> str: ...
|
|
17
25
|
NOTHING: _NothingType
|
|
18
26
|
|
|
27
|
+
# noinspection PyPep8Naming
|
|
28
|
+
class _KW_ONLY_TYPE:
|
|
29
|
+
def __repr__(self) -> str: ...
|
|
30
|
+
|
|
31
|
+
KW_ONLY: _KW_ONLY_TYPE
|
|
19
32
|
# Stub Only
|
|
20
|
-
_codegen_type = Callable[[type],
|
|
33
|
+
_codegen_type = Callable[[type], GeneratedCode]
|
|
34
|
+
|
|
35
|
+
class GeneratedCode:
|
|
36
|
+
__slots__: tuple[str, str]
|
|
37
|
+
source_code: str
|
|
38
|
+
globs: dict[str, typing.Any]
|
|
39
|
+
|
|
40
|
+
def __init__(self, source_code: str, globs: dict[str, typing.Any]) -> None: ...
|
|
41
|
+
def __repr__(self) -> str: ...
|
|
42
|
+
|
|
21
43
|
|
|
22
44
|
class MethodMaker:
|
|
23
45
|
funcname: str
|
|
24
46
|
code_generator: _codegen_type
|
|
25
47
|
def __init__(self, funcname: str, code_generator: _codegen_type) -> None: ...
|
|
26
48
|
def __repr__(self) -> str: ...
|
|
27
|
-
def __get__(self, instance, cls) -> Callable: ...
|
|
49
|
+
def __get__(self, instance, cls=None) -> Callable: ...
|
|
28
50
|
|
|
29
51
|
def get_init_generator(
|
|
30
52
|
null: _NothingType = NOTHING,
|
|
31
53
|
extra_code: None | list[str] = None
|
|
32
|
-
) -> Callable[[type],
|
|
54
|
+
) -> Callable[[type], GeneratedCode]: ...
|
|
55
|
+
|
|
56
|
+
def init_generator(cls: type) -> GeneratedCode: ...
|
|
33
57
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
58
|
+
def get_repr_generator(
|
|
59
|
+
recursion_safe: bool = False,
|
|
60
|
+
eval_safe: bool = False
|
|
61
|
+
) -> Callable[[type], GeneratedCode]: ...
|
|
62
|
+
def repr_generator(cls: type) -> GeneratedCode: ...
|
|
63
|
+
def eq_generator(cls: type) -> GeneratedCode: ...
|
|
37
64
|
|
|
38
|
-
def frozen_setattr_generator(cls: type) ->
|
|
65
|
+
def frozen_setattr_generator(cls: type) -> GeneratedCode: ...
|
|
39
66
|
|
|
40
|
-
def frozen_delattr_generator(cls: type) ->
|
|
67
|
+
def frozen_delattr_generator(cls: type) -> GeneratedCode: ...
|
|
41
68
|
|
|
42
69
|
init_maker: MethodMaker
|
|
43
70
|
repr_maker: MethodMaker
|
|
@@ -69,12 +96,32 @@ def builder(
|
|
|
69
96
|
) -> Callable[[type[_T]], type[_T]]: ...
|
|
70
97
|
|
|
71
98
|
|
|
72
|
-
class
|
|
99
|
+
class SlotFields(dict):
|
|
100
|
+
...
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class SlotMakerMeta(type):
|
|
104
|
+
def __new__(
|
|
105
|
+
cls: type[_T],
|
|
106
|
+
name: str,
|
|
107
|
+
bases: tuple[type, ...],
|
|
108
|
+
ns: dict[str, typing.Any],
|
|
109
|
+
slots: bool = True,
|
|
110
|
+
**kwargs: typing.Any,
|
|
111
|
+
) -> _T: ...
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class Field(metaclass=SlotMakerMeta):
|
|
73
115
|
default: _NothingType | typing.Any
|
|
74
116
|
default_factory: _NothingType | typing.Any
|
|
75
117
|
type: _NothingType | _py_type
|
|
76
118
|
doc: None | str
|
|
119
|
+
init: bool
|
|
120
|
+
repr: bool
|
|
121
|
+
compare: bool
|
|
122
|
+
kw_only: bool
|
|
77
123
|
|
|
124
|
+
__slots__: dict[str, str]
|
|
78
125
|
__classbuilder_internals__: dict
|
|
79
126
|
|
|
80
127
|
def __init__(
|
|
@@ -84,7 +131,13 @@ class Field:
|
|
|
84
131
|
default_factory: _NothingType | typing.Any = NOTHING,
|
|
85
132
|
type: _NothingType | _py_type = NOTHING,
|
|
86
133
|
doc: None | str = None,
|
|
134
|
+
init: bool = True,
|
|
135
|
+
repr: bool = True,
|
|
136
|
+
compare: bool = True,
|
|
137
|
+
kw_only: bool = False,
|
|
87
138
|
) -> None: ...
|
|
139
|
+
|
|
140
|
+
def __init_subclass__(cls, frozen: bool = False): ...
|
|
88
141
|
def __repr__(self) -> str: ...
|
|
89
142
|
def __eq__(self, other: Field | object) -> bool: ...
|
|
90
143
|
def validate_field(self) -> None: ...
|
|
@@ -92,24 +145,64 @@ class Field:
|
|
|
92
145
|
def from_field(cls, fld: Field, /, **kwargs: typing.Any) -> Field: ...
|
|
93
146
|
|
|
94
147
|
|
|
95
|
-
|
|
96
|
-
|
|
148
|
+
# type[Field] doesn't work due to metaclass
|
|
149
|
+
# This is not really precise enough because isinstance is used
|
|
150
|
+
_ReturnsField = Callable[..., Field]
|
|
151
|
+
_FieldType = typing.TypeVar("_FieldType", bound=Field)
|
|
97
152
|
|
|
153
|
+
|
|
154
|
+
@typing.overload
|
|
98
155
|
def make_slot_gatherer(
|
|
99
|
-
|
|
100
|
-
) -> Callable[[type], tuple[dict[str,
|
|
156
|
+
field_type: type[_FieldType]
|
|
157
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, _FieldType], dict[str, typing.Any]]]: ...
|
|
101
158
|
|
|
102
|
-
|
|
103
|
-
|
|
159
|
+
@typing.overload
|
|
160
|
+
def make_slot_gatherer(
|
|
161
|
+
field_type: _ReturnsField = Field
|
|
162
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, Field], dict[str, typing.Any]]]: ...
|
|
104
163
|
|
|
105
|
-
|
|
164
|
+
@typing.overload
|
|
165
|
+
def make_annotation_gatherer(
|
|
166
|
+
field_type: type[_FieldType],
|
|
167
|
+
leave_default_values: bool = True,
|
|
168
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, _FieldType], dict[str, typing.Any]]]: ...
|
|
106
169
|
|
|
170
|
+
@typing.overload
|
|
107
171
|
def make_annotation_gatherer(
|
|
108
|
-
field_type:
|
|
172
|
+
field_type: _ReturnsField = Field,
|
|
173
|
+
leave_default_values: bool = True,
|
|
174
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, Field], dict[str, typing.Any]]]: ...
|
|
175
|
+
|
|
176
|
+
@typing.overload
|
|
177
|
+
def make_field_gatherer(
|
|
178
|
+
field_type: type[_FieldType],
|
|
109
179
|
leave_default_values: bool = True,
|
|
110
|
-
) -> Callable[[type], tuple[dict[str,
|
|
180
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, _FieldType], dict[str, typing.Any]]]: ...
|
|
181
|
+
|
|
182
|
+
@typing.overload
|
|
183
|
+
def make_field_gatherer(
|
|
184
|
+
field_type: _ReturnsField = Field,
|
|
185
|
+
leave_default_values: bool = True,
|
|
186
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, Field], dict[str, typing.Any]]]: ...
|
|
187
|
+
|
|
188
|
+
@typing.overload
|
|
189
|
+
def make_unified_gatherer(
|
|
190
|
+
field_type: type[_FieldType],
|
|
191
|
+
leave_default_values: bool = True,
|
|
192
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, _FieldType], dict[str, typing.Any]]]: ...
|
|
193
|
+
|
|
194
|
+
@typing.overload
|
|
195
|
+
def make_unified_gatherer(
|
|
196
|
+
field_type: _ReturnsField = Field,
|
|
197
|
+
leave_default_values: bool = True,
|
|
198
|
+
) -> Callable[[type | _CopiableMappings], tuple[dict[str, Field], dict[str, typing.Any]]]: ...
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def slot_gatherer(cls_or_ns: type | _CopiableMappings) -> tuple[dict[str, Field], dict[str, typing.Any]]: ...
|
|
202
|
+
def annotation_gatherer(cls_or_ns: type | _CopiableMappings) -> tuple[dict[str, Field], dict[str, typing.Any]]: ...
|
|
203
|
+
|
|
204
|
+
def unified_gatherer(cls_or_ns: type | _CopiableMappings) -> tuple[dict[str, Field], dict[str, typing.Any]]: ...
|
|
111
205
|
|
|
112
|
-
def annotation_gatherer(cls: type) -> tuple[dict[str, Field], dict[str, typing.Any]]: ...
|
|
113
206
|
|
|
114
207
|
def check_argument_order(cls: type) -> None: ...
|
|
115
208
|
|
|
@@ -131,24 +224,35 @@ def slotclass(
|
|
|
131
224
|
syntax_check: bool = True
|
|
132
225
|
) -> Callable[[type[_T]], type[_T]]: ...
|
|
133
226
|
|
|
134
|
-
@typing.overload
|
|
135
|
-
def annotationclass(
|
|
136
|
-
cls: type[_T],
|
|
137
|
-
/,
|
|
138
|
-
*,
|
|
139
|
-
methods: frozenset[MethodMaker] | set[MethodMaker] = default_methods,
|
|
140
|
-
) -> type[_T]: ...
|
|
141
227
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
228
|
+
_gatherer_type = Callable[[type | _CopiableMappings], tuple[dict[str, Field], dict[str, typing.Any]]]
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@dataclass_transform(field_specifiers=(Field,))
|
|
232
|
+
class AnnotationClass(metaclass=SlotMakerMeta):
|
|
233
|
+
__slots__: dict
|
|
234
|
+
|
|
235
|
+
def __init_subclass__(
|
|
236
|
+
cls,
|
|
147
237
|
methods: frozenset[MethodMaker] | set[MethodMaker] = default_methods,
|
|
148
|
-
|
|
238
|
+
gatherer: _gatherer_type = make_unified_gatherer(leave_default_values=True),
|
|
239
|
+
**kwargs,
|
|
240
|
+
) -> None: ...
|
|
149
241
|
|
|
150
|
-
|
|
151
|
-
|
|
242
|
+
class GatheredFields:
|
|
243
|
+
__slots__: dict[str, None]
|
|
152
244
|
|
|
153
|
-
|
|
154
|
-
|
|
245
|
+
fields: dict[str, Field]
|
|
246
|
+
modifications: dict[str, typing.Any]
|
|
247
|
+
|
|
248
|
+
__classbuilder_internals__: dict
|
|
249
|
+
|
|
250
|
+
def __init__(
|
|
251
|
+
self,
|
|
252
|
+
fields: dict[str, Field],
|
|
253
|
+
modifications: dict[str, typing.Any]
|
|
254
|
+
) -> None: ...
|
|
255
|
+
|
|
256
|
+
def __repr__(self) -> str: ...
|
|
257
|
+
def __eq__(self, other) -> bool: ...
|
|
258
|
+
def __call__(self, cls: type) -> tuple[dict[str, Field], dict[str, typing.Any]]: ...
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2024 David C Ellis
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
import sys
|
|
24
|
+
import builtins
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class _StringGlobs(dict):
|
|
28
|
+
"""
|
|
29
|
+
Based on the fake globals dictionary used for annotations
|
|
30
|
+
from 3.14. This allows us to evaluate containers which
|
|
31
|
+
include forward references.
|
|
32
|
+
|
|
33
|
+
It's just a dictionary that returns the key if the key
|
|
34
|
+
is not found.
|
|
35
|
+
"""
|
|
36
|
+
def __missing__(self, key):
|
|
37
|
+
return key
|
|
38
|
+
|
|
39
|
+
def __repr__(self):
|
|
40
|
+
cls_name = self.__class__.__name__
|
|
41
|
+
dict_repr = super().__repr__()
|
|
42
|
+
return f"{cls_name}({dict_repr})"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def eval_hint(hint, context=None, *, recursion_limit=2):
|
|
46
|
+
"""
|
|
47
|
+
Attempt to evaluate a string type hint in the given
|
|
48
|
+
context.
|
|
49
|
+
|
|
50
|
+
If this raises an exception, return the last string.
|
|
51
|
+
|
|
52
|
+
If the recursion limit is hit or a previous value returns
|
|
53
|
+
on evaluation, return the original hint string.
|
|
54
|
+
|
|
55
|
+
Example::
|
|
56
|
+
import builtins
|
|
57
|
+
from typing import ClassVar
|
|
58
|
+
|
|
59
|
+
from ducktools.classbuilder.annotations import eval_hint
|
|
60
|
+
|
|
61
|
+
foo = "foo"
|
|
62
|
+
|
|
63
|
+
context = {**vars(builtins), **globals(), **locals()}
|
|
64
|
+
eval_hint("foo", context) # returns 'foo'
|
|
65
|
+
|
|
66
|
+
eval_hint("ClassVar[str]", context) # returns typing.ClassVar[str]
|
|
67
|
+
eval_hint("ClassVar[forwardref]", context) # returns typing.ClassVar[ForwardRef('forwardref')]
|
|
68
|
+
|
|
69
|
+
:param hint: The existing type hint
|
|
70
|
+
:param context: merged context
|
|
71
|
+
:param recursion_limit: maximum number of evaluation loops before
|
|
72
|
+
returning the original string.
|
|
73
|
+
:return: evaluated hint, or string if it could not evaluate
|
|
74
|
+
"""
|
|
75
|
+
if context is not None:
|
|
76
|
+
context = _StringGlobs(context)
|
|
77
|
+
|
|
78
|
+
original_hint = hint
|
|
79
|
+
|
|
80
|
+
# Using a set would require the hint always be hashable
|
|
81
|
+
# This is only going to be 2 items at most usually
|
|
82
|
+
seen = []
|
|
83
|
+
i = 0
|
|
84
|
+
while isinstance(hint, str):
|
|
85
|
+
seen.append(hint)
|
|
86
|
+
|
|
87
|
+
# noinspection PyBroadException
|
|
88
|
+
try:
|
|
89
|
+
hint = eval(hint, context)
|
|
90
|
+
except Exception:
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
if hint in seen or i >= recursion_limit:
|
|
94
|
+
hint = original_hint
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
i += 1
|
|
98
|
+
|
|
99
|
+
return hint
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def get_ns_annotations(ns, eval_str=True):
|
|
103
|
+
"""
|
|
104
|
+
Given a class namespace, attempt to retrieve the
|
|
105
|
+
annotations dictionary and evaluate strings.
|
|
106
|
+
|
|
107
|
+
Note: This only evaluates in the context of module level globals
|
|
108
|
+
and values in the class namespace. Non-local variables will not
|
|
109
|
+
be evaluated.
|
|
110
|
+
|
|
111
|
+
:param ns: Class namespace (eg cls.__dict__)
|
|
112
|
+
:param eval_str: Attempt to evaluate string annotations (default to True)
|
|
113
|
+
:return: dictionary of evaluated annotations
|
|
114
|
+
"""
|
|
115
|
+
raw_annotations = ns.get("__annotations__", {})
|
|
116
|
+
|
|
117
|
+
if not eval_str:
|
|
118
|
+
return raw_annotations.copy()
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
obj_modulename = ns["__module__"]
|
|
122
|
+
except KeyError:
|
|
123
|
+
obj_module = None
|
|
124
|
+
else:
|
|
125
|
+
obj_module = sys.modules.get(obj_modulename, None)
|
|
126
|
+
|
|
127
|
+
if obj_module:
|
|
128
|
+
obj_globals = vars(obj_module)
|
|
129
|
+
else:
|
|
130
|
+
obj_globals = {}
|
|
131
|
+
|
|
132
|
+
# Type parameters should be usable in hints without breaking
|
|
133
|
+
# This is for Python 3.12+
|
|
134
|
+
type_params = {
|
|
135
|
+
repr(param): param
|
|
136
|
+
for param in ns.get("__type_params__", ())
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
context = {**vars(builtins), **obj_globals, **type_params, **ns}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
k: eval_hint(v, context)
|
|
143
|
+
for k, v in raw_annotations.items()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def is_classvar(hint):
|
|
148
|
+
_typing = sys.modules.get("typing")
|
|
149
|
+
if _typing:
|
|
150
|
+
# Annotated is a nightmare I'm never waking up from
|
|
151
|
+
# 3.8 and 3.9 need Annotated from typing_extensions
|
|
152
|
+
# 3.8 also needs get_origin from typing_extensions
|
|
153
|
+
if sys.version_info < (3, 10):
|
|
154
|
+
_typing_extensions = sys.modules.get("typing_extensions")
|
|
155
|
+
if _typing_extensions:
|
|
156
|
+
_Annotated = _typing_extensions.Annotated
|
|
157
|
+
_get_origin = _typing_extensions.get_origin
|
|
158
|
+
else:
|
|
159
|
+
_Annotated, _get_origin = None, None
|
|
160
|
+
else:
|
|
161
|
+
_Annotated = _typing.Annotated
|
|
162
|
+
_get_origin = _typing.get_origin
|
|
163
|
+
|
|
164
|
+
if _Annotated and _get_origin(hint) is _Annotated:
|
|
165
|
+
hint = getattr(hint, "__origin__", None)
|
|
166
|
+
|
|
167
|
+
if (
|
|
168
|
+
hint is _typing.ClassVar
|
|
169
|
+
or getattr(hint, "__origin__", None) is _typing.ClassVar
|
|
170
|
+
):
|
|
171
|
+
return True
|
|
172
|
+
return False
|
|
173
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
import types
|
|
3
|
+
|
|
4
|
+
_T = typing.TypeVar("_T")
|
|
5
|
+
_CopiableMappings = dict[str, typing.Any] | types.MappingProxyType[str, typing.Any]
|
|
6
|
+
|
|
7
|
+
class _StringGlobs:
|
|
8
|
+
def __missing__(self, key: _T) -> _T: ...
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def eval_hint(
|
|
12
|
+
hint: type | str,
|
|
13
|
+
context: None | dict[str, typing.Any] = None,
|
|
14
|
+
*,
|
|
15
|
+
recursion_limit: int = 2
|
|
16
|
+
) -> type | str: ...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_ns_annotations(
|
|
20
|
+
ns: _CopiableMappings,
|
|
21
|
+
eval_str: bool = True,
|
|
22
|
+
) -> dict[str, typing.Any]: ...
|
|
23
|
+
|
|
24
|
+
def is_classvar(
|
|
25
|
+
hint: object,
|
|
26
|
+
) -> bool: ...
|