@@ -17,29 +17,35 @@ Install from PyPI with:
1717The classbuilder tools make up the core of this module and there is an implementation
1818using these tools in the ` prefab ` submodule.
1919
20- There is also a minimal ` @slotclass ` example that can construct classes from a special
21- mapping used in ` __slots__ ` .
20+ The implementation provides both a base class ` Prefab ` that will also generate ` __slots__ `
21+ and a decorator ` @prefab ` which does not support ` __slots__ ` .
2222
2323``` python
24- from ducktools.classbuilder import Field, SlotFields, slotclass
25-
26- @slotclass
27- class SlottedDC :
28- __slots__ = SlotFields(
29- the_answer = 42 ,
30- the_question = Field(
31- default = " What do you get if you multiply six by nine?" ,
32- doc = " Life, the Universe, and Everything" ,
33- ),
24+ from ducktools.classbuilder.prefab import Prefab, attribute
25+
26+ class Slotted (Prefab ):
27+ the_answer: int = 42
28+ the_question: str = attribute(
29+ default = " What do you get if you multiply six by nine?" ,
30+ doc = " Life the universe and everything" ,
3431 )
3532
36- ex = SlottedDC ()
33+ ex = Slotted ()
3734print (ex)
35+ print (ex.__slots__ )
36+ ```
37+
38+ The generated source code for the methods can be viewed using the ` print_generated_code ` helper function.
39+
40+ ``` python
41+ from ducktools.classbuilder import print_generated_code
42+
43+ print_generated_code(SlottedDC)
3844```
3945
4046### Core ###
4147
42- The core of the module provides tools for creating a customized version of the ` dataclass ` concept.
48+ The base ` ducktools.classbuilder ` module provides tools for creating a customized version of the ` dataclass ` concept.
4349
4450* ` MethodMaker `
4551 * This tool takes a function that generates source code and converts it into a descriptor
@@ -75,12 +81,6 @@ This prebuilt implementation is available from the `ducktools.classbuilder.prefa
7581This includes more customization including ` __prefab_pre_init__ ` and ` __prefab_post_init__ `
7682functions for subclass customization.
7783
78- A ` @prefab ` decorator and ` Prefab ` base class are provided.
79-
80- ` Prefab ` will generate ` __slots__ ` by default.
81- decorated classes with ` @prefab ` that do not declare fields using ` __slots__ `
82- will ** not** be slotted and there is no ` slots ` argument to apply this.
83-
8484Here is an example of applying a conversion in ` __post_init__ ` :
8585``` python
8686from pathlib import Path
@@ -106,7 +106,7 @@ print(steam)
106106#### Features ####
107107
108108` Prefab ` and ` @prefab ` support many standard dataclass features along with
109- a few extras .
109+ some extra features and some intentional differences in design .
110110
111111* All standard methods are generated on-demand
112112 * This makes the construction of classes much faster in general
@@ -132,20 +132,20 @@ a few extras.
132132 * ` iter=True ` will include the attribute in the iterable if ` __iter__ ` is generated
133133 * ` serialize=True ` decides if the attribute is include in ` as_dict `
134134 * ` exclude_field ` is short for ` repr=False ` , ` compare=False ` , ` iter=False ` , ` serialize=False `
135- * ` private ` is short for ` exclude_field=True ` and ` init=False ` and requires a default/ factory
135+ * ` private ` is short for ` exclude_field=True ` and ` init=False ` and requires a default or factory
136136 * ` doc ` will add this string as the value in slotted classes, which appears in ` help() `
137137* ` build_prefab ` can be used to dynamically create classes and * does* support a slots argument
138138 * Unlike dataclasses, this does not create the class twice in order to provide slots
139139
140140There are also some intentionally missing features:
141141
142- * The ` @prefab ` decorator does not and will not support a ` slots ` argument
142+ * The ` @prefab ` decorator does not and will never support a ` slots ` argument
143143 * Use ` Prefab ` for slots.
144144* ` as_dict ` and the generated ` .as_dict ` method ** do not** recurse or deep copy
145145* ` unsafe_hash ` is not provided
146146* ` weakref_slot ` is not available as an argument
147147 * ` __weakref__ ` can be added to slots by declaring it as if it were an attribute
148- * There is no check for mutable defaults
148+ * There is no safety check for mutable defaults
149149 * You should still use ` default_factory ` as you would for dataclasses, not doing so
150150 is still incorrect
151151 * ` dataclasses ` uses hashability as a proxy for mutability, but technically this is
@@ -162,7 +162,7 @@ There are also some intentionally missing features:
162162If you want to use ` __slots__ ` in order to save memory you have to declare
163163them when the class is originally created as you can't add them later.
164164
165- When you use ` @dataclass(slots=True) ` [ ^ 2 ] with ` dataclasses ` , the function
165+ When you use ` @dataclass(slots=True) ` [ ^ 1 ] with ` dataclasses ` , the function
166166has to make a new class and attempt to copy over everything from the original.
167167
168168This is because decorators operate on classes * after they have been created*
@@ -305,8 +305,4 @@ with a specific feature, you can create or add it yourself.
305305
306306Heavily inspired by [ David Beazley's Cluegen] ( https://github.com/dabeaz/cluegen )
307307
308- [ ^ 1 ] : ` SlotFields ` is actually just a subclassed ` dict ` with no changes. ` __slots__ `
309- works with dictionaries using the values of the keys, while fields are normally
310- used for documentation.
311-
312- [ ^ 2 ] : or ` @attrs.define ` .
308+ [ ^ 1 ] : or ` @attrs.define ` .
0 commit comments