dataclass-wizard 0.35.2__tar.gz → 0.35.4__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.
Files changed (138) hide show
  1. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/CONTRIBUTING.rst +1 -1
  2. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/HISTORY.rst +16 -0
  3. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/PKG-INFO +6 -5
  4. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/README.rst +1 -1
  5. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/__version__.py +1 -1
  6. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/constants.py +3 -0
  7. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/lookups.pyi +4 -4
  8. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/models.py +72 -3
  9. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/property_wizard.py +9 -1
  10. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/object_path.pyi +3 -3
  11. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/v1/models.py +216 -69
  12. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/v1/models.pyi +13 -0
  13. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/wizard_mixins.pyi +1 -1
  14. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/PKG-INFO +6 -5
  15. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/requires.txt +6 -4
  16. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/conf.py +6 -0
  17. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/setup.cfg +1 -1
  18. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/setup.py +2 -3
  19. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/LICENSE +0 -0
  20. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/MANIFEST.in +0 -0
  21. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/__init__.py +0 -0
  22. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/abstractions.py +0 -0
  23. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/abstractions.pyi +0 -0
  24. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/bases.py +0 -0
  25. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/bases_meta.py +0 -0
  26. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/bases_meta.pyi +0 -0
  27. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/class_helper.py +0 -0
  28. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/class_helper.pyi +0 -0
  29. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/decorators.py +0 -0
  30. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/dumpers.py +0 -0
  31. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/enums.py +0 -0
  32. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/__init__.py +0 -0
  33. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/dumpers.py +0 -0
  34. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/loaders.py +0 -0
  35. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/lookups.py +0 -0
  36. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/wizard.py +0 -0
  37. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/environ/wizard.pyi +0 -0
  38. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/errors.py +0 -0
  39. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/errors.pyi +0 -0
  40. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/lazy_imports.py +0 -0
  41. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/loader_selection.py +0 -0
  42. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/loaders.py +0 -0
  43. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/log.py +0 -0
  44. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/models.pyi +0 -0
  45. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/parsers.py +0 -0
  46. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/py.typed +0 -0
  47. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/serial_json.py +0 -0
  48. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/serial_json.pyi +0 -0
  49. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/type_def.py +0 -0
  50. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/__init__.py +0 -0
  51. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/dataclass_compat.py +0 -0
  52. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/dict_helper.py +0 -0
  53. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/function_builder.py +0 -0
  54. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/json_util.py +0 -0
  55. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/lazy_loader.py +0 -0
  56. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/object_path.py +0 -0
  57. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/string_conv.py +0 -0
  58. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/type_conv.py +0 -0
  59. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/typing_compat.py +0 -0
  60. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/utils/wrappers.py +0 -0
  61. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/v1/__init__.py +0 -0
  62. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/v1/decorators.py +0 -0
  63. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/v1/enums.py +0 -0
  64. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/v1/loaders.py +0 -0
  65. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/wizard_cli/__init__.py +0 -0
  66. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/wizard_cli/cli.py +0 -0
  67. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/wizard_cli/schema.py +0 -0
  68. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard/wizard_mixins.py +0 -0
  69. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/SOURCES.txt +0 -0
  70. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/dependency_links.txt +0 -0
  71. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/entry_points.txt +0 -0
  72. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/not-zip-safe +0 -0
  73. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/dataclass_wizard.egg-info/top_level.txt +0 -0
  74. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/Makefile +0 -0
  75. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/advanced_usage/index.rst +0 -0
  76. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/advanced_usage/serializer_hooks.rst +0 -0
  77. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/advanced_usage/type_hooks.rst +0 -0
  78. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/custom_key_mappings.rst +0 -0
  79. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/cyclic_or_recursive_dataclasses.rst +0 -0
  80. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/dataclasses_in_union_types.rst +0 -0
  81. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/easier_debug_mode.rst +0 -0
  82. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/handling_unknown_json_keys.rst +0 -0
  83. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/index.rst +0 -0
  84. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/meta.rst +0 -0
  85. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/nested_key_paths.rst +0 -0
  86. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/patterned_date_time.rst +0 -0
  87. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/serialization_options.rst +0 -0
  88. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/skip_inheritance.rst +0 -0
  89. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/skip_the_str.rst +0 -0
  90. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/v1_alias.rst +0 -0
  91. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/v1_patterned_date_time.rst +0 -0
  92. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/common_use_cases/wizard_mixins.rst +0 -0
  93. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/contributing.rst +0 -0
  94. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/dataclass_wizard.environ.rst +0 -0
  95. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/dataclass_wizard.rst +0 -0
  96. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/dataclass_wizard.utils.rst +0 -0
  97. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/dataclass_wizard.v1.rst +0 -0
  98. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/dataclass_wizard.wizard_cli.rst +0 -0
  99. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/env_magic.rst +0 -0
  100. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/examples.rst +0 -0
  101. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/history.rst +0 -0
  102. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/index.rst +0 -0
  103. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/installation.rst +0 -0
  104. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/make.bat +0 -0
  105. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/modules.rst +0 -0
  106. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/overview.rst +0 -0
  107. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/python_compatibility.rst +0 -0
  108. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/quickstart.rst +0 -0
  109. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/readme.rst +0 -0
  110. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/using_field_properties.rst +0 -0
  111. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/docs/wiz_cli.rst +0 -0
  112. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/__init__.py +0 -0
  113. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/conftest.py +0 -0
  114. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/testdata/__init__.py +0 -0
  115. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/__init__.py +0 -0
  116. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/conftest.py +0 -0
  117. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/environ/__init__.py +0 -0
  118. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/environ/test_dumpers.py +0 -0
  119. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/environ/test_loaders.py +0 -0
  120. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/environ/test_lookups.py +0 -0
  121. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/environ/test_wizard.py +0 -0
  122. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_bases_meta.py +0 -0
  123. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_dump.py +0 -0
  124. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_load.py +0 -0
  125. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_load_with_future_import.py +0 -0
  126. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_models.py +0 -0
  127. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_parsers.py +0 -0
  128. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_property_wizard.py +0 -0
  129. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_property_wizard_with_future_import.py +0 -0
  130. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_wizard_cli.py +0 -0
  131. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/test_wizard_mixins.py +0 -0
  132. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/utils/__init__.py +0 -0
  133. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/utils/test_lazy_loader.py +0 -0
  134. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/utils/test_string_conv.py +0 -0
  135. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/utils/test_typing_compat.py +0 -0
  136. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/v1/__init__.py +0 -0
  137. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/v1/test_loaders.py +0 -0
  138. {dataclass_wizard-0.35.2 → dataclass_wizard-0.35.4}/tests/unit/v1/test_union_as_type_alias_recursive.py +0 -0
