marshmallow 3.25.1__tar.gz → 3.26.1__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-3.25.1 → marshmallow-3.26.1}/CHANGELOG.rst +44 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/CONTRIBUTING.rst +3 -3
- {marshmallow-3.25.1 → marshmallow-3.26.1}/PKG-INFO +1 -1
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/custom.css +0 -6
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/conf.py +14 -3
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/custom_fields.rst +2 -2
- marshmallow-3.26.1/docs/examples/index.rst +16 -0
- marshmallow-3.26.1/docs/examples/inflection.rst +19 -0
- marshmallow-3.26.1/docs/examples/quotes_api.rst +96 -0
- marshmallow-3.26.1/docs/examples/validating_package_json.rst +51 -0
- marshmallow-3.26.1/docs/extending/custom_error_handling.rst +28 -0
- marshmallow-3.26.1/docs/extending/custom_error_messages.rst +31 -0
- marshmallow-3.26.1/docs/extending/custom_options.rst +81 -0
- marshmallow-3.26.1/docs/extending/index.rst +16 -0
- marshmallow-3.26.1/docs/extending/overriding_attribute_access.rst +17 -0
- marshmallow-3.26.1/docs/extending/pre_and_post_processing_methods.rst +210 -0
- marshmallow-3.26.1/docs/extending/schema_validation.rst +83 -0
- marshmallow-3.26.1/docs/extending/using_context.rst +20 -0
- marshmallow-3.26.1/docs/extending/using_original_input_data.rst +30 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/index.rst +3 -3
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/install.rst +0 -2
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.schema.rst +1 -1
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/nesting.rst +17 -12
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/quickstart.rst +80 -37
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/top_level.rst +1 -1
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/upgrading.rst +140 -7
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/why.rst +2 -2
- marshmallow-3.26.1/pyproject.toml +134 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/class_registry.py +8 -7
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/decorators.py +15 -10
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/error_store.py +3 -3
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/fields.py +51 -48
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/orderedset.py +1 -1
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/schema.py +181 -89
- marshmallow-3.26.1/src/marshmallow/types.py +40 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/utils.py +11 -13
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/validate.py +32 -18
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/base.py +5 -4
- marshmallow-3.26.1/tests/mypy_test_cases/test_schema.py +29 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_decorators.py +61 -7
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_deserialization.py +25 -20
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_error_store.py +45 -37
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_fields.py +11 -11
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_options.py +16 -2
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_registry.py +13 -13
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_schema.py +33 -33
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_serialization.py +34 -23
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_utils.py +7 -6
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_validate.py +41 -7
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tox.ini +10 -8
- marshmallow-3.25.1/docs/examples.rst +0 -299
- marshmallow-3.25.1/docs/extending.rst +0 -507
- marshmallow-3.25.1/pyproject.toml +0 -97
- marshmallow-3.25.1/src/marshmallow/types.py +0 -16
- {marshmallow-3.25.1 → marshmallow-3.26.1}/LICENSE +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/NOTICE +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/README.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/SECURITY.md +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/.gitignore +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/apple-touch-icon.png +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/favicon.ico +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/marshmallow-logo-200.png +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/marshmallow-logo-with-title-for-dark-theme.png +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/marshmallow-logo-with-title.png +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/_static/marshmallow-logo.png +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/api_reference.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/authors.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/changelog.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/code_of_conduct.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/contributing.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/dashing.json +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/donate.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/kudos.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/license.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.class_registry.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.decorators.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.error_store.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.exceptions.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.fields.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.types.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.utils.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/marshmallow.validate.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/docs/whos_using.rst +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/__init__.py +6 -6
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/base.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/exceptions.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/py.typed +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/src/marshmallow/warnings.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/__init__.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/conftest.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/foo_serializer.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/mypy_test_cases/test_class_registry.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/mypy_test_cases/test_validation_error.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_exceptions.py +0 -0
- {marshmallow-3.25.1 → marshmallow-3.26.1}/tests/test_version_attributes.py +0 -0
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
---------
|
|
3
3
|
|
|
4
|
+
3.26.1 (2025-02-03)
|
|
5
|
+
*******************
|
|
6
|
+
|
|
7
|
+
Bug fixes:
|
|
8
|
+
|
|
9
|
+
- Typing: Fix type annotations for `class Meta <marshmallow.Schema.Meta>` options (:issue:`2804`).
|
|
10
|
+
Thanks :user:`lawrence-law` for reporting.
|
|
11
|
+
|
|
12
|
+
Other changes:
|
|
13
|
+
|
|
14
|
+
- Remove default value for the ``data`` param of `Nested._deserialize <marshmallow.fields.Nested._deserialize>` (:issue:`2802`).
|
|
15
|
+
Thanks :user:`gbenson` for reporting.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
3.26.0 (2025-01-22)
|
|
19
|
+
*******************
|
|
20
|
+
|
|
21
|
+
Features:
|
|
22
|
+
|
|
23
|
+
- Typing: Add type annotations and improved documentation for `class Meta <marshmallow.Schema.Meta>` options (:pr:`2760`).
|
|
24
|
+
- Typing: Improve type coverage of `marshmallow.Schema.SchemaMeta` (:pr:`2761`).
|
|
25
|
+
- Typing: `marshmallow.Schema.loads` parameter allows `bytes` and `bytesarray` (:pr:`2769`).
|
|
26
|
+
|
|
27
|
+
Bug fixes:
|
|
28
|
+
|
|
29
|
+
- Respect ``data_key`` when schema validators raise a `ValidationError <marshmallow.exceptions.ValidationError>`
|
|
30
|
+
with a ``field_name`` argument (:issue:`2170`). Thanks :user:`matejsp` for reporting.
|
|
31
|
+
- Correctly handle multiple `@post_load <marshmallow.post_load>` methods where one method appends to
|
|
32
|
+
the data and another passes ``pass_original=True`` (:issue:`1755`).
|
|
33
|
+
Thanks :user:`ghostwheel42` for reporting.
|
|
34
|
+
- ``URL`` fields now properly validate ``file`` paths (:issue:`2249`).
|
|
35
|
+
Thanks :user:`0xDEC0DE` for reporting and fixing.
|
|
36
|
+
|
|
37
|
+
Documentation:
|
|
38
|
+
|
|
39
|
+
- Add :doc:`upgrading guides <upgrading>` for 3.24 and 3.26 (:pr:`2780`).
|
|
40
|
+
- Various documentation improvements (:pr:`2757`, :pr:`2759`, :pr:`2765`, :pr:`2774`, :pr:`2778`, :pr:`2783`, :pr:`2796`).
|
|
41
|
+
|
|
42
|
+
Deprecations:
|
|
43
|
+
|
|
44
|
+
- The ``ordered`` `class Meta <marshmallow.Schema.Meta>` option is deprecated (:issue:`2146`, :pr:`2762`).
|
|
45
|
+
Field order is already preserved by default. Set `marshmallow.Schema.dict_class` to `collections.OrderedDict`
|
|
46
|
+
to maintain the previous behavior.
|
|
47
|
+
|
|
4
48
|
3.25.1 (2025-01-11)
|
|
5
49
|
*******************
|
|
6
50
|
|
|
@@ -135,13 +135,13 @@ Documentation
|
|
|
135
135
|
|
|
136
136
|
Contributions to the documentation are welcome. Documentation is written in `reStructuredText`_ (rST). A quick rST reference can be found `here <https://docutils.sourceforge.io/docs/user/rst/quickref.html>`_. Builds are powered by Sphinx_.
|
|
137
137
|
|
|
138
|
-
To build the docs in "watch" mode:
|
|
138
|
+
To build and serve the docs in "watch" mode:
|
|
139
139
|
|
|
140
140
|
.. code-block:: shell-session
|
|
141
141
|
|
|
142
|
-
$ tox -e
|
|
142
|
+
$ tox -e docs-serve
|
|
143
143
|
|
|
144
|
-
Changes
|
|
144
|
+
Changes to documentation will automatically trigger a rebuild.
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
.. _contributing_examples:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: marshmallow
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.26.1
|
|
4
4
|
Summary: A lightweight library for converting complex datatypes to and from native Python datatypes.
|
|
5
5
|
Author-email: Steven Loria <sloria1@gmail.com>
|
|
6
6
|
Maintainer-email: Steven Loria <sloria1@gmail.com>, Jérôme Lafréchoux <jerome@jolimont.fr>, Jared Deckard <jared@shademaps.com>
|
|
@@ -10,12 +10,6 @@ h2, h3, h4, h5, h6 {
|
|
|
10
10
|
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
/* Links */
|
|
14
|
-
|
|
15
|
-
a:link, a:visited {
|
|
16
|
-
color: var(--color-link);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
13
|
/* Hide ToC caption text within the main body (but leave them in the side-bar). */
|
|
20
14
|
/* https://github.com/hynek/structlog/blob/b488a8bf589a01aabc41e3bf8df81a9848cd426c/docs/_static/custom.css#L17-L20 */
|
|
21
15
|
#furo-main-content span.caption-text {
|
|
@@ -22,7 +22,7 @@ source_suffix = ".rst"
|
|
|
22
22
|
master_doc = "index"
|
|
23
23
|
|
|
24
24
|
project = "marshmallow"
|
|
25
|
-
copyright = "Steven Loria and contributors"
|
|
25
|
+
copyright = "Steven Loria and contributors" # noqa: A001
|
|
26
26
|
|
|
27
27
|
version = release = importlib.metadata.version("marshmallow")
|
|
28
28
|
|
|
@@ -46,14 +46,25 @@ html_theme_options = {
|
|
|
46
46
|
},
|
|
47
47
|
"top_of_page_buttons": ["view"],
|
|
48
48
|
}
|
|
49
|
+
pygments_dark_style = "lightbulb"
|
|
49
50
|
html_favicon = "_static/favicon.ico"
|
|
50
51
|
html_static_path = ["_static"]
|
|
51
52
|
html_css_files = ["custom.css"]
|
|
52
|
-
|
|
53
|
+
html_copy_source = False # Don't copy source files to _build/sources
|
|
54
|
+
html_show_sourcelink = False # Don't link to source files
|
|
53
55
|
ogp_image = "_static/marshmallow-logo-200.png"
|
|
54
56
|
|
|
55
57
|
# Strip the dollar prompt when copying code
|
|
56
58
|
# https://sphinx-copybutton.readthedocs.io/en/latest/use.html#strip-and-configure-input-prompts-for-code-cells
|
|
57
59
|
copybutton_prompt_text = "$ "
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
autodoc_default_options = {
|
|
62
|
+
"exclude-members": "__new__",
|
|
63
|
+
# Don't show signatures in the summary tables
|
|
64
|
+
"autosummary-nosignatures": True,
|
|
65
|
+
# Don't render summaries for classes within modules
|
|
66
|
+
"autosummary-no-nesting": True,
|
|
67
|
+
}
|
|
68
|
+
# Only display type hints next to params but not within the signature
|
|
69
|
+
# to avoid the signature from getting too long
|
|
70
|
+
autodoc_typehints = "description"
|
|
@@ -169,5 +169,5 @@ Error messages can also be passed to a `Field's` constructor.
|
|
|
169
169
|
Next steps
|
|
170
170
|
----------
|
|
171
171
|
|
|
172
|
-
- Need to add schema-level validation, post-processing, or error handling behavior? See the :doc:`extending` page.
|
|
173
|
-
- For example applications using marshmallow, check out the :doc:`examples` page.
|
|
172
|
+
- Need to add schema-level validation, post-processing, or error handling behavior? See the :doc:`extending/index` page.
|
|
173
|
+
- For example applications using marshmallow, check out the :doc:`examples/index` page.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
********
|
|
2
|
+
Examples
|
|
3
|
+
********
|
|
4
|
+
|
|
5
|
+
The below examples demonstrate how to use marshmallow in various contexts.
|
|
6
|
+
To run each example, you will need to have `uv <https://docs.astral.sh/uv/getting-started/installation/>`_ installed.
|
|
7
|
+
The examples use `PEP 723 inline metadata <https://peps.python.org/pep-0723/>`_
|
|
8
|
+
to declare the dependencies of each script. ``uv`` will install the
|
|
9
|
+
dependencies automatically when running these scripts.
|
|
10
|
+
|
|
11
|
+
.. toctree::
|
|
12
|
+
:maxdepth: 1
|
|
13
|
+
|
|
14
|
+
validating_package_json
|
|
15
|
+
quotes_api
|
|
16
|
+
inflection
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
*****************************
|
|
2
|
+
Inflection (camel-cased keys)
|
|
3
|
+
*****************************
|
|
4
|
+
|
|
5
|
+
HTTP APIs will often use camel-cased keys for their input and output representations. This example shows how you can use the
|
|
6
|
+
`Schema.on_bind_field <marshmallow.Schema.on_bind_field>` hook to automatically inflect keys.
|
|
7
|
+
|
|
8
|
+
.. literalinclude:: ../../examples/inflection_example.py
|
|
9
|
+
:language: python
|
|
10
|
+
|
|
11
|
+
To run the example:
|
|
12
|
+
|
|
13
|
+
.. code-block:: shell-session
|
|
14
|
+
|
|
15
|
+
$ uv run examples/inflection_example.py
|
|
16
|
+
Loaded data:
|
|
17
|
+
{'first_name': 'David', 'last_name': 'Bowie'}
|
|
18
|
+
Dumped data:
|
|
19
|
+
{'firstName': 'David', 'lastName': 'Bowie'}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
*******************************
|
|
2
|
+
Quotes API (Flask + SQLAlchemy)
|
|
3
|
+
*******************************
|
|
4
|
+
|
|
5
|
+
Below is a full example of a REST API for a quotes app using `Flask <http://flask.pocoo.org/>`_ and `SQLAlchemy <https://www.sqlalchemy.org/>`_ with marshmallow. It demonstrates a number of features, including:
|
|
6
|
+
|
|
7
|
+
- Custom validation
|
|
8
|
+
- Nesting fields
|
|
9
|
+
- Using ``dump_only=True`` to specify read-only fields
|
|
10
|
+
- Output filtering using the ``only`` parameter
|
|
11
|
+
- Using `@pre_load <marshmallow.decorators.pre_load>` to preprocess input data.
|
|
12
|
+
|
|
13
|
+
.. literalinclude:: ../../examples/flask_example.py
|
|
14
|
+
:language: python
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
**Using The API**
|
|
18
|
+
|
|
19
|
+
Run the app.
|
|
20
|
+
|
|
21
|
+
.. code-block:: shell-session
|
|
22
|
+
|
|
23
|
+
$ uv run examples/flask_example.py
|
|
24
|
+
|
|
25
|
+
We'll use the `httpie cli <https://httpie.io/cli>`_ to send requests
|
|
26
|
+
Install it with ``uv``.
|
|
27
|
+
|
|
28
|
+
.. code-block:: shell-session
|
|
29
|
+
|
|
30
|
+
$ uv tool install httpie
|
|
31
|
+
|
|
32
|
+
First we'll POST some quotes.
|
|
33
|
+
|
|
34
|
+
.. code-block:: shell-session
|
|
35
|
+
|
|
36
|
+
$ http POST :5000/quotes/ author="Tim Peters" content="Beautiful is better than ugly."
|
|
37
|
+
$ http POST :5000/quotes/ author="Tim Peters" content="Now is better than never."
|
|
38
|
+
$ http POST :5000/quotes/ author="Peter Hintjens" content="Simplicity is always better than functionality."
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
If we provide invalid input data, we get 400 error response. Let's omit "author" from the input data.
|
|
42
|
+
|
|
43
|
+
.. code-block:: shell-session
|
|
44
|
+
|
|
45
|
+
$ http POST :5000/quotes/ content="I have no author"
|
|
46
|
+
{
|
|
47
|
+
"author": [
|
|
48
|
+
"Data not provided."
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Now we can GET a list of all the quotes.
|
|
53
|
+
|
|
54
|
+
.. code-block:: shell-session
|
|
55
|
+
|
|
56
|
+
$ http :5000/quotes/
|
|
57
|
+
{
|
|
58
|
+
"quotes": [
|
|
59
|
+
{
|
|
60
|
+
"content": "Beautiful is better than ugly.",
|
|
61
|
+
"id": 1
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"content": "Now is better than never.",
|
|
65
|
+
"id": 2
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"content": "Simplicity is always better than functionality.",
|
|
69
|
+
"id": 3
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
We can also GET the quotes for a single author.
|
|
75
|
+
|
|
76
|
+
.. code-block:: shell-session
|
|
77
|
+
|
|
78
|
+
$ http :5000/authors/1
|
|
79
|
+
{
|
|
80
|
+
"author": {
|
|
81
|
+
"first": "Tim",
|
|
82
|
+
"formatted_name": "Peters, Tim",
|
|
83
|
+
"id": 1,
|
|
84
|
+
"last": "Peters"
|
|
85
|
+
},
|
|
86
|
+
"quotes": [
|
|
87
|
+
{
|
|
88
|
+
"content": "Beautiful is better than ugly.",
|
|
89
|
+
"id": 1
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"content": "Now is better than never.",
|
|
93
|
+
"id": 2
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
***************************
|
|
2
|
+
Validating ``package.json``
|
|
3
|
+
***************************
|
|
4
|
+
|
|
5
|
+
marshmallow can be used to validate configuration according to a schema.
|
|
6
|
+
Below is a schema that could be used to validate
|
|
7
|
+
``package.json`` files. This example demonstrates the following features:
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
- Validation and deserialization using `Schema.load <marshmallow.Schema.load>`
|
|
11
|
+
- :doc:`Custom fields <../custom_fields>`
|
|
12
|
+
- Specifying deserialization keys using ``data_key``
|
|
13
|
+
- Including unknown keys using ``unknown = INCLUDE``
|
|
14
|
+
|
|
15
|
+
.. literalinclude:: ../../examples/package_json_example.py
|
|
16
|
+
:language: python
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Given the following ``package.json`` file...
|
|
20
|
+
|
|
21
|
+
.. literalinclude:: ../../examples/package.json
|
|
22
|
+
:language: json
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
We can validate it using the above script.
|
|
26
|
+
|
|
27
|
+
.. code-block:: shell-session
|
|
28
|
+
|
|
29
|
+
$ uv run examples/package_json_example.py < examples/package.json
|
|
30
|
+
{'description': 'The Pythonic JavaScript toolkit',
|
|
31
|
+
'dev_dependencies': {'pest': '^23.4.1'},
|
|
32
|
+
'license': 'MIT',
|
|
33
|
+
'main': 'index.js',
|
|
34
|
+
'name': 'dunderscore',
|
|
35
|
+
'scripts': {'test': 'pest'},
|
|
36
|
+
'version': <Version('1.2.3')>}
|
|
37
|
+
|
|
38
|
+
Notice that our custom field deserialized the version string to a ``Version`` object.
|
|
39
|
+
|
|
40
|
+
But if we pass an invalid package.json file...
|
|
41
|
+
|
|
42
|
+
.. literalinclude:: ../../examples/invalid_package.json
|
|
43
|
+
:language: json
|
|
44
|
+
|
|
45
|
+
We see the corresponding error messages.
|
|
46
|
+
|
|
47
|
+
.. code-block:: shell-session
|
|
48
|
+
|
|
49
|
+
$ uv run examples/package_json_example.py < examples/invalid_package.json
|
|
50
|
+
ERROR: package.json is invalid
|
|
51
|
+
{'homepage': ['Not a valid URL.'], 'version': ['Not a valid version.']}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Custom error handling
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
By default, `Schema.load <marshmallow.Schema.load>` will raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>` if passed invalid data.
|
|
5
|
+
|
|
6
|
+
You can specify a custom error-handling function for a :class:`Schema` by overriding the `handle_error <marshmallow.Schema.handle_error>` method. The method receives the :exc:`ValidationError <marshmallow.exceptions.ValidationError>` and the original input data to be deserialized.
|
|
7
|
+
|
|
8
|
+
.. code-block:: python
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
from marshmallow import Schema, fields
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AppError(Exception):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class UserSchema(Schema):
|
|
19
|
+
email = fields.Email()
|
|
20
|
+
|
|
21
|
+
def handle_error(self, exc, data, **kwargs):
|
|
22
|
+
"""Log and raise our custom exception when (de)serialization fails."""
|
|
23
|
+
logging.error(exc.messages)
|
|
24
|
+
raise AppError("An error occurred with input: {0}".format(data))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
schema = UserSchema()
|
|
28
|
+
schema.load({"email": "invalid-email"}) # raises AppError
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Custom error messages
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
To customize the schema-level error messages that `load <marshmallow.Schema.load>` and `loads <marshmallow.Schema.loads>` use when raising a `ValidationError <marshmallow.exceptions.ValidationError>`, override the `error_messages <marshmallow.Schema.error_messages>` class variable:
|
|
5
|
+
|
|
6
|
+
.. code-block:: python
|
|
7
|
+
|
|
8
|
+
class MySchema(Schema):
|
|
9
|
+
error_messages = {
|
|
10
|
+
"unknown": "Custom unknown field error message.",
|
|
11
|
+
"type": "Custom invalid type error message.",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Field-level error message defaults can be set on `Field.default_error_messages <marshmallow.fields.Field.default_error_messages>`.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
.. code-block:: python
|
|
19
|
+
|
|
20
|
+
from marshmallow import Schema, fields
|
|
21
|
+
|
|
22
|
+
fields.Field.default_error_messages["required"] = "You missed something!"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ArtistSchema(Schema):
|
|
26
|
+
name = fields.Str(required=True)
|
|
27
|
+
label = fields.Str(required=True, error_messages={"required": "Label missing."})
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
print(ArtistSchema().validate({}))
|
|
31
|
+
# {'label': ['Label missing.'], 'name': ['You missed something!']}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Custom `class Meta <marshmallow.Schema.Meta>` options
|
|
2
|
+
=====================================================
|
|
3
|
+
|
|
4
|
+
`class Meta <marshmallow.Schema.Meta>` options are a way to configure and modify a `Schema's <Schema>` behavior. See `marshmallow.Schema.Meta` for a listing of available options.
|
|
5
|
+
|
|
6
|
+
You can add custom `class Meta <marshmallow.Schema.Meta>` options by subclassing `marshmallow.SchemaOpts`.
|
|
7
|
+
|
|
8
|
+
Example: Enveloping, revisited
|
|
9
|
+
------------------------------
|
|
10
|
+
|
|
11
|
+
Let's build upon the :ref:`previous enveloping implementation <enveloping_1>` above for adding an envelope to serialized output.
|
|
12
|
+
This time, we will allow the envelope key to be customizable with `class Meta <marshmallow.Schema.Meta>` options.
|
|
13
|
+
|
|
14
|
+
::
|
|
15
|
+
|
|
16
|
+
# Example outputs
|
|
17
|
+
{
|
|
18
|
+
'user': {
|
|
19
|
+
'name': 'Keith',
|
|
20
|
+
'email': 'keith@stones.com'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
# List output
|
|
24
|
+
{
|
|
25
|
+
'users': [{'name': 'Keith'}, {'name': 'Mick'}]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
First, we'll add our namespace configuration to a custom options class.
|
|
30
|
+
|
|
31
|
+
.. code-block:: python
|
|
32
|
+
|
|
33
|
+
from marshmallow import Schema, SchemaOpts
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class NamespaceOpts(SchemaOpts):
|
|
37
|
+
"""Same as the default class Meta options, but adds "name" and
|
|
38
|
+
"plural_name" options for enveloping.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, meta, **kwargs):
|
|
42
|
+
SchemaOpts.__init__(self, meta, **kwargs)
|
|
43
|
+
self.name = getattr(meta, "name", None)
|
|
44
|
+
self.plural_name = getattr(meta, "plural_name", self.name)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
Then we create a custom :class:`Schema` that uses our options class.
|
|
48
|
+
|
|
49
|
+
.. code-block:: python
|
|
50
|
+
|
|
51
|
+
class NamespacedSchema(Schema):
|
|
52
|
+
OPTIONS_CLASS = NamespaceOpts
|
|
53
|
+
|
|
54
|
+
@pre_load(pass_many=True)
|
|
55
|
+
def unwrap_envelope(self, data, many, **kwargs):
|
|
56
|
+
key = self.opts.plural_name if many else self.opts.name
|
|
57
|
+
return data[key]
|
|
58
|
+
|
|
59
|
+
@post_dump(pass_many=True)
|
|
60
|
+
def wrap_with_envelope(self, data, many, **kwargs):
|
|
61
|
+
key = self.opts.plural_name if many else self.opts.name
|
|
62
|
+
return {key: data}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Our application schemas can now inherit from our custom schema class.
|
|
66
|
+
|
|
67
|
+
.. code-block:: python
|
|
68
|
+
|
|
69
|
+
class UserSchema(NamespacedSchema):
|
|
70
|
+
name = fields.String()
|
|
71
|
+
email = fields.Email()
|
|
72
|
+
|
|
73
|
+
class Meta:
|
|
74
|
+
name = "user"
|
|
75
|
+
plural_name = "users"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
ser = UserSchema()
|
|
79
|
+
user = User("Keith", email="keith@stones.com")
|
|
80
|
+
result = ser.dump(user)
|
|
81
|
+
result # {"user": {"name": "Keith", "email": "keith@stones.com"}}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Extending schemas
|
|
2
|
+
=================
|
|
3
|
+
|
|
4
|
+
The guides below demonstrate how to extend schemas in various ways.
|
|
5
|
+
|
|
6
|
+
.. toctree::
|
|
7
|
+
:maxdepth: 1
|
|
8
|
+
|
|
9
|
+
pre_and_post_processing_methods
|
|
10
|
+
schema_validation
|
|
11
|
+
using_original_input_data
|
|
12
|
+
overriding_attribute_access
|
|
13
|
+
custom_error_handling
|
|
14
|
+
custom_options
|
|
15
|
+
using_context
|
|
16
|
+
custom_error_messages
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Overriding how attributes are accessed
|
|
2
|
+
======================================
|
|
3
|
+
|
|
4
|
+
By default, marshmallow uses `utils.get_value <marshmallow.utils.get_value>` to pull attributes from various types of objects for serialization. This will work for *most* use cases.
|
|
5
|
+
|
|
6
|
+
However, if you want to specify how values are accessed from an object, you can override the :meth:`get_attribute <marshmallow.Schema.get_attribute>` method.
|
|
7
|
+
|
|
8
|
+
.. code-block:: python
|
|
9
|
+
|
|
10
|
+
class UserDictSchema(Schema):
|
|
11
|
+
name = fields.Str()
|
|
12
|
+
email = fields.Email()
|
|
13
|
+
|
|
14
|
+
# If we know we're only serializing dictionaries, we can
|
|
15
|
+
# use dict.get for all input objects
|
|
16
|
+
def get_attribute(self, obj, key, default):
|
|
17
|
+
return obj.get(key, default)
|