ducktools-classbuilder 0.7.3__tar.gz → 0.7.5__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.

Files changed (92) hide show
  1. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/PKG-INFO +1 -1
  2. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/__init__.py +0 -5
  3. ducktools_classbuilder-0.7.5/src/ducktools/classbuilder/_version.py +2 -0
  4. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/annotations.py +7 -77
  5. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/annotations.pyi +0 -5
  6. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools_classbuilder.egg-info/PKG-INFO +1 -1
  7. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools_classbuilder.egg-info/SOURCES.txt +0 -1
  8. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_creation.py +0 -9
  9. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/py314_tests/test_forwardref_annotations.py +3 -2
  10. ducktools_classbuilder-0.7.3/src/ducktools/classbuilder/_version.py +0 -2
  11. ducktools_classbuilder-0.7.3/tests/prefab/shared/examples/fails/creation_1.py +0 -6
  12. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/.github/dependabot.yml +0 -0
  13. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/.github/workflows/auto_test.yml +0 -0
  14. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/.github/workflows/publish_to_pypi.yml +0 -0
  15. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/.github/workflows/publish_to_testpypi.yml +0 -0
  16. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/.gitignore +0 -0
  17. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/.readthedocs.yaml +0 -0
  18. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/LICENSE.md +0 -0
  19. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/MANIFEST.in +0 -0
  20. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/README.md +0 -0
  21. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/Makefile +0 -0
  22. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/api.md +0 -0
  23. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/approach_vs_tool.md +0 -0
  24. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/conf.py +0 -0
  25. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/extension_examples.md +0 -0
  26. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/generated_code.md +0 -0
  27. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/index.md +0 -0
  28. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/make.bat +0 -0
  29. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/perf/performance_tests.md +0 -0
  30. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/prefab/index.md +0 -0
  31. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs/tutorial.md +0 -0
  32. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex10_frozen_attributes.py +0 -0
  33. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex1_basic.py +0 -0
  34. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex2_register.py +0 -0
  35. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex3_iterable.py +0 -0
  36. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex5_frozen.py +0 -0
  37. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex7_posonly.py +0 -0
  38. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex8_converters.py +0 -0
  39. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/docs_ex9_annotated.py +0 -0
  40. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/docs_code/tutorial_code.py +0 -0
  41. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/perf/cluegen.py +0 -0
  42. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/perf/dataklasses.py +0 -0
  43. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/perf/hyperfine_testmaker.py +0 -0
  44. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/perf/perf_profile.py +0 -0
  45. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/pyproject.toml +0 -0
  46. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/setup.cfg +0 -0
  47. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/__init__.pyi +0 -0
  48. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/prefab.py +0 -0
  49. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/prefab.pyi +0 -0
  50. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools/classbuilder/py.typed +0 -0
  51. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools_classbuilder.egg-info/dependency_links.txt +0 -0
  52. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools_classbuilder.egg-info/requires.txt +0 -0
  53. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/src/ducktools_classbuilder.egg-info/top_level.txt +0 -0
  54. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/annotations/test_annotated.py +0 -0
  55. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/annotations/test_annotations_module.py +0 -0
  56. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/annotations/test_future_annotations.py +0 -0
  57. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/conftest.py +0 -0
  58. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_compare_attrib.py +0 -0
  59. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_construction.py +0 -0
  60. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_frozen.py +0 -0
  61. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_internals.py +0 -0
  62. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_pre_post_init.py +0 -0
  63. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_private.py +0 -0
  64. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_slots_novalues.py +0 -0
  65. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_slotted_class.py +0 -0
  66. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/dynamic/test_subclass_implementation.py +0 -0
  67. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/conftest.py +0 -0
  68. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/creation.py +0 -0
  69. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/creation_empty.py +0 -0
  70. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/dunders.py +0 -0
  71. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/fails/creation_2.py +0 -0
  72. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/fails/creation_3.py +0 -0
  73. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/fails/creation_5.py +0 -0
  74. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/fails/inheritance_1.py +0 -0
  75. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/fails/inheritance_2.py +0 -0
  76. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/funcs_prefabs.py +0 -0
  77. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/hint_syntax.py +0 -0
  78. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/inheritance.py +0 -0
  79. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/init_ex.py +0 -0
  80. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/kw_only.py +0 -0
  81. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/examples/repr_func.py +0 -0
  82. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_dunders.py +0 -0
  83. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_funcs.py +0 -0
  84. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_hint_syntax.py +0 -0
  85. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_inheritance.py +0 -0
  86. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_init.py +0 -0
  87. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_kw_only.py +0 -0
  88. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/prefab/shared/test_repr.py +0 -0
  89. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/py312_tests/test_generic_annotations.py +0 -0
  90. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/test_core.py +0 -0
  91. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/test_field_flags.py +0 -0
  92. {ducktools_classbuilder-0.7.3 → ducktools_classbuilder-0.7.5}/tests/test_slotmakermeta.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ducktools-classbuilder
