marshmallow 4.0.0__tar.gz → 4.1.0__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.
- {marshmallow-4.0.0 → marshmallow-4.1.0}/CHANGELOG.rst +24 -5
- {marshmallow-4.0.0 → marshmallow-4.1.0}/CONTRIBUTING.rst +1 -2
- {marshmallow-4.0.0 → marshmallow-4.1.0}/PKG-INFO +7 -7
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/code_of_conduct.rst +3 -3
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/conf.py +1 -2
- {marshmallow-4.0.0 → marshmallow-4.1.0}/pyproject.toml +8 -7
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/__init__.py +0 -1
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/constants.py +3 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/decorators.py +17 -17
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/exceptions.py +0 -1
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/fields.py +12 -12
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/orderedset.py +1 -1
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/schema.py +7 -5
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/types.py +3 -10
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/utils.py +4 -11
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/base.py +0 -11
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_decorators.py +3 -3
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_deserialization.py +12 -2
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_registry.py +3 -3
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_schema.py +1 -1
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_serialization.py +2 -2
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_utils.py +1 -1
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tox.ini +1 -1
- {marshmallow-4.0.0 → marshmallow-4.1.0}/LICENSE +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/NOTICE +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/README.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/SECURITY.md +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/.gitignore +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/apple-touch-icon.png +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/custom.css +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/favicon.ico +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/marshmallow-logo-200.png +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/marshmallow-logo-with-title-for-dark-theme.png +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/marshmallow-logo-with-title.png +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/marshmallow-logo.png +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/api_reference.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/authors.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/changelog.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/contributing.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/custom_fields.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/dashing.json +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/donate.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/examples/index.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/examples/inflection.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/examples/quotes_api.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/examples/validating_package_json.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/custom_error_handling.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/custom_error_messages.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/custom_options.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/index.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/overriding_attribute_access.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/pre_and_post_processing_methods.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/schema_validation.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/extending/using_original_input_data.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/index.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/install.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/kudos.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/license.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.class_registry.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.decorators.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.error_store.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.exceptions.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.experimental.context.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.fields.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.schema.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.types.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.utils.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/marshmallow.validate.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/nesting.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/quickstart.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/top_level.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/upgrading.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/whos_using.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/docs/why.rst +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/class_registry.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/error_store.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/experimental/__init__.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/experimental/context.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/py.typed +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/src/marshmallow/validate.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/__init__.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/conftest.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/foo_serializer.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/mypy_test_cases/test_class_registry.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/mypy_test_cases/test_schema.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/mypy_test_cases/test_validation_error.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_context.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_error_store.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_exceptions.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_fields.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_options.py +0 -0
- {marshmallow-4.0.0 → marshmallow-4.1.0}/tests/test_validate.py +0 -0
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
---------
|
|
3
3
|
|
|
4
|
+
4.1.0 (2025-11-01)
|
|
5
|
+
++++++++++++++++++
|
|
6
|
+
|
|
7
|
+
Other changes:
|
|
8
|
+
|
|
9
|
+
- Add `__len__` implementation to `missing` so that it can be used with
|
|
10
|
+
`validate.Length <marshmallow.validate.Length>` (:pr:`2861`).
|
|
11
|
+
Thanks :user:`agentgodzilla` for the PR.
|
|
12
|
+
- Drop support for Python 3.9 (:pr:`2363`).
|
|
13
|
+
- Test against Python 3.14.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
4.0.1 (2025-08-28)
|
|
17
|
+
++++++++++++++++++
|
|
18
|
+
|
|
19
|
+
Bug fixes:
|
|
20
|
+
|
|
21
|
+
- Fix wildcard import of ``from marshmallow import *`` (:pr:`2823`).
|
|
22
|
+
Thanks :user:`Florian-Laport` for the PR.
|
|
23
|
+
|
|
24
|
+
|
|
4
25
|
4.0.0 (2025-04-16)
|
|
5
26
|
******************
|
|
6
27
|
|
|
@@ -22,16 +43,14 @@ Other changes:
|
|
|
22
43
|
|
|
23
44
|
- Typing: `Field <marshmallow.fields.Field>` is now a generic type with a type argument for the internal value type.
|
|
24
45
|
- `marshmallow.fields.UUID` no longer subclasses `marshmallow.fields.String`.
|
|
25
|
-
-
|
|
26
|
-
- `marshmallow.Schema.load` no longer silently fails to call schema validators when a generator is passed (:issue:`1898`).
|
|
46
|
+
- `marshmallow.Schema.load` no longer silently fails to call schema validators when a generator is passed (:issue:`1898`).
|
|
27
47
|
The typing of `data` is also updated to be more accurate.
|
|
28
48
|
Thanks :user:`ziplokk1` for reporting.
|
|
29
|
-
|
|
49
|
+
- *Backwards-incompatible*: Use `datetime.date.fromisoformat`, `datetime.time.fromisoformat`, and `datetime.datetime.fromisoformat` from the standard library to deserialize dates, times and datetimes (:pr:`2078`).
|
|
30
50
|
As a consequence of this change:
|
|
31
51
|
- Time with time offsets are now supported.
|
|
32
52
|
- YYYY-MM-DD is now accepted as a datetime and deserialized as naive 00:00 AM.
|
|
33
53
|
- `from_iso_date`, `from_iso_time` and `from_iso_datetime` are removed from `marshmallow.utils`.
|
|
34
|
-
|
|
35
54
|
- Remove `isoformat`, `to_iso_time` and `to_iso_datetime` from `marshmallow.utils` (:pr:`2766`).
|
|
36
55
|
- Remove `from_rfc`, and `rfcformat` from `marshmallow.utils` (:pr:`2767`).
|
|
37
56
|
- Remove `is_keyed_tuple` from `marshmallow.utils` (:pr:`2768`).
|
|
@@ -152,7 +171,7 @@ Features:
|
|
|
152
171
|
|
|
153
172
|
Bug fixes:
|
|
154
173
|
|
|
155
|
-
- Respect ``data_key`` when schema validators raise a `ValidationError <marshmallow.exceptions.ValidationError>`
|
|
174
|
+
- Respect ``data_key`` when schema validators raise a `ValidationError <marshmallow.exceptions.ValidationError>`
|
|
156
175
|
with a ``field_name`` argument (:issue:`2170`). Thanks :user:`matejsp` for reporting.
|
|
157
176
|
- Correctly handle multiple `@post_load <marshmallow.post_load>` methods where one method appends to
|
|
158
177
|
the data and another passes ``pass_original=True`` (:issue:`1755`).
|
|
@@ -26,8 +26,7 @@ Ways to contribute
|
|
|
26
26
|
|
|
27
27
|
- Comment on some of marshmallow's `open issues <https://github.com/marshmallow-code/marshmallow/issues>`_ (especially those `labeled "feedback welcome" <https://github.com/marshmallow-code/marshmallow/issues?q=is%3Aopen+is%3Aissue+label%3A%22feedback+welcome%22>`_). Share a solution or workaround. Make a suggestion for how a feature can be made better. Opinions are welcome!
|
|
28
28
|
- Improve `the docs <https://marshmallow.readthedocs.io>`_.
|
|
29
|
-
For straightforward edits,
|
|
30
|
-
click the ReadTheDocs menu button in the bottom-right corner of the page and click "Edit".
|
|
29
|
+
For straightforward edits, click the edit button in the top-right corner of the page.
|
|
31
30
|
See the :ref:`Documentation <contributing_documentation>` section of this page if you want to build the docs locally.
|
|
32
31
|
- If you think you've found a bug, `open an issue <https://github.com/marshmallow-code/marshmallow/issues>`_.
|
|
33
32
|
- Contribute an :ref:`example usage <contributing_examples>` of marshmallow.
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: marshmallow
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.1.0
|
|
4
4
|
Summary: A lightweight library for converting complex datatypes to and from native Python datatypes.
|
|
5
|
-
Author-email: Steven Loria <
|
|
6
|
-
Maintainer-email: Steven Loria <
|
|
7
|
-
Requires-Python: >=3.
|
|
5
|
+
Author-email: Steven Loria <oss@stevenloria.com>
|
|
6
|
+
Maintainer-email: Steven Loria <oss@stevenloria.com>, Jérôme Lafréchoux <jerome@jolimont.fr>, Jared Deckard <jared@shademaps.com>
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
8
|
Description-Content-Type: text/x-rst
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
18
|
License-File: LICENSE
|
|
19
19
|
Requires-Dist: backports-datetime-fromisoformat; python_version < '3.11'
|
|
20
20
|
Requires-Dist: typing-extensions; python_version < '3.11'
|
|
@@ -22,11 +22,11 @@ Requires-Dist: marshmallow[tests] ; extra == "dev"
|
|
|
22
22
|
Requires-Dist: tox ; extra == "dev"
|
|
23
23
|
Requires-Dist: pre-commit>=3.5,<5.0 ; extra == "dev"
|
|
24
24
|
Requires-Dist: autodocsumm==0.2.14 ; extra == "docs"
|
|
25
|
-
Requires-Dist: furo==
|
|
25
|
+
Requires-Dist: furo==2025.9.25 ; extra == "docs"
|
|
26
26
|
Requires-Dist: sphinx-copybutton==0.5.2 ; extra == "docs"
|
|
27
27
|
Requires-Dist: sphinx-issues==5.0.1 ; extra == "docs"
|
|
28
28
|
Requires-Dist: sphinx==8.2.3 ; extra == "docs"
|
|
29
|
-
Requires-Dist: sphinxext-opengraph==0.
|
|
29
|
+
Requires-Dist: sphinxext-opengraph==0.13.0 ; extra == "docs"
|
|
30
30
|
Requires-Dist: pytest ; extra == "tests"
|
|
31
31
|
Requires-Dist: simplejson ; extra == "tests"
|
|
32
32
|
Project-URL: Changelog, https://marshmallow.readthedocs.io/en/latest/changelog.html
|
|
@@ -136,10 +136,10 @@ members. This section covers actual concrete steps.
|
|
|
136
136
|
Contacting maintainers
|
|
137
137
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
138
138
|
|
|
139
|
-
As a small
|
|
139
|
+
As a small project, we don't yet have a Code of Conduct
|
|
140
140
|
enforcement team. Hopefully that will be addressed as we grow, but for
|
|
141
|
-
now, any issues should be addressed to
|
|
142
|
-
<https://github.com/sloria>`__, via `email <mailto:
|
|
141
|
+
now, any issues should be addressed to `@sloria
|
|
142
|
+
<https://github.com/sloria>`__, via `email <mailto:oss@stevenloria.com>`__
|
|
143
143
|
or any other medium that you feel comfortable with. Using words like
|
|
144
144
|
"marshmallow code of conduct" in your subject will help make sure your
|
|
145
145
|
message is noticed quickly.
|
|
@@ -37,7 +37,6 @@ html_theme_options = {
|
|
|
37
37
|
"light_logo": "marshmallow-logo-with-title.png",
|
|
38
38
|
"dark_logo": "marshmallow-logo-with-title-for-dark-theme.png",
|
|
39
39
|
"source_repository": "https://github.com/marshmallow-code/marshmallow",
|
|
40
|
-
"announcement": 'This is the documentation for the unreleased 4.0 version. The latest v3 docs are <a href="https://marshmallow.readthedocs.io/en/3.x-line/">here</a>.',
|
|
41
40
|
"source_branch": "dev",
|
|
42
41
|
"source_directory": "docs/",
|
|
43
42
|
"sidebar_hide_name": True,
|
|
@@ -45,7 +44,7 @@ html_theme_options = {
|
|
|
45
44
|
# Serif system font stack: https://systemfontstack.com/
|
|
46
45
|
"font-stack": "Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;",
|
|
47
46
|
},
|
|
48
|
-
"top_of_page_buttons": ["view"],
|
|
47
|
+
"top_of_page_buttons": ["view", "edit"],
|
|
49
48
|
}
|
|
50
49
|
pygments_dark_style = "lightbulb"
|
|
51
50
|
html_favicon = "_static/favicon.ico"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "marshmallow"
|
|
3
|
-
version = "4.
|
|
3
|
+
version = "4.1.0"
|
|
4
4
|
description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
|
|
5
5
|
readme = "README.rst"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
7
|
-
authors = [{ name = "Steven Loria", email = "
|
|
7
|
+
authors = [{ name = "Steven Loria", email = "oss@stevenloria.com" }]
|
|
8
8
|
maintainers = [
|
|
9
|
-
{ name = "Steven Loria", email = "
|
|
9
|
+
{ name = "Steven Loria", email = "oss@stevenloria.com" },
|
|
10
10
|
{ name = "Jérôme Lafréchoux", email = "jerome@jolimont.fr" },
|
|
11
11
|
{ name = "Jared Deckard", email = "jared@shademaps.com" },
|
|
12
12
|
]
|
|
@@ -15,13 +15,13 @@ classifiers = [
|
|
|
15
15
|
"Intended Audience :: Developers",
|
|
16
16
|
"License :: OSI Approved :: MIT License",
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
|
-
"Programming Language :: Python :: 3.9",
|
|
19
18
|
"Programming Language :: Python :: 3.10",
|
|
20
19
|
"Programming Language :: Python :: 3.11",
|
|
21
20
|
"Programming Language :: Python :: 3.12",
|
|
22
21
|
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
23
|
]
|
|
24
|
-
requires-python = ">=3.
|
|
24
|
+
requires-python = ">=3.10"
|
|
25
25
|
dependencies = [
|
|
26
26
|
"backports-datetime-fromisoformat; python_version < '3.11'",
|
|
27
27
|
"typing-extensions; python_version < '3.11'",
|
|
@@ -37,11 +37,11 @@ Tidelift = "https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=py
|
|
|
37
37
|
[project.optional-dependencies]
|
|
38
38
|
docs = [
|
|
39
39
|
"autodocsumm==0.2.14",
|
|
40
|
-
"furo==
|
|
40
|
+
"furo==2025.9.25",
|
|
41
41
|
"sphinx-copybutton==0.5.2",
|
|
42
42
|
"sphinx-issues==5.0.1",
|
|
43
43
|
"sphinx==8.2.3",
|
|
44
|
-
"sphinxext-opengraph==0.
|
|
44
|
+
"sphinxext-opengraph==0.13.0",
|
|
45
45
|
]
|
|
46
46
|
tests = ["pytest", "simplejson"]
|
|
47
47
|
dev = ["marshmallow[tests]", "tox", "pre-commit>=3.5,<5.0"]
|
|
@@ -108,6 +108,7 @@ ignore = [
|
|
|
108
108
|
"PLR0915", # allow lots of statements
|
|
109
109
|
"PT007", # ignore false positives due to https://github.com/astral-sh/ruff/issues/14743
|
|
110
110
|
"PT011", # don't require match when using pytest.raises
|
|
111
|
+
"RUF043", # allow metacharacters in match patterns
|
|
111
112
|
"S", # allow asserts
|
|
112
113
|
"SIM117", # allow nested with statements because it's more readable sometimes
|
|
113
114
|
"SLF001", # allow private attribute access
|
|
@@ -68,8 +68,8 @@ Example: ::
|
|
|
68
68
|
from __future__ import annotations
|
|
69
69
|
|
|
70
70
|
import functools
|
|
71
|
+
import typing
|
|
71
72
|
from collections import defaultdict
|
|
72
|
-
from typing import Any, Callable, cast
|
|
73
73
|
|
|
74
74
|
PRE_DUMP = "pre_dump"
|
|
75
75
|
POST_DUMP = "post_dump"
|
|
@@ -80,10 +80,10 @@ VALIDATES_SCHEMA = "validates_schema"
|
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class MarshmallowHook:
|
|
83
|
-
__marshmallow_hook__: dict[str, list[tuple[bool, Any]]] | None = None
|
|
83
|
+
__marshmallow_hook__: dict[str, list[tuple[bool, typing.Any]]] | None = None
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def validates(*field_names: str) -> Callable[..., Any]:
|
|
86
|
+
def validates(*field_names: str) -> typing.Callable[..., typing.Any]:
|
|
87
87
|
"""Register a validator method for field(s).
|
|
88
88
|
|
|
89
89
|
:param field_names: Names of the fields that the method validates.
|
|
@@ -95,12 +95,12 @@ def validates(*field_names: str) -> Callable[..., Any]:
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
def validates_schema(
|
|
98
|
-
fn: Callable[..., Any] | None = None,
|
|
98
|
+
fn: typing.Callable[..., typing.Any] | None = None,
|
|
99
99
|
*,
|
|
100
100
|
pass_collection: bool = False,
|
|
101
101
|
pass_original: bool = False,
|
|
102
102
|
skip_on_field_errors: bool = True,
|
|
103
|
-
) -> Callable[..., Any]:
|
|
103
|
+
) -> typing.Callable[..., typing.Any]:
|
|
104
104
|
"""Register a schema-level validator.
|
|
105
105
|
|
|
106
106
|
By default it receives a single object at a time, transparently handling the ``many``
|
|
@@ -131,10 +131,10 @@ def validates_schema(
|
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
def pre_dump(
|
|
134
|
-
fn: Callable[..., Any] | None = None,
|
|
134
|
+
fn: typing.Callable[..., typing.Any] | None = None,
|
|
135
135
|
*,
|
|
136
136
|
pass_collection: bool = False,
|
|
137
|
-
) -> Callable[..., Any]:
|
|
137
|
+
) -> typing.Callable[..., typing.Any]:
|
|
138
138
|
"""Register a method to invoke before serializing an object. The method
|
|
139
139
|
receives the object to be serialized and returns the processed object.
|
|
140
140
|
|
|
@@ -150,11 +150,11 @@ def pre_dump(
|
|
|
150
150
|
|
|
151
151
|
|
|
152
152
|
def post_dump(
|
|
153
|
-
fn: Callable[..., Any] | None = None,
|
|
153
|
+
fn: typing.Callable[..., typing.Any] | None = None,
|
|
154
154
|
*,
|
|
155
155
|
pass_collection: bool = False,
|
|
156
156
|
pass_original: bool = False,
|
|
157
|
-
) -> Callable[..., Any]:
|
|
157
|
+
) -> typing.Callable[..., typing.Any]:
|
|
158
158
|
"""Register a method to invoke after serializing an object. The method
|
|
159
159
|
receives the serialized object and returns the processed object.
|
|
160
160
|
|
|
@@ -173,10 +173,10 @@ def post_dump(
|
|
|
173
173
|
|
|
174
174
|
|
|
175
175
|
def pre_load(
|
|
176
|
-
fn: Callable[..., Any] | None = None,
|
|
176
|
+
fn: typing.Callable[..., typing.Any] | None = None,
|
|
177
177
|
*,
|
|
178
178
|
pass_collection: bool = False,
|
|
179
|
-
) -> Callable[..., Any]:
|
|
179
|
+
) -> typing.Callable[..., typing.Any]:
|
|
180
180
|
"""Register a method to invoke before deserializing an object. The method
|
|
181
181
|
receives the data to be deserialized and returns the processed data.
|
|
182
182
|
|
|
@@ -194,11 +194,11 @@ def pre_load(
|
|
|
194
194
|
|
|
195
195
|
|
|
196
196
|
def post_load(
|
|
197
|
-
fn: Callable[..., Any] | None = None,
|
|
197
|
+
fn: typing.Callable[..., typing.Any] | None = None,
|
|
198
198
|
*,
|
|
199
199
|
pass_collection: bool = False,
|
|
200
200
|
pass_original: bool = False,
|
|
201
|
-
) -> Callable[..., Any]:
|
|
201
|
+
) -> typing.Callable[..., typing.Any]:
|
|
202
202
|
"""Register a method to invoke after deserializing an object. The method
|
|
203
203
|
receives the deserialized data and returns the processed data.
|
|
204
204
|
|
|
@@ -219,12 +219,12 @@ def post_load(
|
|
|
219
219
|
|
|
220
220
|
|
|
221
221
|
def set_hook(
|
|
222
|
-
fn: Callable[..., Any] | None,
|
|
222
|
+
fn: typing.Callable[..., typing.Any] | None,
|
|
223
223
|
tag: str,
|
|
224
224
|
*,
|
|
225
225
|
many: bool = False,
|
|
226
|
-
**kwargs: Any,
|
|
227
|
-
) -> Callable[..., Any]:
|
|
226
|
+
**kwargs: typing.Any,
|
|
227
|
+
) -> typing.Callable[..., typing.Any]:
|
|
228
228
|
"""Mark decorated function as a hook to be picked up later.
|
|
229
229
|
You should not need to use this method directly.
|
|
230
230
|
|
|
@@ -241,7 +241,7 @@ def set_hook(
|
|
|
241
241
|
|
|
242
242
|
# Set a __marshmallow_hook__ attribute instead of wrapping in some class,
|
|
243
243
|
# because I still want this to end up as a normal (unbound) method.
|
|
244
|
-
function = cast("MarshmallowHook", fn)
|
|
244
|
+
function = typing.cast("MarshmallowHook", fn)
|
|
245
245
|
try:
|
|
246
246
|
hook_config = function.__marshmallow_hook__
|
|
247
247
|
except AttributeError:
|
|
@@ -20,7 +20,6 @@ class ValidationError(MarshmallowError):
|
|
|
20
20
|
:param message: An error message, list of error messages, or dict of
|
|
21
21
|
error messages. If a dict, the keys are subitems and the values are error messages.
|
|
22
22
|
:param field_name: Field name to store the error on.
|
|
23
|
-
If `None`, the error is stored as schema-level error.
|
|
24
23
|
:param data: Raw input data.
|
|
25
24
|
:param valid_data: Valid (de)serialized data.
|
|
26
25
|
"""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ruff: noqa:
|
|
1
|
+
# ruff: noqa: SLF001
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import abc
|
|
@@ -530,7 +530,7 @@ class Nested(Field):
|
|
|
530
530
|
else:
|
|
531
531
|
nested = typing.cast("Schema", self.nested)
|
|
532
532
|
# defer the import of `marshmallow.schema` to avoid circular imports
|
|
533
|
-
from marshmallow.schema import Schema
|
|
533
|
+
from marshmallow.schema import Schema # noqa: PLC0415
|
|
534
534
|
|
|
535
535
|
if isinstance(nested, dict):
|
|
536
536
|
nested = Schema.from_dict(nested)
|
|
@@ -558,7 +558,7 @@ class Nested(Field):
|
|
|
558
558
|
f"`Schema`, not {nested.__class__}."
|
|
559
559
|
)
|
|
560
560
|
else:
|
|
561
|
-
schema_class = class_registry.get_class(nested, all=False)
|
|
561
|
+
schema_class = class_registry.get_class(nested, all=False) # type: ignore[unreachable]
|
|
562
562
|
self._schema = schema_class(
|
|
563
563
|
many=self.many,
|
|
564
564
|
only=self.only,
|
|
@@ -591,7 +591,9 @@ class Nested(Field):
|
|
|
591
591
|
raise self.make_error("type", input=value, type=value.__class__.__name__)
|
|
592
592
|
|
|
593
593
|
def _load(
|
|
594
|
-
self,
|
|
594
|
+
self,
|
|
595
|
+
value: typing.Any,
|
|
596
|
+
partial: bool | types.StrSequenceOrSet | None = None, # noqa: FBT001
|
|
595
597
|
):
|
|
596
598
|
try:
|
|
597
599
|
valid_data = self.schema.load(value, unknown=self.unknown, partial=partial)
|
|
@@ -606,7 +608,7 @@ class Nested(Field):
|
|
|
606
608
|
value: typing.Any,
|
|
607
609
|
attr: str | None,
|
|
608
610
|
data: typing.Mapping[str, typing.Any] | None,
|
|
609
|
-
partial: bool | types.StrSequenceOrSet | None = None,
|
|
611
|
+
partial: bool | types.StrSequenceOrSet | None = None, # noqa: FBT001
|
|
610
612
|
**kwargs,
|
|
611
613
|
):
|
|
612
614
|
"""Same as :meth:`Field._deserialize` with additional ``partial`` argument.
|
|
@@ -683,7 +685,7 @@ class Pluck(Nested):
|
|
|
683
685
|
return self._load(value, partial=partial)
|
|
684
686
|
|
|
685
687
|
|
|
686
|
-
class List(Field[list[
|
|
688
|
+
class List(Field[list[_InternalT | None]]):
|
|
687
689
|
"""A list field, composed with another `Field` class or
|
|
688
690
|
instance.
|
|
689
691
|
|
|
@@ -814,7 +816,7 @@ class Tuple(Field[tuple]):
|
|
|
814
816
|
|
|
815
817
|
return tuple(
|
|
816
818
|
field._serialize(each, attr, obj, **kwargs)
|
|
817
|
-
for field, each in zip(self.tuple_fields, value)
|
|
819
|
+
for field, each in zip(self.tuple_fields, value, strict=True)
|
|
818
820
|
)
|
|
819
821
|
|
|
820
822
|
def _deserialize(
|
|
@@ -832,7 +834,7 @@ class Tuple(Field[tuple]):
|
|
|
832
834
|
result = []
|
|
833
835
|
errors = {}
|
|
834
836
|
|
|
835
|
-
for idx, (field, each) in enumerate(zip(self.tuple_fields, value)):
|
|
837
|
+
for idx, (field, each) in enumerate(zip(self.tuple_fields, value, strict=True)):
|
|
836
838
|
try:
|
|
837
839
|
result.append(field.deserialize(each, **kwargs))
|
|
838
840
|
except ValidationError as error:
|
|
@@ -1743,7 +1745,7 @@ class Email(String):
|
|
|
1743
1745
|
self.validators.insert(0, validator)
|
|
1744
1746
|
|
|
1745
1747
|
|
|
1746
|
-
class IP(Field[
|
|
1748
|
+
class IP(Field[ipaddress.IPv4Address | ipaddress.IPv6Address]):
|
|
1747
1749
|
"""A IP address field.
|
|
1748
1750
|
|
|
1749
1751
|
:param exploded: If `True`, serialize ipv6 address in long form, ie. with groups
|
|
@@ -1800,9 +1802,7 @@ class IPv6(IP):
|
|
|
1800
1802
|
DESERIALIZATION_CLASS = ipaddress.IPv6Address
|
|
1801
1803
|
|
|
1802
1804
|
|
|
1803
|
-
class IPInterface(
|
|
1804
|
-
Field[typing.Union[ipaddress.IPv4Interface, ipaddress.IPv6Interface]]
|
|
1805
|
-
):
|
|
1805
|
+
class IPInterface(Field[ipaddress.IPv4Interface | ipaddress.IPv6Interface]):
|
|
1806
1806
|
"""A IPInterface field.
|
|
1807
1807
|
|
|
1808
1808
|
IP interface is the non-strict form of the IPNetwork type where arbitrary host
|
|
@@ -550,7 +550,7 @@ class Schema(metaclass=SchemaMeta):
|
|
|
550
550
|
:return: Serialized data
|
|
551
551
|
|
|
552
552
|
.. versionchanged:: 3.0.0b7
|
|
553
|
-
This method returns the serialized data rather than a ``(data, errors)``
|
|
553
|
+
This method returns the serialized data rather than a ``(data, errors)`` tuple.
|
|
554
554
|
A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised
|
|
555
555
|
if ``obj`` is invalid.
|
|
556
556
|
.. versionchanged:: 3.0.0rc9
|
|
@@ -582,7 +582,7 @@ class Schema(metaclass=SchemaMeta):
|
|
|
582
582
|
:return: A ``json`` string
|
|
583
583
|
|
|
584
584
|
.. versionchanged:: 3.0.0b7
|
|
585
|
-
This method returns the serialized data rather than a ``(data, errors)``
|
|
585
|
+
This method returns the serialized data rather than a ``(data, errors)`` tuple.
|
|
586
586
|
A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised
|
|
587
587
|
if ``obj`` is invalid.
|
|
588
588
|
"""
|
|
@@ -723,7 +723,7 @@ class Schema(metaclass=SchemaMeta):
|
|
|
723
723
|
:return: Deserialized data
|
|
724
724
|
|
|
725
725
|
.. versionchanged:: 3.0.0b7
|
|
726
|
-
This method returns the deserialized data rather than a ``(data, errors)``
|
|
726
|
+
This method returns the deserialized data rather than a ``(data, errors)`` tuple.
|
|
727
727
|
A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised
|
|
728
728
|
if invalid data are passed.
|
|
729
729
|
"""
|
|
@@ -757,7 +757,7 @@ class Schema(metaclass=SchemaMeta):
|
|
|
757
757
|
:return: Deserialized data
|
|
758
758
|
|
|
759
759
|
.. versionchanged:: 3.0.0b7
|
|
760
|
-
This method returns the deserialized data rather than a ``(data, errors)``
|
|
760
|
+
This method returns the deserialized data rather than a ``(data, errors)`` tuple.
|
|
761
761
|
A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised
|
|
762
762
|
if invalid data are passed.
|
|
763
763
|
.. versionchanged:: 4.0.0
|
|
@@ -1188,7 +1188,9 @@ class Schema(metaclass=SchemaMeta):
|
|
|
1188
1188
|
pass_original = validator_kwargs.get("pass_original", False)
|
|
1189
1189
|
|
|
1190
1190
|
if many and not pass_collection:
|
|
1191
|
-
for idx, (item, orig) in enumerate(
|
|
1191
|
+
for idx, (item, orig) in enumerate(
|
|
1192
|
+
zip(data, original_data, strict=True)
|
|
1193
|
+
):
|
|
1192
1194
|
self._run_validator(
|
|
1193
1195
|
validator,
|
|
1194
1196
|
item,
|
|
@@ -7,23 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
try:
|
|
11
|
-
from typing import TypeAlias
|
|
12
|
-
except ImportError: # Remove when dropping Python 3.9
|
|
13
|
-
from typing_extensions import TypeAlias
|
|
14
|
-
|
|
15
10
|
import typing
|
|
16
11
|
|
|
17
12
|
#: A type that can be either a sequence of strings or a set of strings
|
|
18
|
-
StrSequenceOrSet: TypeAlias = typing.
|
|
19
|
-
typing.Sequence[str], typing.AbstractSet[str]
|
|
20
|
-
]
|
|
13
|
+
StrSequenceOrSet: typing.TypeAlias = typing.Sequence[str] | typing.AbstractSet[str]
|
|
21
14
|
|
|
22
15
|
#: Type for validator functions
|
|
23
|
-
Validator: TypeAlias = typing.Callable[[typing.Any], typing.Any]
|
|
16
|
+
Validator: typing.TypeAlias = typing.Callable[[typing.Any], typing.Any]
|
|
24
17
|
|
|
25
18
|
#: A valid option for the ``unknown`` schema option and argument
|
|
26
|
-
UnknownOption: TypeAlias = typing.Literal["exclude", "include", "raise"]
|
|
19
|
+
UnknownOption: typing.TypeAlias = typing.Literal["exclude", "include", "raise"]
|
|
27
20
|
|
|
28
21
|
|
|
29
22
|
class SchemaValidator(typing.Protocol):
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Utility methods for marshmallow."""
|
|
2
2
|
|
|
3
|
-
# ruff: noqa: T201, T203
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
5
|
import datetime as dt
|
|
@@ -8,31 +7,25 @@ import inspect
|
|
|
8
7
|
import typing
|
|
9
8
|
from collections.abc import Mapping, Sequence
|
|
10
9
|
|
|
11
|
-
# Remove when we drop Python 3.9
|
|
12
|
-
try:
|
|
13
|
-
from typing import TypeGuard
|
|
14
|
-
except ImportError:
|
|
15
|
-
from typing_extensions import TypeGuard
|
|
16
|
-
|
|
17
10
|
from marshmallow.constants import missing
|
|
18
11
|
|
|
19
12
|
|
|
20
|
-
def is_generator(obj) -> TypeGuard[typing.Generator]:
|
|
13
|
+
def is_generator(obj) -> typing.TypeGuard[typing.Generator]:
|
|
21
14
|
"""Return True if ``obj`` is a generator"""
|
|
22
15
|
return inspect.isgeneratorfunction(obj) or inspect.isgenerator(obj)
|
|
23
16
|
|
|
24
17
|
|
|
25
|
-
def is_iterable_but_not_string(obj) -> TypeGuard[typing.Iterable]:
|
|
18
|
+
def is_iterable_but_not_string(obj) -> typing.TypeGuard[typing.Iterable]:
|
|
26
19
|
"""Return True if ``obj`` is an iterable object that isn't a string."""
|
|
27
20
|
return (hasattr(obj, "__iter__") and not hasattr(obj, "strip")) or is_generator(obj)
|
|
28
21
|
|
|
29
22
|
|
|
30
|
-
def is_sequence_but_not_string(obj) -> TypeGuard[Sequence]:
|
|
23
|
+
def is_sequence_but_not_string(obj) -> typing.TypeGuard[Sequence]:
|
|
31
24
|
"""Return True if ``obj`` is a sequence that isn't a string."""
|
|
32
25
|
return isinstance(obj, Sequence) and not isinstance(obj, (str, bytes))
|
|
33
26
|
|
|
34
27
|
|
|
35
|
-
def is_collection(obj) -> TypeGuard[typing.Iterable]:
|
|
28
|
+
def is_collection(obj) -> typing.TypeGuard[typing.Iterable]:
|
|
36
29
|
"""Return True if ``obj`` is a collection type, e.g list, tuple, queryset."""
|
|
37
30
|
return is_iterable_but_not_string(obj) and not isinstance(obj, Mapping)
|
|
38
31
|
|
|
@@ -161,17 +161,6 @@ class Blog:
|
|
|
161
161
|
return item.name in [each.name for each in self.collaborators]
|
|
162
162
|
|
|
163
163
|
|
|
164
|
-
class DummyModel:
|
|
165
|
-
def __init__(self, foo):
|
|
166
|
-
self.foo = foo
|
|
167
|
-
|
|
168
|
-
def __eq__(self, other):
|
|
169
|
-
return self.foo == other.foo
|
|
170
|
-
|
|
171
|
-
def __str__(self):
|
|
172
|
-
return f"bar {self.foo}"
|
|
173
|
-
|
|
174
|
-
|
|
175
164
|
###### Schemas #####
|
|
176
165
|
|
|
177
166
|
|
|
@@ -165,7 +165,7 @@ class TestPassOriginal:
|
|
|
165
165
|
def post_load(self, data, original, many, **kwargs):
|
|
166
166
|
if many:
|
|
167
167
|
ret = []
|
|
168
|
-
for item, orig_item in zip(data, original):
|
|
168
|
+
for item, orig_item in zip(data, original, strict=True):
|
|
169
169
|
item["_post_load"] = orig_item["sentinel"]
|
|
170
170
|
ret.append(item)
|
|
171
171
|
else:
|
|
@@ -177,7 +177,7 @@ class TestPassOriginal:
|
|
|
177
177
|
def post_dump(self, data, original, many, **kwargs):
|
|
178
178
|
if many:
|
|
179
179
|
ret = []
|
|
180
|
-
for item, orig_item in zip(data, original):
|
|
180
|
+
for item, orig_item in zip(data, original, strict=True):
|
|
181
181
|
item["_post_dump"] = orig_item["sentinel"]
|
|
182
182
|
ret.append(item)
|
|
183
183
|
else:
|
|
@@ -234,7 +234,7 @@ def test_decorated_processor_inheritance():
|
|
|
234
234
|
item["overridden"] = "overridden"
|
|
235
235
|
return item
|
|
236
236
|
|
|
237
|
-
deleted = None
|
|
237
|
+
deleted = None # type: ignore[assignment]
|
|
238
238
|
|
|
239
239
|
parent_dumped = ParentSchema().dump({})
|
|
240
240
|
assert parent_dumped == {
|
|
@@ -14,6 +14,7 @@ from marshmallow import (
|
|
|
14
14
|
RAISE,
|
|
15
15
|
Schema,
|
|
16
16
|
fields,
|
|
17
|
+
missing,
|
|
17
18
|
validate,
|
|
18
19
|
)
|
|
19
20
|
from marshmallow.exceptions import ValidationError
|
|
@@ -1005,6 +1006,13 @@ class TestFieldDeserialization:
|
|
|
1005
1006
|
field = fields.Function(lambda x: None, deserialize=lambda val: val.upper())
|
|
1006
1007
|
assert field.deserialize("foo") == "FOO"
|
|
1007
1008
|
|
|
1009
|
+
def test_function_field_deserialization_missing_with_length_validator(self):
|
|
1010
|
+
field = fields.Function(
|
|
1011
|
+
deserialize=lambda value: value.get("some-key", missing),
|
|
1012
|
+
validate=validate.Length(min=0),
|
|
1013
|
+
)
|
|
1014
|
+
assert field.deserialize({}) is missing
|
|
1015
|
+
|
|
1008
1016
|
def test_function_field_passed_deserialize_only_is_load_only(self):
|
|
1009
1017
|
field = fields.Function(deserialize=lambda val: val.upper())
|
|
1010
1018
|
assert field.load_only is True
|
|
@@ -1306,7 +1314,7 @@ class TestFieldDeserialization:
|
|
|
1306
1314
|
field = fields.List(fields.DateTime())
|
|
1307
1315
|
result = field.deserialize(dstrings)
|
|
1308
1316
|
assert all(isinstance(each, dt.datetime) for each in result)
|
|
1309
|
-
for actual, expected in zip(result, dtimes):
|
|
1317
|
+
for actual, expected in zip(result, dtimes, strict=True):
|
|
1310
1318
|
assert_date_equal(actual, expected)
|
|
1311
1319
|
|
|
1312
1320
|
def test_list_field_deserialize_invalid_item(self):
|
|
@@ -1347,7 +1355,9 @@ class TestFieldDeserialization:
|
|
|
1347
1355
|
|
|
1348
1356
|
assert isinstance(result, tuple)
|
|
1349
1357
|
assert len(result) == 2
|
|
1350
|
-
for val, type_, true_val in zip(
|
|
1358
|
+
for val, type_, true_val in zip(
|
|
1359
|
+
result, (dt.datetime, int), (dtime, 42), strict=True
|
|
1360
|
+
):
|
|
1351
1361
|
assert isinstance(val, type_)
|
|
1352
1362
|
assert val == true_val
|
|
1353
1363
|
|
|
@@ -189,7 +189,7 @@ class FooSerializer(Schema):
|
|
|
189
189
|
|
|
190
190
|
def test_multiple_classes_with_same_name_raises_error():
|
|
191
191
|
# Import a class with the same name
|
|
192
|
-
from .foo_serializer import FooSerializer as FooSerializer1 # noqa: F401
|
|
192
|
+
from .foo_serializer import FooSerializer as FooSerializer1 # noqa: PLC0415, F401
|
|
193
193
|
|
|
194
194
|
class MySchema(Schema):
|
|
195
195
|
foo = fields.Nested("FooSerializer")
|
|
@@ -204,14 +204,14 @@ def test_multiple_classes_with_same_name_raises_error():
|
|
|
204
204
|
|
|
205
205
|
def test_multiple_classes_with_all():
|
|
206
206
|
# Import a class with the same name
|
|
207
|
-
from .foo_serializer import FooSerializer as FooSerializer1 # noqa: F401
|
|
207
|
+
from .foo_serializer import FooSerializer as FooSerializer1 # noqa: PLC0415, F401
|
|
208
208
|
|
|
209
209
|
classes = class_registry.get_class("FooSerializer", all=True)
|
|
210
210
|
assert len(classes) == 2
|
|
211
211
|
|
|
212
212
|
|
|
213
213
|
def test_can_use_full_module_path_to_class():
|
|
214
|
-
from .foo_serializer import FooSerializer as FooSerializer1 # noqa: F401
|
|
214
|
+
from .foo_serializer import FooSerializer as FooSerializer1 # noqa: PLC0415, F401
|
|
215
215
|
|
|
216
216
|
# Using full paths is ok
|
|
217
217
|
|
|
@@ -2265,7 +2265,7 @@ class TestGetAttribute:
|
|
|
2265
2265
|
]
|
|
2266
2266
|
schema = UserDictSchema(many=True)
|
|
2267
2267
|
results = schema.dump(user_dicts)
|
|
2268
|
-
for result, user_dict in zip(results, user_dicts):
|
|
2268
|
+
for result, user_dict in zip(results, user_dicts, strict=True):
|
|
2269
2269
|
assert result["name"] == user_dict["_name"]
|
|
2270
2270
|
assert result["email"] == user_dict["_email"]
|
|
2271
2271
|
# can't serialize User object
|
|
@@ -438,7 +438,7 @@ class TestFieldSerialization:
|
|
|
438
438
|
)
|
|
439
439
|
|
|
440
440
|
def test_structured_dict_value_serialize(self, user):
|
|
441
|
-
user.various_data = {"foo": decimal.Decimal(
|
|
441
|
+
user.various_data = {"foo": decimal.Decimal(1)}
|
|
442
442
|
field = fields.Dict(values=fields.Decimal)
|
|
443
443
|
assert field.serialize("various_data", user) == {"foo": 1}
|
|
444
444
|
|
|
@@ -448,7 +448,7 @@ class TestFieldSerialization:
|
|
|
448
448
|
assert field.serialize("various_data", user) == {"1": "bar"}
|
|
449
449
|
|
|
450
450
|
def test_structured_dict_key_value_serialize(self, user):
|
|
451
|
-
user.various_data = {1: decimal.Decimal(
|
|
451
|
+
user.various_data = {1: decimal.Decimal(1)}
|
|
452
452
|
field = fields.Dict(keys=fields.Str, values=fields.Decimal)
|
|
453
453
|
assert field.serialize("various_data", user) == {"1": 1}
|
|
454
454
|
|
|
@@ -124,7 +124,7 @@ def test_from_timestamp_with_negative_value():
|
|
|
124
124
|
|
|
125
125
|
def test_from_timestamp_with_overflow_value():
|
|
126
126
|
value = 9223372036854775
|
|
127
|
-
with pytest.raises(ValueError, match="out of range"):
|
|
127
|
+
with pytest.raises(ValueError, match=r"out of range|year must be in 1\.\.9999"):
|
|
128
128
|
utils.from_timestamp(value)
|
|
129
129
|
|
|
130
130
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{marshmallow-4.0.0 → marshmallow-4.1.0}/docs/_static/marshmallow-logo-with-title-for-dark-theme.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|