ducktools-classbuilder 0.9.0__py3-none-any.whl → 0.9.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.

@@ -385,6 +385,36 @@ def eq_generator(cls, funcname="__eq__"):
385
385
  return GeneratedCode(code, globs)
386
386
 
387
387
 
388
+ def replace_generator(cls, funcname="__replace__"):
389
+ # Generate the replace method for built classes
390
+ # unlike the dataclasses implementation this is generated
391
+ attribs = get_fields(cls)
392
+
393
+ # This is essentially the as_dict generator for prefabs
394
+ # except based on attrib.init instead of .serialize
395
+ vals = ", ".join(
396
+ f"'{name}': self.{name}"
397
+ for name, attrib in attribs.items()
398
+ if attrib.init
399
+ )
400
+ init_dict = f"{{{vals}}}"
401
+
402
+ code = (
403
+ f"def {funcname}(self, /, **changes):\n"
404
+ f" new_kwargs = {init_dict}\n"
405
+ f" for name, value in changes.items():\n"
406
+ f" if name not in new_kwargs:\n"
407
+ f" raise TypeError(\n"
408
+ f" f\"{{name!r}} is not a valid replacable \"\n"
409
+ f" f\"field on {{self.__class__.__name__!r}}\"\n"
410
+ f" )\n"
411
+ f" new_kwargs[name] = value\n"
412
+ f" return self.__class__(**new_kwargs)\n"
413
+ )
414
+ globs = {}
415
+ return GeneratedCode(code, globs)
416
+
417
+
388
418
  def frozen_setattr_generator(cls, funcname="__setattr__"):
389
419
  globs = {}
390
420
  field_names = set(get_fields(cls))
@@ -433,6 +463,7 @@ def frozen_delattr_generator(cls, funcname="__delattr__"):
433
463
  init_maker = MethodMaker("__init__", init_generator)
434
464
  repr_maker = MethodMaker("__repr__", repr_generator)
435
465
  eq_maker = MethodMaker("__eq__", eq_generator)
466
+ replace_maker = MethodMaker("__replace__", replace_generator)
436
467
  frozen_setattr_maker = MethodMaker("__setattr__", frozen_setattr_generator)
437
468
  frozen_delattr_maker = MethodMaker("__delattr__", frozen_delattr_generator)
438
469
  default_methods = frozenset({init_maker, repr_maker, eq_maker})
@@ -73,6 +73,7 @@ def get_repr_generator(
73
73
  ) -> _CodegenType: ...
74
74
  def repr_generator(cls: type, funcname: str = "__repr__") -> GeneratedCode: ...
75
75
  def eq_generator(cls: type, funcname: str = "__eq__") -> GeneratedCode: ...
76
+ def replace_generator(cls: type, funcname: str = "__replace__") -> GeneratedCode: ...
76
77
 
77
78
  def frozen_setattr_generator(cls: type, funcname: str = "__setattr__") -> GeneratedCode: ...
78
79
 
@@ -81,6 +82,7 @@ def frozen_delattr_generator(cls: type, funcname: str = "__delattr__") -> Genera
81
82
  init_maker: MethodMaker
82
83
  repr_maker: MethodMaker
83
84
  eq_maker: MethodMaker
85
+ replace_maker: MethodMaker
84
86
  frozen_setattr_maker: MethodMaker
85
87
  frozen_delattr_maker: MethodMaker
86
88
  default_methods: frozenset[MethodMaker]
@@ -1,2 +1,2 @@
1
- __version__ = "0.9.0"
2
- __version_tuple__ = (0, 9, 0)
1
+ __version__ = "0.9.1"
2
+ __version_tuple__ = (0, 9, 1)
@@ -30,7 +30,7 @@ from . import (
30
30
  Field, MethodMaker, GatheredFields, GeneratedCode, SlotMakerMeta,
31
31
  builder, get_flags, get_fields,
32
32
  make_unified_gatherer,
33
- frozen_setattr_maker, frozen_delattr_maker, eq_maker,
33
+ eq_maker, frozen_setattr_maker, frozen_delattr_maker, replace_maker,
34
34
  get_repr_generator,
35
35
  )
36
36
 