@@ -107,7 +107,7 @@ Before you submit a pull request, check that it meets these guidelines:
107
107
  2. If the pull request adds functionality, the docs should be updated. Put
108
108
  your new functionality into a function with a docstring, and add the
109
109
  feature to the list in README.rst.
110
- 3. The pull request should work for Python 3.9, 3.10, 3.11, 3.12 and 3.13, and for PyPy. Check
110
+ 3. The pull request should work for Python 3.9, 3.10, 3.11, 3.12, 3.13 and 3.14, and for PyPy. Check
111
111
  https://github.com/rnag/dataclass-wizard/actions/workflows/dev.yml
112
112
  and make sure that the tests pass for all supported Python versions.
113
113
 
@@ -2,6 +2,22 @@
2
2
  History
3
3
  =======
4
4
 
5
+ 0.35.4 (2025-12-12)
6
+ -------------------
7
+
8
+ **Features and Improvements**
9
+
10
+ * Add compatability and support for **Python 3.14**. Thanks to :user:`rexzhang` in :pr:`204`!
11
+
12
+ 0.35.3 (2025-12-12)
13
+ -------------------
14
+
15
+ **Bugfixes**
16
+
17
+ * Fix typing stub (``.pyi``) compatibility for older Python/tooling versions
18
+ by removing Python 3.12-only ``type`` statement syntax and using
19
+ ``TypeAlias``/``typing``-compatible annotations instead (fixes :issue:`176`).
20
+
5
21
  0.35.2 (2025-12-12)
