ducktools-classbuilder 0.7.4__py3-none-any.whl → 0.8.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 +2 -2
- ducktools/classbuilder/_version.py +2 -2
- ducktools/classbuilder/annotations.py +47 -249
- ducktools/classbuilder/annotations.pyi +0 -20
- {ducktools_classbuilder-0.7.4.dist-info → ducktools_classbuilder-0.8.0.dist-info}/METADATA +15 -15
- ducktools_classbuilder-0.8.0.dist-info/RECORD +13 -0
- {ducktools_classbuilder-0.7.4.dist-info → ducktools_classbuilder-0.8.0.dist-info}/WHEEL +1 -1
- ducktools_classbuilder-0.7.4.dist-info/RECORD +0 -13
- {ducktools_classbuilder-0.7.4.dist-info → ducktools_classbuilder-0.8.0.dist-info}/LICENSE.md +0 -0
- {ducktools_classbuilder-0.7.4.dist-info → ducktools_classbuilder-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -769,7 +769,7 @@ def make_annotation_gatherer(
|
|
|
769
769
|
if is_classvar(v):
|
|
770
770
|
continue
|
|
771
771
|
|
|
772
|
-
if v is KW_ONLY:
|
|
772
|
+
if v is KW_ONLY or (isinstance(v, str) and v == "KW_ONLY"):
|
|
773
773
|
if kw_flag:
|
|
774
774
|
raise SyntaxError("KW_ONLY sentinel may only appear once.")
|
|
775
775
|
kw_flag = True
|
|
@@ -868,7 +868,7 @@ def make_unified_gatherer(
|
|
|
868
868
|
# To choose between annotation and attribute gatherers
|
|
869
869
|
# compare sets of names.
|
|
870
870
|
# Don't bother evaluating string annotations, as we only need names
|
|
871
|
-
cls_annotations = get_ns_annotations(cls_dict
|
|
871
|
+
cls_annotations = get_ns_annotations(cls_dict)
|
|
872
872
|
cls_attributes = {
|
|
873
873
|
k: v for k, v in cls_dict.items() if isinstance(v, field_type)
|
|
874
874
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.
|
|
2
|
-
__version_tuple__ = (0,
|
|
1
|
+
__version__ = "0.8.0"
|
|
2
|
+
__version_tuple__ = (0, 8, 0)
|
|
@@ -19,275 +19,73 @@
|
|
|
19
19
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
|
-
|
|
23
22
|
import sys
|
|
24
|
-
import builtins
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# Evil stuff from types.py
|
|
28
|
-
def _cell_factory():
|
|
29
|
-
a = 1
|
|
30
|
-
|
|
31
|
-
def f():
|
|
32
|
-
nonlocal a
|
|
33
|
-
return f.__closure__[0]
|
|
34
|
-
_FunctionType = type(_cell_factory)
|
|
35
|
-
_CellType = type(_cell_factory())
|
|
36
|
-
del _cell_factory
|
|
37
|
-
# End evil stuff from types.py
|
|
38
|
-
|
|
39
23
|
|
|
40
|
-
class _Stringlike(str):
|
|
41
|
-
# There are typing operators that are not supported by strings
|
|
42
|
-
# This adds the 'or' operator '|'
|
|
43
24
|
|
|
44
|
-
|
|
45
|
-
if isinstance(other, str):
|
|
46
|
-
other_r = other
|
|
47
|
-
elif name := getattr(other, "__name__", None):
|
|
48
|
-
other_r = name
|
|
49
|
-
else:
|
|
50
|
-
other_r = str(other)
|
|
51
|
-
|
|
52
|
-
return type(self)(f"{self} | {other_r}")
|
|
53
|
-
|
|
54
|
-
def __ror__(self, other):
|
|
55
|
-
if isinstance(other, str):
|
|
56
|
-
other_r = other
|
|
57
|
-
elif name := getattr(other, "__name__", None):
|
|
58
|
-
other_r = name
|
|
59
|
-
else:
|
|
60
|
-
other_r = str(other)
|
|
61
|
-
|
|
62
|
-
return type(self)(f"{other_r} | {self}")
|
|
63
|
-
|
|
64
|
-
def __repr__(self):
|
|
65
|
-
base = super().__repr__()
|
|
66
|
-
clsname = type(self).__name__
|
|
67
|
-
return f"{clsname}({base})"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class _StringGlobs(dict):
|
|
71
|
-
"""
|
|
72
|
-
Based on the fake globals dictionary used for annotations
|
|
73
|
-
from 3.14. This allows us to evaluate containers which
|
|
74
|
-
include forward references.
|
|
75
|
-
|
|
76
|
-
It's just a dictionary that returns the key if the key
|
|
77
|
-
is not found.
|
|
78
|
-
"""
|
|
79
|
-
def __missing__(self, key):
|
|
80
|
-
return _Stringlike(key)
|
|
81
|
-
|
|
82
|
-
def __repr__(self):
|
|
83
|
-
cls_name = self.__class__.__name__
|
|
84
|
-
dict_repr = super().__repr__()
|
|
85
|
-
return f"{cls_name}({dict_repr})"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def eval_hint(hint, context=None, *, recursion_limit=2):
|
|
89
|
-
"""
|
|
90
|
-
Attempt to evaluate a string type hint in the given
|
|
91
|
-
context.
|
|
92
|
-
|
|
93
|
-
If this raises an exception, return the last string.
|
|
94
|
-
|
|
95
|
-
If the recursion limit is hit or a previous value returns
|
|
96
|
-
on evaluation, return the original hint string.
|
|
97
|
-
|
|
98
|
-
Example::
|
|
99
|
-
import builtins
|
|
100
|
-
from typing import ClassVar
|
|
101
|
-
|
|
102
|
-
from ducktools.classbuilder.annotations import eval_hint
|
|
103
|
-
|
|
104
|
-
foo = "foo"
|
|
105
|
-
|
|
106
|
-
context = {**vars(builtins), **globals(), **locals()}
|
|
107
|
-
eval_hint("foo", context) # returns 'foo'
|
|
108
|
-
|
|
109
|
-
eval_hint("ClassVar[str]", context) # returns typing.ClassVar[str]
|
|
110
|
-
eval_hint("ClassVar[forwardref]", context) # returns typing.ClassVar[ForwardRef('forwardref')]
|
|
111
|
-
|
|
112
|
-
:param hint: The existing type hint
|
|
113
|
-
:param context: merged context
|
|
114
|
-
:param recursion_limit: maximum number of evaluation loops before
|
|
115
|
-
returning the original string.
|
|
116
|
-
:return: evaluated hint, or string if it could not evaluate
|
|
117
|
-
"""
|
|
118
|
-
if context is not None:
|
|
119
|
-
context = _StringGlobs(context)
|
|
120
|
-
|
|
121
|
-
original_hint = hint
|
|
122
|
-
|
|
123
|
-
# Using a set would require the hint always be hashable
|
|
124
|
-
# This is only going to be 2 items at most usually
|
|
125
|
-
seen = []
|
|
126
|
-
i = 0
|
|
127
|
-
while isinstance(hint, str):
|
|
128
|
-
seen.append(hint)
|
|
129
|
-
|
|
130
|
-
# noinspection PyBroadException
|
|
131
|
-
try:
|
|
132
|
-
hint = eval(hint, context)
|
|
133
|
-
except Exception:
|
|
134
|
-
break
|
|
135
|
-
|
|
136
|
-
if hint in seen or i >= recursion_limit:
|
|
137
|
-
hint = original_hint
|
|
138
|
-
break
|
|
139
|
-
|
|
140
|
-
i += 1
|
|
141
|
-
|
|
142
|
-
return hint
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def call_annotate_func(annotate):
|
|
146
|
-
# Python 3.14 breaks the old methods of getting annotations
|
|
147
|
-
# The new annotationlib currently relies on 'ast' and 'functools'
|
|
148
|
-
# that this project tries to avoid importing.
|
|
149
|
-
|
|
150
|
-
# The basic logic is copied from there, however, replacing ForwardRef
|
|
151
|
-
# with a more basic class.
|
|
152
|
-
# While `annotationlib` is trying to return ForwardRef objects that can
|
|
153
|
-
# be evaluated later, this module only cares about annotations that can
|
|
154
|
-
# be evaluated at the point this function is called.
|
|
155
|
-
# As such we throw away the other information and just return strings
|
|
156
|
-
# instead of forwardrefs.
|
|
157
|
-
|
|
158
|
-
try:
|
|
159
|
-
raw_annotations = annotate(1)
|
|
160
|
-
except NameError:
|
|
161
|
-
pass
|
|
162
|
-
else:
|
|
163
|
-
return raw_annotations
|
|
164
|
-
|
|
165
|
-
# The annotate func may support forwardref natively
|
|
166
|
-
try:
|
|
167
|
-
raw_annotations = annotate(2)
|
|
168
|
-
except NotImplementedError:
|
|
169
|
-
pass
|
|
170
|
-
else:
|
|
171
|
-
return raw_annotations
|
|
172
|
-
|
|
173
|
-
# Not supported so we have to implement our own deferred handling
|
|
174
|
-
# Some modified logic from annotationlib
|
|
175
|
-
namespace = {**annotate.__builtins__, **annotate.__globals__}
|
|
176
|
-
globs = _StringGlobs(namespace)
|
|
177
|
-
|
|
178
|
-
# This handles closures where the variable is defined after get annotations is called.
|
|
179
|
-
if annotate.__closure__:
|
|
180
|
-
freevars = annotate.__code__.co_freevars
|
|
181
|
-
new_closure = []
|
|
182
|
-
for i, cell in enumerate(annotate.__closure__):
|
|
183
|
-
try:
|
|
184
|
-
cell.cell_contents
|
|
185
|
-
except ValueError:
|
|
186
|
-
if i < len(freevars):
|
|
187
|
-
name = freevars[i]
|
|
188
|
-
else:
|
|
189
|
-
name = "__cell__"
|
|
190
|
-
new_closure.append(_CellType(name))
|
|
191
|
-
else:
|
|
192
|
-
new_closure.append(cell)
|
|
193
|
-
closure = tuple(new_closure)
|
|
194
|
-
else:
|
|
195
|
-
closure = None
|
|
196
|
-
|
|
197
|
-
new_annotate = _FunctionType(annotate.__code__, globs, closure=closure)
|
|
198
|
-
|
|
199
|
-
# Convert _Stringlike back to str
|
|
200
|
-
annos = {
|
|
201
|
-
k: str(v) if isinstance(v, _Stringlike) else v
|
|
202
|
-
for k, v in new_annotate(1).items()
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return annos
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
def get_ns_annotations(ns, eval_str=True):
|
|
25
|
+
def get_ns_annotations(ns):
|
|
209
26
|
"""
|
|
210
27
|
Given a class namespace, attempt to retrieve the
|
|
211
|
-
annotations dictionary
|
|
212
|
-
|
|
213
|
-
Note: This only evaluates in the context of module level globals
|
|
214
|
-
and values in the class namespace. Non-local variables will not
|
|
215
|
-
be evaluated.
|
|
28
|
+
annotations dictionary.
|
|
216
29
|
|
|
217
30
|
:param ns: Class namespace (eg cls.__dict__)
|
|
218
|
-
:
|
|
219
|
-
:return: dictionary of evaluated annotations
|
|
31
|
+
:return: dictionary of annotations
|
|
220
32
|
"""
|
|
221
33
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if annotate is not None:
|
|
227
|
-
raw_annotations = call_annotate_func(annotate)
|
|
34
|
+
annotations = ns.get("__annotations__")
|
|
35
|
+
if annotations is not None:
|
|
36
|
+
annotations = annotations.copy()
|
|
228
37
|
else:
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
# This will catch cases where someone has used a literal string for a
|
|
233
|
-
# single attribute.
|
|
234
|
-
if eval_str:
|
|
38
|
+
# See if we're using PEP-649 annotations
|
|
39
|
+
# Guarding this with a try/except instead of a version check
|
|
40
|
+
# In case there's a change and PEP-649 somehow doesn't make 3.14
|
|
235
41
|
try:
|
|
236
|
-
|
|
237
|
-
except
|
|
238
|
-
|
|
239
|
-
else:
|
|
240
|
-
obj_module = sys.modules.get(obj_modulename, None)
|
|
241
|
-
|
|
242
|
-
if obj_module:
|
|
243
|
-
obj_globals = vars(obj_module)
|
|
42
|
+
from annotationlib import Format, call_annotate_function, get_annotate_function
|
|
43
|
+
except ImportError:
|
|
44
|
+
pass
|
|
244
45
|
else:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
repr(param): param
|
|
251
|
-
for param in ns.get("__type_params__", ())
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
context = {**vars(builtins), **obj_globals, **type_params, **ns}
|
|
255
|
-
|
|
256
|
-
annotations = {
|
|
257
|
-
k: eval_hint(v, context)
|
|
258
|
-
for k, v in raw_annotations.items()
|
|
259
|
-
}
|
|
46
|
+
annotate = ns.get("__annotate__") # Works in the alphas, but may break
|
|
47
|
+
if not annotate:
|
|
48
|
+
annotate = get_annotate_function(ns)
|
|
49
|
+
if annotate:
|
|
50
|
+
annotations = call_annotate_function(annotate, format=Format.FORWARDREF)
|
|
260
51
|
|
|
261
|
-
|
|
262
|
-
annotations =
|
|
52
|
+
if annotations is None:
|
|
53
|
+
annotations = {}
|
|
263
54
|
|
|
264
55
|
return annotations
|
|
265
56
|
|
|
266
57
|
|
|
267
58
|
def is_classvar(hint):
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
#
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
59
|
+
if isinstance(hint, str):
|
|
60
|
+
# String annotations, just check if the string 'ClassVar' is in there
|
|
61
|
+
# This is overly broad and could be smarter.
|
|
62
|
+
return "ClassVar" in hint
|
|
63
|
+
elif (annotationlib := sys.modules.get("annotationlib")) and isinstance(hint, annotationlib.ForwardRef):
|
|
64
|
+
return "ClassVar" in hint.__arg__
|
|
65
|
+
else:
|
|
66
|
+
_typing = sys.modules.get("typing")
|
|
67
|
+
if _typing:
|
|
68
|
+
# Annotated is a nightmare I'm never waking up from
|
|
69
|
+
# 3.8 and 3.9 need Annotated from typing_extensions
|
|
70
|
+
# 3.8 also needs get_origin from typing_extensions
|
|
71
|
+
if sys.version_info < (3, 10):
|
|
72
|
+
_typing_extensions = sys.modules.get("typing_extensions")
|
|
73
|
+
if _typing_extensions:
|
|
74
|
+
_Annotated = _typing_extensions.Annotated
|
|
75
|
+
_get_origin = _typing_extensions.get_origin
|
|
76
|
+
else:
|
|
77
|
+
_Annotated, _get_origin = None, None
|
|
278
78
|
else:
|
|
279
|
-
_Annotated
|
|
280
|
-
|
|
281
|
-
_Annotated = _typing.Annotated
|
|
282
|
-
_get_origin = _typing.get_origin
|
|
79
|
+
_Annotated = _typing.Annotated
|
|
80
|
+
_get_origin = _typing.get_origin
|
|
283
81
|
|
|
284
|
-
|
|
285
|
-
|
|
82
|
+
if _Annotated and _get_origin(hint) is _Annotated:
|
|
83
|
+
hint = getattr(hint, "__origin__", None)
|
|
286
84
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
85
|
+
if (
|
|
86
|
+
hint is _typing.ClassVar
|
|
87
|
+
or getattr(hint, "__origin__", None) is _typing.ClassVar
|
|
88
|
+
):
|
|
89
|
+
return True
|
|
292
90
|
return False
|
|
293
91
|
|
|
@@ -1,30 +1,10 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
1
|
import typing
|
|
3
2
|
import types
|
|
4
3
|
|
|
5
|
-
_T = typing.TypeVar("_T")
|
|
6
4
|
_CopiableMappings = dict[str, typing.Any] | types.MappingProxyType[str, typing.Any]
|
|
7
5
|
|
|
8
|
-
class _StringGlobs(dict):
|
|
9
|
-
def __missing__(self, key: _T) -> _T: ...
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def call_annotate_func(
|
|
13
|
-
annotate: Callable[[int], dict[str, type | typing.ForwardRef]]
|
|
14
|
-
) -> dict[str, type | str]: ...
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def eval_hint(
|
|
18
|
-
hint: type | str,
|
|
19
|
-
context: None | dict[str, typing.Any] = None,
|
|
20
|
-
*,
|
|
21
|
-
recursion_limit: int = 2
|
|
22
|
-
) -> type | str: ...
|
|
23
|
-
|
|
24
|
-
|
|
25
6
|
def get_ns_annotations(
|
|
26
7
|
ns: _CopiableMappings,
|
|
27
|
-
eval_str: bool = True,
|
|
28
8
|
) -> dict[str, typing.Any]: ...
|
|
29
9
|
|
|
30
10
|
def is_classvar(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ducktools-classbuilder
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Toolkit for creating class boilerplate generators
|
|
5
5
|
Author: David C Ellis
|
|
6
6
|
License: MIT License
|
|
@@ -86,10 +86,12 @@ These tools are available from the main `ducktools.classbuilder` module.
|
|
|
86
86
|
* `@slotclass`
|
|
87
87
|
* A decorator based implementation that uses a special dict subclass assigned
|
|
88
88
|
to `__slots__` to describe the fields for method generation.
|
|
89
|
-
* `
|
|
90
|
-
* A
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
* `SlotMakerMeta`
|
|
90
|
+
* A metaclass for creating other implementations using annotations, fields or slots.
|
|
91
|
+
* This metaclass will allow for creating `__slots__` correctly in subclasses.
|
|
92
|
+
* `builder`
|
|
93
|
+
* This is the main tool used for constructing decorators and base classes to provide
|
|
94
|
+
generated methods.
|
|
93
95
|
|
|
94
96
|
Each of these forms of class generation will result in the same methods being
|
|
95
97
|
attached to the class after the field information has been obtained.
|
|
@@ -119,8 +121,9 @@ This includes more customization including `__prefab_pre_init__` and `__prefab_p
|
|
|
119
121
|
functions for subclass customization.
|
|
120
122
|
|
|
121
123
|
A `@prefab` decorator and `Prefab` base class are provided.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
|
|
125
|
+
`Prefab` will generate `__slots__` by default.
|
|
126
|
+
decorated classes with `@prefab` that do not declare fields using `__slots__`
|
|
124
127
|
will **not** be slotted and there is no `slots` argument to apply this.
|
|
125
128
|
|
|
126
129
|
Here is an example of applying a conversion in `__post_init__`:
|
|
@@ -164,7 +167,7 @@ the fields can be set *before* the class is constructed, so the class
|
|
|
164
167
|
will work correctly without needing to be rebuilt.
|
|
165
168
|
|
|
166
169
|
For example these two classes would be roughly equivalent, except that
|
|
167
|
-
`@dataclass` has had to recreate the class from scratch while `
|
|
170
|
+
`@dataclass` has had to recreate the class from scratch while `Prefab`
|
|
168
171
|
has created `__slots__` and added the methods on to the original class.
|
|
169
172
|
This means that any references stored to the original class *before*
|
|
170
173
|
`@dataclass` has rebuilt the class will not be pointing towards the
|
|
@@ -179,7 +182,7 @@ functions.
|
|
|
179
182
|
```python
|
|
180
183
|
import json
|
|
181
184
|
from dataclasses import dataclass
|
|
182
|
-
from ducktools.classbuilder import
|
|
185
|
+
from ducktools.classbuilder.prefab import Prefab, attribute
|
|
183
186
|
|
|
184
187
|
|
|
185
188
|
class _RegisterDescriptor:
|
|
@@ -222,10 +225,10 @@ class DataCoords:
|
|
|
222
225
|
return {"x": self.x, "y": self.y}
|
|
223
226
|
|
|
224
227
|
|
|
225
|
-
# slots=True is the default for
|
|
226
|
-
class BuilderCoords(
|
|
228
|
+
# slots=True is the default for Prefab
|
|
229
|
+
class BuilderCoords(Prefab):
|
|
227
230
|
x: float = 0.0
|
|
228
|
-
y: float =
|
|
231
|
+
y: float = attribute(default=0.0, doc="y coordinate")
|
|
229
232
|
|
|
230
233
|
@register.register_method
|
|
231
234
|
def to_json(self):
|
|
@@ -289,9 +292,6 @@ It will copy values provided as the `type` to `Field` into the
|
|
|
289
292
|
Values provided to `doc` will be placed in the final `__slots__`
|
|
290
293
|
field so they are present on the class if `help(...)` is called.
|
|
291
294
|
|
|
292
|
-
`AnnotationClass` offers the same features with additional methods of gathering
|
|
293
|
-
fields.
|
|
294
|
-
|
|
295
295
|
If you want something with more features you can look at the `prefab`
|
|
296
296
|
submodule which provides more specific features that differ further from the
|
|
297
297
|
behaviour of `dataclasses`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ducktools/classbuilder/__init__.py,sha256=LfPJ6WgDye3juzSovwicQpFKrEmBbl6dPmhxbVLwRaQ,32381
|
|
2
|
+
ducktools/classbuilder/__init__.pyi,sha256=t2KrEsEhKFbLpl0QeX0CiCy_VTRFRZO_2ABdfndRfZY,7939
|
|
3
|
+
ducktools/classbuilder/_version.py,sha256=kiXGlQhMHQWiHk12ZeZ9CjneqMQ_CbyHdpnt8oCSThg,52
|
|
4
|
+
ducktools/classbuilder/annotations.py,sha256=BJRZnGbsXeoXCpXIgjfEDNVNvtoz65LH2VKZsasj_kw,3601
|
|
5
|
+
ducktools/classbuilder/annotations.pyi,sha256=c5vYtULdDgMYWtkzeYMsHIbmnEuT2Ru-nNZieWvYuQ4,247
|
|
6
|
+
ducktools/classbuilder/prefab.py,sha256=6YOVVYYeuMF5gv9DnK-sCvNKxBaBoqDXNLUQ22-xINk,24097
|
|
7
|
+
ducktools/classbuilder/prefab.pyi,sha256=x2ioTpkhNjQXFeKABFOzE0xNeZ8f_W5vusmuAzE19mc,4491
|
|
8
|
+
ducktools/classbuilder/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
|
9
|
+
ducktools_classbuilder-0.8.0.dist-info/LICENSE.md,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
|
|
10
|
+
ducktools_classbuilder-0.8.0.dist-info/METADATA,sha256=glZbRUQ85WZJvhCxWMr0tqfxFc60eGx78dkzLi6_VXQ,10887
|
|
11
|
+
ducktools_classbuilder-0.8.0.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
12
|
+
ducktools_classbuilder-0.8.0.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
|
|
13
|
+
ducktools_classbuilder-0.8.0.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
ducktools/classbuilder/__init__.py,sha256=DA5ZisvBEQGK3Mx2Y_SS43ZkIOHd1WZs2JF2g9n1URs,32354
|
|
2
|
-
ducktools/classbuilder/__init__.pyi,sha256=t2KrEsEhKFbLpl0QeX0CiCy_VTRFRZO_2ABdfndRfZY,7939
|
|
3
|
-
ducktools/classbuilder/_version.py,sha256=Z7KmGeeyyT2ppHJrXQg4HcQhc0Y9QqZpNm00ZQT7MuY,52
|
|
4
|
-
ducktools/classbuilder/annotations.py,sha256=cgFlMmEXIhBUZ3DWbPQgFVqPx56s1vR3KROaiypDroo,9174
|
|
5
|
-
ducktools/classbuilder/annotations.pyi,sha256=vW3YQIiKYYQJll9_B4oTkBwIh4nOy1AnU9Ny8_a0dRY,686
|
|
6
|
-
ducktools/classbuilder/prefab.py,sha256=6YOVVYYeuMF5gv9DnK-sCvNKxBaBoqDXNLUQ22-xINk,24097
|
|
7
|
-
ducktools/classbuilder/prefab.pyi,sha256=x2ioTpkhNjQXFeKABFOzE0xNeZ8f_W5vusmuAzE19mc,4491
|
|
8
|
-
ducktools/classbuilder/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
|
|
9
|
-
ducktools_classbuilder-0.7.4.dist-info/LICENSE.md,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
|
|
10
|
-
ducktools_classbuilder-0.7.4.dist-info/METADATA,sha256=ToPo40dXDorKyD_bL_pJwIZbDsiptuJJ4QpqoBdrSBc,11004
|
|
11
|
-
ducktools_classbuilder-0.7.4.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
12
|
-
ducktools_classbuilder-0.7.4.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
|
|
13
|
-
ducktools_classbuilder-0.7.4.dist-info/RECORD,,
|
{ducktools_classbuilder-0.7.4.dist-info → ducktools_classbuilder-0.8.0.dist-info}/LICENSE.md
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.7.4.dist-info → ducktools_classbuilder-0.8.0.dist-info}/top_level.txt
RENAMED
|
File without changes
|