@@ -441,6 +441,8 @@ def _make_prefab(
441
441
  if dict_method:
442
442
  methods.add(asdict_maker)
443
443
 
444
+ methods.add(replace_maker)
445
+
444
446
  flags = {
445
447
  "kw_only": kw_only,
446
448
  "slotted": slotted,
@@ -779,3 +781,8 @@ def as_dict(o):
779
781
  for name, attrib in flds.items()
780
782
  if attrib.serialize
781
783
  }
784
+
785
+ def replace(obj, /, **changes):
786
+ if not is_prefab_instance(obj):
787
+ raise TypeError("replace() should be called on prefab instances")
788
+ return obj.__replace__(**changes)
@@ -238,3 +238,5 @@ def is_prefab(o: typing.Any) -> bool: ...
238
238
  def is_prefab_instance(o: object) -> bool: ...
239
239
 
240
240
  def as_dict(o) -> dict[str, typing.Any]: ...
241
+
242
+ def replace(obj: _T, /, **changes: typing.Any) -> _T: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ducktools-classbuilder
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Toolkit for creating class boilerplate generators
5
5
  Author: David C Ellis
6
6
  Project-URL: Homepage, https://github.com/davidcellis/ducktools-classbuilder
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3.10
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
14
15
  Classifier: Operating System :: OS Independent
15
16
  Classifier: License :: OSI Approved :: MIT License
16
17
  Requires-Python: >=3.8
@@ -0,0 +1,13 @@
1
+ ducktools/classbuilder/__init__.py,sha256=5vagbDiErapPudNG5-gP3yarlA6-q8IriMcRrAzBBr4,33433
2
+ ducktools/classbuilder/__init__.pyi,sha256=6nEfVyeF1HE4YlvcNkFetACqMd1EObu3hYwoLYBbRNo,7796
3
+ ducktools/classbuilder/_version.py,sha256=Ti7IekFg9SsQHXFYa9yzblMN29C0yL2OG6aLOfnSQOc,52
4
+ ducktools/classbuilder/annotations.py,sha256=VEZsCM8lwfhaWrQi8dUOAkicYHxUHaSAyM-FzL34wXI,3583
5
+ ducktools/classbuilder/annotations.pyi,sha256=c5vYtULdDgMYWtkzeYMsHIbmnEuT2Ru-nNZieWvYuQ4,247
6
+ ducktools/classbuilder/prefab.py,sha256=RiVbESwFiPv3Y4PpclSZAwdwBomILbhGEF8XHAaDzW4,24643
7
+ ducktools/classbuilder/prefab.pyi,sha256=_Tm2V97Udt3-WlbBRuOSt11PPYdw1TrFeSd4Mcs2EKM,6422
8
+ ducktools/classbuilder/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
9
+ ducktools_classbuilder-0.9.1.dist-info/LICENSE,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
10
+ ducktools_classbuilder-0.9.1.dist-info/METADATA,sha256=45E7CeSoBEii1Tra1U16WUvcBepEQ4vCsay_y_2UinY,9687
11
+ ducktools_classbuilder-0.9.1.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
12
+ ducktools_classbuilder-0.9.1.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
13
+ ducktools_classbuilder-0.9.1.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- ducktools/classbuilder/__init__.py,sha256=IfMN45iuJJ0BadtmjwjoYhXCLw6WOSQTMk9s_cxGT0M,32312
2
- ducktools/classbuilder/__init__.pyi,sha256=66VOHYndP7z83Bl7QzTOyoF8j2nLFRRFfaQ6-mTdnmo,7683
3
- ducktools/classbuilder/_version.py,sha256=RJaQx44-8b_pifglxqeP0c25pHPZ-Zu98duqjj_ZSOg,52
4
- ducktools/classbuilder/annotations.py,sha256=VEZsCM8lwfhaWrQi8dUOAkicYHxUHaSAyM-FzL34wXI,3583
5
- ducktools/classbuilder/annotations.pyi,sha256=c5vYtULdDgMYWtkzeYMsHIbmnEuT2Ru-nNZieWvYuQ4,247
6
- ducktools/classbuilder/prefab.py,sha256=I1FRb1avVp6u1TPJgEs5QB1pnRH0xh8PQoI3oF8su5Q,24415
7
- ducktools/classbuilder/prefab.pyi,sha256=sd800Hx2jf3CIaIfcurzanKGV-7-Km6_dY8JrM2FRHw,6363
8
- ducktools/classbuilder/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
9
- ducktools_classbuilder-0.9.0.dist-info/LICENSE,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
10
- ducktools_classbuilder-0.9.0.dist-info/METADATA,sha256=l6eUeDAEMjJKTInGL2Q7oXGSfj0ur0sKy8UWdbtB15c,9636
11
- ducktools_classbuilder-0.9.0.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
12
- ducktools_classbuilder-0.9.0.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
13
- ducktools_classbuilder-0.9.0.dist-info/RECORD,,