6
22
  -------------------
7
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataclass-wizard
3
- Version: 0.35.2
3
+ Version: 0.35.4
4
4
  Summary: Lightning-fast JSON wizardry for Python dataclasses — effortless serialization right out of the box!
5
5
  Home-page: https://github.com/rnag/dataclass-wizard
6
6
  Author: Ritvik Nag
@@ -24,10 +24,11 @@ Classifier: Programming Language :: Python :: 3.10
24
24
  Classifier: Programming Language :: Python :: 3.11
25
25
  Classifier: Programming Language :: Python :: 3.12
26
26
  Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: 3.14
27
28
  Classifier: Programming Language :: Python
28
29
  Description-Content-Type: text/x-rst
29
30
  License-File: LICENSE
30
- Requires-Dist: typing-extensions>=4.9.0; python_version <= "3.12"
31
+ Requires-Dist: typing-extensions>=4.13.0; python_version <= "3.13"
31
32
  Provides-Extra: dotenv
32
33
  Requires-Dist: python-dotenv<2,>=1; extra == "dotenv"
33
34
  Provides-Extra: timedelta
@@ -56,7 +57,7 @@ Requires-Dist: Sphinx==8.1.3; python_version >= "3.10" and extra == "dev"
56
57
  Requires-Dist: twine==6.0.1; extra == "dev"
57
58
  Requires-Dist: dataclass-wizard[toml]; extra == "dev"
58
59
  Requires-Dist: sphinx-issues==5.0.0; extra == "dev"
59
- Requires-Dist: sphinx-autodoc-typehints==2.5.0; extra == "dev"
60
+ Requires-Dist: sphinx-autodoc-typehints==2.5.0; python_version >= "3.10" and extra == "dev"
60
61
  Requires-Dist: sphinx-copybutton==0.5.2; extra == "dev"
61
62
  Requires-Dist: typing-extensions>=4.9.0; extra == "dev"
62
63
  Requires-Dist: pytest==8.3.4; extra == "dev"
@@ -69,7 +70,7 @@ Requires-Dist: jsons==1.6.3; extra == "dev"
69
70
  Requires-Dist: dataclass-factory==2.16; extra == "dev"
70
71
  Requires-Dist: dacite==1.8.1; extra == "dev"
71
72
  Requires-Dist: mashumaro==3.15; extra == "dev"
72
- Requires-Dist: pydantic==2.10.3; extra == "dev"
73
+ Requires-Dist: pydantic==2.10.3; python_version < "3.14" and extra == "dev"
73
74
  Requires-Dist: attrs==24.3.0; extra == "dev"
74
75
  Dynamic: author
75
76
  Dynamic: author-email
@@ -89,7 +90,7 @@ Dynamic: summary
89
90
  Dataclass Wizard
90
91
  ================
91
92
 
92
- Release v\ 0.35.2 | 📚 Full docs on `Read the Docs`_ (`Installation`_).
93
+ Release v\ 0.35.4 | 📚 Full docs on `Read the Docs`_ (`Installation`_).
93
94
 
94
95
  .. image:: https://github.com/rnag/dataclass-wizard/actions/workflows/dev.yml/badge.svg
95
96
  :target: https://github.com/rnag/dataclass-wizard/actions/workflows/dev.yml
@@ -2,7 +2,7 @@
2
2
  Dataclass Wizard
3
3
  ================
4
4
 
5
- Release v\ 0.35.2 | 📚 Full docs on `Read the Docs`_ (`Installation`_).
5
+ Release v\ 0.35.4 | 📚 Full docs on `Read the Docs`_ (`Installation`_).
6
6
 
7
7
  .. image:: https://github.com/rnag/dataclass-wizard/actions/workflows/dev.yml/badge.svg
