ducktools-classbuilder 0.7.5__py3-none-any.whl → 0.8.1__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 -179
- ducktools/classbuilder/annotations.pyi +0 -15
- {ducktools_classbuilder-0.7.5.dist-info → ducktools_classbuilder-0.8.1.dist-info}/METADATA +16 -38
- ducktools_classbuilder-0.8.1.dist-info/RECORD +13 -0
- {ducktools_classbuilder-0.7.5.dist-info → ducktools_classbuilder-0.8.1.dist-info}/WHEEL +1 -1
- ducktools_classbuilder-0.7.5.dist-info/RECORD +0 -13
- /ducktools_classbuilder-0.7.5.dist-info/LICENSE.md → /ducktools_classbuilder-0.8.1.dist-info/LICENSE +0 -0
- {ducktools_classbuilder-0.7.5.dist-info → ducktools_classbuilder-0.8.1.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.1"
|
|
2
|
+
__version_tuple__ = (0, 8, 1)
|
|
@@ -19,205 +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
|
-
class _Stringlike(str):
|
|
28
|
-
# There are typing operators that are not supported by strings
|
|
29
|
-
# This adds the 'or' operator '|'
|
|
30
|
-
|
|
31
|
-
def __or__(self, other):
|
|
32
|
-
if isinstance(other, str):
|
|
33
|
-
other_r = other
|
|
34
|
-
elif name := getattr(other, "__name__", None):
|
|
35
|
-
other_r = name
|
|
36
|
-
else:
|
|
37
|
-
other_r = str(other)
|
|
38
|
-
|
|
39
|
-
return type(self)(f"{self} | {other_r}")
|
|
40
|
-
|
|
41
|
-
def __ror__(self, other):
|
|
42
|
-
if isinstance(other, str):
|
|
43
|
-
other_r = other
|
|
44
|
-
elif name := getattr(other, "__name__", None):
|
|
45
|
-
other_r = name
|
|
46
|
-
else:
|
|
47
|
-
other_r = str(other)
|
|
48
|
-
|
|
49
|
-
return type(self)(f"{other_r} | {self}")
|
|
50
|
-
|
|
51
|
-
def __repr__(self):
|
|
52
|
-
base = super().__repr__()
|
|
53
|
-
clsname = type(self).__name__
|
|
54
|
-
return f"{clsname}({base})"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class _StringGlobs(dict):
|
|
58
|
-
"""
|
|
59
|
-
Based on the fake globals dictionary used for annotations
|
|
60
|
-
from 3.14. This allows us to evaluate containers which
|
|
61
|
-
include forward references.
|
|
62
|
-
|
|
63
|
-
It's just a dictionary that returns the key if the key
|
|
64
|
-
is not found.
|
|
65
|
-
"""
|
|
66
|
-
def __missing__(self, key):
|
|
67
|
-
return _Stringlike(key)
|
|
68
23
|
|
|
69
|
-
def __repr__(self):
|
|
70
|
-
cls_name = self.__class__.__name__
|
|
71
|
-
dict_repr = super().__repr__()
|
|
72
|
-
return f"{cls_name}({dict_repr})"
|
|
73
24
|
|
|
74
|
-
|
|
75
|
-
def eval_hint(hint, context=None, *, recursion_limit=2):
|
|
76
|
-
"""
|
|
77
|
-
Attempt to evaluate a string type hint in the given
|
|
78
|
-
context.
|
|
79
|
-
|
|
80
|
-
If this raises an exception, return the last string.
|
|
81
|
-
|
|
82
|
-
If the recursion limit is hit or a previous value returns
|
|
83
|
-
on evaluation, return the original hint string.
|
|
84
|
-
|
|
85
|
-
Example::
|
|
86
|
-
import builtins
|
|
87
|
-
from typing import ClassVar
|
|
88
|
-
|
|
89
|
-
from ducktools.classbuilder.annotations import eval_hint
|
|
90
|
-
|
|
91
|
-
foo = "foo"
|
|
92
|
-
|
|
93
|
-
context = {**vars(builtins), **globals(), **locals()}
|
|
94
|
-
eval_hint("foo", context) # returns 'foo'
|
|
95
|
-
|
|
96
|
-
eval_hint("ClassVar[str]", context) # returns typing.ClassVar[str]
|
|
97
|
-
eval_hint("ClassVar[forwardref]", context) # returns typing.ClassVar[ForwardRef('forwardref')]
|
|
98
|
-
|
|
99
|
-
:param hint: The existing type hint
|
|
100
|
-
:param context: merged context
|
|
101
|
-
:param recursion_limit: maximum number of evaluation loops before
|
|
102
|
-
returning the original string.
|
|
103
|
-
:return: evaluated hint, or string if it could not evaluate
|
|
104
|
-
"""
|
|
105
|
-
if context is not None:
|
|
106
|
-
context = _StringGlobs(context)
|
|
107
|
-
|
|
108
|
-
original_hint = hint
|
|
109
|
-
|
|
110
|
-
# Using a set would require the hint always be hashable
|
|
111
|
-
# This is only going to be 2 items at most usually
|
|
112
|
-
seen = []
|
|
113
|
-
i = 0
|
|
114
|
-
while isinstance(hint, str):
|
|
115
|
-
seen.append(hint)
|
|
116
|
-
|
|
117
|
-
# noinspection PyBroadException
|
|
118
|
-
try:
|
|
119
|
-
hint = eval(hint, context)
|
|
120
|
-
except Exception:
|
|
121
|
-
break
|
|
122
|
-
|
|
123
|
-
if hint in seen or i >= recursion_limit:
|
|
124
|
-
hint = original_hint
|
|
125
|
-
break
|
|
126
|
-
|
|
127
|
-
i += 1
|
|
128
|
-
|
|
129
|
-
return hint
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def get_ns_annotations(ns, eval_str=True):
|
|
25
|
+
def get_ns_annotations(ns):
|
|
133
26
|
"""
|
|
134
27
|
Given a class namespace, attempt to retrieve the
|
|
135
|
-
annotations dictionary
|
|
136
|
-
|
|
137
|
-
Note: This only evaluates in the context of module level globals
|
|
138
|
-
and values in the class namespace. Non-local variables will not
|
|
139
|
-
be evaluated.
|
|
28
|
+
annotations dictionary.
|
|
140
29
|
|
|
141
30
|
:param ns: Class namespace (eg cls.__dict__)
|
|
142
|
-
:
|
|
143
|
-
:return: dictionary of evaluated annotations
|
|
31
|
+
:return: dictionary of annotations
|
|
144
32
|
"""
|
|
145
33
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
annotate = ns.get("__annotate__")
|
|
150
|
-
|
|
151
|
-
if annotate is not None:
|
|
152
|
-
try:
|
|
153
|
-
raw_annotations = annotate(1) # VALUE call
|
|
154
|
-
except (NameError, AttributeError):
|
|
155
|
-
# Slow path, only used if annotations can't be evaluated.
|
|
156
|
-
from annotationlib import Format, call_annotate_function
|
|
157
|
-
raw_annotations = call_annotate_function(annotate, format=Format.FORWARDREF)
|
|
34
|
+
annotations = ns.get("__annotations__")
|
|
35
|
+
if annotations is not None:
|
|
36
|
+
annotations = annotations.copy()
|
|
158
37
|
else:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
# This will catch cases where someone has used a literal string for a
|
|
163
|
-
# single attribute.
|
|
164
|
-
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
|
|
165
41
|
try:
|
|
166
|
-
|
|
167
|
-
except
|
|
168
|
-
|
|
42
|
+
from annotationlib import Format, call_annotate_function, get_annotate_function
|
|
43
|
+
except ImportError:
|
|
44
|
+
pass
|
|
169
45
|
else:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
obj_globals = {}
|
|
176
|
-
|
|
177
|
-
# Type parameters should be usable in hints without breaking
|
|
178
|
-
# This is for Python 3.12+
|
|
179
|
-
type_params = {
|
|
180
|
-
repr(param): param
|
|
181
|
-
for param in ns.get("__type_params__", ())
|
|
182
|
-
}
|
|
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)
|
|
183
51
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
annotations = {
|
|
187
|
-
k: eval_hint(v, context)
|
|
188
|
-
for k, v in raw_annotations.items()
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
else:
|
|
192
|
-
annotations = raw_annotations.copy()
|
|
52
|
+
if annotations is None:
|
|
53
|
+
annotations = {}
|
|
193
54
|
|
|
194
55
|
return annotations
|
|
195
56
|
|
|
196
57
|
|
|
197
58
|
def is_classvar(hint):
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
#
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
|
208
78
|
else:
|
|
209
|
-
_Annotated
|
|
210
|
-
|
|
211
|
-
_Annotated = _typing.Annotated
|
|
212
|
-
_get_origin = _typing.get_origin
|
|
79
|
+
_Annotated = _typing.Annotated
|
|
80
|
+
_get_origin = _typing.get_origin
|
|
213
81
|
|
|
214
|
-
|
|
215
|
-
|
|
82
|
+
if _Annotated and _get_origin(hint) is _Annotated:
|
|
83
|
+
hint = getattr(hint, "__origin__", None)
|
|
216
84
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
85
|
+
if (
|
|
86
|
+
hint is _typing.ClassVar
|
|
87
|
+
or getattr(hint, "__origin__", None) is _typing.ClassVar
|
|
88
|
+
):
|
|
89
|
+
return True
|
|
222
90
|
return False
|
|
223
91
|
|
|
@@ -1,25 +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 eval_hint(
|
|
13
|
-
hint: type | str,
|
|
14
|
-
context: None | dict[str, typing.Any] = None,
|
|
15
|
-
*,
|
|
16
|
-
recursion_limit: int = 2
|
|
17
|
-
) -> type | str: ...
|
|
18
|
-
|
|
19
|
-
|
|
20
6
|
def get_ns_annotations(
|
|
21
7
|
ns: _CopiableMappings,
|
|
22
|
-
eval_str: bool = True,
|
|
23
8
|
) -> dict[str, typing.Any]: ...
|
|
24
9
|
|
|
25
10
|
def is_classvar(
|
|
@@ -1,30 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ducktools-classbuilder
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: Toolkit for creating class boilerplate generators
|
|
5
5
|
Author: David C Ellis
|
|
6
|
-
License: MIT License
|
|
7
|
-
|
|
8
|
-
Copyright (c) 2024 David C Ellis
|
|
9
|
-
|
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
-
in the Software without restriction, including without limitation the rights
|
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
-
furnished to do so, subject to the following conditions:
|
|
16
|
-
|
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
|
18
|
-
copies or substantial portions of the Software.
|
|
19
|
-
|
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
-
SOFTWARE.
|
|
27
|
-
|
|
28
6
|
Project-URL: Homepage, https://github.com/davidcellis/ducktools-classbuilder
|
|
29
7
|
Classifier: Development Status :: 4 - Beta
|
|
30
8
|
Classifier: Programming Language :: Python :: 3.8
|
|
@@ -37,7 +15,7 @@ Classifier: Operating System :: OS Independent
|
|
|
37
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
38
16
|
Requires-Python: >=3.8
|
|
39
17
|
Description-Content-Type: text/markdown
|
|
40
|
-
License-File: LICENSE
|
|
18
|
+
License-File: LICENSE
|
|
41
19
|
Provides-Extra: docs
|
|
42
20
|
Requires-Dist: sphinx ; extra == 'docs'
|
|
43
21
|
Requires-Dist: myst-parser ; extra == 'docs'
|
|
@@ -86,10 +64,12 @@ These tools are available from the main `ducktools.classbuilder` module.
|
|
|
86
64
|
* `@slotclass`
|
|
87
65
|
* A decorator based implementation that uses a special dict subclass assigned
|
|
88
66
|
to `__slots__` to describe the fields for method generation.
|
|
89
|
-
* `
|
|
90
|
-
* A
|
|
91
|
-
|
|
92
|
-
|
|
67
|
+
* `SlotMakerMeta`
|
|
68
|
+
* A metaclass for creating other implementations using annotations, fields or slots.
|
|
69
|
+
* This metaclass will allow for creating `__slots__` correctly in subclasses.
|
|
70
|
+
* `builder`
|
|
71
|
+
* This is the main tool used for constructing decorators and base classes to provide
|
|
72
|
+
generated methods.
|
|
93
73
|
|
|
94
74
|
Each of these forms of class generation will result in the same methods being
|
|
95
75
|
attached to the class after the field information has been obtained.
|
|
@@ -119,8 +99,9 @@ This includes more customization including `__prefab_pre_init__` and `__prefab_p
|
|
|
119
99
|
functions for subclass customization.
|
|
120
100
|
|
|
121
101
|
A `@prefab` decorator and `Prefab` base class are provided.
|
|
122
|
-
|
|
123
|
-
|
|
102
|
+
|
|
103
|
+
`Prefab` will generate `__slots__` by default.
|
|
104
|
+
decorated classes with `@prefab` that do not declare fields using `__slots__`
|
|
124
105
|
will **not** be slotted and there is no `slots` argument to apply this.
|
|
125
106
|
|
|
126
107
|
Here is an example of applying a conversion in `__post_init__`:
|
|
@@ -164,7 +145,7 @@ the fields can be set *before* the class is constructed, so the class
|
|
|
164
145
|
will work correctly without needing to be rebuilt.
|
|
165
146
|
|
|
166
147
|
For example these two classes would be roughly equivalent, except that
|
|
167
|
-
`@dataclass` has had to recreate the class from scratch while `
|
|
148
|
+
`@dataclass` has had to recreate the class from scratch while `Prefab`
|
|
168
149
|
has created `__slots__` and added the methods on to the original class.
|
|
169
150
|
This means that any references stored to the original class *before*
|
|
170
151
|
`@dataclass` has rebuilt the class will not be pointing towards the
|
|
@@ -179,7 +160,7 @@ functions.
|
|
|
179
160
|
```python
|
|
180
161
|
import json
|
|
181
162
|
from dataclasses import dataclass
|
|
182
|
-
from ducktools.classbuilder import
|
|
163
|
+
from ducktools.classbuilder.prefab import Prefab, attribute
|
|
183
164
|
|
|
184
165
|
|
|
185
166
|
class _RegisterDescriptor:
|
|
@@ -222,10 +203,10 @@ class DataCoords:
|
|
|
222
203
|
return {"x": self.x, "y": self.y}
|
|
223
204
|
|
|
224
205
|
|
|
225
|
-
# slots=True is the default for
|
|
226
|
-
class BuilderCoords(
|
|
206
|
+
# slots=True is the default for Prefab
|
|
207
|
+
class BuilderCoords(Prefab):
|
|
227
208
|
x: float = 0.0
|
|
228
|
-
y: float =
|
|
209
|
+
y: float = attribute(default=0.0, doc="y coordinate")
|
|
229
210
|
|
|
230
211
|
@register.register_method
|
|
231
212
|
def to_json(self):
|
|
@@ -289,9 +270,6 @@ It will copy values provided as the `type` to `Field` into the
|
|
|
289
270
|
Values provided to `doc` will be placed in the final `__slots__`
|
|
290
271
|
field so they are present on the class if `help(...)` is called.
|
|
291
272
|
|
|
292
|
-
`AnnotationClass` offers the same features with additional methods of gathering
|
|
293
|
-
fields.
|
|
294
|
-
|
|
295
273
|
If you want something with more features you can look at the `prefab`
|
|
296
274
|
submodule which provides more specific features that differ further from the
|
|
297
275
|
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=6rcSpKS_Wuf2hPZDjzhezNIcky7glqQWxkKJXThFcLc,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.1.dist-info/LICENSE,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
|
|
10
|
+
ducktools_classbuilder-0.8.1.dist-info/METADATA,sha256=gTTON4Uwak33DCOq41KpYsJPWyVTMtYEEs4r0si5Egs,9636
|
|
11
|
+
ducktools_classbuilder-0.8.1.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
12
|
+
ducktools_classbuilder-0.8.1.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
|
|
13
|
+
ducktools_classbuilder-0.8.1.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=o9df2KexrwOUrw2GuPKSVwZk5OtIJ6Z5AHyArVPvEzg,52
|
|
4
|
-
ducktools/classbuilder/annotations.py,sha256=9QWofrFwYUxtyzwZ4vrFcoFG1Hi9gMe3mrVS3h_Sn1o,7212
|
|
5
|
-
ducktools/classbuilder/annotations.pyi,sha256=hnXC7eN3bosx0DbIpu7iCK4p16p4n9JAp5rZar9qe80,557
|
|
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.5.dist-info/LICENSE.md,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
|
|
10
|
-
ducktools_classbuilder-0.7.5.dist-info/METADATA,sha256=ZKoBZozXg4yJD5ToSOJosDJE8oeBCMgHrU_CGXymzQQ,11004
|
|
11
|
-
ducktools_classbuilder-0.7.5.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
12
|
-
ducktools_classbuilder-0.7.5.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
|
|
13
|
-
ducktools_classbuilder-0.7.5.dist-info/RECORD,,
|
/ducktools_classbuilder-0.7.5.dist-info/LICENSE.md → /ducktools_classbuilder-0.8.1.dist-info/LICENSE
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.7.5.dist-info → ducktools_classbuilder-0.8.1.dist-info}/top_level.txt
RENAMED
|
File without changes
|