3
- Version: 0.7.3
3
+ Version: 0.7.5
4
4
  Summary: Toolkit for creating class boilerplate generators
5
5
  Author: David C Ellis
6
6
  License: MIT License
@@ -654,11 +654,6 @@ class Field(metaclass=SlotMakerMeta):
654
654
  f"{cls_name} cannot define both a default value and a default factory."
655
655
  )
656
656
 
657
- if self.kw_only and not self.init:
658
- raise AttributeError(
659
- f"{cls_name} cannot be keyword only if it is not in init."
660
- )
661
-
662
657
  @classmethod
663
658
  def from_field(cls, fld, /, **kwargs):
664
659
  """
@@ -0,0 +1,2 @@
1
+ __version__ = "0.7.5"
2
+ __version_tuple__ = (0, 7, 5)
@@ -24,19 +24,6 @@ import sys
24
24
  import builtins
25
25
 
26
26
 
27
- # Evil stuff from types.py
28
- def _cell_factory():
29
- a = 1
30
-
31
- def f():
32
- nonlocal a
33
- return f.__closure__[0]
34
- _FunctionType = type(_cell_factory)
35
- _CellType = type(_cell_factory())
36
- del _cell_factory
37
- # End evil stuff from types.py
38
-
39
-
40
27
  class _Stringlike(str):
41
28
  # There are typing operators that are not supported by strings
42
29
  # This adds the 'or' operator '|'
@@ -142,69 +129,6 @@ def eval_hint(hint, context=None, *, recursion_limit=2):
142
129
  return hint
143
130
 
144
131
 
145
- def call_annotate_func(annotate):
146
- # Python 3.14 breaks the old methods of getting annotations
147
- # The new annotationlib currently relies on 'ast' and 'functools'
148
- # that this project tries to avoid importing.
149
-
150
- # The basic logic is copied from there, however, replacing ForwardRef
151
- # with a more basic class.
152
- # While `annotationlib` is trying to return ForwardRef objects that can
153
- # be evaluated later, this module only cares about annotations that can
154
- # be evaluated at the point this function is called.
155
- # As such we throw away the other information and just return strings
156
- # instead of forwardrefs.
157
-
158
- try:
159
- raw_annotations = annotate(1)
160
- except NameError:
161
- pass
162
- else:
163
- return raw_annotations
164
-
165
- # The annotate func may support forwardref natively
166
- try:
167
- raw_annotations = annotate(2)
168
- except NotImplementedError:
169
- pass
170
- else:
171
- return raw_annotations
172
-
173
- # Not supported so we have to implement our own deferred handling
174
- # Some modified logic from annotationlib
175
- namespace = {**annotate.__builtins__, **annotate.__globals__}
176
- globs = _StringGlobs(namespace)
177
-
178
- # This handles closures where the variable is defined after get annotations is called.
179
- if annotate.__closure__:
180
- freevars = annotate.__code__.co_freevars
181
- new_closure = []
182
- for i, cell in enumerate(annotate.__closure__):
183
- try:
184
- cell.cell_contents
185
- except ValueError:
186
- if i < len(freevars):
187
- name = freevars[i]
188
- else:
189
- name = "__cell__"
190
- new_closure.append(_CellType(name))
191
- else:
192
- new_closure.append(cell)
193
- closure = tuple(new_closure)
194
- else:
195
- closure = None
196
-
197
- new_annotate = _FunctionType(annotate.__code__, globs, closure=closure)
198
-
199
- # Convert _Stringlike back to str
200
- annos = {
201
- k: str(v) if isinstance(v, _Stringlike) else v
202
- for k, v in new_annotate(1).items()
203
- }
204
-
205
- return annos
206
-
207
-
208
132
  def get_ns_annotations(ns, eval_str=True):
209
133
  """