8
8
  :target: https://github.com/rnag/dataclass-wizard/actions/workflows/dev.yml
@@ -7,7 +7,7 @@ __title__ = 'dataclass-wizard'
7
7
  __description__ = ('Lightning-fast JSON wizardry for Python dataclasses — '
8
8
  'effortless serialization right out of the box!')
9
9
  __url__ = 'https://github.com/rnag/dataclass-wizard'
10
- __version__ = '0.35.2'
10
+ __version__ = '0.35.4'
11
11
  __author__ = 'Ritvik Nag'
12
12
  __author_email__ = 'me@ritviknag.com'
13
13
  __license__ = 'Apache 2.0'
@@ -23,6 +23,9 @@ PY312_OR_ABOVE = _PY_VERSION >= (3, 12)
23
23
  # Check if currently running Python 3.13 or higher
24
24
  PY313_OR_ABOVE = _PY_VERSION >= (3, 13)
25
25
 
26
+ # Check if currently running Python 3.14 or higher
27
+ PY314_OR_ABOVE = _PY_VERSION >= (3, 14)
28
+
26
29
  # The name of the dictionary object that contains `load` hooks for each
27
30
  # object type. Also used to check if a class is a :class:`BaseLoadHook`
28
31
  _LOAD_HOOKS = '__LOAD_HOOKS__'
@@ -1,13 +1,13 @@
1
1
  from dataclasses import MISSING
2
- from typing import ClassVar
2
+ from typing import ClassVar, TypeAlias, Union
3
3
 
4
4
  from ..decorators import cached_class_property
5
5
  from ..type_def import StrCollection, EnvFileType
6
6
 
7
7
 
8
- type _MISSING_TYPE = type(MISSING)
9
- type STR_OR_MISSING = str | _MISSING_TYPE
10
- type STR_OR_NONE = str | None
8
+ _MISSING_TYPE: TypeAlias = type(MISSING)
9
+ STR_OR_MISSING: TypeAlias = Union[str, _MISSING_TYPE]
10
+ STR_OR_NONE: TypeAlias = Union[str, None]
11
11
 
12
12
  # Type of `os.environ` or `DotEnv` dict
13
13
  Environ = dict[str, STR_OR_NONE]
@@ -3,7 +3,7 @@ from dataclasses import MISSING, Field
3
3
  from datetime import date, datetime, time
4
4
  from typing import Generic, Mapping, NewType, Any, TypedDict
5
5
 
6
- from .constants import PY310_OR_ABOVE
6
+ from .constants import PY310_OR_ABOVE, PY314_OR_ABOVE
7
7
  from .decorators import cached_property
8
8
  from .type_def import T, DT, PyNotRequired
9
9
  # noinspection PyProtectedMember
@@ -90,11 +90,51 @@ class JSONField(Field):
90
90
 
91
91
  __slots__ = ('json', )
92
92
 
93
+ # In Python 3.14, dataclasses adds a new parameter to the :class:`Field`
94
+ # constructor: `doc`
95
+ #
96
+ # Ref: https://docs.python.org/3.14/library/dataclasses.html#dataclasses.field
97
+ if PY314_OR_ABOVE: # pragma: no cover
98
+ # noinspection PyShadowingBuiltins
99
+ def __init__(
100
+ self,
101
+ keys,
102
+ all: bool,
103
+ dump: bool,
104
+ default,
105
+ default_factory,
106
+ init,
107
+ repr,
108
+ hash,
109
+ compare,
110
+ metadata,
111
+ path: bool = False,
112
+ ):
113
+
114
+ super().__init__(
115
+ default,
116
+ default_factory,
117
+ init,
118
+ repr,
119
+ hash,
120
+ compare,
121
+ metadata,
122
+ False,
123
+ None,
124
+ )
125
+
126
+ if isinstance(keys, str):
127
+ keys = split_object_path(keys) if path else (keys,)
128
+ elif keys is ...:
129
+ keys = ()
130
+
131
+ self.json = JSON(*keys, all=all, dump=dump, path=path)
132
+
93
133
  # In Python 3.10, dataclasses adds a new parameter to the :class:`Field`
