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

@@ -30,11 +30,10 @@
30
30
  # but is also the metaclass used to construct 'Field'.
31
31
  # Field itself sidesteps this by defining __slots__ to avoid that branch.
32
32
 
33
- import sys
33
+ import os
34
34
 
35
35
  from .annotations import get_ns_annotations, is_classvar
36
-
37
- __version__ = "v0.6.2"
36
+ from ._version import __version__, __version_tuple__
38
37
 
39
38
  # Change this name if you make heavy modifications
40
39
  INTERNALS_DICT = "__classbuilder_internals__"
@@ -43,7 +42,7 @@ META_GATHERER_NAME = "_meta_gatherer"
43
42
 
44
43
  # If testing, make Field classes frozen to make sure attributes are not
45
44
  # overwritten. When running this is a performance penalty so it is not required.
46
- _UNDER_TESTING = "pytest" in sys.modules
45
+ _UNDER_TESTING = os.environ.get("PYTEST_VERSION") is not None
47
46
 
48
47
  # Obtain types the same way types.py does in pypy
49
48
  # See: https://github.com/pypy/pypy/blob/19d9fa6be11165116dd0839b9144d969ab426ae7/lib-python/3/types.py#L61-L73
@@ -11,6 +11,7 @@ _py_type = type | str # Alias for type hint values
11
11
  _CopiableMappings = dict[str, typing.Any] | MappingProxyType[str, typing.Any]
12
12
 
13
13
  __version__: str
14
+ __version_tuple__: tuple[str | int, ...]
14
15
  INTERNALS_DICT: str
15
16
  META_GATHERER_NAME: str
16
17
 
@@ -0,0 +1,2 @@
1
+ __version__ = "0.7.0"
2
+ __version_tuple__ = (0, 7, 0)
@@ -241,12 +241,24 @@ def as_dict_generator(cls, funcname="as_dict"):
241
241
  if attrib.serialize
242
242
  )
243
243
  out_dict = f"{{{vals}}}"
244
- code = f"def {funcname}(self): return {out_dict}"
244
+ code = f"def {funcname}(self): return {out_dict}\n"
245
245
 
246
246
  globs = {}
247
247
  return GeneratedCode(code, globs)
248
248
 
249
249
 
250
+ def hash_generator(cls, funcname="__hash__"):
251
+ fields = get_attributes(cls)
252
+ vals = ", ".join(
253
+ f"self.{name}"
254
+ for name, attrib in fields.items()
255
+ if attrib.compare
256
+ )
257
+ code = f"def {funcname}(self): return hash(({vals}))\n"
258
+ globs = {}
259
+ return GeneratedCode(code, globs)
260
+
261
+
250
262
  init_maker = MethodMaker("__init__", init_generator)
251
263
  prefab_init_maker = MethodMaker(PREFAB_INIT_FUNC, init_generator)
