ducktools-classbuilder 0.6.1__tar.gz → 0.6.2__tar.gz
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-0.6.1/src/ducktools_classbuilder.egg-info → ducktools_classbuilder-0.6.2}/PKG-INFO +1 -1
- ducktools_classbuilder-0.6.2/docs/approach_vs_tool.md +30 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/__init__.py +58 -13
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/__init__.pyi +12 -1
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/prefab.pyi +3 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2/src/ducktools_classbuilder.egg-info}/PKG-INFO +1 -1
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/test_core.py +31 -0
- ducktools_classbuilder-0.6.1/docs/approach_vs_tool.md +0 -16
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/LICENSE.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/MANIFEST.in +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/README.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/Makefile +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/api.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/conf.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/extension_examples.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/generated_code.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/index.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/make.bat +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/perf/performance_tests.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/prefab/index.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/tutorial.md +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/pyproject.toml +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/setup.cfg +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/annotations.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/annotations.pyi +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/prefab.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/py.typed +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools_classbuilder.egg-info/SOURCES.txt +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools_classbuilder.egg-info/dependency_links.txt +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools_classbuilder.egg-info/requires.txt +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools_classbuilder.egg-info/top_level.txt +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/annotations/test_annotated.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/annotations/test_annotations_module.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/conftest.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_compare_attrib.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_construction.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_internals.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_pre_post_init.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_slots_novalues.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_slotted_class.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_subclass_implementation.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/conftest.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/creation.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/creation_empty.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/dunders.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/fails/creation_1.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/fails/creation_2.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/fails/creation_3.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/fails/creation_5.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/fails/inheritance_1.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/fails/inheritance_2.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/frozen_prefabs.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/funcs_prefabs.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/hint_syntax.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/inheritance.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/init_ex.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/kw_only.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/examples/repr_func.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_creation.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_dunders.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_frozen.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_funcs.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_hint_syntax.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_inheritance.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_init.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_kw_only.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_repr.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/py312_tests/test_generic_annotations.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/test_field_flags.py +0 -0
- {ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/test_slotmakermeta.py +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Approaches and tools #
|
|
2
|
+
|
|
3
|
+
As this module's code generation is inspired by the workings of [David Beazley's Cluegen](https://github.com/dabeaz/cluegen)
|
|
4
|
+
I thought it was briefly worth discussing his note on learning an approach vs using a tool.
|
|
5
|
+
|
|
6
|
+
I think that learning an approach is valuable, this module would not exist without the
|
|
7
|
+
example given by `cluegen`.
|
|
8
|
+
|
|
9
|
+
However, what I found was that in essentially every case where I wanted to use
|
|
10
|
+
these generating tools, I needed to modify them - often significantly.
|
|
11
|
+
It quickly became easier to just create my own tool and upload it as a package.
|
|
12
|
+
|
|
13
|
+
For example, `cluegen` has a few subtle "exercises for the reader". It needs extending
|
|
14
|
+
and fixing for some use-cases.
|
|
15
|
+
* Default values that are not builtins need to be passed as part of the globals
|
|
16
|
+
dict to `exec`.
|
|
17
|
+
* No support for mutable defaults.
|
|
18
|
+
* Subclass methods will be overwritten if they call a cluegen method that has not been
|
|
19
|
+
generated via `super().methodname(...)`
|
|
20
|
+
* `inspect.signature(cls)` does not work if `cls.__init__` has not already been generated.
|
|
21
|
+
(I think this is actually a bug in inspect).
|
|
22
|
+
* Need an extra filter to support things like `ClassVar`.
|
|
23
|
+
|
|
24
|
+
In the general spirit though, this module intends to provide some basic tools to help
|
|
25
|
+
create your own customized boilerplate generators.
|
|
26
|
+
The generator included in the base module is intended to be used to help 'bootstrap' a
|
|
27
|
+
modified generator with features that work how **you** want them to work.
|
|
28
|
+
|
|
29
|
+
The `prefab` module is the more fully featured tool that handles the additional cases *I*
|
|
30
|
+
needed.
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/__init__.py
RENAMED
|
@@ -34,7 +34,7 @@ import sys
|
|
|
34
34
|
|
|
35
35
|
from .annotations import get_ns_annotations, is_classvar
|
|
36
36
|
|
|
37
|
-
__version__ = "v0.6.
|
|
37
|
+
__version__ = "v0.6.2"
|
|
38
38
|
|
|
39
39
|
# Change this name if you make heavy modifications
|
|
40
40
|
INTERNALS_DICT = "__classbuilder_internals__"
|
|
@@ -158,32 +158,69 @@ class MethodMaker:
|
|
|
158
158
|
def __repr__(self):
|
|
159
159
|
return f"<MethodMaker for {self.funcname!r} method>"
|
|
160
160
|
|
|
161
|
-
def __get__(self,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
def __get__(self, inst, cls):
|
|
162
|
+
local_vars = {}
|
|
163
|
+
|
|
164
|
+
# This can be called via super().funcname(...) in which case the class
|
|
165
|
+
# may not be the correct one. If this is the correct class
|
|
166
|
+
# it should have this descriptor in the class dict under
|
|
167
|
+
# the correct funcname.
|
|
168
|
+
# Otherwise is should be found in the MRO of the class.
|
|
169
|
+
if cls.__dict__.get(self.funcname) is self:
|
|
170
|
+
gen_cls = cls
|
|
165
171
|
else:
|
|
166
|
-
#
|
|
167
|
-
|
|
172
|
+
for c in cls.__mro__[1:]: # skip 'cls' as special cased
|
|
173
|
+
if c.__dict__.get(self.funcname) is self:
|
|
174
|
+
gen_cls = c
|
|
175
|
+
break
|
|
176
|
+
else: # pragma: no cover
|
|
177
|
+
# This should only be reached if called with incorrect arguments
|
|
178
|
+
# manually
|
|
179
|
+
raise AttributeError(
|
|
180
|
+
f"Could not find {self!r} in class {cls.__name__!r} MRO."
|
|
181
|
+
)
|
|
168
182
|
|
|
169
|
-
|
|
170
|
-
gen = self.code_generator(cls, self.funcname)
|
|
183
|
+
gen = self.code_generator(gen_cls, self.funcname)
|
|
171
184
|
exec(gen.source_code, gen.globs, local_vars)
|
|
172
185
|
method = local_vars.get(self.funcname)
|
|
173
186
|
|
|
174
187
|
try:
|
|
175
|
-
method.__qualname__ = f"{
|
|
188
|
+
method.__qualname__ = f"{gen_cls.__qualname__}.{self.funcname}"
|
|
176
189
|
except AttributeError:
|
|
177
190
|
# This might be a property or some other special
|
|
178
191
|
# descriptor. Don't try to rename.
|
|
179
192
|
pass
|
|
180
193
|
|
|
181
194
|
# Replace this descriptor on the class with the generated function
|
|
182
|
-
setattr(
|
|
195
|
+
setattr(gen_cls, self.funcname, method)
|
|
183
196
|
|
|
184
197
|
# Use 'get' to return the generated function as a bound method
|
|
185
198
|
# instead of as a regular function for first usage.
|
|
186
|
-
return method.__get__(
|
|
199
|
+
return method.__get__(inst, cls)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class _SignatureMaker:
|
|
203
|
+
# 'inspect.signature' calls the `__get__` method of the `__init__` methodmaker with
|
|
204
|
+
# the wrong arguments.
|
|
205
|
+
# Instead of __get__(None, cls) or __get__(inst, type(inst))
|
|
206
|
+
# it uses __get__(cls, type(cls)).
|
|
207
|
+
#
|
|
208
|
+
# If this is done before `__init__` has been generated then
|
|
209
|
+
# help(cls) will fail along with inspect.signature(cls)
|
|
210
|
+
# This signature maker descriptor is placed to override __signature__ and force
|
|
211
|
+
# the `__init__` signature to be generated first if the signature is requested.
|
|
212
|
+
def __get__(self, instance, cls):
|
|
213
|
+
import inspect # Deferred inspect import
|
|
214
|
+
_ = cls.__init__ # force generation of `__init__` function
|
|
215
|
+
# Remove this attribute from the class
|
|
216
|
+
# This prevents recursion back into this __get__ method.
|
|
217
|
+
delattr(cls, "__signature__")
|
|
218
|
+
sig = inspect.signature(cls)
|
|
219
|
+
setattr(cls, "__signature__", sig)
|
|
220
|
+
return sig
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
signature_maker = _SignatureMaker()
|
|
187
224
|
|
|
188
225
|
|
|
189
226
|
def get_init_generator(null=NOTHING, extra_code=None):
|
|
@@ -402,7 +439,7 @@ _field_init_maker = MethodMaker(
|
|
|
402
439
|
)
|
|
403
440
|
|
|
404
441
|
|
|
405
|
-
def builder(cls=None, /, *, gatherer, methods, flags=None):
|
|
442
|
+
def builder(cls=None, /, *, gatherer, methods, flags=None, fix_signature=True):
|
|
406
443
|
"""
|
|
407
444
|
The main builder for class generation
|
|
408
445
|
|
|
@@ -413,6 +450,10 @@ def builder(cls=None, /, *, gatherer, methods, flags=None):
|
|
|
413
450
|
:type methods: set[MethodMaker]
|
|
414
451
|
:param flags: additional flags to store in the internals dictionary
|
|
415
452
|
for use by method generators.
|
|
453
|
+
:type flags: None | dict[str, bool]
|
|
454
|
+
:param fix_signature: Add a __signature__ attribute to work-around an issue with
|
|
455
|
+
inspect.signature incorrectly handling __init__ descriptors.
|
|
456
|
+
:type fix_signature: bool
|
|
416
457
|
:return: The modified class (the class itself is modified, but this is expected).
|
|
417
458
|
"""
|
|
418
459
|
# Handle `None` to make wrapping with a decorator easier.
|
|
@@ -459,6 +500,10 @@ def builder(cls=None, /, *, gatherer, methods, flags=None):
|
|
|
459
500
|
|
|
460
501
|
internals["methods"] = _MappingProxyType(internal_methods)
|
|
461
502
|
|
|
503
|
+
# Fix for inspect.signature(cls)
|
|
504
|
+
if fix_signature:
|
|
505
|
+
setattr(cls, "__signature__", signature_maker)
|
|
506
|
+
|
|
462
507
|
return cls
|
|
463
508
|
|
|
464
509
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import types
|
|
2
2
|
import typing
|
|
3
3
|
|
|
4
|
+
import inspect
|
|
5
|
+
|
|
4
6
|
from collections.abc import Callable
|
|
5
7
|
from types import MappingProxyType
|
|
6
8
|
from typing_extensions import dataclass_transform
|
|
@@ -49,7 +51,12 @@ class MethodMaker:
|
|
|
49
51
|
code_generator: _CodegenType
|
|
50
52
|
def __init__(self, funcname: str, code_generator: _CodegenType) -> None: ...
|
|
51
53
|
def __repr__(self) -> str: ...
|
|
52
|
-
def __get__(self, instance, cls
|
|
54
|
+
def __get__(self, instance, cls) -> Callable: ...
|
|
55
|
+
|
|
56
|
+
class _SignatureMaker:
|
|
57
|
+
def __get__(self, instance, cls) -> inspect.Signature: ...
|
|
58
|
+
|
|
59
|
+
signature_maker: _SignatureMaker
|
|
53
60
|
|
|
54
61
|
def get_init_generator(
|
|
55
62
|
null: _NothingType = NOTHING,
|
|
@@ -86,6 +93,7 @@ def builder(
|
|
|
86
93
|
gatherer: Callable[[type], tuple[dict[str, Field], dict[str, typing.Any]]],
|
|
87
94
|
methods: frozenset[MethodMaker] | set[MethodMaker],
|
|
88
95
|
flags: dict[str, bool] | None = None,
|
|
96
|
+
fix_signature: bool = ...,
|
|
89
97
|
) -> type[_T]: ...
|
|
90
98
|
|
|
91
99
|
@typing.overload
|
|
@@ -96,6 +104,7 @@ def builder(
|
|
|
96
104
|
gatherer: Callable[[type], tuple[dict[str, Field], dict[str, typing.Any]]],
|
|
97
105
|
methods: frozenset[MethodMaker] | set[MethodMaker],
|
|
98
106
|
flags: dict[str, bool] | None = None,
|
|
107
|
+
fix_signature: bool = ...,
|
|
99
108
|
) -> Callable[[type[_T]], type[_T]]: ...
|
|
100
109
|
|
|
101
110
|
|
|
@@ -126,6 +135,7 @@ class Field(metaclass=SlotMakerMeta):
|
|
|
126
135
|
|
|
127
136
|
__slots__: dict[str, str]
|
|
128
137
|
__classbuilder_internals__: dict
|
|
138
|
+
__signature__: inspect.Signature
|
|
129
139
|
|
|
130
140
|
def __init__(
|
|
131
141
|
self,
|
|
@@ -249,6 +259,7 @@ class GatheredFields:
|
|
|
249
259
|
modifications: dict[str, typing.Any]
|
|
250
260
|
|
|
251
261
|
__classbuilder_internals__: dict
|
|
262
|
+
__signature__: inspect.Signature
|
|
252
263
|
|
|
253
264
|
def __init__(
|
|
254
265
|
self,
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/prefab.pyi
RENAMED
|
@@ -2,6 +2,8 @@ import typing
|
|
|
2
2
|
from types import MappingProxyType
|
|
3
3
|
from typing_extensions import dataclass_transform
|
|
4
4
|
|
|
5
|
+
import inspect
|
|
6
|
+
|
|
5
7
|
from collections.abc import Callable
|
|
6
8
|
|
|
7
9
|
from . import (
|
|
@@ -42,6 +44,7 @@ asdict_maker: MethodMaker
|
|
|
42
44
|
|
|
43
45
|
class Attribute(Field):
|
|
44
46
|
__slots__: dict
|
|
47
|
+
__signature__: inspect.Signature
|
|
45
48
|
|
|
46
49
|
iter: bool
|
|
47
50
|
serialize: bool
|
|
@@ -8,6 +8,7 @@ from ducktools.classbuilder import (
|
|
|
8
8
|
|
|
9
9
|
builder,
|
|
10
10
|
default_methods,
|
|
11
|
+
eq_maker,
|
|
11
12
|
get_fields,
|
|
12
13
|
get_flags,
|
|
13
14
|
get_methods,
|
|
@@ -527,3 +528,33 @@ def test_signature():
|
|
|
527
528
|
__slots__ = SlotFields(x=42)
|
|
528
529
|
|
|
529
530
|
assert str(inspect.signature(SigClass)) == "(x=42)"
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def test_subclass_method_not_overwritten():
|
|
534
|
+
@slotclass
|
|
535
|
+
class X:
|
|
536
|
+
__slots__ = SlotFields(x=Field())
|
|
537
|
+
|
|
538
|
+
class Y(X):
|
|
539
|
+
def __init__(self, x, y):
|
|
540
|
+
self.y = y
|
|
541
|
+
super().__init__(x=x)
|
|
542
|
+
|
|
543
|
+
y_init_func = Y.__init__
|
|
544
|
+
|
|
545
|
+
assert X.__dict__["__eq__"] is eq_maker
|
|
546
|
+
|
|
547
|
+
y_inst = Y(0, 1)
|
|
548
|
+
|
|
549
|
+
# super().__init__ method generated correctly
|
|
550
|
+
assert y_init_func is Y.__init__
|
|
551
|
+
assert X.__dict__["__init__"] is not init_maker
|
|
552
|
+
assert (y_inst.x, y_inst.y) == (0, 1)
|
|
553
|
+
|
|
554
|
+
# Would fail previously as __init__ would be overwritten
|
|
555
|
+
y_inst_2 = Y(0, 2)
|
|
556
|
+
|
|
557
|
+
assert y_inst == y_inst_2
|
|
558
|
+
|
|
559
|
+
assert X.__dict__["__eq__"] is not eq_maker
|
|
560
|
+
assert "__eq__" not in Y.__dict__
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Approaches and tools #
|
|
2
|
-
|
|
3
|
-
As this module's code generation is inspired by the workings of [David Beazley's Cluegen](https://github.com/dabeaz/cluegen)
|
|
4
|
-
I thought it was briefly worth discussing his note on learning an approach vs using a tool.
|
|
5
|
-
|
|
6
|
-
I think that learning an approach is valuable, this module would not exist without the
|
|
7
|
-
example given by `cluegen`. It also wouldn't exist if I hadn't needed to extend `cluegen`
|
|
8
|
-
for some basic features (try using `Path` default values with `cluegen`).
|
|
9
|
-
|
|
10
|
-
In the general spirit though, this module intends to provide some basic tools to help
|
|
11
|
-
build your own custom class generators.
|
|
12
|
-
The generator included in the base module is intended to be used to help 'bootstrap' a
|
|
13
|
-
modified generator with features that work how **you** want them to work.
|
|
14
|
-
|
|
15
|
-
The `prefab` module is the more fully featured powertool *I* built with these tools.
|
|
16
|
-
However, much like a prefabricated building, it may not be what you desire.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/docs/perf/performance_tests.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/prefab.py
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/src/ducktools/classbuilder/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/annotations/test_annotated.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/dynamic/test_internals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_creation.py
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_dunders.py
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_frozen.py
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_funcs.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_init.py
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_kw_only.py
RENAMED
|
File without changes
|
{ducktools_classbuilder-0.6.1 → ducktools_classbuilder-0.6.2}/tests/prefab/shared/test_repr.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|