94
134
  # constructor: `kw_only`
95
135
  #
96
136
  # Ref: https://docs.python.org/3.10/library/dataclasses.html#dataclasses.dataclass
97
- if PY310_OR_ABOVE: # pragma: no cover
137
+ elif PY310_OR_ABOVE: # pragma: no cover
98
138
  # noinspection PyShadowingBuiltins
99
139
  def __init__(self, keys, all: bool, dump: bool,
100
140
  default, default_factory, init, repr, hash, compare,
@@ -312,11 +352,40 @@ def path_field(keys, *,
312
352
  hash, compare, metadata, True)
313
353
 
314
354
 
355
+ if PY314_OR_ABOVE:
356
+
357
+ def skip_if_field(
358
+ condition,
359
+ *,
360
+ default=MISSING,
361
+ default_factory=MISSING,
362
+ init=True,
363
+ repr=True,
364
+ hash=None,
365
+ compare=True,
366
+ metadata=None,
367
+ kw_only=MISSING,
368
+ doc=None,
369
+ ):
370
+
371
+ if default is not MISSING and default_factory is not MISSING:
372
+ raise ValueError("cannot specify both default and default_factory")
373
+
374
+ if metadata is None:
375
+ metadata = {}
376
+
377
+ metadata["__skip_if__"] = condition
378
+
379
+ return Field(
380
+ default, default_factory, init, repr, hash, compare, metadata, kw_only, doc
381
+ )
382
+
383
+
315
384
  # In Python 3.10, dataclasses adds a new parameter to the :class:`Field`
316
385
  # constructor: `kw_only`
317
386
  #
318
387
  # Ref: https://docs.python.org/3.10/library/dataclasses.html#dataclasses.dataclass
319
- if PY310_OR_ABOVE: # pragma: no cover
388
+ elif PY310_OR_ABOVE: # pragma: no cover
320
389
  def skip_if_field(condition, *, default=MISSING, default_factory=MISSING, init=True, repr=True,
321
390
  hash=None, compare=True, metadata=None, kw_only=MISSING):
322
391
 
@@ -2,11 +2,18 @@ from dataclasses import MISSING, Field, field as dataclass_field
2
2
  from functools import wraps
3
3
  from typing import Dict, Any, Type, Union, Tuple, Optional
4
4
 
5
+ from .constants import PY314_OR_ABOVE
5
6
  from .type_def import T, NoneType
6
7
  from .utils.typing_compat import (
7
8
  get_origin, get_args, is_generic, is_literal, is_annotated, eval_forward_ref_if_needed
8
9
  )
9
10
 
11
+ if PY314_OR_ABOVE: # pragma: no cover
12
+ from annotationlib import get_annotations
13
+ else:
14
+ # https://typing-extensions.readthedocs.io/en/latest/index.html#typing_extensions.get_annotations
15
+ from typing_extensions import get_annotations
16
+
10
17
 
11
18
  AnnotationType = Dict[str, Type[T]]
12
19
  AnnotationReplType = Dict[str, str]
@@ -26,7 +33,8 @@ def property_wizard(*args, **kwargs):
26
33
 
27
34
  cls: Type = type(*args, **kwargs)
28
35
  cls_dict: Dict[str, Any] = args[2]
29
- annotations: AnnotationType = cls_dict.get('__annotations__', {})
36
+ # https://docs.python.org/3.14/whatsnew/3.14.html#implications-for-readers-of-annotations
37
+ annotations: AnnotationType = get_annotations(cls)
30
38
 
31
39
  # For each property, we want to replace the annotation for the underscore-
32
40
  # leading field associated with that property with the 'public' field
@@ -1,8 +1,8 @@
1
1
  from dataclasses import MISSING
2
- from typing import Any, Sequence
2
+ from typing import Any, Sequence, TypeAlias, Union
3
3
 
4
- type PathPart = str | int | float | bool
5
- type PathType = Sequence[PathPart]
4
+ PathPart: TypeAlias = Union[str, int, float, bool]
5
+ PathType: TypeAlias = Sequence[PathPart]
6
6
 
7
7
 
8
8
  def safe_get(data: dict | list,
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any, TypedDict, cast
6
6
  from zoneinfo import ZoneInfo
7
7
 
8
8
  from .decorators import setup_recursive_safe_function
9
- from ..constants import PY310_OR_ABOVE, PY311_OR_ABOVE
9
+ from ..constants import PY310_OR_ABOVE, PY311_OR_ABOVE, PY314_OR_ABOVE
10
10
  from ..log import LOG
11
11
  from ..type_def import DefFactory, ExplicitNull, PyNotRequired, NoneType
12
12
  from ..utils.function_builder import FunctionBuilder
@@ -450,6 +450,44 @@ UTCDateTimePattern = PatternBase(datetime, tz_info=UTC)
450
450
  UTCTimePattern = PatternBase(time, tz_info=UTC)
451
451
 
452
452
 
453
+ def _normalize_alias_path_args(all_paths, load, dump):
454
+ """Normalize `AliasPath` arguments and canonicalize path values."""
455
+ if load is not None:
456
+ all_paths = load
457
+ load = None
458
+ dump = ExplicitNull
459
+
460
+ elif dump is not None:
461
+ all_paths = dump
462
+ dump = None
463
+ load = ExplicitNull
464
+
465
+ if isinstance(all_paths, str):
466
+ all_paths = (split_object_path(all_paths),)
467
+ else:
468
+ all_paths = tuple([
469
+ split_object_path(a) if isinstance(a, str) else a
470
+ for a in all_paths
471
+ ])
472
+
473
+ return all_paths, load, dump
474
+
475
+
476
+ def _normalize_alias_args(default, default_factory, all_aliases, load, dump):
477
+ """Normalize `Alias` arguments and canonicalize alias values."""
478
+
479
+ if default is not MISSING and default_factory is not MISSING:
480
+ raise ValueError('cannot specify both default and default_factory')
481
+
482
+ if all_aliases:
483
+ load = dump = all_aliases
484
+
485
+ elif load is not None and isinstance(load, str):
486
+ load = (load,)
487
+
488
+ return all_aliases, load, dump
489
+
490
+
453
491
  # Instances of Field are only ever created from within this module,
454
492
  # and only from the field() function, although Field instances are
455
493
  # exposed externally as (conceptually) read-only objects.
@@ -461,11 +499,125 @@ UTCTimePattern = PatternBase(time, tz_info=UTC)
461
499
  # When cls._FIELDS is filled in with a list of Field objects, the name
462
500
  # and type fields will have been populated.
463
501
 
502
+ # In Python 3.14, dataclasses adds a new parameter to the :class:`Field`
503
+ # constructor: `doc`
504
+ #
505
+ # Ref: https://docs.python.org/3.14/library/dataclasses.html#dataclasses.field
506
+ if PY314_OR_ABOVE:
507
+ # noinspection PyPep8Naming,PyShadowingBuiltins
508
+ def Alias(
509
+ *all,
510
+ load=None,
511
+ dump=None,
512
+ skip=False,
513
+ default=MISSING,
514
+ default_factory=MISSING,
515
+ init=True,
516
+ repr=True,
517
+ hash=None,
518
+ compare=True,
519
+ metadata=None,
520
+ kw_only=False,
521
+ doc=None,
522
+ ):
523
+
524
+ all, load, dump = _normalize_alias_args(default, default_factory, all, load, dump)
525
+
526
+ return Field(
527
+ load,
528
+ dump,
529
+ skip,
530
+ None,
531
+ default,
532
+ default_factory,
533
+ init,
534
+ repr,
535
+ hash,
536
+ compare,
537
+ metadata,
538
+ kw_only,
539
+ doc,
540
+ )
541
+
542
+ # noinspection PyPep8Naming,PyShadowingBuiltins
543
+ def AliasPath(
544
+ *all,
545
+ load=None,
546
+ dump=None,
547
+ skip=False,
548
+ default=MISSING,
549
+ default_factory=MISSING,
550
+ init=True,
551
+ repr=True,
552
+ hash=None,
553
+ compare=True,
554
+ metadata=None,
555
+ kw_only=False,
556
+ doc=None,
557
+ ):
558
+ all, load, dump = _normalize_alias_path_args(all, load, dump)
559
+
560
+ return Field(
561
+ load,
562
+ dump,
563
+ skip,
564
+ all,
565
+ default,
566
+ default_factory,
567
+ init,
568
+ repr,
569
+ hash,
570
+ compare,
571
+ metadata,
572
+ kw_only,
573
+ doc,
574
+ )
575
+
576
+ class Field(_Field):
577
+
578
+ __slots__ = ("load_alias", "dump_alias", "skip", "path")
579
+
580
+ # noinspection PyShadowingBuiltins
581
+ def __init__(
582
+ self,
583
+ load_alias,
584
+ dump_alias,
585
+ skip,
586
+ path,
587
+ default,
588
+ default_factory,
589
+ init,
590
+ repr,
591
+ hash,
592
+ compare,
593
+ metadata,
594
+ kw_only,
595
+ doc=None,
596
+ ):
597
+
598
+ super().__init__(
599
+ default,
600
+ default_factory,
601
+ init,
602
+ repr,
603
+ hash,
604
+ compare,
605
+ metadata,
606
+ kw_only,
607
+ doc,
608
+ )
609
+
610
+ self.load_alias = load_alias
611
+ self.dump_alias = dump_alias
612
+ self.skip = skip
613
+ self.path = path
614
+
615
+
464
616
  # In Python 3.10, dataclasses adds a new parameter to the :class:`Field`
465
617
  # constructor: `kw_only`
466
618
  #
467
619
  # Ref: https://docs.python.org/3.10/library/dataclasses.html#dataclasses.dataclass
468
- if PY310_OR_ABOVE: # pragma: no cover
620
+ elif PY310_OR_ABOVE: # pragma: no cover
469
621
 
470
622
  # noinspection PyPep8Naming,PyShadowingBuiltins
471
623
  def Alias(*all,
@@ -478,17 +630,22 @@ if PY310_OR_ABOVE: # pragma: no cover
478
630
  hash=None, compare=True,
479
631
  metadata=None, kw_only=False):
480
632
 
481
- if default is not MISSING and default_factory is not MISSING:
482
- raise ValueError('cannot specify both default and default_factory')
483
-
484
- if all:
485
- load = dump = all
486
-
487
- elif load is not None and isinstance(load, str):
488
- load = (load, )
489
-
490
- return Field(load, dump, skip, None, default, default_factory, init, repr,
491
- hash, compare, metadata, kw_only)
633
+ all, load, dump = _normalize_alias_args(default, default_factory, all, load, dump)
634
+
635
+ return Field(
636
+ load,
637
+ dump,
638
+ skip,
639
+ None,
640
+ default,
641
+ default_factory,
642
+ init,
643
+ repr,
644
+ hash,
645
+ compare,
646
+ metadata,
647
+ kw_only,
648
+ )
492
649
 
493
650
  # noinspection PyPep8Naming,PyShadowingBuiltins
494
651
  def AliasPath(*all,
@@ -500,28 +657,22 @@ if PY310_OR_ABOVE: # pragma: no cover
500
657
  init=True, repr=True,
501
658
  hash=None, compare=True,
502
659
  metadata=None, kw_only=False):
503
-
504
- if load is not None:
505
- all = load
506
- load = None
507
- dump = ExplicitNull
508
-
509
- elif dump is not None:
510
- all = dump
511
- dump = None
512
- load = ExplicitNull
513
-
514
- if isinstance(all, str):
515
- all = (split_object_path(all), )
516
- else:
517
- all = tuple([
518
- split_object_path(a) if isinstance(a, str) else a
519
- for a in all
520
- ])
521
-
522
- return Field(load, dump, skip, all, default, default_factory, init, repr,
523
- hash, compare, metadata, kw_only)
524
-
660
+ all, load, dump = _normalize_alias_path_args(all, load, dump)
661
+
662
+ return Field(
663
+ load,
664
+ dump,
665
+ skip,
666
+ all,
667
+ default,
668
+ default_factory,
669
+ init,
670
+ repr,
671
+ hash,
672
+ compare,
673
+ metadata,
674
+ kw_only,
675
+ )
525
676
 
526
677
  class Field(_Field):
527
678
 
@@ -555,18 +706,21 @@ else: # pragma: no cover
555
706
  init=True, repr=True,
556
707
  hash=None, compare=True, metadata=None):
557
708
 
558
- if default is not MISSING and default_factory is not MISSING:
559
- raise ValueError('cannot specify both default and default_factory')
560
-
561
- if all:
562
- load = dump = all
563
-
564
- elif load is not None and isinstance(load, str):
565
- load = (load, )
566
-
567
- return Field(load, dump, skip, None,
568
- default, default_factory, init, repr,
569
- hash, compare, metadata)
709
+ all, load, dump = _normalize_alias_args(default, default_factory, all, load, dump)
710
+
711
+ return Field(
712
+ load,
713
+ dump,
714
+ skip,
715
+ None,
716
+ default,
717
+ default_factory,
718
+ init,
719
+ repr,
720
+ hash,
721
+ compare,
722
+ metadata,
723
+ )
570
724
 
571
725
  # noinspection PyPep8Naming,PyShadowingBuiltins
572
726
  def AliasPath(*all,
@@ -578,28 +732,21 @@ else: # pragma: no cover
578
732
  init=True, repr=True,
579
733
  hash=None, compare=True,
580
734
  metadata=None):
581
-
582
- if load is not None:
583
- all = load
584
- load = None
585
- dump = ExplicitNull
586
-
587
- elif dump is not None:
588
- all = dump
589
- dump = None
590
- load = ExplicitNull
591
-
592
- if isinstance(all, str):
593
- all = (split_object_path(all), )
594
- else:
595
- all = tuple([
596
- split_object_path(a) if isinstance(a, str) else a
597
- for a in all
598
- ])
599
-
600
- return Field(load, dump, skip, all, default, default_factory, init, repr,
601
- hash, compare, metadata)
602
-
735
+ all, load, dump = _normalize_alias_path_args(all, load, dump)
736
+
737
+ return Field(
738
+ load,
739
+ dump,
740
+ skip,
741
+ all,
742
+ default,
743
+ default_factory,
744
+ init,
745
+ repr,
746
+ hash,
747
+ compare,
748
+ metadata,
749
+ )
603
750
 
604
751
  class Field(_Field):
605
752
 
@@ -604,6 +604,19 @@ class Field(_Field):
604
604
  skip: bool
605
605
  path: PathType | None
606
606
 
607
+ # In Python 3.14, dataclasses adds a new parameter to the :class:`Field`
608
+ # constructor: `doc`
609
+ #
610
+ # Ref: https://docs.python.org/3.14/library/dataclasses.html#dataclasses.field
611
+ @overload
612
+ def __init__(self,
613
+ load_alias: str | None,
614
+ dump_alias: str | None,
615
+ skip: bool,
616
+ path: PathType | None,
617
+ default, default_factory, init, repr, hash, compare,
618
+ metadata, kw_only, doc):
619
+
607
620
  # In Python 3.10, dataclasses adds a new parameter to the :class:`Field`
608
621
  # constructor: `kw_only`
609
622
  #
@@ -18,7 +18,7 @@ from .type_def import (T, ListOfJSONObject,
18
18
  # A type that can be string or `path.Path`
19
19
  # https://stackoverflow.com/a/78070015/10237506
20
20
  # A type that can be string, bytes, or `PathLike`
21
- FileType: TypeAlias = Union[str, bytes, PathLike]
21
+ FileType: TypeAlias = str | bytes | PathLike
22
22
 
23
23
 
24
24
  class JSONListWizard(JSONSerializable, str=False):