252
264
  repr_maker = MethodMaker(
@@ -259,6 +271,7 @@ recursive_repr_maker = MethodMaker(
259
271
  )
260
272
  iter_maker = MethodMaker("__iter__", iter_generator)
261
273
  asdict_maker = MethodMaker("as_dict", as_dict_generator)
274
+ hash_maker = MethodMaker("__hash__", hash_generator)
262
275
 
263
276
 
264
277
  # Updated field with additional attributes
@@ -294,6 +307,7 @@ def attribute(
294
307
  kw_only=False,
295
308
  serialize=True,
296
309
  exclude_field=False,
310
+ private=False,
297
311
  doc=None,
298
312
  type=NOTHING,
299
313
  ):
@@ -310,6 +324,7 @@ def attribute(
310
324
  :param kw_only: Make this argument keyword only in init
311
325
  :param serialize: Include this attribute in methods that serialize to dict
312
326
  :param exclude_field: Shorthand for setting repr, compare, iter and serialize to False
327
+ :param private: Short for init, repr, compare, iter, serialize = False, must have default or factory
313
328
  :param doc: Parameter documentation for slotted classes
314
329
  :param type: Type of this attribute (for slotted classes)
315
330
 
@@ -321,6 +336,15 @@ def attribute(
321
336
  iter = False
322
337
  serialize = False
323
338
 
339
+ if private:
340
+ if default is NOTHING and default_factory is NOTHING:
341
+ raise AttributeError("Private attributes must have defaults or factories.")
342
+ init = False
343
+ repr = False
344
+ compare = False
345
+ iter = False
346
+ serialize = False
347
+
324
348
  return Attribute(
325
349
  default=default,
326
350
  default_factory=default_factory,
@@ -408,6 +432,7 @@ def _make_prefab(
408
432
  if frozen:
409
433
  methods.add(frozen_setattr_maker)
410
434
  methods.add(frozen_delattr_maker)
435
+ methods.add(hash_maker)
411
436
  if dict_method:
412
437
  methods.add(asdict_maker)
413
438
 
@@ -33,6 +33,7 @@ def get_attributes(cls: type) -> dict[str, Attribute]: ...
33
33
  def init_generator(cls: type, funcname: str = "__init__") -> GeneratedCode: ...
34
34
  def iter_generator(cls: type, funcname: str = "__iter__") -> GeneratedCode: ...
35
35
  def as_dict_generator(cls: type, funcname: str = "as_dict") -> GeneratedCode: ...
36
+ def hash_generator(cls: type, funcname: str = "__hash__") -> GeneratedCode: ...
36
37
 
37
38
  init_maker: MethodMaker
38
39
  prefab_init_maker: MethodMaker
@@ -41,6 +42,7 @@ recursive_repr_maker: MethodMaker
41
42
  eq_maker: MethodMaker
42
43
  iter_maker: MethodMaker
43
44
  asdict_maker: MethodMaker
45
+ hash_maker: MethodMaker
44
46
 
45
47
  class Attribute(Field):
46
48
  __slots__: dict
@@ -81,6 +83,7 @@ def attribute(
81
83
  kw_only: bool = False,
82
84
  serialize: bool = True,
83
85
  exclude_field: bool = False,
86
+ private: bool = False,
84
87
  ) -> Attribute: ...
85
88
 
86
89
  def prefab_gatherer(cls_or_ns: type | MappingProxyType) -> tuple[dict[str, Attribute], dict[str, typing.Any]]: ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ducktools-classbuilder
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: Toolkit for creating class boilerplate generators
5
5
  Author: David C Ellis
6
6
  License: MIT License
@@ -45,7 +45,7 @@ Provides-Extra: performance_tests
45
45
  Requires-Dist: attrs ; extra == 'performance_tests'
46
46
  Requires-Dist: pydantic ; extra == 'performance_tests'
47
47
  Provides-Extra: testing
48
- Requires-Dist: pytest ; extra == 'testing'
48
+ Requires-Dist: pytest >=8.2 ; extra == 'testing'
49
49
  Requires-Dist: pytest-cov ; extra == 'testing'
50
50
  Requires-Dist: mypy ; extra == 'testing'
51
51
  Requires-Dist: typing-extensions ; extra == 'testing'
@@ -0,0 +1,13 @@
1
+ ducktools/classbuilder/__init__.py,sha256=EylA7K40qGVctuGD_OLtcl-f0xqAICYw0MV-XqcDEhI,32869
2
+ ducktools/classbuilder/__init__.pyi,sha256=NCLMWT3G0Z5lJky8EV_N6XcW8smScti6y2p163nZ8rM,7965
3
+ ducktools/classbuilder/_version.py,sha256=TVtIAaEWunoxD4TTy8EMgVsVwLljxEqhLSu5_PMPjM8,52
4
+ ducktools/classbuilder/annotations.py,sha256=17g1WnWfyMWBHKQp2HD_hvV-n7CKXy_zv8NTODpOsuU,5437
5
+ ducktools/classbuilder/annotations.pyi,sha256=cTZQ-pp2IkfdvwHiU3pIySUzzBKxfOtO-e5PkA8TNwo,520
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.0.dist-info/LICENSE.md,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
10
+ ducktools_classbuilder-0.7.0.dist-info/METADATA,sha256=R5idmDAFadD3tnLKV1b1CtX937TGvjUWGUsQD6u9G6U,10917
11
+ ducktools_classbuilder-0.7.0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
12
+ ducktools_classbuilder-0.7.0.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
13
+ ducktools_classbuilder-0.7.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
2
+ Generator: setuptools (70.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,12 +0,0 @@
1
- ducktools/classbuilder/__init__.py,sha256=9IBwSOSXY9SFbbV6msfS9oUx2BneNrQvjZsb-iLSLZ4,32820
2
- ducktools/classbuilder/__init__.pyi,sha256=JaAfc6y4Jj920y4lm9peduNXeb9XUJwKN-QqFpqG5pw,7924
3
- ducktools/classbuilder/annotations.py,sha256=17g1WnWfyMWBHKQp2HD_hvV-n7CKXy_zv8NTODpOsuU,5437
4
- ducktools/classbuilder/annotations.pyi,sha256=cTZQ-pp2IkfdvwHiU3pIySUzzBKxfOtO-e5PkA8TNwo,520
5
- ducktools/classbuilder/prefab.py,sha256=LCrnS2zKADX5FS0SdzCYLF4n5yR43CIlv2QLL6PDjl4,23292
6
- ducktools/classbuilder/prefab.pyi,sha256=kmqZcP2aGHEAb3-cLCBlYi6gclzsQAAmY7cnHvKT7jQ,4360
7
- ducktools/classbuilder/py.typed,sha256=la67KBlbjXN-_-DfGNcdOcjYumVpKG_Tkw-8n5dnGB4,8
8
- ducktools_classbuilder-0.6.2.dist-info/LICENSE.md,sha256=6Thz9Dbw8R4fWInl6sGl8Rj3UnKnRbDwrc6jZerpugQ,1070
9
- ducktools_classbuilder-0.6.2.dist-info/METADATA,sha256=fGjzXJdePiVfTkzZozk9-HHFW-zZJakoPnBrTmMepAE,10911
10
- ducktools_classbuilder-0.6.2.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
11
- ducktools_classbuilder-0.6.2.dist-info/top_level.txt,sha256=uSDLtio3ZFqdwcsMJ2O5yhjB4Q3ytbBWbA8rJREganc,10
12
- ducktools_classbuilder-0.6.2.dist-info/RECORD,,