210
134
  Given a class namespace, attempt to retrieve the
@@ -221,10 +145,16 @@ def get_ns_annotations(ns, eval_str=True):
221
145
 
222
146
  # In 3.14 the 'canonical' method of getting annotations is to use __annotate__
223
147
  # If this doesn't exist, check __annotations__ and treat as 3.13 or earlier.
148
+ # This is disabled if __future__ annotations are used, however.
224
149
  annotate = ns.get("__annotate__")
225
150
 
226
151
  if annotate is not None:
227
- raw_annotations = call_annotate_func(annotate)
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)
228
158
  else:
229
159
  raw_annotations = ns.get("__annotations__", {})
230
160
 
@@ -9,11 +9,6 @@ class _StringGlobs(dict):
9
9
  def __missing__(self, key: _T) -> _T: ...
10
10
 
11
11
 
12
- def call_annotate_func(
13
- annotate: Callable[[int], dict[str, type | typing.ForwardRef]]
14
- ) -> dict[str, type | str]: ...
15
-
16
-
17
12
  def eval_hint(
18
13
  hint: type | str,
19
14
  context: None | dict[str, typing.Any] = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ducktools-classbuilder
3
- Version: 0.7.3
3
+ Version: 0.7.5
4
4
  Summary: Toolkit for creating class boilerplate generators
5
5
  Author: David C Ellis
6
6
  License: MIT License
@@ -79,7 +79,6 @@ tests/prefab/shared/examples/inheritance.py
79
79
  tests/prefab/shared/examples/init_ex.py
80
80
  tests/prefab/shared/examples/kw_only.py
81
81
  tests/prefab/shared/examples/repr_func.py
82
- tests/prefab/shared/examples/fails/creation_1.py
83
82
  tests/prefab/shared/examples/fails/creation_2.py
84
83
  tests/prefab/shared/examples/fails/creation_3.py
85
84
  tests/prefab/shared/examples/fails/creation_5.py
@@ -144,15 +144,6 @@ class TestClassVar:
144
144
 
145
145
 
146
146
  class TestExceptions:
147
- def test_kw_not_in_init(self):
148
- with pytest.raises(AttributeError) as e_info:
149
- from fails.creation_1 import Construct
150
-
151
- assert (
152
- e_info.value.args[0]
153
- == "Attribute cannot be keyword only if it is not in init."
154
- )
155
-
156
147
  def test_positional_after_kw_error(self):
157
148
  with pytest.raises(SyntaxError) as e_info:
158
149
  from fails.creation_2 import FailSyntax
@@ -1,6 +1,7 @@
1
1
  # Bare forwardrefs only work in 3.14 or later
2
2
 
3
3
  from ducktools.classbuilder.annotations import get_ns_annotations
4
+ from annotationlib import ForwardRef
4
5
 
5
6
  from pathlib import Path
6
7
 
@@ -14,7 +15,7 @@ def test_bare_forwardref():
14
15
 
15
16
  annos = get_ns_annotations(Ex.__dict__)
16
17
 
17
- assert annos == {'a': str, 'b': Path, 'c': "plain_forwardref"}
18
+ assert annos == {'a': str, 'b': Path, 'c': ForwardRef("plain_forwardref")}
18
19
 
19
20
 
20
21
  def test_inner_outer_ref():
@@ -37,7 +38,7 @@ def test_inner_outer_ref():
37
38
  cls, annos = make_func()
38
39
 
39
40
  # Forwardref given as string if used before it can be evaluated
40
- assert annos == {"a_val": str, "b_val": int, "c_val": "hyper_type"}
41
+ assert annos == {"a_val": str, "b_val": int, "c_val": ForwardRef("hyper_type")}
41
42
 
42
43
  # Correctly evaluated if it exists
43
44
  assert get_ns_annotations(cls.__dict__) == {
@@ -1,2 +0,0 @@
1
- __version__ = "0.7.3"
2
- __version_tuple__ = (0, 7, 3)
@@ -1,6 +0,0 @@
1
- from ducktools.classbuilder.prefab import prefab, attribute
2
-
3
-
4
- @prefab
5
- class Construct:
6
- x = attribute(default="test", kw_only=True, init=False)