[
  {
    "path": ".github/FUNDING.yml",
    "content": "open_collective: \"marshmallow\"\ntidelift: \"pypi/marshmallow\"\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: pip\n  directory: \"/\"\n  schedule:\n    interval: daily\n  open-pull-requests-limit: 10\n- package-ecosystem: \"github-actions\"\n  directory: \"/\"\n  schedule:\n    interval: \"monthly\"\n"
  },
  {
    "path": ".github/workflows/build-release.yml",
    "content": "name: build\non:\n  push:\n    branches: [\"dev\", \"*.x-line\"]\n    tags: [\"*\"]\n  pull_request:\n\njobs:\n  docs:\n    name: docs\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - run: pip install tox\n      - run: tox -e docs\n  tests:\n    name: ${{ matrix.name }}\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - { name: \"3.10\", python: \"3.10\", tox: py310 }\n          - { name: \"3.14\", python: \"3.14\", tox: py314 }\n          - { name: \"mypy\", python: \"3.13\", tox: mypy }\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-python@v6\n        with:\n          python-version: ${{ matrix.python }}\n          allow-prereleases: true\n      - run: python -m pip install tox\n      - run: python -m tox -e ${{ matrix.tox }}\n  build:\n    name: Build package\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - name: Install pypa/build\n        run: python -m pip install build\n      - name: Build a binary wheel and a source tarball\n        run: python -m build\n      - name: Install twine\n        run: python -m pip install twine\n      - name: Check build\n        run: python -m twine check --strict dist/*\n      - name: Store the distribution packages\n        uses: actions/upload-artifact@v7\n        with:\n          name: python-package-distributions\n          path: dist/\n  # this duplicates pre-commit.ci, so only run it on tags\n  # it guarantees that linting is passing prior to a release\n  lint-pre-release:\n    if: startsWith(github.ref, 'refs/tags')\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - run: python -m pip install tox\n      - run: python -m tox -e lint\n  publish-to-pypi:\n    name: PyPI release\n    if: startsWith(github.ref, 'refs/tags/')\n    needs: [build, tests, lint-pre-release]\n    runs-on: ubuntu-latest\n    environment:\n      name: pypi\n      url: https://pypi.org/p/marshmallow\n    permissions:\n      id-token: write\n    steps:\n      - name: Download all the dists\n        uses: actions/download-artifact@v8\n        with:\n          name: python-package-distributions\n          path: dist/\n      - name: Publish distribution to PyPI\n        uses: pypa/gh-action-pypi-publish@release/v1\n"
  },
  {
    "path": ".gitignore",
    "content": "*.py[cod]\n\n# C extensions\n*.so\n\n# Packages\n*.egg\n*.egg-info\ndist\nbuild\neggs\nparts\nbin\nvar\nsdist\ndevelop-eggs\n.installed.cfg\nlib\nlib64\npip-wheel-metadata\n\n# Installer logs\npip-log.txt\n\n# Unit test / coverage reports\n.coverage\nhtmlcov\n.tox\nnosetests.xml\n.cache\n.pytest_cache\n\n# Translations\n*.mo\n\n# Mr Developer\n.mr.developer.cfg\n\n# IDE\n.project\n.pydevproject\n.idea\n\n# Coverage\ncover\n.coveragerc\n\n# Sphinx\ndocs/_build\nREADME.html\n\n*.ipynb\n.ipynb_checkpoints\n\nVagrantfile\n.vagrant\n\n*.db\n*.ai\n.konchrc\n_sandbox\npylintrc\n\n# Virtualenvs\nenv\nvenv\n\n# pyenv\n.python-version\n\n# pytest\n.pytest_cache\n\n# Other\n.directory\n*.pprof\n\n# mypy\n.mypy_cache/\n.dmypy.json\ndmypy.json\n\n# ruff\n.ruff_cache\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "ci:\n  autoupdate_schedule: monthly\nrepos:\n- repo: https://github.com/astral-sh/ruff-pre-commit\n  rev: v0.15.4\n  hooks:\n    - id: ruff-check\n    - id: ruff-format\n- repo: https://github.com/python-jsonschema/check-jsonschema\n  rev: 0.37.0\n  hooks:\n    - id: check-github-workflows\n    - id: check-readthedocs\n# TODO: Remove blacken-docs when https://github.com/astral-sh/ruff/issues/8237 is implemented\n- repo: https://github.com/asottile/blacken-docs\n  rev: 1.20.0\n  hooks:\n  - id: blacken-docs\n    additional_dependencies: [black==25.1.0]\n"
  },
  {
    "path": ".readthedocs.yml",
    "content": "version: 2\nsphinx:\n  configuration: docs/conf.py\nformats:\n  - pdf\nbuild:\n  os: ubuntu-22.04\n  tools:\n    python: \"3.13\"\npython:\n  install:\n    - method: pip\n      path: .\n      extra_requirements:\n        - docs\n"
  },
  {
    "path": "AUTHORS.rst",
    "content": "*******\nAuthors\n*******\n\nLeads\n=====\n\n- Steven Loria `@sloria <https://github.com/sloria>`_\n- Jérôme Lafréchoux  `@lafrech <https://github.com/lafrech>`_\n- Jared Deckard `@deckar01 <https://github.com/deckar01>`_\n\nContributors (chronological)\n============================\n\n- Sebastian Vetter `@elbaschid <https://github.com/elbaschid>`_\n- Eduard Carreras `@ecarreras <https://github.com/ecarreras>`_\n- Joakim Ekberg `@kalasjocke <https://github.com/kalasjocke>`_\n- Mark Grey `@DeaconDesperado <https://github.com/DeaconDesperado>`_\n- Anders Steinlein `@asteinlein <https://github.com/asteinlein>`_\n- Cyril Thomas `@Ketouem <https://github.com/Ketouem>`_\n- Austin Macdonald `@asmacdo <https://github.com/asmacdo>`_\n- Josh Carp `@jmcarp <https://github.com/jmcarp>`_\n- `@amikholap <https://github.com/amikholap>`_\n- Sven-Hendrik Haase `@svenstaro <https://github.com/svenstaro>`_\n- Eric Wang `@ewang <https://github.com/ewang>`_\n- `@philtay <https://github.com/philtay>`_\n- `@malexer <https://github.com/malexer>`_\n- Andriy Yurchuk `@Ch00k <https://github.com/Ch00k>`_\n- Vesa Uimonen `@vesauimonen <https://github.com/vesauimonen>`_\n- David Lord `@davidism <https://github.com/davidism>`_\n- Daniel Castro `@0xDCA <https://github.com/0xDCA>`_\n- Ben Jones `@RealSalmon <https://github.com/RealSalmon>`_\n- Patrick Woods `@hakjoon <https://github.com/hakjoon>`_\n- Lukas Heiniger `@3rdcycle <https://github.com/3rdcycle>`_\n- Ryan Lowe `@ryanlowe0 <https://github.com/ryanlowe0>`_\n- Jimmy Jia `@taion <https://github.com/taion>`_\n- `@lustdante <https://github.com/lustdante>`_\n- Sergey Aganezov, Jr. `@sergey-aganezov-jr <https://github.com/sergey-aganezov-jr>`_\n- Kevin Stone `@kevinastone <https://github.com/kevinastone>`_\n- Alex Morken `@alexmorken <https://github.com/alexmorken>`_\n- Sergey Polzunov `@traut <https://github.com/traut>`_\n- Kelvin Hammond `@kelvinhammond <https://github.com/kelvinhammond>`_\n- Matt Stobo `@mwstobo <https://github.com/mwstobo>`_\n- Max Orhai `@max-orhai <https://github.com/max-orhai>`_\n- Praveen `@praveen-p <https://github.com/praveen-p>`_\n- Stas Sușcov `@stas <https://github.com/stas>`_\n- Florian `@floqqi <https://github.com/floqqi>`_\n- Evgeny Sureev `@evgeny-sureev <https://github.com/evgeny-sureev>`_\n- Matt Bachmann `@Bachmann1234 <https://github.com/Bachmann1234>`_\n- Daniel Imhoff `@dwieeb <https://github.com/dwieeb>`_\n- Juan Rossi `@juanrossi <https://github.com/juanrossi>`_\n- Andrew Haigh `@nelfin <https://github.com/nelfin>`_\n- `@Mise <https://github.com/Mise>`_\n- Taylor Edmiston `@tedmiston <https://github.com/tedmiston>`_\n- Francisco Demartino `@franciscod <https://github.com/franciscod>`_\n- Eric Wang `@ewang <https://github.com/ewang>`_\n- Eugene Prikazchikov `@eprikazc <https://github.com/eprikazc>`_\n- Damian Heard `@DamianHeard <https://github.com/DamianHeard>`_\n- Alec Reiter `@justanr <https://github.com/justanr>`_\n- Dan Sutherland `@d-sutherland <https://github.com/d-sutherland>`_\n- Jeff Widman `@jeffwidman <https://github.com/jeffwidman>`_\n- Simeon Visser `@svisser <https://github.com/svisser>`_\n- Taylan Develioglu `@tdevelioglu <https://github.com/tdevelioglu>`_\n- Danilo Akamine `@daniloakamine <https://github.com/daniloakamine>`_\n- Maxim Kulkin `@maximkulkin <https://github.com/maximkulkin>`_\n- `@immerrr <https://github.com/immerrr>`_\n- Mike Yumatov `@yumike <https://github.com/yumike>`_\n- Tim Mundt `@Tim-Erwin <https://github.com/Tim-Erwin>`_\n- Russell Davies `@russelldavies <https://github.com/russelldavies>`_\n- Jared Deckard `@deckar01 <https://github.com/deckar01>`_\n- David Thornton `@davidthornton <https://github.com/davidthornton>`_\n- Vuong Hoang `@vuonghv <https://github.com/vuonghv>`_\n- David Bertouille `@dbertouille <https://github.com/dbertouille>`_\n- Alexandre Bonnetain `@Shir0kamii <https://github.com/Shir0kamii>`_\n- Tuukka Mustonen `@tuukkamustonen <https://github.com/tuukkamustonen>`_\n- Tero Vuotila `@tvuotila <https://github.com/tvuotila>`_\n- Paul Zumbrun `@pauljz <https://github.com/pauljz>`_\n- Gary Wilson Jr. `@gdub <https://github.com/gdub>`_\n- Sabine Maennel `@sabinem <https://github.com/sabinem>`_\n- Victor Varvaryuk `@mindojo-victor <https://github.com/mindojo-victor>`_\n- Jāzeps Baško `@jbasko <https://github.com/jbasko>`_\n- `@podhmo <https://github.com/podhmo>`_\n- Dmitry Orlov `@mosquito <https://github.com/mosquito>`_\n- Yuri Heupa `@YuriHeupa <https://github.com/YuriHeupa>`_\n- Roy Williams `@rowillia <https://github.com/rowillia>`_\n- Vlad Frolov `@frol <https://github.com/frol>`_\n- Erling Børresen `@erlingbo <https://github.com/erlingbo>`_\n- Jérôme Lafréchoux  `@lafrech <https://github.com/lafrech>`_\n- Roy Williams `@rowillia <https://github.com/rowillia>`_\n- `@dradetsky <https://github.com/dradetsky>`_\n- Michal Kononenko `@MichalKononenko <https://github.com/MichalKononenko>`_\n- Yoichi NAKAYAMA `@yoichi <https://github.com/yoichi>`_\n- Bernhard M. Wiedemann `@bmwiedemann <https://github.com/bmwiedemann>`_\n- Scott Werner `@scottwernervt <https://github.com/scottwernervt>`_\n- Leonardo Fedalto `@Fedalto <https://github.com/Fedalto>`_\n- `@sduthil <https://github.com/sduthil>`_\n- Steven Sklar `@sklarsa <https://github.com/sklarsa>`_\n- Alisson Silveira `@4lissonsilveira <https://github.com/4lissonsilveira>`_\n- Harlov Nikita `@harlov <https://github.com/harlov>`_\n- `@stj <https://github.com/stj>`_\n- Tomasz Magulski `@magul <https://github.com/magul>`_\n- Suren Khorenyan `@mahenzon <https://github.com/mahenzon>`_\n- Jeffrey Berger `@JeffBerger <https://github.com/JeffBerger>`_\n- Felix Yan `@felixonmars <https://github.com/felixonmars>`_\n- Prasanjit Prakash `@ikilledthecat <https://github.com/ikilledthecat>`_\n- Guillaume Gelin `@ramnes <https://github.com/ramnes>`_\n- Maxim Novikov `@m-novikov <https://github.com/m-novikov>`_\n- James Remeika `@remeika <https://github.com/remeika>`_\n- Karandeep Singh Nagra `@knagra <https://github.com/knagra>`_\n- Dushyant Rijhwani `@dushr <https://github.com/dushr>`_\n- Viktor Kerkez `@alefnula <https://github.com/alefnula>`_\n- Victor Gavro `@vgavro <https://github.com/vgavro>`_\n- Kamil Gałuszka `@galuszkak <https://github.com/galuszkak>`_\n- David Watson `@arbor-dwatson <https://github.com/arbor-dwatson>`_\n- Jan Margeta `@jmargeta <https://github.com/jmargeta>`_\n- AlexV `@asmodehn <https://github.com/asmodehn>`_\n- `@toffan <https://github.com/toffan>`_\n- Hampus Dunström `@Dunstrom <https://github.com/Dunstrom>`_\n- Robert Jensen `@r1b <https://github.com/r1b>`_\n- Arijit Basu `@sayanarijit <https://github.com/sayanarijit>`_\n- Sanjay P `@snjypl <https://github.com/snjypl>`_\n- Víctor Zabalza `@zblz <https://github.com/zblz>`_\n- Riley Gibbs `@rileyjohngibbs <https://github.com/rileyjohngibbs>`_\n- Henry Doupe `@hdoupe <https://github.com/hdoupe>`_\n- `@miniscruff <https://github.com/miniscruff>`_\n- `@maxalbert <https://github.com/maxalbert>`_\n- Kim Gustyr `@khvn26 <https://github.com/khvn26>`_\n- Bryce Drennan `@brycedrennan <https://github.com/brycedrennan>`_\n- Tim Shaffer `@timster <https://github.com/timster>`_\n- Hugo van Kemenade `@hugovk <https://github.com/hugovk>`_\n- Maciej Urbański `@rooterkyberian <https://github.com/rooterkyberian>`_\n- Kostas Konstantopoulos `@kdop <https://github.com/kdop>`_\n- Stephen J. Fuhry `@fuhrysteve <https://github.com/fuhrysteve>`_\n- `@dursk <https://github.com/dursk>`_\n- Ezra MacDonald `@macdonaldezra <https://github.com/macdonaldezra>`_\n- Stanislav Rogovskiy `@atmo <https://github.com/atmo>`_\n- Cristi Scoarta `@cristi23 <https://github.com/cristi23>`_\n- Anthony Sottile `@asottile <https://github.com/asottile>`_\n- Charles-Axel Dein `@charlax <https://github.com/charlax>`_\n- `@phrfpeixoto <https://github.com/phrfpeixoto>`_\n- `@jceresini <https://github.com/jceresini>`_\n- Nikolay Shebanov `@killthekitten <https://github.com/killthekitten>`_\n- Taneli Hukkinen `@hukkinj1 <https://github.com/hukkinj1>`_\n- `@Reskov <https://github.com/Reskov>`_\n- Albert Tugushev `@atugushev <https://github.com/atugushev>`_\n- `@dfirst <https://github.com/dfirst>`_\n- Tim Gates `@timgates42 <https://github.com/timgates42>`_\n- Nathan `@nbanmp <https://github.com/nbanmp>`_\n- Ronan Murphy `@Resinderate <https://github.com/Resinderate>`_\n- Laurie Opperman `@EpicWink <https://github.com/EpicWink>`_\n- Ram Rachum `@cool-RR <https://github.com/cool-RR>`_\n- `@weeix <https://github.com/weeix>`_\n- Juan Norris `@juannorris <https://github.com/juannorris>`_\n- 장준영 `@jun0jang <https://github.com/jun0jang>`_\n- `@ebargtuo <https://github.com/ebargtuo>`_\n- Michał Getka `@mgetka <https://github.com/mgetka>`_\n- Nadège Michel `@nadege <https://github.com/nadege>`_\n- Tamara `@infinityxxx <https://github.com/infinityxxx>`_\n- Stephen Rosen `@sirosen <https://github.com/sirosen>`_\n- Vladimir Mikhaylov `@vemikhaylov <https://github.com/vemikhaylov>`_\n- Stephen Eaton `@madeinoz67 <https://github.com/madeinoz67>`_\n- Antonio Lassandro `@lassandroan <https://github.com/lassandroan>`_\n- Javier Fernández `@jfernandz <https://github.com/jfernandz>`_\n- Michael Dimchuk  `@michaeldimchuk <https://github.com/michaeldimchuk>`_\n- Jochen Kupperschmidt  `@homeworkprod <https://github.com/homeworkprod>`_\n- `@yourun-proger <https://github.com/yourun-proger>`_\n- Ryan Morehart `@traherom <https://github.com/traherom>`_\n- Ben Windsor `@bwindsor <https://github.com/bwindsor>`_\n- Kevin Kirsche `@kkirsche <https://github.com/kkirsche>`_\n- Isira Seneviratne `@Isira-Seneviratne <https://github.com/Isira-Seneviratne>`_\n- Karthikeyan Singaravelan `@tirkarthi  <https://github.com/tirkarthi>`_\n- Marco Satti `@marcosatti  <https://github.com/marcosatti>`_\n- Ivo Reumkens `@vanHoi <https://github.com/vanHoi>`_\n- Aditya Tewary `@aditkumar72 <https://github.com/aditkumar72>`_\n- Sebastien Lovergne `@TheBigRoomXXL <https://github.com/TheBigRoomXXL>`_\n- Peter C `@somethingnew2-0 <https://github.com/somethingnew2-0>`_\n- Marcel Jackwerth `@mrcljx` <https://github.com/mrcljx>`_\n- Fares Abubaker `@Fares-Abubaker <https://github.com/Fares-Abubaker>`_\n- Dharanikumar Sekar `@dharani7998 <https://github.com/dharani7998>`_\n- Nicolas Simonds `@0xDEC0DE <https://github.com/0xDEC0DE>`_\n- Florian Laport `@Florian-Laport <https://github.com/Florian-Laport>`_\n- `@agentgodzilla <https://github.com/agentgodzilla>`_\n- Xiao `@T90REAL <https://github.com/T90REAL>`_\n- jfo `@jafournier <https://github.com/jafournier>`_\n- thanhlecongg `@thanhlecongg <https://github.com/thanhlecongg>`_\n- Emmanuel Ferdman  `@emmanuel-ferdman  <https://github.com/emmanuel-ferdman>`_\n"
  },
  {
    "path": "CHANGELOG.rst",
    "content": "Changelog\n=========\n\n4.2.2 (2026-02-04)\n------------------\n\nBug fixes:\n\n- Fix behavior of ``fields.Contant(None)`` (:issue:`2868`).\n  Thanks :user:`T90REAL` for reporting and `emmanuel-ferdman` for the fix.\n\n\n4.2.1 (2026-01-23)\n------------------\n\nBug fixes:\n\n- Fix validation of URLs beginning with uppercare `FILE` (:issue:`2891`).\n  Thanks :user:`thanhlecongg` for reporting and fixing.\n\n4.2.0 (2026-01-04)\n------------------\n\nOther changes:\n\n- ``many`` argument of ``Nested`` properly overrides schema instance\n  value (:pr:`2854`). Thanks :user:`jafournier` for the PR.\n\n4.1.2 (2025-12-19)\n------------------\n\nBug fixes:\n\n- :cve:`2025-68480`: Merge error store messages without rebuilding collections.\n  Thanks 카푸치노 for reporting and :user:`deckar01` for the fix.\n\n4.1.1 (2025-11-05)\n------------------\n\nBug fixes:\n\n- Ensure ``URL`` validator is case-insensitive when using custom schemes (:pr:`2874`).\n  Thanks :user:`T90REAL` for the PR.\n\n4.1.0 (2025-11-01)\n------------------\n\nOther changes:\n\n- Add `__len__` implementation to `missing` so that it can be used with\n  `validate.Length <marshmallow.validate.Length>` (:pr:`2861`).\n  Thanks :user:`agentgodzilla` for the PR.\n- Drop support for Python 3.9 (:pr:`2363`).\n- Test against Python 3.14 (:pr:`2864`).\n\n4.0.1 (2025-08-28)\n------------------\n\nBug fixes:\n\n- Fix wildcard import of ``from marshmallow import *`` (:pr:`2823`).\n  Thanks :user:`Florian-Laport` for the PR.\n\n\n4.0.0 (2025-04-16)\n------------------\n\nSee :ref:`upgrading_4_0` for a guide on updating your code.\n\nFeatures:\n\n- Typing: Add types to all `Field <marshmallow.fields.Field>` constructor kwargs (:issue:`2285`).\n  Thanks :user:`navignaw` for the suggestion.\n- `DateTime <marshmallow.fields.DateTime>`, `Date <marshmallow.fields.Date>`, `Time <marshmallow.fields.Time>`,\n  `TimeDelta <marshmallow.fields.TimeDelta>`, and `Enum <marshmallow.fields.Enum>`\n  accept their internal value types as valid input (:issue:`1415`).\n  Thanks :user:`bitdancer` for the suggestion.\n- `@validates <marshmallow.validates>` accepts multiple field names (:issue:`1960`).\n  *Backwards-incompatible*: Decorated methods now receive ``data_key`` as a keyword argument.\n  Thanks :user:`dpriskorn` for the suggestion and :user:`dharani7998` for the PR.\n\nOther changes:\n\n- Typing: `Field <marshmallow.fields.Field>` is now a generic type with a type argument for the internal value type.\n- `marshmallow.fields.UUID` no longer subclasses `marshmallow.fields.String`.\n- `marshmallow.Schema.load` no longer silently fails to call schema validators when a generator is passed (:issue:`1898`).\n  The typing of `data` is also updated to be more accurate.\n  Thanks :user:`ziplokk1` for reporting.\n- *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`).\nAs a consequence of this change:\n  - Time with time offsets are now supported.\n  - YYYY-MM-DD is now accepted as a datetime and deserialized as naive 00:00 AM.\n  - `from_iso_date`, `from_iso_time` and `from_iso_datetime` are removed from `marshmallow.utils`.\n- Remove `isoformat`, `to_iso_time` and `to_iso_datetime` from `marshmallow.utils` (:pr:`2766`).\n- Remove `from_rfc`, and `rfcformat` from `marshmallow.utils` (:pr:`2767`).\n- Remove `is_keyed_tuple` from `marshmallow.utils` (:pr:`2768`).\n- Remove `get_fixed_timezone` from `marshmallow.utils` (:pr:`2773`).\n\n- *Backwards-incompatible*: `marshmallow.fields.Boolean` no longer serializes non-boolean values (:pr:`2725`).\n- *Backwards-incompatible*: Rename ``schema`` parameter to ``parent`` in `marshmallow.fields.Field._bind_to_schema` (:issue:`1360`).\n- *Backwards-incompatible*: Rename ``pass_many`` parameter to ``pass_collection`` in pre/post processing methods (:issue:`1369`).\n- *Backwards-incompatible*: `marshmallow.fields.TimeDelta` no longer truncates float values when\n  deserializing (:pr:`2654`). This allows microseconds to be preserved, e.g.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n    field = fields.TimeDelta()\n\n    # Before\n    field.deserialize(12.9)\n    datetime.timedelta(seconds=12)\n    # datetime.timedelta(seconds=12)\n\n    # After\n    field.deserialize(12.9)\n    # datetime.timedelta(seconds=12, microseconds=900000)\n\n- Improve performance and minimize float precision loss of `marshmallow.fields.TimeDelta` serialization (:pr:`2654`).\n- *Backwards-incompatible*: Remove ``serialization_type`` parameter from\n  `marshmallow.fields.TimeDelta` (:pr:`2654`).\n\nThanks :user:`ddelange` for the PR.\n\n- *Backwards-incompatible*: Remove `Schema <marshmallow.schema.Schema>`'s ``context`` attribute (deprecated since 3.24.0). Passing a context\n  should be done using `contextvars.ContextVar` (:issue:`1826`).\n  marshmallow 4 provides an experimental `Context <marshmallow.experimental.context.Context>`\n  manager class that can be used to both set and retrieve context.\n\n.. code-block:: python\n\n    import typing\n\n    from marshmallow import Schema, fields\n    from marshmallow.experimental.context import Context\n\n\n    class UserContext(typing.TypedDict):\n        suffix: str\n\n\n    class UserSchema(Schema):\n        name_suffixed = fields.Function(\n            lambda obj: obj[\"name\"] + Context[UserContext].get()[\"suffix\"]\n        )\n\n\n    with Context[UserContext]({\"suffix\": \"bar\"}):\n        UserSchema().dump({\"name\": \"foo\"})\n        # {'name_suffixed': 'foobar'}\n\n- Methods decorated with `marshmallow.pre_load`, `marshmallow.post_load`, `marshmallow.validates_schema`,\n  receive ``unknown`` as a keyword argument (:pr:`1632`).\n  Thanks :user:`jforand` for the PR.\n- *Backwards-incompatible*: Arguments to `decorators <marshmallow.decorators>` are keyword-only arguments.\n- *Backwards-incompatible*: Rename ``json_data`` parameter of `marshmallow.Schema.loads` to ``s``\n  for compatibility with most render module implementations (`json`, ``simplejson``, etc.) (:pr:`2764`).\n  Also make it a positional-only argument.\n- Incorrectly declaring a field using a field class rather than instance\n  errors at class declaration time (previously happended when the schema was instantiated) (:pr:`2772`).\n- Passing invalid values for ``unknown`` will cause an error in type checkers (:pr:`2771`).\n\nDeprecations/Removals:\n\n- *Backwards-incompatible*: Remove implicit field creation, i.e. using the ``fields`` or ``additional`` class Meta options with undeclared fields (:issue:`1356`).\n- The `ordered` class Meta option is removed  (:issue:`2146`). Field order is already preserved by default.\n  Set `Schema.dict_class` to `OrderedDict` to maintain the previous behavior.\n- The `marshmallow.base` module is removed (:pr:`2722`).\n\nPreviously-deprecated APIs have been removed, including:\n\n- The ``ordered`` `class Meta <marshmallow.Schema.Meta>` option is removed  (:issue:`2146`) (deprecated in 3.26.0).\n- *Backwards-incompatible*: `marshmallow.fields.Number` is no longer usable as a field in a schema (deprecated in 3.24.0).\n  Use `marshmallow.fields.Integer`, `marshmallow.fields.Float`, or `marshmallow.fields.Decimal` instead.\n- *Backwards-incompatible*: `marshmallow.fields.Mapping` is no longer usable as a field in a schema (deprecated in 3.24.0).\n- *Backwards-incompatible*: Custom validators must raise a `ValidationError <marshmallow.exceptions.ValidationError>` for invalid values (deprecated in 3.24.0).\n  Returning `False` is no longer supported (:issue:`1775`).\n  Use `marshmallow.fields.Dict` instead.\n- Remove ``__version__``, ``__parsed_version__``, and ``__version_info__`` attributes (deprecated in 3.21.0).\n- `default` and `missing` parameters, which were replaced by `dump_default` and `load_default` in 3.13.0 (:pr:`1742`, :pr:`2700`).\n- Passing field metadata via keyword arguments (deprecated in 3.10.0). Use the explicit ``metadata=...``\n  argument instead (:issue:`1350`).\n- `marshmallow.utils.pprint` (deprecated in 3.7.0). Use `pprint.pprint` instead.\n- Passing `\"self\"` to `fields.Nested` (deprecated in 3.3.0). Use a callable instead.\n- ``Field.fail``, which was replaced by ``Field.make_error`` in 3.0.0.\n- `json_module` class Meta option (deprecated in 3.0.0b3). Use `render_module` instead.\n\n3.26.2 (2025-12-19)\n-------------------\n\nBug fixes:\n\n- :cve:`2025-68480`: Merge error store messages without rebuilding collections.\n  Thanks 카푸치노 for reporting and :user:`deckar01` for the fix.\n\n3.26.1 (2025-02-03)\n-------------------\n\nBug fixes:\n\n- Typing: Fix type annotations for `class Meta <marshmallow.Schema.Meta>` options (:issue:`2804`).\n  Thanks :user:`lawrence-law` for reporting.\n\nOther changes:\n\n- Remove default value for the ``data`` param of `Nested._deserialize <marshmallow.fields.Nested._deserialize>` (:issue:`2802`).\n  Thanks :user:`gbenson` for reporting.\n\n\n3.26.0 (2025-01-22)\n-------------------\n\nFeatures:\n\n- Typing: Add type annotations and improved documentation for `class Meta <marshmallow.Schema.Meta>` options (:pr:`2760`).\n- Typing: Improve type coverage of `marshmallow.Schema.SchemaMeta` (:pr:`2761`).\n- Typing: `marshmallow.Schema.loads` parameter allows `bytes` and `bytesarray` (:pr:`2769`).\n\nBug fixes:\n\n- Respect ``data_key`` when schema validators raise a `ValidationError <marshmallow.exceptions.ValidationError>`\n  with a ``field_name`` argument (:issue:`2170`). Thanks :user:`matejsp` for reporting.\n- Correctly handle multiple `@post_load <marshmallow.post_load>` methods where one method appends to\n  the data and another passes ``pass_original=True`` (:issue:`1755`).\n  Thanks :user:`ghostwheel42` for reporting.\n- ``URL`` fields now properly validate ``file`` paths (:issue:`2249`).\n  Thanks :user:`0xDEC0DE` for reporting and fixing.\n\nDocumentation:\n\n- Add :doc:`upgrading guides <upgrading>` for 3.24 and 3.26 (:pr:`2780`).\n- Various documentation improvements (:pr:`2757`, :pr:`2759`, :pr:`2765`, :pr:`2774`, :pr:`2778`, :pr:`2783`, :pr:`2796`).\n\nDeprecations:\n\n- The ``ordered`` `class Meta <marshmallow.Schema.Meta>` option is deprecated (:issue:`2146`, :pr:`2762`).\n  Field order is already preserved by default. Set `marshmallow.Schema.dict_class` to `collections.OrderedDict`\n  to maintain the previous behavior.\n\n3.25.1 (2025-01-11)\n-------------------\n\nBug fixes:\n\n- Typing: Fix type annotations for `Tuple <marshmallow.fields.Tuple>`,\n  `Boolean <marshmallow.fields.Boolean>`, and `Pluck <marshmallow.fields.Pluck>`\n  constructors (:pr:`2756`).\n- Typing: Fix overload for `marshmallow.class_registry.get_class` (:pr:`2756`).\n\nDocumentation:\n\n- Various documentation improvements (:pr:`2746`, :pr:`2747`, :pr:`2748`, :pr:`2749`, :pr:`2750`, :pr:`2751`).\n\n3.25.0 (2025-01-09)\n-------------------\n\nFeatures:\n\n- Typing: Improve type annotations for ``SchemaMeta.get_declared_fields`` (:pr:`2742`).\n\nBug fixes:\n\n- Typing: Relax type annotation for ``Schema.opts`` to allow subclasses to define their own\n  options classes (:pr:`2744`).\n\nOther changes:\n\n- Restore ``marshmallow.base.SchemaABC`` for backwards-compatibility (:issue:`2743`).\n  Note that this class is deprecated and will be removed in marshmallow 4.\n  Use `marshmallow.schema.Schema` as a base class for type-checking instead.\n\n3.24.2 (2025-01-08)\n-------------------\n\nChanges:\n\n- Don't override ``__new__`` to avoid breaking usages of `inspect.signature` with\n  `Field <marshmallow.fields.Field>` classes.\n  This allows marshmallow-sqlalchemy users to upgrade marshmallow without\n  upgrading to marshmallow-sqlalchemy>=1.1.1.\n\nDocumentation:\n\n- Add top-level API back to docs (:issue:`2739`).\n  Thanks :user:`llucax` for reporting.\n\n3.24.1 (2025-01-06)\n-------------------\n\nBug fixes:\n\n- Typing: Fix typing for `class_registry.get_class <marshmallow.class_registry.get_class>` (:pr:`2735`).\n\n3.24.0 (2025-01-06)\n-------------------\n\nFeatures:\n\n- Typing: Improve typings in `marshmallow.fields` (:pr:`2723`).\n- Typing: Replace type comments with inline typings (:pr:`2718`).\n\nBug fixes:\n\n- Typing: Fix type hint for ``nested`` parameter of `Nested <marshmallow.fields.Nested>` (:pr:`2721`).\n\nDeprecations:\n\n- Custom validators should raise a `ValidationError <marshmallow.exceptions.ValidationError>` for invalid values.\n  Returning `False`` is no longer supported .\n- Deprecate ``context`` parameter of `Schema <marshmallow.schema.Schema>` (:issue:`1826`).\n  Use `contextVars.ContextVar` to pass context data instead.\n- `Field <marshmallow.fields.Field>`, `Mapping <marshmallow.fields.Mapping>`,\n  and `Number <marshmallow.fields.Number>` should no longer be used as fields within schemas.\n  Use their subclasses instead.\n\n\n3.23.3 (2025-01-03)\n-------------------\n\nBug fixes:\n\n- Typing: Fix typing for `Schema.from_dict <marshmallow.schema.Schema.from_dict>` (:issue:`1653`).\n  Thanks :user:`SteadBytes` for reporting.\n\nSupport:\n\n- Documentation: Various documentation cleanups, including more concise docs in the `marshmallow.fields` API reference (:issue:`2307`).\n  Thanks :user:`AbdealiLoKo` for reporting.\n\n3.23.2 (2024-12-18)\n-------------------\n\nBug fixes:\n\n- Improve type hint formatting for ``Field``, ``Nested``, and ``Function`` fields\n  to resolve PyCharm warnings (:issue:`2268`).\n  Thanks :user:`Fares-Abubaker` for reporting and fixing.\n\n\n3.23.1 (2024-11-01)\n-------------------\n\nSupport:\n\n- Document ``absolute`` parameter of ``URL`` field (:pr:`2327`).\n- Documentation: Remove (outdated) minimum Python 3 minor version in\n  documentation and README (:pr:`2323`).\n\n3.23.0 (2024-10-17)\n-------------------\n\nFeatures:\n\n- Typing: replace \"type\" with specific metaclass for ``Schema`` and ``Field``.\n\nOther changes:\n\n- Officially support Python 3.13 (:pr:`2319`).\n- Drop support for Python 3.8 (:pr:`2318`).\n\n3.22.0 (2024-08-20)\n-------------------\n\nFeatures:\n\n- Add ``many`` Meta option to ``Schema`` so it expects a collection by default (:issue:`2270`).\n  Thanks :user:`himalczyk` for reporting and :user:`deckar01` for the PR.\n- Refactor hooks (:pr:`2279`).\n  Thanks :user:`deckar01` for the PR.\n\n3.21.3 (2024-06-05)\n-------------------\n\nBug fixes:\n\n- Fix memory leak that prevented schema instances from getting GC'd (:pr:`2277`).\n  Thanks :user:`mrcljx` for the PR.\n\n3.21.2 (2024-05-01)\n-------------------\n\nBug fixes:\n\n- Allow timestamp 0 in ``fields.DateTime`` (:issue:`2133`).\n  Thanks :user:`flydzen` for reporting.\n\n3.21.1 (2024-03-04)\n-------------------\n\nBug fixes:\n\n- Fix error message when field is declared as a class and not an instance (:issue:`2245`).\n  Thanks :user:`travnick` for reporting.\n\n3.21.0 (2024-02-26)\n-------------------\n\nBug fixes:\n\n- Fix validation of ``URL`` fields to allow missing user field,\n  per NWG RFC 3986 (:issue:`2232`). Thanks :user:`ddennerline3` for reporting\n  and :user:`deckar01` for the PR.\n\nOther changes:\n\n- *Backwards-incompatible*: ``__version__``, ``__parsed_version__``, and ``__version_info__``\n  attributes are deprecated (:issue:`2227`). Use feature detection or\n  ``importlib.metadata.version(\"marshmallow\")`` instead.\n\n3.20.2 (2024-01-09)\n-------------------\n\nBug fixes:\n\n- Fix ``Nested`` field type hint for lambda ``Schema`` types (:pr:`2164`).\n  Thanks :user:`somethingnew2-0` for the PR.\n\nOther changes:\n\n- Officially support Python 3.12 (:pr:`2188`).\n  Thanks :user:`hugovk` for the PR.\n\n3.20.1 (2023-07-20)\n-------------------\n\nBug fixes:\n\n- Fix call to ``get_declared_fields``: pass ``dict_cls`` again (:issue:`2152`).\n  Thanks :user:`Cheaterman` for reporting.\n\n3.20.0 (2023-07-20)\n-------------------\n\nFeatures:\n\n- Add ``absolute`` parameter to ``URL`` validator and ``Url`` field (:pr:`2123`).\n  Thanks :user:`sirosen` for the PR.\n- Use Abstract Base Classes to define ``FieldABC`` and ``SchemaABC``\n  (:issue:`1449`). Thanks :user:`aditkumar72` for the PR.\n- Use `OrderedSet` as default `set_class`. Schemas are now ordered by default.\n  (:issue:`1744`)\n\nBug fixes:\n\n- Handle ``OSError`` and ``OverflowError`` in ``utils.from_timestamp`` (:pr:`2102`).\n  Thanks :user:`TheBigRoomXXL` for the PR.\n- Fix the default inheritance of nested partial schemas (:issue:`2149`).\n  Thanks :user:`matejsp` for reporting.\n\nOther changes:\n\n- Officially support Python 3.11 (:pr:`2067`).\n- Drop support for Python 3.7 (:pr:`2135`).\n\n3.19.0 (2022-11-11)\n-------------------\n\nFeatures:\n\n- Add ``timestamp`` and ``timestamp_ms`` formats to ``fields.DateTime``\n  (:issue:`612`).\n  Thanks :user:`vgavro` for the suggestion and thanks :user:`vanHoi` for\n  the PR.\n\n3.18.0 (2022-09-15)\n-------------------\n\nFeatures:\n\n- Add ``Enum`` field (:pr:`2017`) and (:pr:`2044`).\n\nBug fixes:\n\n- Fix typing in ``Field._serialize`` signature (:pr:`2046`).\n\n3.17.1 (2022-08-22)\n-------------------\n\nBug fixes:\n\n- Add return type to ``fields.Email.__init__`` (:pr:`2018`).\n  Thanks :user:`kkirsche` for the PR.\n- Add missing type hint to IPInterface __init__ (:pr:`2036`).\n\n3.17.0 (2022-06-26)\n-------------------\n\nFeatures:\n\n- Support serialization as float in ``TimeDelta`` field (:pr:`1998`).\n  Thanks :user:`marcosatti` for the PR.\n- Add ``messages_dict`` property to ``ValidationError`` to facilitate type checking\n  (:pr:`1976`).\n  Thanks :user:`sirosen` for the PR.\n\n3.16.0 (2022-05-29)\n-------------------\n\nFeatures:\n\n- Raise ``ValueError`` if an invalid value is passed to the ``unknown``\n  argument (:issue:`1721`, :issue:`1732`).\n  Thanks :user:`sirosen` for the PR.\n\nOther changes:\n\n- Set lower bound for ``packaging`` requirement (:issue:`1957`).\n  Thanks :user:`MatthewNicolTR` for reporting and thanks :user:`sirosen` for the PR.\n- Improve warning messages by passing ``stacklevel`` (:pr:`1986`).\n  Thanks :user:`tirkarthi` for the PR.\n\n3.15.0 (2022-03-12)\n-------------------\n\nFeatures:\n\n- Allow passing a ``dict`` to ``fields.Nested`` (:pr:`1935`).\n  Thanks :user:`sirosen` for the PR.\n\nOther changes:\n\n- Address distutils deprecation warning in Python 3.10 (:pr:`1903`).\n  Thanks :user:`kkirsche` for the PR.\n- Add py310 to black target-version (:pr:`1921`).\n- Drop support for Python 3.6 (:pr:`1923`).\n- Use postponed evaluation of annotations (:pr:`1932`).\n  Thanks :user:`Isira-Seneviratne` for the PR.\n\n3.14.1 (2021-11-13)\n-------------------\n\nBug fixes:\n\n- Fix publishing type hints per `PEP-561 <https://www.python.org/dev/peps/pep-0561/>`_\n  (:pr:`1905`). Thanks :user:`bwindsor` for the catch and patch.\n\n3.14.0 (2021-10-17)\n-------------------\n\nBug fixes:\n\n- Fix ``fields.TimeDelta`` serialization precision (:issue:`1865`).\n  Thanks :user:`yarsanich` for reporting.\n\nOther changes:\n\n- Fix type-hints for ``data`` arg in ``Schema.validate`` to accept\n  list of dictionaries (:issue:`1790`, :pr:`1868`).\n  Thanks  :user:`yourun-proger` for PR.\n- Improve warning when passing metadata as keyword arguments (:pr:`1882`).\n  Thanks :user:`traherom` for the PR.\n- Don't build universal wheels. We don't support Python 2 anymore.\n  (:issue:`1860`) Thanks :user:`YKdvd` for reporting.\n- Make the build reproducible (:pr:`1862`).\n- Drop support for Python 3.5 (:pr:`1863`).\n- Test against Python 3.10 (:pr:`1888`).\n\n3.13.0 (2021-07-21)\n-------------------\n\nFeatures:\n\n- Replace ``missing``/``default`` field parameters with\n  ``load_default``/``dump_default`` (:pr:`1742`).\n  Thanks :user:`sirosen` for the PR.\n\nDeprecations:\n\n- The use of ``missing``/``default`` field parameters is deprecated and will be\n  removed in marshmallow 4. ``load_default``/``dump_default`` should be used\n  instead.\n\n3.12.2 (2021-07-06)\n-------------------\n\nBug fixes:\n\n- Don't expose ``Field``\\s as ``Schema`` attributes. This reverts a change\n  introduced in 3.12.0 that causes issues when field names conflict with\n  ``Schema`` attributes or methods. ``Fields``\\s are still accessible on a\n  ``Schema`` instance through the ``fields`` attribute. (:pr:`1843`)\n\n3.12.1 (2021-05-10)\n-------------------\n\nBug fixes:\n\n- Fix bug that raised an ``AttributeError`` when instantiating a\n  ``Schema`` with a field named ``parent`` (:issue:`1808`).\n  Thanks :user:`flying-sheep` for reporting and helping with the fix.\n\n3.12.0 (2021-05-09)\n-------------------\n\nFeatures:\n\n- Add ``validate.And`` (:issue:`1768`).\n  Thanks :user:`rugleb` for the suggestion.\n- Add type annotations to ``marshmallow.decorators`` (:issue:`1788`, :pr:`1789`).\n  Thanks :user:`michaeldimchuk` for the PR.\n- Let ``Field``\\s be accessed by name as ``Schema`` attributes (:pr:`1631`).\n\nOther changes:\n\n- Improve types in ``marshmallow.validate`` (:pr:`1786`).\n- Make ``marshmallow.validate.Validator`` an abstract base class (:pr:`1786`).\n- Remove unnecessary list cast (:pr:`1785`).\n\n3.11.1 (2021-03-29)\n-------------------\n\nBug fixes:\n\n- Fix treatment of dotted keys when ``unknown=INCLUDE`` (:issue:`1506`).\n  Thanks :user:`rbu` for reporting and thanks :user:`sirosen` for the fix (:pr:`1745`).\n\n3.11.0 (2021-03-28)\n-------------------\n\nFeatures:\n\n- Add ``fields.IPInterface``, ``fields.IPv4Interface``, and\n  ``IPv6Interface`` (:issue:`1733`). Thanks :user:`madeinoz67`\n  for the suggestion and the PR.\n- Raise ``AttributeError`` for missing methods when using ``fields.Method`` (:pr:`1675`).\n  Thanks :user:`lassandroan`.\n\nOther changes:\n\n- Remove unnecessary ``hasattr`` and ``getattr`` checks in ``Field`` (:pr:`1770`).\n\n3.10.0 (2020-12-19)\n-------------------\n\nDeprecations:\n\n- Passing field metadata via keyword arguments is deprecated and will be\n  removed in marshmallow 4 (:issue:`1350`). Use the explicit ``metadata=...``\n  argument instead. Thanks :user:`sirosen`.\n\n3.9.1 (2020-11-07)\n------------------\n\nBug fixes:\n\n- Cast to mapping type in ``Mapping.serialize`` and ``Mapping.deserialize``\n  (:pr:`1685`).\n- Fix bug letting ``Dict`` pass invalid dict on deserialization when no key or\n  value ``Field`` is specified (:pr:`1685`).\n\n3.9.0 (2020-10-31)\n------------------\n\nFeatures:\n\n- Add ``format`` argument to ``fields.Time`` and ``timeformat`` ``class Meta`` option (:issue:`686`).\n  Thanks :user:`BennyAlex` for the suggestion and thanks :user:`infinityxxx` for the PR.\n\nOther changes:\n\n- Remove usage of implicit ``typing.Optional`` (:issue:`1663`).\n  Thanks :user:`nadega` for the PR.\n\n3.8.0 (2020-09-16)\n------------------\n\nFeatures:\n\n- Add ``fields.IP``, ``fields.IPv4`` and ``fields.IPv6`` (:pr:`1485`). Thanks\n  :user:`mgetka` for the PR.\n\nBug fixes:\n\n- Fix typing in ``AwareDateTime`` (:pr:`1658`). Thanks :user:`adithyabsk` for\n  reporting.\n\n3.7.1 (2020-07-20)\n------------------\n\nBug fixes:\n\n- ``fields.Boolean`` correctly serializes non-hashable types (:pr:`1633`).\n  Thanks :user:`jun0jang` for the PR.\n\n3.7.0 (2020-07-08)\n------------------\n\nDeprecations:\n\n- ``marshmallow.pprint`` is deprecated and will be removed in marshmallow 4 (:issue:`1588`).\n\nSupport:\n\n- Document ``default_error_messages`` on field classes (:pr:`1619`). Thanks :user:`weeix`.\n\nBug fixes:\n\n- Fix passing ``only`` and ``exclude`` to ``Nested`` with an ordered ``Schema`` (:pr:`1627`).\n  Thanks :user:`juannorris` for the PR.\n\n3.6.1 (2020-06-02)\n------------------\n\nNo code changes--only docs and contributor-facing updates in this release.\n\nSupport:\n\n- Documentation: improve custom fields example (:issue:`1538`).\n  Thanks :user:`pablospizzamiglio` for reporting the problem with the\n  old example and thanks :user:`Resinderate` for the PR.\n- Documentation: Split up API reference into multiple pages and\n  add summary tables (:pr:`1587`). Thanks :user:`EpicWink` for the PR.\n\n3.6.0 (2020-05-08)\n------------------\n\nFeatures:\n\n- Add ``validate.ContainsNoneOf`` (:issue:`1528`).\n  Thanks :user:`Resinderate` for the suggestion and the PR.\n\n\n3.5.2 (2020-04-30)\n------------------\n\nBug fixes:\n\n- Fix typing in ``class_registry`` (:pr:`1574`). Thanks :user:`mahenzon`.\n\n3.5.1 (2020-03-05)\n------------------\n\nBug fixes:\n\n- Includes bug fix from 2.21.0.\n\n3.5.0 (2020-02-19)\n------------------\n\nBug fixes:\n\n- Fix list of nullable nested fields ``List(Nested(Field, allow_none=True)``\n  (:issue:`1497`). Because this fix reverts an optimization introduced to\n  speed-up serialization and deserialization of lists of nested fields, a\n  negative impact on performance in this specific case is expected.\n\n3.4.0 (2020-02-02)\n------------------\n\nFeatures:\n\n- Improve type coverage (:issue:`1479`). Thanks :user:`Reskov`.\n\nBug fixes:\n\n- Fix typing for ``data`` param of ``Schema.load`` and ``ValidationError`` (:issue:`1492`).\n  Thanks :user:`mehdigmira` for reporting and thanks :user:`dfirst` for the PR.\n\nOther changes:\n\n- Remove unnecessary typecasts (:pr:`1500`). Thanks :user:`hukkinj1`.\n- Remove useless ``_serialize`` override in ``UUID`` field (:pr:`1489`).\n\n3.3.0 (2019-12-05)\n------------------\n\nFeatures:\n\n- ``fields.Nested`` may take a callable that returns a schema instance.\n  Use this to resolve order-of-declaration issues when schemas nest each other (:issue:`1146`).\n\n.. code-block:: python\n\n    # <3.3\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        artist = fields.Nested(\"ArtistSchema\", only=(\"name\",))\n\n\n    class ArtistSchema(Schema):\n        name = fields.Str()\n        albums = fields.List(fields.Nested(AlbumSchema))\n\n\n    # >=3.3\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        artist = fields.Nested(lambda: ArtistSchema(only=(\"name\",)))\n\n\n    class ArtistSchema(Schema):\n        name = fields.Str()\n        albums = fields.List(fields.Nested(AlbumSchema))\n\nDeprecations:\n\n- Passing the string ``\"self\"`` to ``fields.Nested`` is deprecated.\n  Use a callable instead.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.3\n    class PersonSchema(Schema):\n        partner = fields.Nested(\"self\", exclude=(\"partner\",))\n        friends = fields.List(fields.Nested(\"self\"))\n\n\n    # >=3.3\n    class PersonSchema(Schema):\n        partner = fields.Nested(lambda: PersonSchema(exclude=(\"partner\")))\n        friends = fields.List(fields.Nested(lambda: PersonSchema()))\n\nOther changes:\n\n- Fix typing for ``Number._format_num`` (:pr:`1466`). Thanks :user:`hukkinj1`.\n- Make mypy stricter and remove dead code (:pr:`1467`). Thanks again, :user:`hukkinj1`.\n\n3.2.2 (2019-11-04)\n------------------\n\nBug fixes:\n\n- Don't load fields for which ``load_only`` and ``dump_only`` are both ``True`` (:pr:`1448`).\n- Fix types in ``marshmallow.validate`` (:pr:`1446`).\n\nSupport:\n\n- Test against Python 3.8 (:pr:`1431`).\n\n3.2.1 (2019-09-30)\n------------------\n\nBug fixes:\n\n- Fix typing for ``Schema.dump[s]`` (:pr:`1416`).\n\n3.2.0 (2019-09-17)\n------------------\n\nFeatures:\n\n- Add type annotations to ``marshmallow.schema`` and ``marshmallow.validate`` (:pr:`1407`, :issue:`663`).\n\nBug fixes:\n\n- Fix compatibility with Python < 3.5.3 (:issue:`1409`). Thanks :user:`lukaszdudek-silvair` for reporting.\n\nRefactoring:\n\n- Remove unnecessary ``BaseSchema`` superclass (:pr:`1406`).\n\n3.1.1 (2019-09-16)\n------------------\n\nBug fixes:\n\n- Restore inheritance hierarchy of ``Number`` fields (:pr:`1403`).\n  ``fields.Integer`` and ``fields.Decimal`` inherit from ``fields.Number``.\n- Fix bug that raised an uncaught error when a nested schema instance had an unpickleable object in its context (:issue:`1404`).\n  Thanks :user:`metheoryt` for reporting.\n\n3.1.0 (2019-09-15)\n------------------\n\nFeatures:\n\n- Add more type annotations (:issue:`663`).\n  Type information is distributed per `PEP 561 <https://www.python.org/dev/peps/pep-0561/>`_ .\n  Thanks :user:`fuhrysteve` for helping with this.\n\nBug fixes:\n\n- Includes bug fix from 2.20.5.\n\n3.0.5 (2019-09-12)\n------------------\n\nBug fixes:\n\n- Fix bug that raised an uncaught error when passing both a schema instance and ``only`` to ``Nested`` (:pr:`1395`).\n  This bug also affected passing a schema instance to ``fields.Pluck``.\n\n\n3.0.4 (2019-09-11)\n------------------\n\nBug fixes:\n\n- Fix propagating dot-delimited ``only`` and ``exclude`` parameters to nested schema instances (:issue:`1384`).\n- Includes bug fix from 2.20.4 (:issue:`1160`).\n\n3.0.3 (2019-09-04)\n------------------\n\nBug fixes:\n\n- Handle when ``data_key`` is an empty string (:issue:`1378`).\n  Thanks :user:`jtrakk` for reporting.\n\n3.0.2 (2019-09-04)\n------------------\n\nBug fixes:\n\n- Includes bug fix from 2.20.3 (:pr:`1376`).\n- Fix incorrect ``super()`` call in ``SchemaMeta.__init__`` (:pr:`1362`).\n\n3.0.1 (2019-08-21)\n------------------\n\nBug fixes:\n\n- Fix bug when nesting ``fields.DateTime`` within ``fields.List`` or ``fields.Tuple`` (:issue:`1357`).\n  This bug was introduced in 3.0.0rc9. Thanks :user:`zblz` for reporting.\n\n3.0.0 (2019-08-18)\n------------------\n\nFeatures:\n\n- Optimize ``List(Nested(...))`` (:issue:`779`).\n- Minor performance improvements and cleanup (:pr:`1328`).\n- Add ``Schema.from_dict`` (:issue:`1312`).\n\nDeprecations/Removals:\n\n- ``Field.fail`` is deprecated. Use ``Field.make_error`` instead.\n- Remove UUID validation from ``fields.UUID``, for consistency with other fields (:issue:`1132`).\n\nSupport:\n\n- Various docs improvements (:pr:`1329`).\n\n3.0.0rc9 (2019-07-31)\n---------------------\n\nFeatures:\n\n- *Backwards-incompatible*: Validation does not occur on serialization (:issue:`1132`).\n  This significantly improves serialization performance.\n- *Backwards-incompatible*: ``DateTime`` does not affect timezone information\n  on serialization and deserialization (:issue:`1234`, :pr:`1278`).\n- Add ``NaiveDateTime`` and ``AwareDateTime`` to enforce timezone awareness\n  (:issue:`1234`, :pr:`1287`).\n- *Backwards-incompatible*: ``List`` does not wrap single values in a list on\n  serialization (:pr:`1307`).\n- *Backwards-incompatible*: ``Schema.handle_error`` receives ``many`` and ``partial`` as keyword arguments (:pr:`1321`).\n- Use ``raise from`` more uniformly to improve stack traces (:pr:`1313`).\n- Rename ``Nested.__schema`` to ``Nested._schema`` to prevent name mangling (:issue:`1289`).\n- Performance improvements (:pr:`1309`).\n\nDeprecations/Removals:\n\n- ``LocalDateTime`` is removed (:issue:`1234`).\n- ``marshmallow.utils.utc`` is removed. Use ``datetime.timezone.utc`` instead.\n\nBug fixes:\n\n- Fix behavior of ``List(Nested(\"self\"))`` (`#779 (comment) <https://github.com/marshmallow-code/marshmallow/issues/779#issuecomment-396354987>`_).\n\nSupport:\n\n- Document usage of ``validate.Regexp``'s usage ``re.search`` (:issue:`1285`). Thanks :user:`macdonaldezra`.\n\n3.0.0rc8 (2019-07-04)\n---------------------\n\nFeatures:\n\n- Propagate ``only`` and ``exclude`` parameters to ``Nested`` fields\n  within ``List`` and ``Dict`` (:issue:`779`, :issue:`946`).\n- Use ``email.utils.parsedate_to_datetime`` instead of conditionally\n  using dateutil for parsing RFC dates (:pr:`1246`).\n- Use internal util functions instead of conditionally using dateutil\n  for parsing  ISO 8601 datetimes, dates and times. Timezone info is now\n  correctly deserialized whether or not dateutil is installed. (:pr:`1265`)\n- Improve error messages for ``validate.Range``.\n- Use ``raise from error`` for better stack traces (:pr:`1254`). Thanks\n  :user:`fuhrysteve`.\n- python-dateutil is no longer used. This resolves the inconsistent behavior\n  based on the presence of python-dateutil (:issue:`497`, :issue:`1234`).\n\nBug fixes:\n\n- Fix method resolution for ``__init__`` method of ``fields.Email`` and\n  ``fields.URL`` (:issue:`1268`). Thanks :user:`dursk` for the catch and patch.\n- Includes bug fixes from 2.19.4 and 2.19.5.\n\nOther changes:\n\n- *Backwards-incompatible*: Rename ``fields.List.container`` to ``fields.List.inner``,\n  ``fields.Dict.key_container`` to ``fields.Dict.key_field``, and\n  ``fields.Dict.value_container`` to ``fields.Dict.value_field``.\n- Switch to Azure Pipelines for CI (:issue:`1261`).\n\n3.0.0rc7 (2019-06-15)\n---------------------\n\nFeatures:\n\n- *Backwards-incompatible*: ``many`` is passed as a keyword argument to methods decorated with\n  ``pre_load``, ``post_load``, ``pre_dump``, ``post_dump``,\n  and ``validates_schema``. ``partial`` is passed as a keyword argument to\n  methods decorated with ``pre_load``, ``post_load`` and ``validates_schema``.\n  ``**kwargs`` should be added to all decorated methods.\n- Add ``min_inclusive`` and ``max_exclusive`` parameters to\n  ``validate.Range`` (:issue:`1221`). Thanks :user:`kdop` for the PR.\n\nBug fixes:\n\n- Fix propagation of ``partial`` to ``Nested`` containers (part of :issue:`779`).\n- Includes bug fix from 2.19.3.\n\nOther changes:\n\n- *Backwards-incompatible*: Use keyword-only arguments (:issue:`1216`).\n\n3.0.0rc6 (2019-05-05)\n---------------------\n\nSupport:\n\n- *Backwards-incompatible*: Remove support for Python 2 (:issue:`1120`).\n  Only Python>=3.5 is supported.\n  Thank you :user:`rooterkyberian` for the suggestion and the PR.\n- *Backwards-incompatible*: Remove special-casing in ``fields.List`` and\n  ``fields.Tuple`` for accessing nested attributes (:pr:`1188`).\n  Use ``fields.List(fields.Pluck(...))`` instead.\n- Add ``python_requires`` to ``setup.py`` (:pr:`1194`).\n  Thanks :user:`hugovk`.\n- Upgrade syntax with ``pyupgrade`` in pre-commit (:pr:`1195`). Thanks\n  again :user:`hugovk`.\n\n3.0.0rc5 (2019-03-30)\n---------------------\n\nFeatures:\n\n- Allow input value to be included in error messages\n  for a number of fields (:pr:`1129`). Thanks :user:`hdoupe` for the PR.\n- Improve default error messages for ``OneOf`` and ``ContainsOnly``\n  (:issue:`885`). Thanks :user:`mcgfeller` for the suggestion\n  and :user:`maxalbert` for the PR.\n\nDeprecations/Removals:\n\n- Remove ``fields.FormattedString`` (:issue:`1141`). Use\n  ``fields.Function`` or ``fields.Method`` instead.\n\nBug fixes:\n\n- Includes bug fix from 2.19.2.\n\n3.0.0rc4 (2019-02-08)\n---------------------\n\nFeatures:\n\n- Add ``fields.Tuple`` (:issue:`1103`) Thanks :user:`zblz` for the PR.\n- Add ``fields.Mapping``, which makes it easier to support other\n  mapping types (e.g. ``OrderedDict``)  (:issue:`1092`).\n  Thank :user:`sayanarijit` for the suggestion and the PR.\n\n3.0.0rc3 (2019-01-13)\n---------------------\n\nFeatures:\n\n- Make the error messages for \"unknown fields\" and \"invalid data type\"\n  configurable (:issue:`852`). Thanks :user:`Dunstrom` for the PR.\n- ``fields.Boolean`` parses ``\"yes\"``/``\"no\"`` values (:pr:`1081`).\n  Thanks :user:`r1b`.\n\nOther changes:\n\n- *Backwards-incompatible with previous 3.x versions*: Change ordering\n  of ``keys`` and ``values`` arguments to ``fields.Dict``.\n- Remove unused code in ``marshmallow.utils``: ``is_indexable_but_not_string``,\n  ``float_to_decimal``, ``decimal_to_fixed``, ``from_iso`` (:pr:`1088`).\n- Remove unused ``marshmallow.compat.string_types``.\n\nBug fixes:\n\n- Includes bug fix from 2.18.0.\n\n3.0.0rc2 (2019-01-03)\n---------------------\n\nFeatures:\n\n- Add ``register`` *class Meta* option to allow bypassing marshmallow's\n  internal class registry when memory usage is critical (:issue:`660`).\n\nBug fixes:\n\n- Fix serializing dict-like objects with properties (:issue:`1060`).\n  Thanks :user:`taion` for the fix.\n- Fix populating ``ValidationError.valid_data`` for ``List`` and\n  ``Dict`` fields (:issue:`766`).\n\nOther changes:\n\n- Add ``marshmallow.__version_info__`` (:pr:`1074`).\n- Remove the ``marshmallow.marshalling`` internal module (:pr:`1070`).\n- A ``ValueError`` is raised when the ``missing`` parameter is passed\n  for required fields (:issue:`1040`).\n- Extra keyword arguments passed to ``ValidationError`` in validators\n  are no longer passed to the final ``ValidationError`` raised upon\n  validation completion (:issue:`996`).\n\n3.0.0rc1 (2018-11-29)\n---------------------\n\nFeatures:\n\n- *Backwards-incompatible*: Rework ``ValidationError`` API.\n  It now expects a single field name, and error structures are merged\n  in the final ``ValidationError`` raised when validation completes.\n  This allows schema-level validators to raise errors for individual\n  fields (:issue:`441`). Thanks :user:`maximkulkin` for\n  writing the original ``merge_errors`` implementation in :pr:`442` and thanks\n  :user:`lafrech` for completing the implementation in :pr:`1026`.\n\nBug fixes:\n\n- Fix ``TypeError`` when serializing ``None`` with ``Pluck`` (:pr:`1049`).\n  Thanks :user:`toffan` for the catch and patch.\n\n3.0.0b20 (2018-11-01)\n---------------------\n\nBug fixes:\n\n- Includes bug fixes from 2.16.2 and 2.16.3.\n\n3.0.0b19 (2018-10-24)\n---------------------\n\nFeatures:\n\n- Support partial loading of nested fields (:pr:`438`). Thanks\n  :user:`arbor-dwatson` for the PR. *Note*: Subclasses of ``fields.Nested``\n  now take an additional ``partial`` parameter in the ``_deserialize``\n  method.\n\nBug fixes:\n\n- Restore ``Schema.TYPE_MAPPING``, which was removed in 3.0.0b17 (:issue:`1012`).\n\nOther changes:\n\n- *Backwards-incompatible*: ``_serialize`` and ``_deserialize`` methods of\n  all ``fields.Field`` subclasses must accept ``**kwargs`` (:pr:`1007`).\n\n\n3.0.0b18 (2018-10-15)\n---------------------\n\nBug fixes:\n\n- Fix ``Date`` deserialization when using custom format (:issue:`1001`). Thanks\n  :user:`Ondkloss` for reporting.\n\nDeprecations/Removals:\n\n- ``prefix`` parameter or ``Schema`` class is removed (:issue:`991`). The same\n  can be achieved using a ``@post_dump`` method.\n\n\n3.0.0b17 (2018-10-13)\n---------------------\n\nFeatures:\n\n- Add ``format`` option to ``Date`` field (:pr:`869`).\n- *Backwards-incompatible*: Rename ``DateTime``'s ``dateformat`` Meta option\n  to ``datetimeformat``. ``dateformat`` now applies to ``Date`` (:pr:`869`).\n  Thanks :user:`knagra` for implementing these changes.\n- Enforce ISO 8601 when deserializing date and time (:issue:`899`).\n  Thanks :user:`dushr` for the report and the work on the PR.\n- *Backwards-incompatible*: Raise ``ValueError`` on ``Schema`` instantiation in\n  case of ``attribute`` or ``data_key`` collision (:pr:`992`).\n\nBug fixes:\n\n- Fix inconsistencies in field inference by refactoring the inference feature\n  into a dedicated field (:issue:`809`). Thanks :user:`taion` for the PR.\n- When ``unknown`` is not passed to ``Nested``, default to nested ``Schema``\n  ``unknown`` meta option rather than ``RAISE`` (:pr:`963`).\n  Thanks :user:`vgavro` for the PR.\n- Fix loading behavior of ``fields.Pluck`` (:pr:`990`).\n- Includes bug fix from 2.16.0.\n\n3.0.0b16 (2018-09-20)\n---------------------\n\nBug fixes:\n\n- Fix ``root`` attribute for nested container fields\n  on inheriting schemas (:issue:`956`). Thanks :user:`bmcbu`\n  for reporting.\n\n3.0.0b15 (2018-09-18)\n---------------------\n\nBug fixes:\n\n- Raise ``ValidationError`` instead of ``TypeError`` when non-iterable types are\n  validated with ``many=True`` (:issue:`851`).\n- ``many=True`` no longer iterates over ``str`` and ``collections.abc.Mapping`` objects and instead\n  raises a ``ValidationError`` with ``{'_schema': ['Invalid input type.']}`` (:issue:`930`).\n- Return ``[]`` as ``ValidationError.valid_data`` instead of ``{}`` when\n  ``many=True`` (:issue:`907`).\n\nThanks :user:`tuukkamustonen` for implementing these changes.\n\n3.0.0b14 (2018-09-15)\n---------------------\n\nFeatures:\n\n- Add ``fields.Pluck`` for serializing a single field from a nested object\n  (:issue:`800`). Thanks :user:`timc13` for the feedback and :user:`deckar01`\n  for the implementation.\n- *Backwards-incompatible*: Passing a string argument as ``only`` to\n  ``fields.Nested`` is no longer supported. Use ``fields.Pluck`` instead\n  (:issue:`800`).\n- Raise a ``StringNotCollectionError`` if ``only`` or ``exclude`` is\n  passed as a string to ``fields.Nested`` (:pr:`931`).\n- *Backwards-incompatible*: ``Float`` takes an ``allow_nan`` parameter to\n  explicitly allow serializing and deserializing special values (``nan``,\n  ``inf`` and ``-inf``). ``allow_nan`` defaults to ``False``.\n\nOther changes:\n\n- *Backwards-incompatible*: ``Nested`` field now defaults to ``unknown=RAISE``\n  instead of ``EXCLUDE``. This harmonizes behavior with ``Schema`` that\n  already defaults to ``RAISE`` (:issue:`908`). Thanks :user:`tuukkamustonen`.\n- Tested against Python 3.7.\n\n3.0.0b13 (2018-08-04)\n---------------------\n\nBug fixes:\n\n- Errors reported by a schema-level validator for a field in a ``Nested`` field\n  are stored under corresponding field name, not ``_schema`` key (:pr:`862`).\n- Includes bug fix from 2.15.4.\n\nOther changes:\n\n- *Backwards-incompatible*: The ``unknown`` option now defaults to ``RAISE``\n  (`#524 (comment) <https://github.com/marshmallow-code/marshmallow/issues/524#issuecomment-397165731>`_,\n  :issue:`851`).\n- *Backwards-incompatible*: When a schema error is raised with a ``dict`` as\n  payload, the ``dict`` overwrites any existing error list. Before this change,\n  it would be appended to the list.\n- Raise a `StringNotCollectionError` if ``only`` or ``exclude`` is\n  passed as a string (:issue:`316`). Thanks :user:`paulocheque` for\n  reporting.\n\n3.0.0b12 (2018-07-04)\n---------------------\n\nFeatures:\n\n- The behavior to apply when encountering unknown fields while deserializing\n  can be controlled with the ``unknown`` option (:issue:`524`,\n  :issue:`747`, :issue:`127`).\n  It makes it possible to either \"include\", \"exclude\", or \"raise\".\n  Thanks :user:`tuukkamustonen` for the suggestion and thanks\n  :user:`ramnes` for the PR.\n\n.. warning::\n\n  The default for ``unknown`` will be changed to ``RAISE`` in the\n  next release.\n\nOther changes:\n\n- *Backwards-incompatible*: Pre/Post-processors MUST return modified data.\n  Returning ``None`` does not imply data were mutated (:issue:`347`). Thanks\n  :user:`tdevelioglu` for reporting.\n- *Backwards-incompatible*: ``only`` and ``exclude`` are bound by\n  declared and additional fields. A ``ValueError`` is raised if invalid\n  fields are passed (:issue:`636`). Thanks :user:`jan-23` for reporting.\n  Thanks :user:`ikilledthecat` and :user:`deckar01` for the PRs.\n- Format code using pre-commit (:pr:`855`).\n\nDeprecations/Removals:\n\n- ``ValidationError.fields`` is removed (:issue:`840`). Access field\n  instances from ``Schema.fields``.\n\n3.0.0b11 (2018-05-20)\n---------------------\n\nFeatures:\n\n- Clean up code for schema hooks (:pr:`814`). Thanks :user:`taion`.\n- Minor performance improvement from simplifying ``utils.get_value`` (:pr:`811`). Thanks again :user:`taion`.\n- Add ``require_tld`` argument to ``fields.URL`` (:issue:`749`). Thanks\n  :user:`DenerKup` for reporting and thanks :user:`surik00` for the PR.\n- ``fields.UUID`` deserializes ``bytes`` strings using ``UUID(bytes=b'...')`` (:pr:`625`).\n  Thanks :user:`JeffBerger` for the suggestion and the PR.\n\nBug fixes:\n\n- Fields nested within ``Dict`` correctly inherit context from their\n  parent schema (:issue:`820`). Thanks :user:`RosanneZe` for reporting\n  and :user:`deckar01` for the PR.\n- Includes bug fix from 2.15.3.\n\n\n3.0.0b10 (2018-05-10)\n---------------------\n\nBug fixes:\n\n- Includes bugfixes from 2.15.2.\n\n3.0.0b9 (2018-04-25)\n--------------------\n\nFeatures:\n\n- *Backwards-incompatible*: ``missing`` and ``default`` values are\n  passed in deserialized form (:issue:`378`). Thanks :user:`chadrik` for\n  the suggestion and thanks :user:`lafrech` for the PR.\n\nBug fixes:\n\n- Includes the bugfix from 2.15.1.\n\n3.0.0b8 (2018-03-24)\n--------------------\n\nFeatures:\n\n- *Backwards-incompatible*: Add ``data_key`` parameter to fields for\n  specifying the key in the input and output data dict. This\n  parameter replaces both ``load_from`` and ``dump_to`` (:issue:`717`).\n  Thanks :user:`lafrech`.\n- *Backwards-incompatible*: When ``pass_original=True`` is passed to one\n  of the decorators and a collection is being (de)serialized, the\n  ``original_data`` argument will be a single object unless\n  ``pass_many=True`` is also passed to the decorator (:issue:`315`,\n  :issue:`743`). Thanks :user:`stj` for the PR.\n- *Backwards-incompatible*: Don't recursively check nested required\n  fields when the ``Nested`` field's key is missing (:issue:`319`). This\n  reverts :pr:`235`. Thanks :user:`chekunkov` reporting and thanks\n  :user:`lafrech` for the PR.\n- *Backwards-incompatible*: Change error message collection for ``Dict`` field (:issue:`730`). Note:\n  this is backwards-incompatible with previous 3.0.0bX versions.\n  Thanks :user:`shabble` for the report and thanks :user:`lafrech` for the PR.\n\n3.0.0b7 (2018-02-03)\n--------------------\n\nFeatures:\n\n- *Backwards-incompatible*: Schemas are always strict (:issue:`377`).\n  The ``strict`` parameter is removed.\n- *Backwards-incompatible*: ``Schema().load`` and ``Schema().dump`` return ``data`` instead of a\n  ``(data, errors)`` tuple (:issue:`598`).\n- *Backwards-incompatible*: ``Schema().load(None)`` raises a\n  ``ValidationError`` (:issue:`511`).\n\nSee :ref:`upgrading_3_0` for a guide on updating your code.\n\nThanks :user:`lafrech` for implementing these changes.\nSpecial thanks to :user:`MichalKononenko`, :user:`douglas-treadwell`, and\n:user:`maximkulkin` for the discussions on these changes.\n\n\nOther changes:\n\n- *Backwards-incompatible*: Field name is not checked when ``load_from``\n  is specified (:pr:`714`). Thanks :user:`lafrech`.\n\nSupport:\n\n- Add `Code of Conduct <https://marshmallow.readthedocs.io/en/dev/code_of_conduct.html>`_.\n\n\n3.0.0b6 (2018-01-02)\n--------------------\n\nBug fixes:\n\n- Fixes ``ValidationError.valid_data`` when a nested field contains errors\n  (:issue:`710`). This bug was introduced in 3.0.0b3. Thanks\n  :user:`lafrech`.\n\nOther changes:\n\n- *Backwards-incompatible*: ``Email`` and ``URL`` fields don't validate\n  on serialization (:issue:`608`). This makes them more consistent with the other\n  fields and improves serialization performance. Thanks again :user:`lafrech`.\n- ``validate.URL`` requires square brackets around IPv6 URLs (:issue:`707`). Thanks :user:`harlov`.\n\n3.0.0b5 (2017-12-30)\n--------------------\n\nFeatures:\n\n- Add support for structured dictionaries by providing values and keys arguments to the\n  ``Dict`` field's constructor. This mirrors the ``List``\n  field's ability to validate its items (:issue:`483`). Thanks :user:`deckar01`.\n\nOther changes:\n\n- *Backwards-incompatible*: ``utils.from_iso`` is deprecated in favor of\n  ``utils.from_iso_datetime`` (:issue:`694`). Thanks :user:`sklarsa`.\n\n3.0.0b4 (2017-10-23)\n--------------------\n\nFeatures:\n\n- Add support for millisecond, minute, hour, and week precisions to\n  ``fields.TimeDelta`` (:issue:`537`). Thanks :user:`Fedalto` for the\n  suggestion and the PR.\n- Includes features from release 2.14.0.\n\n\nSupport:\n\n- Copyright year in docs uses ``CHANGELOG.rst``'s modified date for\n  reproducible builds (:issue:`679`). Thanks :user:`bmwiedemann`.\n- Test against Python 3.6 in tox. Thanks :user:`Fedalto`.\n- Fix typo in exception message (:issue:`659`). Thanks :user:`wonderbeyond`\n  for reporting and thanks :user:`yoichi` for the PR.\n\n3.0.0b3 (2017-08-20)\n--------------------\n\nFeatures:\n\n- Add ``valid_data`` attribute to ``ValidationError``.\n- Add ``strict`` parameter to ``Integer`` (:issue:`667`). Thanks\n  :user:`yoichi`.\n\nDeprecations/Removals:\n\n- Deprecate ``json_module`` option in favor of ``render_module`` (:issue:`364`, :issue:`130`). Thanks :user:`justanr` for the suggestion.\n\nBug fixes:\n\n- Includes bug fixes from releases 2.13.5 and 2.13.6.\n- *Backwards-incompatible*: ``Number`` fields don't accept booleans as valid input (:issue:`623`). Thanks :user:`tuukkamustonen` for the suggestion and thanks :user:`rowillia` for the PR.\n\nSupport:\n\n- Add benchmark script. Thanks :user:`rowillia`.\n\n3.0.0b2 (2017-03-19)\n--------------------\n\nFeatures:\n\n- Add ``truthy`` and ``falsy`` params to ``fields.Boolean`` (:issue:`580`). Thanks :user:`zwack` for the PR. Note: This is potentially a breaking change if your code passes the `default` parameter positionally. Pass `default` as a keyword argument instead, e.g. ``fields.Boolean(default=True)``.\n\nOther changes:\n\n- *Backwards-incompatible*: ``validate.ContainsOnly`` allows empty and duplicate values (:issue:`516`, :issue:`603`). Thanks :user:`maximkulkin` for the suggestion and thanks :user:`lafrech` for the PR.\n\nBug fixes:\n\n- Includes bug fixes from release 2.13.4.\n\n3.0.0b1 (2017-03-10)\n--------------------\n\nFeatures:\n\n- ``fields.Nested`` respects ``only='field'`` when deserializing (:issue:`307`). Thanks :user:`erlingbo` for the suggestion and the PR.\n- ``fields.Boolean`` parses ``\"on\"``/``\"off\"`` (:issue:`580`). Thanks :user:`marcellarius` for the suggestion.\n\n\nOther changes:\n\n- Includes changes from release 2.13.2.\n- *Backwards-incompatible*: ``skip_on_field_errors`` defaults to ``True`` for ``validates_schema`` (:issue:`352`).\n\n3.0.0a1 (2017-02-26)\n--------------------\n\nFeatures:\n\n- ``dump_only`` and ``load_only`` for ``Function`` and ``Method`` are set based on ``serialize`` and ``deserialize`` arguments (:issue:`328`).\n\nOther changes:\n\n- *Backwards-incompatible*: ``fields.Method`` and ``fields.Function`` no longer swallow ``AttributeErrors`` (:issue:`395`). Thanks :user:`bereal` for the suggestion.\n- *Backwards-incompatible*: ``validators.Length`` is no longer a subclass of ``validators.Range`` (:issue:`458`). Thanks :user:`deckar01` for the catch and patch.\n- *Backwards-incompatible*: ``utils.get_func_args`` no longer returns bound arguments. This is consistent with the behavior of ``inspect.signature``. This change prevents a DeprecationWarning on Python 3.5 (:issue:`415`, :issue:`479`). Thanks :user:`deckar01` for the PR.\n- *Backwards-incompatible*: Change the signature of ``utils.get_value`` and ``Schema.get_attribute`` for consistency with Python builtins (e.g. ``getattr``) (:issue:`341`). Thanks :user:`stas` for reporting and thanks :user:`deckar01` for the PR.\n- *Backwards-incompatible*: Don't unconditionally call callable attributes (:issue:`430`, reverts :issue:`242`). Thanks :user:`mirko` for the suggestion.\n- Drop support for Python 2.6 and 3.3.\n\nDeprecation/Removals:\n\n- Remove ``__error_handler__``, ``__accessor__``, ``@Schema.error_handler``, and ``@Schema.accessor``. Override ``Schema.handle_error`` and ``Schema.get_attribute`` instead.\n- Remove ``func`` parameter of ``fields.Function``. Remove ``method_name`` parameter of ``fields.Method`` (issue:`325`). Use the ``serialize`` parameter instead.\n- Remove ``extra`` parameter from ``Schema``. Use a ``@post_dump`` method to add additional data.\n\n2.21.0 (2020-03-05)\n-------------------\n\nBug fixes:\n\n- Don't match string-ending newlines in ``URL`` and ``Email`` fields\n  (:issue:`1522`). Thanks :user:`nbanmp` for the PR.\n\nOther changes:\n\n- Drop support for Python 3.4 (:pr:`1525`).\n\n2.20.5 (2019-09-15)\n-------------------\n\nBug fixes:\n\n- Fix behavior when a non-list collection is passed to the ``validate`` argument of ``fields.Email`` and ``fields.URL`` (:issue:`1400`).\n\n2.20.4 (2019-09-11)\n-------------------\n\nBug fixes:\n\n- Respect the ``many`` value on ``Schema`` instances passed to ``Nested`` (:issue:`1160`).\n  Thanks :user:`Kamforka` for reporting.\n\n2.20.3 (2019-09-04)\n-------------------\n\nBug fixes:\n\n- Don't swallow ``TypeError`` exceptions raised by ``Field._bind_to_schema`` or ``Schema.on_bind_field`` (:pr:`1376`).\n\n2.20.2 (2019-08-20)\n-------------------\n\nBug fixes:\n\n- Prevent warning about importing from ``collections`` on Python 3.7\n  (:pr:`1354`). Thanks :user:`nicktimko` for the PR.\n\n2.20.1 (2019-08-13)\n-------------------\n\nBug fixes:\n\n- Fix bug that raised ``TypeError`` when invalid data type is\n  passed to a nested schema with ``@validates`` (:issue:`1342`).\n\n2.20.0 (2019-08-10)\n-------------------\n\nBug fixes:\n\n- Fix deprecated functions' compatibility with Python 2 (:issue:`1337`).\n  Thanks :user:`airstandley` for the catch and patch.\n- Fix error message consistency for invalid input types on nested fields (:issue:`1303`).\n  This is a backport of the fix in :pr:`857`. Thanks :user:`cristi23` for the\n  thorough bug report and the PR.\n\nDeprecation/Removals:\n\n- Python 2.6 is no longer officially supported (:issue:`1274`).\n\n2.19.5 (2019-06-18)\n-------------------\n\nBug fixes:\n\n- Fix deserializing ISO8601-formatted datetimes with less than 6-digit\n  miroseconds (:issue:`1251`). Thanks :user:`diego-plan9` for reporting.\n\n2.19.4 (2019-06-16)\n-------------------\n\nBug fixes:\n\n- Microseconds no longer gets lost when deserializing datetimes without dateutil\n  installed (:issue:`1147`).\n\n2.19.3 (2019-06-15)\n-------------------\n\nBug fixes:\n\n- Fix bug where nested fields in ``Meta.exclude`` would not work on\n  multiple instantiations (:issue:`1212`). Thanks :user:`MHannila` for\n  reporting.\n\n2.19.2 (2019-03-30)\n-------------------\n\nBug fixes:\n\n- Handle ``OverflowError`` when (de)serializing large integers with\n  ``fields.Float`` (:pr:`1177`). Thanks :user:`brycedrennan` for the PR.\n\n2.19.1 (2019-03-16)\n-------------------\n\nBug fixes:\n\n- Fix bug where ``Nested(many=True)`` would skip first element when\n  serializing a generator (:issue:`1163`). Thanks :user:`khvn26` for the\n  catch and patch.\n\n2.19.0 (2019-03-07)\n-------------------\n\nDeprecation/Removal:\n\n- A ``RemovedInMarshmallow3`` warning is raised when using\n  ``fields.FormattedString``. Use ``fields.Method`` or ``fields.Function``\n  instead (:issue:`1141`).\n\n2.18.1 (2019-02-15)\n-------------------\n\nBug fixes:\n\n- A ``ChangedInMarshmallow3Warning`` is no longer raised when\n  ``strict=False`` (:issue:`1108`). Thanks :user:`Aegdesil` for\n  reporting.\n\n2.18.0 (2019-01-13)\n-------------------\n\nFeatures:\n\n- Add warnings for functions in ``marshmallow.utils`` that are removed in\n  marshmallow 3.\n\nBug fixes:\n\n- Copying ``missing`` with ``copy.copy`` or ``copy.deepcopy`` will not\n  duplicate it (:pr:`1099`).\n\n2.17.0 (2018-12-26)\n-------------------\n\nFeatures:\n\n- Add ``marshmallow.__version_info__`` (:pr:`1074`).\n- Add warnings for API that is deprecated or changed to help users\n  prepare for marshmallow 3 (:pr:`1075`).\n\n2.16.3 (2018-11-01)\n-------------------\n\nBug fixes:\n\n- Prevent memory leak when dynamically creating classes with ``type()``\n  (:issue:`732`). Thanks :user:`asmodehn` for writing the tests to\n  reproduce this issue.\n\n2.16.2 (2018-10-30)\n-------------------\n\nBug fixes:\n\n- Prevent warning about importing from ``collections`` on Python 3.7\n  (:issue:`1027`). Thanks :user:`nkonin` for reporting and\n  :user:`jmargeta` for the PR.\n\n2.16.1 (2018-10-17)\n-------------------\n\nBug fixes:\n\n- Remove spurious warning about implicit collection handling\n  (:issue:`998`). Thanks :user:`lalvarezguillen` for reporting.\n\n2.16.0 (2018-10-10)\n-------------------\n\nBug fixes:\n\n- Allow username without password in basic auth part of the url in\n  ``fields.Url`` (:pr:`982`). Thanks user:`alefnula` for the PR.\n\nOther changes:\n\n- Drop support for Python 3.3 (:pr:`987`).\n\n2.15.6 (2018-09-20)\n-------------------\n\nBug fixes:\n\n- Prevent ``TypeError`` when a non-collection is passed to a ``Schema`` with ``many=True``.\n  Instead, raise ``ValidationError`` with ``{'_schema': ['Invalid input type.']}`` (:issue:`906`).\n- Fix ``root`` attribute for nested container fields on list\n  on inheriting schemas (:issue:`956`). Thanks :user:`bmcbu`\n  for reporting.\n\nThese fixes were backported from 3.0.0b15 and 3.0.0b16.\n\n\n2.15.5 (2018-09-15)\n-------------------\n\nBug fixes:\n\n- Handle empty SQLAlchemy lazy lists gracefully when dumping (:issue:`948`).\n  Thanks :user:`vke-code` for the catch and :user:`YuriHeupa` for the patch.\n\n2.15.4 (2018-08-04)\n-------------------\n\nBug fixes:\n\n- Respect ``load_from`` when reporting errors for ``@validates('field_name')``\n  (:issue:`748`). Thanks :user:`m-novikov` for the catch and patch.\n\n2.15.3 (2018-05-20)\n-------------------\n\nBug fixes:\n\n- Fix passing ``only`` as a string to ``nested`` when the passed field\n  defines ``dump_to`` (:issue:`800`, :issue:`822`). Thanks\n  :user:`deckar01` for the catch and patch.\n\n2.15.2 (2018-05-10)\n-------------------\n\nBug fixes:\n\n- Fix a race condition in validation when concurrent threads use the\n  same ``Schema`` instance (:issue:`783`). Thanks :user:`yupeng0921` and\n  :user:`lafrech` for the fix.\n- Fix serialization behavior of\n  ``fields.List(fields.Integer(as_string=True))`` (:issue:`788`). Thanks\n  :user:`cactus` for reporting and :user:`lafrech` for the fix.\n- Fix behavior of ``exclude`` parameter when passed from parent to\n  nested schemas (:issue:`728`). Thanks :user:`timc13` for reporting and\n  :user:`deckar01` for the fix.\n\n2.15.1 (2018-04-25)\n-------------------\n\nBug fixes:\n\n- :cve:`2018-17175`: Fix behavior when an empty list is passed as the ``only`` argument\n  (:issue:`772`). Thanks :user:`deckar01` for reporting and thanks\n  :user:`lafrech` for the fix.\n\n2.15.0 (2017-12-02)\n-------------------\n\nBug fixes:\n\n- Handle ``UnicodeDecodeError`` when deserializing ``bytes`` with a\n  ``String`` field (:issue:`650`). Thanks :user:`dan-blanchard` for the\n  suggestion and thanks :user:`4lissonsilveira` for the PR.\n\n2.14.0 (2017-10-23)\n-------------------\n\nFeatures:\n\n- Add ``require_tld`` parameter to ``validate.URL`` (:issue:`664`).\n  Thanks :user:`sduthil` for the suggestion and the PR.\n\n2.13.6 (2017-08-16)\n-------------------\n\nBug fixes:\n\n- Fix serialization of types that implement `__getitem__`\n  (:issue:`669`). Thanks :user:`MichalKononenko`.\n\n2.13.5 (2017-04-12)\n-------------------\n\nBug fixes:\n\n- Fix validation of iso8601-formatted dates (:issue:`556`). Thanks :user:`lafrech` for reporting.\n\n2.13.4 (2017-03-19)\n-------------------\n\nBug fixes:\n\n- Fix symmetry of serialization and deserialization behavior when passing a dot-delimited path to the ``attribute`` parameter of fields (:issue:`450`). Thanks :user:`itajaja` for reporting.\n\n2.13.3 (2017-03-11)\n-------------------\n\nBug fixes:\n\n- Restore backwards-compatibility of ``SchemaOpts`` constructor (:issue:`597`). Thanks :user:`Wesmania` for reporting and thanks :user:`frol` for the fix.\n\n2.13.2 (2017-03-10)\n-------------------\n\nBug fixes:\n\n- Fix inheritance of ``ordered`` option when ``Schema`` subclasses define ``class Meta`` (:issue:`593`). Thanks :user:`frol`.\n\nSupport:\n\n- Update contributing docs.\n\n2.13.1 (2017-03-04)\n-------------------\n\nBug fixes:\n\n- Fix sorting on Schema subclasses when ``ordered=True`` (:issue:`592`). Thanks :user:`frol`.\n\n2.13.0 (2017-02-18)\n-------------------\n\nFeatures:\n\n- Minor optimizations (:issue:`577`). Thanks :user:`rowillia` for the PR.\n\n2.12.2 (2017-01-30)\n-------------------\n\nBug fixes:\n\n- Unbound fields return `None` rather returning the field itself. This fixes a corner case introduced in :issue:`572`. Thanks :user:`touilleMan` for reporting and :user:`YuriHeupa` for the fix.\n\n2.12.1 (2017-01-23)\n-------------------\n\nBug fixes:\n\n- Fix behavior when a ``Nested`` field is composed within a ``List`` field (:issue:`572`). Thanks :user:`avish` for reporting and :user:`YuriHeupa` for the PR.\n\n2.12.0 (2017-01-22)\n-------------------\n\nFeatures:\n\n- Allow passing nested attributes (e.g. ``'child.field'``) to the ``dump_only`` and ``load_only`` parameters of ``Schema`` (:issue:`572`). Thanks :user:`YuriHeupa` for the PR.\n- Add ``schemes`` parameter to ``fields.URL`` (:issue:`574`). Thanks :user:`mosquito` for the PR.\n\n2.11.1 (2017-01-08)\n-------------------\n\nBug fixes:\n\n- Allow ``strict`` class Meta option to be overridden by constructor (:issue:`550`). Thanks :user:`douglas-treadwell` for reporting and thanks :user:`podhmo` for the PR.\n\n2.11.0 (2017-01-08)\n-------------------\n\nFeatures:\n\n- Import ``marshmallow.fields`` in ``marshmallow/__init__.py`` to save an import when importing the ``marshmallow`` module (:issue:`557`). Thanks :user:`mindojo-victor`.\n\nSupport:\n\n- Documentation: Improve example in \"Validating Original Input Data\" (:issue:`558`). Thanks :user:`altaurog`.\n- Test against Python 3.6.\n\n2.10.5 (2016-12-19)\n-------------------\n\nBug fixes:\n\n- Reset user-defined kwargs passed to ``ValidationError`` on each ``Schema.load`` call (:issue:`565`). Thanks :user:`jbasko` for the catch and patch.\n\nSupport:\n\n- Tests: Fix redefinition of ``test_utils.test_get_value()`` (:issue:`562`). Thanks :user:`nelfin`.\n\n2.10.4 (2016-11-18)\n-------------------\n\nBug fixes:\n\n- `Function` field works with callables that use Python 3 type annotations (:issue:`540`). Thanks :user:`martinstein` for reporting and thanks :user:`sabinem`, :user:`lafrech`, and :user:`maximkulkin` for the work on the PR.\n\n2.10.3 (2016-10-02)\n-------------------\n\nBug fixes:\n\n- Fix behavior for serializing missing data with ``Number`` fields when ``as_string=True`` is passed (:issue:`538`). Thanks :user:`jessemyers` for reporting.\n\n2.10.2 (2016-09-25)\n-------------------\n\nBug fixes:\n\n- Use fixed-point notation rather than engineering notation when serializing with ``Decimal`` (:issue:`534`). Thanks :user:`gdub`.\n- Fix UUID validation on serialization and deserialization of ``uuid.UUID`` objects (:issue:`532`). Thanks :user:`pauljz`.\n\n2.10.1 (2016-09-14)\n-------------------\n\nBug fixes:\n\n- Fix behavior when using ``validate.Equal(False)`` (:issue:`484`). Thanks :user:`pktangyue` for reporting and thanks :user:`tuukkamustonen` for the fix.\n- Fix ``strict`` behavior when errors are raised in ``pre_dump``/``post_dump`` processors (:issue:`521`). Thanks :user:`tvuotila` for the catch and patch.\n- Fix validation of nested fields on dumping (:issue:`528`). Thanks again :user:`tvuotila`.\n\n2.10.0 (2016-09-05)\n-------------------\n\nFeatures:\n\n- Errors raised by pre/post-load/dump methods will be added to a schema's errors dictionary (:issue:`472`). Thanks :user:`dbertouille` for the suggestion and for the PR.\n\n2.9.1 (2016-07-21)\n------------------\n\nBug fixes:\n\n- Fix serialization of ``datetime.time`` objects with microseconds (:issue:`464`). Thanks :user:`Tim-Erwin` for reporting and thanks :user:`vuonghv` for the fix.\n- Make ``@validates`` consistent with field validator behavior: if validation fails, the field will not be included in the deserialized output (:issue:`391`). Thanks :user:`martinstein` for reporting and thanks :user:`vuonghv` for the fix.\n\n2.9.0 (2016-07-06)\n------------------\n\n- ``Decimal`` field coerces input values to a string before deserializing to a `decimal.Decimal` object in order to avoid transformation of float values under 12 significant digits (:issue:`434`, :issue:`435`). Thanks :user:`davidthornton` for the PR.\n\n2.8.0 (2016-06-23)\n------------------\n\nFeatures:\n\n- Allow ``only`` and ``exclude`` parameters to take nested fields, using dot-delimited syntax (e.g. ``only=['blog.author.email']``) (:issue:`402`). Thanks :user:`Tim-Erwin` and :user:`deckar01` for the discussion and implementation.\n\nSupport:\n\n- Update tasks.py for compatibility with invoke>=0.13.0. Thanks :user:`deckar01`.\n\n2.7.3 (2016-05-05)\n------------------\n\n- Make ``field.parent`` and ``field.name`` accessible to ``on_bind_field`` (:issue:`449`). Thanks :user:`immerrr`.\n\n2.7.2 (2016-04-27)\n------------------\n\nNo code changes in this release. This is a reupload in order to distribute an sdist for the last hotfix release. See :issue:`443`.\n\nSupport:\n\n- Update license entry in setup.py to fix RPM distributions (:issue:`433`). Thanks :user:`rrajaravi` for reporting.\n\n2.7.1 (2016-04-08)\n------------------\n\nBug fixes:\n\n- Only add Schemas to class registry if a class name is provided. This allows Schemas to be\n  constructed dynamically using the ``type`` constructor without getting added to the class registry (which is useful for saving memory).\n\n2.7.0 (2016-04-04)\n------------------\n\nFeatures:\n\n- Make context available to ``Nested`` field's ``on_bind_field`` method (:issue:`408`). Thanks :user:`immerrr` for the PR.\n- Pass through user ``ValidationError`` kwargs (:issue:`418`). Thanks :user:`russelldavies` for helping implement this.\n\nOther changes:\n\n- Remove unused attributes ``root``, ``parent``, and ``name`` from ``SchemaABC`` (:issue:`410`). Thanks :user:`Tim-Erwin` for the PR.\n\n2.6.1 (2016-03-17)\n------------------\n\nBug fixes:\n\n- Respect ``load_from`` when reporting errors for nested required fields (:issue:`414`). Thanks :user:`yumike`.\n\n2.6.0 (2016-02-01)\n------------------\n\nFeatures:\n\n- Add ``partial`` argument to ``Schema.validate`` (:issue:`379`). Thanks :user:`tdevelioglu` for the PR.\n- Add ``equal`` argument to ``validate.Length``. Thanks :user:`daniloakamine`.\n- Collect all validation errors for each item deserialized by a ``List`` field (:issue:`345`). Thanks :user:`maximkulkin` for the report and the PR.\n\n2.5.0 (2016-01-16)\n------------------\n\nFeatures:\n\n- Allow a tuple of field names to be passed as the ``partial`` argument to ``Schema.load`` (:issue:`369`). Thanks :user:`tdevelioglu` for the PR.\n- Add ``schemes`` argument to ``validate.URL`` (:issue:`356`).\n\n2.4.2 (2015-12-08)\n------------------\n\nBug fixes:\n\n- Prevent duplicate error messages when validating nested collections (:issue:`360`). Thanks :user:`alexmorken` for the catch and patch.\n\n2.4.1 (2015-12-07)\n------------------\n\nBug fixes:\n\n- Serializing an iterator will not drop the first item (:issue:`343`, :issue:`353`). Thanks :user:`jmcarp` for the patch. Thanks :user:`edgarallang` and :user:`jmcarp` for reporting.\n\n2.4.0 (2015-12-06)\n------------------\n\nFeatures:\n\n- Add ``skip_on_field_errors`` parameter to ``validates_schema`` (:issue:`323`). Thanks :user:`jjvattamattom` for the suggestion and :user:`d-sutherland` for the PR.\n\nBug fixes:\n\n- Fix ``FormattedString`` serialization (:issue:`348`). Thanks :user:`acaird` for reporting.\n- Fix ``@validates`` behavior when used when ``attribute`` is specified and ``strict=True`` (:issue:`350`). Thanks :user:`density` for reporting.\n\n2.3.0 (2015-11-22)\n------------------\n\nFeatures:\n\n- Add ``dump_to`` parameter to fields (:issue:`310`). Thanks :user:`ShayanArmanPercolate` for the suggestion. Thanks :user:`franciscod` and :user:`ewang` for the PRs.\n- The ``deserialize`` function passed to ``fields.Function`` can optionally receive a ``context`` argument (:issue:`324`). Thanks :user:`DamianHeard`.\n- The ``serialize`` function passed to ``fields.Function`` is optional (:issue:`325`). Thanks again :user:`DamianHeard`.\n- The ``serialize`` function passed to ``fields.Method`` is optional (:issue:`329`). Thanks :user:`justanr`.\n\nDeprecation/Removal:\n\n- The ``func`` argument of ``fields.Function`` has been renamed to ``serialize``.\n- The ``method_name`` argument of ``fields.Method`` has been renamed to ``serialize``.\n\n``func`` and ``method_name`` are still present for backwards-compatibility, but they will both be removed in marshmallow 3.0.\n\n2.2.1 (2015-11-11)\n------------------\n\nBug fixes:\n\n- Skip field validators for fields that aren't included in ``only`` (:issue:`320`). Thanks :user:`carlos-alberto` for reporting and :user:`eprikazc` for the PR.\n\n2.2.0 (2015-10-26)\n------------------\n\nFeatures:\n\n- Add support for partial deserialization with the ``partial`` argument to ``Schema`` and ``Schema.load`` (:issue:`290`). Thanks :user:`taion`.\n\nDeprecation/Removals:\n\n- ``Query`` and ``QuerySelect`` fields are removed.\n- Passing of strings to ``required`` and ``allow_none`` is removed. Pass the ``error_messages`` argument instead.\n\nSupport:\n\n- Add example of Schema inheritance in docs (:issue:`225`). Thanks :user:`martinstein` for the suggestion and :user:`juanrossi` for the PR.\n- Add \"Customizing Error Messages\" section to custom fields docs.\n\n2.1.3 (2015-10-18)\n------------------\n\nBug fixes:\n\n- Fix serialization of collections for which ``iter`` will modify position, e.g. Pymongo cursors (:issue:`303`). Thanks :user:`Mise` for the catch and patch.\n\n2.1.2 (2015-10-14)\n------------------\n\nBug fixes:\n\n- Fix passing data to schema validator when using ``@validates_schema(many=True)`` (:issue:`297`). Thanks :user:`d-sutherland` for reporting.\n- Fix usage of ``@validates`` with a nested field when ``many=True`` (:issue:`298`). Thanks :user:`nelfin` for the catch and patch.\n\n2.1.1 (2015-10-07)\n------------------\n\nBug fixes:\n\n- ``Constant`` field deserializes to its value regardless of whether its field name is present in input data (:issue:`291`). Thanks :user:`fayazkhan` for reporting.\n\n2.1.0 (2015-09-30)\n------------------\n\nFeatures:\n\n- Add ``Dict`` field for arbitrary mapping data (:issue:`251`). Thanks :user:`dwieeb` for adding this and :user:`Dowwie` for the suggestion.\n- Add ``Field.root`` property, which references the field's Schema.\n\nDeprecation/Removals:\n\n- The ``extra`` param of ``Schema`` is deprecated. Add extra data in a ``post_load`` method instead.\n- ``UnmarshallingError`` and ``MarshallingError`` are removed.\n\nBug fixes:\n\n- Fix storing multiple schema-level validation errors (:issue:`287`). Thanks :user:`evgeny-sureev` for the patch.\n- If ``missing=None`` on a field, ``allow_none`` will be set to ``True``.\n\nOther changes:\n\n- A ``List's`` inner field will have the list field set as its parent. Use ``root`` to access the ``Schema``.\n\n2.0.0 (2015-09-25)\n------------------\n\nFeatures:\n\n- Make error messages configurable at the class level and instance level (``Field.default_error_messages`` attribute and ``error_messages`` parameter, respectively).\n\nDeprecation/Removals:\n\n- Remove ``make_object``. Use a ``post_load`` method instead (:issue:`277`).\n- Remove the ``error`` parameter and attribute of ``Field``.\n- Passing string arguments to ``required`` and ``allow_none`` is deprecated. Pass the ``error_messages`` argument instead. **This API will be removed in version 2.2**.\n- Remove ``Arbitrary``, ``Fixed``, and ``Price`` fields (:issue:`86`). Use ``Decimal`` instead.\n- Remove ``Select`` / ``Enum`` fields (:issue:`135`). Use the ``OneOf`` validator instead.\n\nBug fixes:\n\n- Fix error format for ``Nested`` fields when ``many=True``. Thanks :user:`alexmorken`.\n- ``pre_dump`` methods are invoked before implicit field creation. Thanks :user:`makmanalp` for reporting.\n- Return correct \"required\" error message for ``Nested`` field.\n- The ``only`` argument passed to a ``Schema`` is bounded by the ``fields`` option (:issue:`183`). Thanks :user:`lustdante` for the suggestion.\n\nChanges from 2.0.0rc2:\n\n- ``error_handler`` and ``accessor`` options are replaced with the ``handle_error`` and ``get_attribute`` methods :issue:`284`.\n- Remove ``marshmallow.compat.plain_function`` since it is no longer used.\n- Non-collection values are invalid input for ``List`` field (:issue:`231`). Thanks :user:`density` for reporting.\n- Bug fix: Prevent infinite loop when validating a required, self-nested field. Thanks :user:`Bachmann1234` for the fix.\n\n2.0.0rc2 (2015-09-16)\n---------------------\n\nDeprecation/Removals:\n\n- ``make_object`` is deprecated. Use a ``post_load`` method instead (:issue:`277`). **This method will be removed in the final 2.0 release**.\n- ``Schema.accessor`` and ``Schema.error_handler`` decorators are deprecated. Define the ``accessor`` and ``error_handler`` class Meta options instead.\n\nBug fixes:\n\n- Allow non-field names to be passed to ``ValidationError`` (:issue:`273`). Thanks :user:`evgeny-sureev` for the catch and patch.\n\nChanges from 2.0.0rc1:\n\n- The ``raw`` parameter of the ``pre_*``, ``post_*``, ``validates_schema`` decorators was renamed to ``pass_many`` (:issue:`276`).\n- Add ``pass_original`` parameter to ``post_load`` and ``post_dump`` (:issue:`216`).\n- Methods decorated with the ``pre_*``, ``post_*``, and ``validates_*`` decorators must be instance methods. Class methods and instance methods are not supported at this time.\n\n2.0.0rc1 (2015-09-13)\n---------------------\n\nFeatures:\n\n- *Backwards-incompatible*: ``fields.Field._deserialize`` now takes ``attr`` and ``data`` as arguments (:issue:`172`). Thanks :user:`alexmic` and :user:`kevinastone` for the suggestion.\n- Allow a ``Field's`` ``attribute`` to be modified during deserialization (:issue:`266`). Thanks :user:`floqqi`.\n- Allow partially-valid data to be returned for ``Nested`` fields (:issue:`269`). Thanks :user:`jomag` for the suggestion.\n- Add ``Schema.on_bind_field`` hook which allows a ``Schema`` to modify its fields when they are bound.\n- Stricter validation of string, boolean, and number fields (:issue:`231`). Thanks :user:`touilleMan` for the suggestion.\n- Improve consistency of error messages.\n\nDeprecation/Removals:\n\n- ``Schema.validator``, ``Schema.preprocessor``, and ``Schema.data_handler`` are removed. Use ``validates_schema``, ``pre_load``, and ``post_dump`` instead.\n- ``QuerySelect``  and ``QuerySelectList`` are deprecated (:issue:`227`). **These fields will be removed in version 2.1.**\n- ``utils.get_callable_name`` is removed.\n\nBug fixes:\n\n- If a date format string is passed to a ``DateTime`` field, it is always used for deserialization (:issue:`248`). Thanks :user:`bartaelterman` and :user:`praveen-p`.\n\nSupport:\n\n- Documentation: Add \"Using Context\" section to \"Extending Schemas\" page (:issue:`224`).\n- Include tests and docs in release tarballs (:issue:`201`).\n- Test against Python 3.5.\n\n2.0.0b5 (2015-08-23)\n--------------------\n\nFeatures:\n\n- If a field corresponds to a callable attribute, it will be called upon serialization. Thanks :user:`alexmorken`.\n- Add ``load_only`` and ``dump_only`` ``class Meta`` options. Thanks :user:`kelvinhammond`.\n- If a ``Nested`` field is required, recursively validate any required fields in the nested schema (:issue:`235`). Thanks :user:`max-orhai`.\n- Improve error message if a list of dicts is not passed to a ``Nested`` field for which ``many=True``. Thanks again :user:`max-orhai`.\n\nBug fixes:\n\n- ``make_object`` is only called after all validators and postprocessors have finished (:issue:`253`). Thanks :user:`sunsongxp` for reporting.\n- If an invalid type is passed to ``Schema`` and ``strict=False``, store a ``_schema`` error in the errors dict rather than raise an exception (:issue:`261`). Thanks :user:`density` for reporting.\n\nOther changes:\n\n- ``make_object`` is only called when input data are completely valid (:issue:`243`). Thanks :user:`kissgyorgy` for reporting.\n- Change default error messages for ``URL`` and ``Email`` validators so that they don't include user input (:issue:`255`).\n- ``Email`` validator permits email addresses with non-ASCII characters, as per RFC 6530 (:issue:`221`). Thanks :user:`lextoumbourou` for reporting and :user:`mwstobo` for sending the patch.\n\n2.0.0b4 (2015-07-07)\n--------------------\n\nFeatures:\n\n- ``List`` field respects the ``attribute`` argument of the inner field. Thanks :user:`jmcarp`.\n- The ``container`` field ``List`` field has access to its parent ``Schema`` via its ``parent`` attribute. Thanks again :user:`jmcarp`.\n\nDeprecation/Removals:\n\n- Legacy validator functions have been removed (:issue:`73`). Use the class-based validators in ``marshmallow.validate`` instead.\n\nBug fixes:\n\n- ``fields.Nested`` correctly serializes nested ``sets`` (:issue:`233`). Thanks :user:`traut`.\n\nChanges from 2.0.0b3:\n\n- If ``load_from`` is used on deserialization, the value of ``load_from`` is used as the key in the errors dict (:issue:`232`). Thanks :user:`alexmorken`.\n\n2.0.0b3 (2015-06-14)\n---------------------\n\nFeatures:\n\n- Add ``marshmallow.validates_schema`` decorator for defining schema-level validators (:issue:`116`).\n- Add ``marshmallow.validates`` decorator for defining field validators as Schema methods (:issue:`116`). Thanks :user:`philtay`.\n- Performance improvements.\n- Defining ``__marshallable__`` on complex objects is no longer necessary.\n- Add ``fields.Constant``. Thanks :user:`kevinastone`.\n\nDeprecation/Removals:\n\n- Remove ``skip_missing`` class Meta option. By default, missing inputs are excluded from serialized output (:issue:`211`).\n- Remove optional ``context`` parameter that gets passed to methods for ``Method`` fields.\n- ``Schema.validator`` is deprecated. Use ``marshmallow.validates_schema`` instead.\n- ``utils.get_func_name`` is removed. Use ``utils.get_callable_name`` instead.\n\nBug fixes:\n\n- Fix serializing values from keyed tuple types (regression of :issue:`28`). Thanks :user:`makmanalp` for reporting.\n\nOther changes:\n\n- Remove unnecessary call to ``utils.get_value`` for ``Function`` and ``Method`` fields (:issue:`208`). Thanks :user:`jmcarp`.\n- Serializing a collection without passing ``many=True`` will not result in an error. Be very careful to pass the ``many`` argument when necessary.\n\nSupport:\n\n- Documentation: Update Flask and Peewee examples. Update Quickstart.\n\nChanges from 2.0.0b2:\n\n- ``Boolean`` field serializes ``None`` to ``None``, for consistency with other fields (:issue:`213`). Thanks :user:`cmanallen` for reporting.\n- Bug fix: ``load_only`` fields do not get validated during serialization.\n- Implicit passing of original, raw data to Schema validators is removed. Use ``@marshmallow.validates_schema(pass_original=True)`` instead.\n\n2.0.0b2 (2015-05-03)\n--------------------\n\nFeatures:\n\n- Add useful ``__repr__`` methods to validators (:issue:`204`). Thanks :user:`philtay`.\n- *Backwards-incompatible*: By default, ``NaN``, ``Infinity``, and ``-Infinity`` are invalid values for ``fields.Decimal``. Pass ``allow_nan=True`` to allow these values. Thanks :user:`philtay`.\n\nChanges from 2.0.0b1:\n\n- Fix serialization of ``None`` for ``Time``, ``TimeDelta``, and ``Date`` fields (a regression introduced in 2.0.0a1).\n\nIncludes bug fixes from 1.2.6.\n\n2.0.0b1 (2015-04-26)\n--------------------\n\nFeatures:\n\n- Errored fields will not appear in (de)serialized output dictionaries (:issue:`153`, :issue:`202`).\n- Instantiate ``OPTIONS_CLASS`` in ``SchemaMeta``. This makes ``Schema.opts`` available in metaclass methods. It also causes validation to occur earlier (upon ``Schema`` class declaration rather than instantiation).\n- Add ``SchemaMeta.get_declared_fields`` class method to support adding additional declared fields.\n\nDeprecation/Removals:\n\n- Remove ``allow_null`` parameter of ``fields.Nested`` (:issue:`203`).\n\nChanges from 2.0.0a1:\n\n- Fix serialization of `None` for ``fields.Email``.\n\n2.0.0a1 (2015-04-25)\n--------------------\n\nFeatures:\n\n- *Backwards-incompatible*: When ``many=True``, the errors dictionary returned by ``dump`` and ``load`` will be keyed on the indices of invalid items in the (de)serialized collection (:issue:`75`). Add ``index_errors=False`` on a Schema's ``class Meta`` options to disable this behavior.\n- *Backwards-incompatible*: By default, fields will raise a ValidationError if the input is ``None``. The ``allow_none`` parameter can override this behavior.\n- *Backwards-incompatible*: A ``Field's`` ``default`` parameter is only used if explicitly set and the field's value is missing in the input to `Schema.dump`. If not set, the key will not be present in the serialized output for missing values . This is the behavior for *all* fields. ``fields.Str`` no longer defaults to ``''``, ``fields.Int`` no longer defaults to ``0``, etc. (:issue:`199`). Thanks :user:`jmcarp` for the feedback.\n- In ``strict`` mode, a ``ValidationError`` is raised. Error messages are accessed via the ``ValidationError's`` ``messages`` attribute (:issue:`128`).\n- Add ``allow_none`` parameter to ``fields.Field``. If ``False`` (the default), validation fails when the field's value is ``None`` (:issue:`76`, :issue:`111`). If ``allow_none`` is ``True``, ``None`` is considered valid and will deserialize to ``None``.\n- Schema-level validators can store error messages for multiple fields (:issue:`118`). Thanks :user:`ksesong` for the suggestion.\n- Add ``pre_load``, ``post_load``, ``pre_dump``, and ``post_dump`` Schema method decorators for defining pre- and post- processing routines (:issue:`153`, :issue:`179`). Thanks :user:`davidism`, :user:`taion`, and :user:`jmcarp` for the suggestions and feedback. Thanks :user:`taion` for the implementation.\n- Error message for ``required`` validation is configurable. (:issue:`78`). Thanks :user:`svenstaro` for the suggestion. Thanks :user:`0xDCA` for the implementation.\n- Add ``load_from`` parameter to fields (:issue:`125`). Thanks :user:`hakjoon`.\n- Add ``load_only`` and ``dump_only`` parameters to fields (:issue:`61`, :issue:`87`). Thanks :user:`philtay`.\n- Add `missing` parameter to fields (:issue:`115`). Thanks :user:`philtay`.\n- Schema validators can take an optional ``raw_data`` argument which contains raw input data, incl. data not specified in the schema (:issue:`127`). Thanks :user:`ryanlowe0`.\n- Add ``validate.OneOf`` (:issue:`135`) and ``validate.ContainsOnly`` (:issue:`149`) validators. Thanks :user:`philtay`.\n- Error messages for validators can be interpolated with `{input}` and other values (depending on the validator).\n- ``fields.TimeDelta`` always serializes to an integer value in order to avoid rounding errors (:issue:`105`). Thanks :user:`philtay`.\n- Add ``include`` class Meta option to support field names which are Python keywords (:issue:`139`). Thanks :user:`nickretallack` for the suggestion.\n- ``exclude`` parameter is respected when used together with ``only`` parameter (:issue:`165`). Thanks :user:`lustdante` for the catch and patch.\n- ``fields.List`` works as expected with generators and sets (:issue:`185`). Thanks :user:`sergey-aganezov-jr`.\n\nDeprecation/Removals:\n\n- ``MarshallingError`` and ``UnmarshallingError`` error are deprecated in favor of a single ``ValidationError`` (:issue:`160`).\n- ``context`` argument passed to Method fields is deprecated. Use ``self.context`` instead (:issue:`184`).\n- Remove ``ForcedError``.\n- Remove support for generator functions that yield validators (:issue:`74`). Plain generators of validators are still supported.\n- The ``Select/Enum`` field is deprecated in favor of using ``validate.OneOf`` validator (:issue:`135`).\n- Remove legacy, pre-1.0 API (``Schema.data`` and ``Schema.errors`` properties) (:issue:`73`).\n- Remove ``null`` value.\n\nOther changes:\n\n- ``Marshaller``, ``Unmarshaller`` were moved to ``marshmallow.marshalling``. These should be considered private API (:issue:`129`).\n- Make ``allow_null=True`` the default for ``Nested`` fields. This will make ``None`` serialize to ``None`` rather than a dictionary with empty values (:issue:`132`). Thanks :user:`nickrellack` for the suggestion.\n\n1.2.6 (2015-05-03)\n------------------\n\nBug fixes:\n\n- Fix validation error message for ``fields.Decimal``.\n- Allow error message for ``fields.Boolean`` to be customized with the ``error`` parameter (like other fields).\n\n1.2.5 (2015-04-25)\n------------------\n\nBug fixes:\n\n- Fix validation of invalid types passed to a ``Nested`` field when ``many=True`` (:issue:`188`). Thanks :user:`juanrossi` for reporting.\n\nSupport:\n\n- Fix pep8 dev dependency for flake8. Thanks :user:`taion`.\n\n1.2.4 (2015-03-22)\n------------------\n\nBug fixes:\n\n- Fix behavior of ``as_string`` on ``fields.Integer`` (:issue:`173`). Thanks :user:`taion` for the catch and patch.\n\nOther changes:\n\n- Remove dead code from ``fields.Field``. Thanks :user:`taion`.\n\nSupport:\n\n- Correction to ``_postprocess`` method in docs. Thanks again :user:`taion`.\n\n1.2.3 (2015-03-15)\n------------------\n\nBug fixes:\n\n- Fix inheritance of ``ordered`` class Meta option (:issue:`162`). Thanks :user:`stephenfin` for reporting.\n\n1.2.2 (2015-02-23)\n------------------\n\nBug fixes:\n\n- Fix behavior of ``skip_missing`` and ``accessor`` options when ``many=True`` (:issue:`137`). Thanks :user:`3rdcycle`.\n- Fix bug that could cause an ``AttributeError`` when nesting schemas with schema-level validators (:issue:`144`). Thanks :user:`vovanbo` for reporting.\n\n1.2.1 (2015-01-11)\n------------------\n\nBug fixes:\n\n- A ``Schema's`` ``error_handler``--if defined--will execute if ``Schema.validate`` returns validation errors (:issue:`121`).\n- Deserializing `None` returns `None` rather than raising an ``AttributeError`` (:issue:`123`). Thanks :user:`RealSalmon` for the catch and patch.\n\n1.2.0 (2014-12-22)\n------------------\n\nFeatures:\n\n- Add ``QuerySelect`` and ``QuerySelectList`` fields (:issue:`84`).\n- Convert validators in ``marshmallow.validate`` into class-based callables to make them easier to use when declaring fields (:issue:`85`).\n- Add ``Decimal`` field which is safe to use when dealing with precise numbers (:issue:`86`).\n\nThanks :user:`philtay` for these contributions.\n\nBug fixes:\n\n- ``Date`` fields correctly deserializes to a ``datetime.date`` object when ``python-dateutil`` is not installed (:issue:`79`). Thanks :user:`malexer` for the catch and patch.\n- Fix bug that raised an ``AttributeError`` when using a class-based validator.\n- Fix ``as_string`` behavior of Number fields when serializing to default value.\n- Deserializing ``None`` or the empty string with either a ``DateTime``, ``Date``, ``Time`` or ``TimeDelta`` results in the correct unmarshalling errors (:issue:`96`). Thanks :user:`svenstaro` for reporting and helping with this.\n- Fix error handling when deserializing invalid UUIDs (:issue:`106`). Thanks :user:`vesauimonen` for the catch and patch.\n- ``Schema.loads`` correctly defaults to use the value of ``self.many`` rather than defaulting to ``False`` (:issue:`108`). Thanks :user:`davidism` for the catch and patch.\n- Validators, data handlers, and preprocessors are no longer shared between schema subclasses (:issue:`88`). Thanks :user:`amikholap` for reporting.\n- Fix error handling when passing a ``dict`` or ``list`` to a ``ValidationError`` (:issue:`110`). Thanks :user:`ksesong` for reporting.\n\nDeprecation:\n\n- The validator functions in the ``validate`` module are deprecated in favor of the class-based validators (:issue:`85`).\n- The ``Arbitrary``, ``Price``, and ``Fixed`` fields are deprecated in favor of the ``Decimal`` field (:issue:`86`).\n\nSupport:\n\n- Update docs theme.\n- Update contributing docs (:issue:`77`).\n- Fix namespacing example in \"Extending Schema\" docs. Thanks :user:`Ch00k`.\n- Exclude virtualenv directories from syntax checking (:issue:`99`). Thanks :user:`svenstaro`.\n\n\n1.1.0 (2014-12-02)\n------------------\n\nFeatures:\n\n- Add ``Schema.validate`` method which validates input data against a schema. Similar to ``Schema.load``, but does not call ``make_object`` and only returns the errors dictionary.\n- Add several validation functions to the ``validate`` module. Thanks :user:`philtay`.\n- Store field name and instance on exceptions raised in ``strict`` mode.\n\nBug fixes:\n\n- Fix serializing dictionaries when field names are methods of ``dict`` (e.g. ``\"items\"``). Thanks :user:`rozenm` for reporting.\n- If a Nested field is passed ``many=True``, ``None`` serializes to an empty list. Thanks :user:`nickretallack` for reporting.\n- Fix behavior of ``many`` argument passed to ``dump`` and ``load``. Thanks :user:`svenstaro` for reporting and helping with this.\n- Fix ``skip_missing`` behavior for ``String`` and ``List`` fields. Thanks :user:`malexer` for reporting.\n- Fix compatibility with python-dateutil 2.3.\n- More consistent error messages across ``DateTime``, ``TimeDelta``, ``Date``, and ``Time`` fields.\n\nSupport:\n\n- Update Flask and Peewee examples.\n\n1.0.1 (2014-11-18)\n------------------\n\nHotfix release.\n\n- Ensure that errors dictionary is correctly cleared on each call to ``Schema.dump`` and ``Schema.load``.\n\n1.0.0 (2014-11-16)\n------------------\n\nAdds new features, speed improvements, better error handling, and updated documentation.\n\n- Add ``skip_missing`` ``class Meta`` option.\n- A field's ``default`` may be a callable.\n- Allow accessor function to be configured via the ``Schema.accessor`` decorator or the ``__accessor__`` class member.\n- ``URL`` and ``Email`` fields are validated upon serialization.\n- ``dump`` and ``load`` can receive the ``many`` argument.\n- Move a number of utility functions from fields.py to utils.py.\n- More useful ``repr`` for ``Field`` classes.\n- If a field's default is ``fields.missing`` and its serialized value is ``None``, it will not be included in the final serialized result.\n- Schema.dumps no longer coerces its result to a binary string on Python 3.\n- *Backwards-incompatible*: Schema output is no longer an ``OrderedDict`` by default. If you want ordered field output, you must explicitly set the ``ordered`` option to ``True``.\n- *Backwards-incompatible*: ``error`` parameter of the ``Field`` constructor is deprecated. Raise a ``ValidationError`` instead.\n- Expanded test coverage.\n- Updated docs.\n\n1.0.0-a (2014-10-19)\n--------------------\n\nMajor reworking and simplification of the public API, centered around support for deserialization, improved validation, and a less stateful ``Schema`` class.\n\n* Rename ``Serializer`` to ``Schema``.\n* Support for deserialization.\n* Use the ``Schema.dump`` and ``Schema.load`` methods for serializing and deserializing, respectively.\n* *Backwards-incompatible*: Remove ``Serializer.json`` and ``Serializer.to_json``. Use ``Schema.dumps`` instead.\n* Reworked fields interface.\n* *Backwards-incompatible*: ``Field`` classes implement ``_serialize`` and ``_deserialize`` methods. ``serialize`` and ``deserialize`` comprise the public API for a ``Field``. ``Field.format`` and ``Field.output`` have been removed.\n* Add ``exceptions.ForcedError`` which allows errors to be raised during serialization (instead of storing errors in the ``errors`` dict).\n* *Backwards-incompatible*: ``DateTime`` field serializes to ISO8601 format by default (instead of RFC822).\n* *Backwards-incompatible*: Remove ``Serializer.factory`` method. It is no longer necessary with the ``dump`` method.\n* *Backwards-incompatible*: Allow nesting a serializer within itself recursively. Use ``exclude`` or ``only`` to prevent infinite recursion.\n* *Backwards-incompatible*: Multiple errors can be stored for a single field. The errors dictionary returned by ``load`` and ``dump`` have lists of error messages keyed by field name.\n* Remove ``validated`` decorator. Validation occurs within ``Field`` methods.\n* ``Function`` field raises a ``ValueError`` if an uncallable object is passed to its constructor.\n* ``Nested`` fields inherit context from their parent.\n* Add ``Schema.preprocessor`` and ``Schema.validator`` decorators for registering preprocessing and schema-level validation functions respectively.\n* Custom error messages can be specified by raising a ``ValidationError`` within a validation function.\n* Extra keyword arguments passed to a Field are stored as metadata.\n* Fix ordering of field output.\n* Fix behavior of the ``required`` parameter on ``Nested`` fields.\n* Fix serializing keyed tuple types (e.g. ``namedtuple``) with ``class Meta`` options.\n* Fix default value for ``Fixed`` and ``Price`` fields.\n* Fix serialization of binary strings.\n* ``Schemas`` can inherit fields from non-``Schema`` base classes (e.g. mixins). Also, fields are inherited according to the MRO (rather than recursing over base classes). Thanks :user:`jmcarp`.\n* Add ``Str``, ``Bool``, and ``Int`` field class aliases.\n\n0.7.0 (2014-06-22)\n------------------\n\n* Add ``Serializer.error_handler`` decorator that registers a custom error handler.\n* Add ``Serializer.data_handler`` decorator that registers data post-processing callbacks.\n* *Backwards-incompatible*: ``process_data`` method is deprecated. Use the ``data_handler`` decorator instead.\n* Fix bug that raised error when passing ``extra`` data together with ``many=True``. Thanks :user:`buttsicles` for reporting.\n* If ``required=True`` validation is violated for a given ``Field``, it will raise an error message that is different from the message specified by the ``error`` argument. Thanks :user:`asteinlein`.\n* More generic error message raised when required field is missing.\n* ``validated`` decorator should only wrap a ``Field`` class's ``output`` method.\n\n0.6.0 (2014-06-03)\n------------------\n\n* Fix bug in serializing keyed tuple types, e.g. ``namedtuple`` and ``KeyedTuple``.\n* Nested field can load a serializer by its class name as a string. This makes it easier to implement 2-way nesting.\n* Make ``Serializer.data`` override-able.\n\n0.5.5 (2014-05-02)\n------------------\n\n* Add ``Serializer.factory`` for creating a factory function that returns a Serializer instance.\n* ``MarshallingError`` stores its underlying exception as an instance variable. This is useful for inspecting errors.\n* ``fields.Select`` is aliased to ``fields.Enum``.\n* Add ``fields.__all__`` and ``marshmallow.__all__`` so that the modules can be more easily extended.\n* Expose ``Serializer.OPTIONS_CLASS`` as a class variable so that options defaults can be overridden.\n* Add ``Serializer.process_data`` hook that allows subclasses to manipulate the final output data.\n\n0.5.4 (2014-04-17)\n------------------\n\n* Add ``json_module`` class Meta option.\n* Add ``required`` option to fields . Thanks :user:`DeaconDesperado`.\n* Tested on Python 3.4 and PyPy.\n\n0.5.3 (2014-03-02)\n------------------\n\n* Fix ``Integer`` field default. It is now ``0`` instead of ``0.0``. Thanks :user:`kalasjocke`.\n* Add ``context`` param to ``Serializer``. Allows accessing arbitrary objects in ``Function`` and ``Method`` fields.\n* ``Function`` and ``Method`` fields raise ``MarshallingError`` if their argument is uncallable.\n\n\n0.5.2 (2014-02-10)\n------------------\n\n* Enable custom field validation via the ``validate`` parameter.\n* Add ``utils.from_rfc`` for parsing RFC datestring to Python datetime object.\n\n0.5.1 (2014-02-02)\n------------------\n\n* Avoid unnecessary attribute access in ``utils.to_marshallable_type`` for improved performance.\n* Fix RFC822 formatting for localized datetimes.\n\n0.5.0 (2013-12-29)\n------------------\n\n* Can customize validation error messages by passing the ``error`` parameter to a field.\n* *Backwards-incompatible*: Rename ``fields.NumberField`` -> ``fields.Number``.\n* Add ``fields.Select``. Thanks :user:`ecarreras`.\n* Support nesting a Serializer within itself by passing ``\"self\"`` into ``fields.Nested`` (only up to depth=1).\n* *Backwards-incompatible*: No implicit serializing of collections. Must set ``many=True`` if serializing to a list. This ensures that marshmallow handles singular objects correctly, even if they are iterable.\n* If Nested field ``only`` parameter is a field name, only return a single value for the nested object (instead of a dict) or a flat list of values.\n* Improved performance and stability.\n\n0.4.1 (2013-12-01)\n------------------\n\n* An object's ``__marshallable__`` method, if defined, takes precedence over ``__getitem__``.\n* Generator expressions can be passed to a serializer.\n* Better support for serializing list-like collections (e.g. ORM querysets).\n* Other minor bugfixes.\n\n0.4.0 (2013-11-24)\n------------------\n\n* Add ``additional`` `class Meta` option.\n* Add ``dateformat`` `class Meta` option.\n* Support for serializing UUID, date, time, and timedelta objects.\n* Remove ``Serializer.to_data`` method. Just use ``Serialize.data`` property.\n* String field defaults to empty string instead of ``None``.\n* *Backwards-incompatible*: ``isoformat`` and ``rfcformat`` functions moved to utils.py.\n* *Backwards-incompatible*: Validation functions moved to validate.py.\n* *Backwards-incompatible*: Remove types.py.\n* Reorder parameters to ``DateTime`` field (first parameter is dateformat).\n* Ensure that ``to_json`` returns bytestrings.\n* Fix bug with including an object property in ``fields`` Meta option.\n* Fix bug with passing ``None`` to a serializer.\n\n0.3.1 (2013-11-16)\n------------------\n\n* Fix bug with serializing dictionaries.\n* Fix error raised when serializing empty list.\n* Add ``only`` and ``exclude`` parameters to Serializer constructor.\n* Add ``strict`` parameter and option: causes Serializer to raise an error if invalid data are passed in, rather than storing errors.\n* Updated Flask + SQLA example in docs.\n\n0.3.0 (2013-11-14)\n------------------\n\n* Declaring Serializers just got easier. The ``class Meta`` paradigm allows you to specify fields more concisely. Can specify ``fields`` and ``exclude`` options.\n* Allow date formats to be changed by passing ``format`` parameter to ``DateTime`` field constructor. Can either be ``\"rfc\"`` (default), ``\"iso\"``, or a date format string.\n* More useful error message when declaring fields as classes (instead of an instance, which is the correct usage).\n* Rename ``MarshallingException`` -> ``MarshallingError``.\n* Rename ``marshmallow.core`` -> ``marshmallow.serializer``.\n\n0.2.1 (2013-11-12)\n------------------\n\n* Allow prefixing field names.\n* Fix storing errors on Nested Serializers.\n* Python 2.6 support.\n\n0.2.0 (2013-11-11)\n------------------\n\n* Field-level validation.\n* Add ``fields.Method``.\n* Add ``fields.Function``.\n* Allow binding of extra data to a serialized object by passing the ``extra`` param when initializing a ``Serializer``.\n* Add ``relative`` parameter to ``fields.Url`` that allows for relative URLs.\n\n0.1.0 (2013-11-10)\n------------------\n\n* First release.\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "For the marshmallow code of conduct, see https://marshmallow.readthedocs.io/en/latest/code_of_conduct.html\n"
  },
  {
    "path": "CONTRIBUTING.rst",
    "content": "Contributing guidelines\n=======================\n\nSo you're interested in contributing to marshmallow or `one of our associated\nprojects <https://github.com/marshmallow-code>`__? That's awesome! We\nwelcome contributions from anyone willing to work in good faith with\nother contributors and the community (see also our\n:doc:`code_of_conduct`).\n\nSecurity contact information\n----------------------------\n\nTo report a security vulnerability, please use the\n`Tidelift security contact <https://tidelift.com/security>`_.\nTidelift will coordinate the fix and disclosure.\n\nQuestions, feature requests, bug reports, and feedback…\n-------------------------------------------------------\n\n…should all be reported on the `Github Issue Tracker`_ .\n\n.. _`Github Issue Tracker`: https://github.com/marshmallow-code/marshmallow/issues?state=open\n\nWays to contribute\n------------------\n\n- 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!\n- Improve `the docs <https://marshmallow.readthedocs.io>`_.\n  For straightforward edits, click the edit button in the top-right corner of the page.\n  See the :ref:`Documentation <contributing_documentation>` section of this page if you want to build the docs locally.\n- If you think you've found a bug, `open an issue <https://github.com/marshmallow-code/marshmallow/issues>`_.\n- Contribute an :ref:`example usage <contributing_examples>` of marshmallow.\n- Send a PR for an open issue (especially one `labeled \"help wanted\" <https://github.com/marshmallow-code/marshmallow/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22>`_). The next section details how to contribute code.\n\n\nContributing code\n-----------------\n\nSetting up for local development\n++++++++++++++++++++++++++++++++\n\n1. Fork marshmallow_ on Github.\n\n.. code-block:: shell-session\n\n    $ git clone https://github.com/marshmallow-code/marshmallow.git\n    $ cd marshmallow\n\n2. Install development requirements. **It is highly recommended that you use a virtualenv.**\n   Use the following command to install an editable version of\n   marshmallow along with its development requirements.\n\n.. code-block:: shell-session\n\n    # After activating your virtualenv\n    $ pip install -e '.[dev]'\n\n3. Install the pre-commit hooks, which will format and lint your git staged files.\n\n.. code-block:: shell-session\n\n    # The pre-commit CLI was installed above\n    $ pre-commit install --allow-missing-config\n\nGit branch structure\n++++++++++++++++++++\n\nmarshmallow abides by the following branching model:\n\n``dev``\n    Current development branch. **New features should branch off here**.\n\n``X.Y-line``\n    Maintenance branch for release ``X.Y``. **Bug fixes should be sent to the most recent release branch.** A maintainer will forward-port the fix to ``dev``. Note: exceptions may be made for bug fixes that introduce large code changes.\n\n**Always make a new branch for your work**, no matter how small. Also, **do not put unrelated changes in the same branch or pull request**. This makes it more difficult to merge your changes.\n\nPull requests\n++++++++++++++\n\n1. Create a new local branch.\n\nFor a new feature:\n\n.. code-block:: shell-session\n\n    $ git checkout -b name-of-feature dev\n\nFor a bugfix:\n\n.. code-block:: shell-session\n\n    $ git checkout -b fix-something 3.x-line\n\n2. Commit your changes. Write `good commit messages <https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html>`_.\n\n.. code-block:: shell-session\n\n    $ git commit -m \"Detailed commit message\"\n    $ git push origin name-of-feature\n\n3. Before submitting a pull request, check the following:\n\n- If the pull request adds functionality, it is tested and the docs are updated.\n- You've added yourself to ``AUTHORS.rst``.\n\n4. Submit a pull request to ``marshmallow-code:dev`` or the appropriate maintenance branch. The `CI <https://dev.azure.com/sloria1/sloria/_build/latest?definitionId=5&branchName=dev>`_ build must be passing before your pull request is merged.\n\nRunning tests\n+++++++++++++\n\nTo run all tests:\n\n.. code-block:: shell-session\n\n    $ pytest\n\nTo run formatting and syntax checks:\n\n.. code-block:: shell-session\n\n    $ tox -e lint\n\n(Optional) To run tests in all supported Python versions in their own virtual environments (must have each interpreter installed):\n\n.. code-block:: shell-session\n\n    $ tox\n\n.. _contributing_documentation:\n\nDocumentation\n+++++++++++++\n\nContributions 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_.\n\nTo build and serve the docs in \"watch\" mode:\n\n.. code-block:: shell-session\n\n   $ tox -e docs-serve\n\nChanges to documentation will automatically trigger a rebuild.\n\n\n.. _contributing_examples:\n\nContributing examples\n+++++++++++++++++++++\n\nHave a usage example you'd like to share? A custom `Field <marshmallow.fields.Field>` that others might find useful? Feel free to add it to the `examples <https://github.com/marshmallow-code/marshmallow/tree/dev/examples>`_ directory and send a pull request.\n\n\n.. _Sphinx: https://www.sphinx-doc.org/\n.. _`reStructuredText`: https://docutils.sourceforge.io/rst.html\n.. _marshmallow: https://github.com/marshmallow-code/marshmallow\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright Steven Loria and contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "NOTICE",
    "content": "marshmallow includes code adapted from Django.\n\nDjango License\n==============\n\nCopyright (c) Django Software Foundation and individual contributors.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n    1. Redistributions of source code must retain the above copyright notice,\n       this list of conditions and the following disclaimer.\n\n    2. Redistributions in binary form must reproduce the above copyright\n       notice, this list of conditions and the following disclaimer in the\n       documentation and/or other materials provided with the distribution.\n\n    3. Neither the name of Django nor the names of its contributors may be used\n       to endorse or promote products derived from this software without\n       specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\nANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.rst",
    "content": "********************************************\nmarshmallow: simplified object serialization\n********************************************\n\n|pypi| |build-status| |pre-commit| |docs|\n\n.. |pypi| image:: https://badgen.net/pypi/v/marshmallow\n    :target: https://pypi.org/project/marshmallow/\n    :alt: Latest version\n\n.. |build-status| image:: https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml/badge.svg\n    :target: https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml\n    :alt: Build status\n\n.. |pre-commit| image:: https://results.pre-commit.ci/badge/github/marshmallow-code/marshmallow/dev.svg\n   :target: https://results.pre-commit.ci/latest/github/marshmallow-code/marshmallow/dev\n   :alt: pre-commit.ci status\n\n.. |docs| image:: https://readthedocs.org/projects/marshmallow/badge/\n   :target: https://marshmallow.readthedocs.io/\n   :alt: Documentation\n\n.. start elevator-pitch\n\n**marshmallow** is an ORM/ODM/framework-agnostic library for converting complex datatypes, such as objects, to and from native Python datatypes.\n\n.. code-block:: python\n\n    from datetime import date\n    from pprint import pprint\n\n    from marshmallow import Schema, fields\n\n\n    class ArtistSchema(Schema):\n        name = fields.Str()\n\n\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        release_date = fields.Date()\n        artist = fields.Nested(ArtistSchema())\n\n\n    bowie = dict(name=\"David Bowie\")\n    album = dict(artist=bowie, title=\"Hunky Dory\", release_date=date(1971, 12, 17))\n\n    schema = AlbumSchema()\n    result = schema.dump(album)\n    pprint(result, indent=2)\n    # { 'artist': {'name': 'David Bowie'},\n    #   'release_date': '1971-12-17',\n    #   'title': 'Hunky Dory'}\n\nIn short, marshmallow schemas can be used to:\n\n- **Validate** input data.\n- **Deserialize** input data to app-level objects.\n- **Serialize** app-level objects to primitive Python types. The serialized objects can then be rendered to standard formats such as JSON for use in an HTTP API.\n\nGet it now\n==========\n\n.. code-block:: shell-session\n\n    $ pip install -U marshmallow\n\n.. end elevator-pitch\n\nDocumentation\n=============\n\nFull documentation is available at https://marshmallow.readthedocs.io/ .\n\nEcosystem\n=========\n\nA list of marshmallow-related libraries can be found at the GitHub wiki here:\n\nhttps://github.com/marshmallow-code/marshmallow/wiki/Ecosystem\n\nCredits\n=======\n\nContributors\n------------\n\nThis project exists thanks to all the people who contribute.\n\n**You're highly encouraged to participate in marshmallow's development.**\nCheck out the `Contributing Guidelines <https://marshmallow.readthedocs.io/en/latest/contributing.html>`_ to see how you can help.\n\nThank you to all who have already contributed to marshmallow!\n\n.. image:: https://opencollective.com/marshmallow/contributors.svg?width=890&button=false\n    :target: https://marshmallow.readthedocs.io/en/latest/authors.html\n    :alt: Contributors\n\nBackers\n-------\n\nIf you find marshmallow useful, please consider supporting the team with\na donation. Your donation helps move marshmallow forward.\n\nThank you to all our backers! [`Become a backer`_]\n\n.. _`Become a backer`: https://opencollective.com/marshmallow#backer\n\n.. image:: https://opencollective.com/marshmallow/backers.svg?width=890\n    :target: https://opencollective.com/marshmallow#backers\n    :alt: Backers\n\nSponsors\n--------\n\n.. start sponsors\n\nmarshmallow is sponsored by `Route4Me <https://route4me.com>`_.\n\n.. image:: https://github.com/user-attachments/assets/018c2e23-032e-4a11-98da-8b6dc25b9054\n    :target: https://route4me.com\n    :alt: Routing Planner\n\nSupport this project by becoming a sponsor (or ask your company to support this project by becoming a sponsor).\nYour logo will be displayed here with a link to your website. [`Become a sponsor`_]\n\n.. _`Become a sponsor`: https://opencollective.com/marshmallow#sponsor\n\n.. end sponsors\n\nProfessional Support\n====================\n\nProfessionally-supported marshmallow is now available through the\n`Tidelift Subscription <https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=pypi-marshmallow&utm_medium=readme>`_.\n\nTidelift gives software development teams a single source for purchasing and maintaining their software,\nwith professional-grade assurances from the experts who know it best,\nwhile seamlessly integrating with existing tools. [`Get professional support`_]\n\n.. _`Get professional support`: https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=marshmallow&utm_medium=referral&utm_campaign=github\n\n.. image:: https://user-images.githubusercontent.com/2379650/45126032-50b69880-b13f-11e8-9c2c-abd16c433495.png\n    :target: https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=pypi-marshmallow&utm_medium=readme\n    :alt: Get supported marshmallow with Tidelift\n\n\nProject Links\n=============\n\n- Docs: https://marshmallow.readthedocs.io/\n- Changelog: https://marshmallow.readthedocs.io/en/latest/changelog.html\n- Contributing Guidelines: https://marshmallow.readthedocs.io/en/latest/contributing.html\n- PyPI: https://pypi.org/project/marshmallow/\n- Issues: https://github.com/marshmallow-code/marshmallow/issues\n- Donate: https://opencollective.com/marshmallow\n\nLicense\n=======\n\nMIT licensed. See the bundled `LICENSE <https://github.com/marshmallow-code/marshmallow/blob/dev/LICENSE>`_ file for more details.\n"
  },
  {
    "path": "RELEASING.md",
    "content": "# Releasing\n\n1. Bump version in `pyproject.toml` and update the changelog\n   with today's date.\n2. Commit: `git commit -m \"Bump version and update changelog\"`\n3. Tag the commit: `git tag x.y.z`\n4. Push: `git push --tags origin dev`. CI will take care of the\n   PyPI release.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Contact Information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure.\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "marshmallow.docset\nmarshmallow.tgz\n"
  },
  {
    "path": "docs/_static/custom.css",
    "content": "/* Headings */\n\nh2, h3, h4, h5, h6 {\n  font-weight: 400;\n}\n\n/* UI elements: left and right sidebars, \"Back to top\" button, admonitions, Copy button */\n.sidebar-drawer, .toc-drawer, .back-to-top, .admonition, .copybtn {\n  /* Sans-serif system font stack */\n  font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;\n}\n\n/* Hide ToC caption text within the main body (but leave them in the side-bar). */\n/* https://github.com/hynek/structlog/blob/b488a8bf589a01aabc41e3bf8df81a9848cd426c/docs/_static/custom.css#L17-L20 */\n#furo-main-content span.caption-text {\n  display: none;\n}\n"
  },
  {
    "path": "docs/api_reference.rst",
    "content": ".. _api:\n\n.. toctree::\n    :caption: API Reference\n\n    top_level\n    marshmallow.schema\n    marshmallow.fields\n    marshmallow.decorators\n    marshmallow.validate\n    marshmallow.utils\n    marshmallow.experimental.context\n    marshmallow.exceptions\n\nPrivate API\n===========\n\n.. toctree::\n    :caption: Private API\n\n    marshmallow.types\n    marshmallow.class_registry\n    marshmallow.error_store\n"
  },
  {
    "path": "docs/authors.rst",
    "content": ".. include:: ../AUTHORS.rst\n"
  },
  {
    "path": "docs/changelog.rst",
    "content": ".. seealso::\n  Need help upgrading to newer versions? Check out the :doc:`upgrading guide <upgrading>`.\n\n.. include:: ../CHANGELOG.rst\n"
  },
  {
    "path": "docs/code_of_conduct.rst",
    "content": "Code of Conduct\n===============\n\nThis code of conduct applies to the marshmallow project and all associated\nprojects in the `marshmallow-code <https://github.com/marshmallow-code>`__\norganization.\n\n\n.. _coc-when-something-happens:\n\nWhen something happens\n----------------------\n\nIf you see a Code of Conduct violation, follow these steps:\n\n1. Let the person know that what they did is not appropriate and ask\n   them to stop and/or edit their message(s) or commits.\n2. That person should immediately stop the behavior and correct the\n   issue.\n3. If this doesn’t happen, or if you're uncomfortable speaking up,\n   :ref:`contact the maintainers <coc-contacting-maintainers>`.\n4. As soon as possible, a maintainer will look into the issue, and take\n   :ref:`further action (see below) <coc-further-enforcement>`, starting with\n   a warning, then temporary block, then long-term repo or organization\n   ban.\n\nWhen reporting, please include any relevant details, links, screenshots,\ncontext, or other information that may be used to better understand and\nresolve the situation.\n\n**The maintainer team will prioritize the well-being and comfort of the\nrecipients of the violation over the comfort of the violator.** See\n:ref:`some examples below <coc-enforcement-examples>`.\n\nOur pledge\n----------\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers of this project pledge to making\nparticipation in our community a harassment-free experience for\neveryone, regardless of age, body size, disability, ethnicity, gender\nidentity and expression, level of experience, technical preferences,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\nOur standards\n-------------\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n-  Using welcoming and inclusive language.\n-  Being respectful of differing viewpoints and experiences.\n-  Gracefully accepting constructive feedback.\n-  Focusing on what is best for the community.\n-  Showing empathy and kindness towards other community members.\n-  Encouraging and raising up your peers in the project so you can all\n   bask in hacks and glory.\n\nExamples of unacceptable behavior by participants include:\n\n-  The use of sexualized language or imagery and unwelcome sexual\n   attention or advances, including when simulated online. The only\n   exception to sexual topics is channels/spaces specifically for topics\n   of sexual identity.\n-  Casual mention of slavery or indentured servitude and/or false\n   comparisons of one's occupation or situation to slavery. Please\n   consider using or asking about alternate terminology when referring\n   to such metaphors in technology.\n-  Making light of/making mocking comments about trigger warnings and\n   content warnings.\n-  Trolling, insulting/derogatory comments, and personal or political\n   attacks.\n-  Public or private harassment, deliberate intimidation, or threats.\n-  Publishing others' private information, such as a physical or\n   electronic address, without explicit permission. This includes any\n   sort of \"outing\" of any aspect of someone's identity without their\n   consent.\n-  Publishing private screenshots or quotes of interactions in the\n   context of this project without all quoted users' *explicit* consent.\n-  Publishing of private communication that doesn't have to do with\n   reporting harassment.\n-  Any of the above even when `presented as \"ironic\" or\n   \"joking\" <https://en.wikipedia.org/wiki/Hipster_racism>`__.\n-  Any attempt to present \"reverse-ism\" versions of the above as\n   violations. Examples of reverse-isms are \"reverse racism\", \"reverse\n   sexism\", \"heterophobia\", and \"cisphobia\".\n-  Unsolicited explanations under the assumption that someone doesn't\n   already know it. Ask before you teach! Don't assume what people's\n   knowledge gaps are.\n-  `Feigning or exaggerating\n   surprise <https://www.recurse.com/manual#no-feigned-surprise>`__ when\n   someone admits to not knowing something.\n-  \"`Well-actuallies <https://www.recurse.com/manual#no-well-actuallys>`__\"\n-  Other conduct which could reasonably be considered inappropriate in a\n   professional or community setting.\n\nScope\n-----\n\nThis Code of Conduct applies both within spaces involving this project\nand in other spaces involving community members. This includes the\nrepository, its Pull Requests and Issue tracker, its Twitter community,\nprivate email communications in the context of the project, and any\nevents where members of the project are participating, as well as\nadjacent communities and venues affecting the project's members.\n\nDepending on the violation, the maintainers may decide that violations\nof this code of conduct that have happened outside of the scope of the\ncommunity may deem an individual unwelcome, and take appropriate action\nto maintain the comfort and safety of its members.\n\n.. _coc-other-community-standards:\n\nOther community standards\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAs a project on GitHub, this project is additionally covered by the\n`GitHub Community\nGuidelines <https://help.github.com/articles/github-community-guidelines/>`__.\n\nEnforcement of those guidelines after violations overlapping with the\nabove are the responsibility of the entities, and enforcement may happen\nin any or all of the services/communities.\n\nMaintainer enforcement process\n------------------------------\n\nOnce the maintainers get involved, they will follow a documented series\nof steps and do their best to preserve the well-being of project\nmembers. This section covers actual concrete steps.\n\n\n.. _coc-contacting-maintainers:\n\nContacting maintainers\n~~~~~~~~~~~~~~~~~~~~~~\n\nAs a small project, we don't yet have a Code of Conduct\nenforcement team. Hopefully that will be addressed as we grow, but for\nnow, any issues should be addressed to `@sloria\n<https://github.com/sloria>`__, via `email <mailto:oss@stevenloria.com>`__\nor any other medium that you feel comfortable with. Using words like\n\"marshmallow code of conduct\" in your subject will help make sure your\nmessage is noticed quickly.\n\n\n.. _coc-further-enforcement:\n\nFurther enforcement\n~~~~~~~~~~~~~~~~~~~\n\nIf you've already followed the :ref:`initial enforcement steps\n<coc-when-something-happens>`, these are the steps maintainers will\ntake for further enforcement, as needed:\n\n1. Repeat the request to stop.\n2. If the person doubles down, they will be given an official warning. The PR or Issue\n   may be locked.\n3. If the behavior continues or is repeated later, the person will be\n   blocked from participating for 24 hours.\n4. If the behavior continues or is repeated after the temporary block, a\n   long-term (6-12mo) ban will be used.\n5. If after this the behavior still continues, a permanent ban may be\n   enforced.\n\nOn top of this, maintainers may remove any offending messages, images,\ncontributions, etc, as they deem necessary.\n\nMaintainers reserve full rights to skip any of these steps, at their\ndiscretion, if the violation is considered to be a serious and/or\nimmediate threat to the health and well-being of members of the\ncommunity. These include any threats, serious physical or verbal\nattacks, and other such behavior that would be completely unacceptable\nin any social setting that puts our members at risk.\n\nMembers expelled from events or venues with any sort of paid attendance\nwill not be refunded.\n\nWho watches the watchers?\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nMaintainers and other leaders who do not follow or enforce the Code of\nConduct in good faith may face temporary or permanent repercussions as\ndetermined by other members of the project's leadership. These may\ninclude anything from removal from the maintainer team to a permanent\nban from the community.\n\nAdditionally, as a project hosted on GitHub, :ref:`their Code of\nConduct may be applied against maintainers of this project\n<coc-other-community-standards>`, externally of this project's\nprocedures.\n\n\n.. _coc-enforcement-examples:\n\nEnforcement examples\n--------------------\n\nThe best case\n~~~~~~~~~~~~~\n\nThe vast majority of situations work out like this. This interaction is\ncommon, and generally positive.\n\n    Alex: \"Yeah I used X and it was really crazy!\"\n\n    Patt (not a maintainer): \"Hey, could you not use that word? What\n    about 'ridiculous' instead?\"\n\n    Alex: \"oh sorry, sure.\" -> edits old comment to say \"it was really\n    confusing!\"\n\nThe maintainer case\n~~~~~~~~~~~~~~~~~~~\n\nSometimes, though, you need to get maintainers involved. Maintainers\nwill do their best to resolve conflicts, but people who were harmed by\nsomething **will take priority**.\n\n    Patt: \"Honestly, sometimes I just really hate using $library and\n    anyone who uses it probably sucks at their job.\"\n\n    Alex: \"Whoa there, could you dial it back a bit? There's a CoC thing\n    about attacking folks' tech use like that.\"\n\n    Patt: \"I'm not attacking anyone, what's your problem?\"\n\n    Alex: \"@maintainers hey uh. Can someone look at this issue? Patt is\n    getting a bit aggro. I tried to nudge them about it, but nope.\"\n\n    KeeperOfCommitBits: (on issue) \"Hey Patt, maintainer here. Could you\n    tone it down? This sort of attack is really not okay in this space.\"\n\n    Patt: \"Leave me alone I haven't said anything bad wtf is wrong with\n    you.\"\n\n    KeeperOfCommitBits: (deletes user's comment), \"@patt I mean it.\n    Please refer to the CoC over at (URL to this CoC) if you have\n    questions, but you can consider this an actual warning. I'd\n    appreciate it if you reworded your messages in this thread, since\n    they made folks there uncomfortable. Let's try and be kind, yeah?\"\n\n    Patt: \"@KeeperOfCommitBits Okay sorry. I'm just frustrated and I'm kinda\n    burnt out and I guess I got carried away. I'll DM Alex a note\n    apologizing and edit my messages. Sorry for the trouble.\"\n\n    KeeperOfCommitBits: \"@patt Thanks for that. I hear you on the\n    stress. Burnout sucks :/. Have a good one!\"\n\nThe nope case\n~~~~~~~~~~~~~\n\n    PepeTheFrog🐸: \"Hi, I am a literal actual nazi and I think white\n    supremacists are quite fashionable.\"\n\n    Patt: \"NOOOOPE. OH NOPE NOPE.\"\n\n    Alex: \"JFC NO. NOPE. @KeeperOfCommitBits NOPE NOPE LOOK HERE\"\n\n    KeeperOfCommitBits: \"👀 Nope. NOPE NOPE NOPE. 🔥\"\n\n    PepeTheFrog🐸 has been banned from all organization or user\n    repositories belonging to KeeperOfCommitBits.\n\nAttribution\n-----------\n\nThis Code of Conduct is based on `Trio's Code of Conduct <https://trio.readthedocs.io/en/latest/code-of-conduct.html>`_, which is based on the\n`WeAllJS Code of Conduct <https://wealljs.org/code-of-conduct>`__, which\nis itself based on `Contributor\nCovenant <https://contributor-covenant.org>`__, version 1.4, available at\nhttps://contributor-covenant.org/version/1/4, and the LGBTQ in Technology\nSlack `Code of Conduct <https://lgbtq.technology/coc.html>`__.\n"
  },
  {
    "path": "docs/conf.py",
    "content": "import importlib.metadata\n\nextensions = [\n    \"autodocsumm\",\n    \"sphinx.ext.autodoc\",\n    \"sphinx.ext.autodoc.typehints\",\n    \"sphinx.ext.intersphinx\",\n    \"sphinx.ext.viewcode\",\n    \"sphinx_copybutton\",\n    \"sphinx_issues\",\n    \"sphinxext.opengraph\",\n]\n\nprimary_domain = \"py\"\ndefault_role = \"py:obj\"\n\nintersphinx_mapping = {\"python\": (\"https://docs.python.org/3\", None)}\n\nissues_github_path = \"marshmallow-code/marshmallow\"\n\nsource_suffix = \".rst\"\nmaster_doc = \"index\"\n\nproject = \"marshmallow\"\ncopyright = \"Steven Loria and contributors\"  # noqa: A001\n\nversion = release = importlib.metadata.version(\"marshmallow\")\n\nexclude_patterns = [\"_build\"]\n# Ignore WARNING: more than one target found for cross-reference 'Schema': marshmallow.schema.Schema, marshmallow.Schema\nsuppress_warnings = [\"ref.python\"]\n\n# THEME\n\nhtml_theme = \"furo\"\nhtml_theme_options = {\n    \"light_logo\": \"marshmallow-logo-with-title.png\",\n    \"dark_logo\": \"marshmallow-logo-with-title-for-dark-theme.png\",\n    \"source_repository\": \"https://github.com/marshmallow-code/marshmallow\",\n    \"source_branch\": \"dev\",\n    \"source_directory\": \"docs/\",\n    \"sidebar_hide_name\": True,\n    \"light_css_variables\": {\n        # Serif system font stack: https://systemfontstack.com/\n        \"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;\",\n    },\n    \"top_of_page_buttons\": [\"view\", \"edit\"],\n}\npygments_dark_style = \"lightbulb\"\nhtml_favicon = \"_static/favicon.ico\"\nhtml_static_path = [\"_static\"]\nhtml_css_files = [\"custom.css\"]\nhtml_copy_source = False  # Don't copy source files to _build/sources\nhtml_show_sourcelink = False  # Don't link to source files\nogp_image = \"_static/marshmallow-logo-200.png\"\n\n# Strip the dollar prompt when copying code\n# https://sphinx-copybutton.readthedocs.io/en/latest/use.html#strip-and-configure-input-prompts-for-code-cells\ncopybutton_prompt_text = \"$ \"\n\nautodoc_default_options = {\n    \"exclude-members\": \"__new__\",\n    # Don't show signatures in the summary tables\n    \"autosummary-nosignatures\": True,\n    # Don't render summaries for classes within modules\n    \"autosummary-no-nesting\": True,\n}\n# Only display type hints next to params but not within the signature\n# to avoid the signature from getting too long\nautodoc_typehints = \"description\"\n"
  },
  {
    "path": "docs/contributing.rst",
    "content": ".. include:: ../CONTRIBUTING.rst\n"
  },
  {
    "path": "docs/custom_fields.rst",
    "content": "Custom fields\n=============\n\nThere are three ways to create a custom-formatted field for a `Schema <marshmallow.Schema>`:\n\n- Create a custom :class:`Field <marshmallow.fields.Field>` class\n- Use a :class:`Method <marshmallow.fields.Method>` field\n- Use a :class:`Function <marshmallow.fields.Function>` field\n\nThe method you choose will depend on the manner in which you intend to reuse the field.\n\nCreating a field class\n----------------------\n\nTo create a custom field class, create a subclass of :class:`marshmallow.fields.Field` and implement its :meth:`_serialize <marshmallow.fields.Field._serialize>` and/or :meth:`_deserialize <marshmallow.fields.Field._deserialize>` methods.\nField's type argument is the internal type, i.e. the type that the field deserializes to.\n\n.. code-block:: python\n\n    from marshmallow import fields, ValidationError\n\n\n    class PinCode(fields.Field[list[int]]):\n        \"\"\"Field that serializes to a string of numbers and deserializes\n        to a list of numbers.\n        \"\"\"\n\n        def _serialize(self, value, attr, obj, **kwargs):\n            if value is None:\n                return \"\"\n            return \"\".join(str(d) for d in value)\n\n        def _deserialize(self, value, attr, data, **kwargs):\n            try:\n                return [int(c) for c in value]\n            except ValueError as error:\n                raise ValidationError(\"Pin codes must contain only digits.\") from error\n\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.String()\n        created_at = fields.DateTime()\n        pin_code = PinCode()\n\nMethod fields\n-------------\n\nA :class:`Method <marshmallow.fields.Method>` field will serialize to the value returned by a method of the Schema. The method must take an ``obj`` parameter which is the object to be serialized.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.String()\n        created_at = fields.DateTime()\n        since_created = fields.Method(\"get_days_since_created\")\n\n        def get_days_since_created(self, obj):\n            return dt.datetime.now().day - obj.created_at.day\n\nFunction fields\n---------------\n\nA :class:`Function <marshmallow.fields.Function>` field will serialize the value of a function that is passed directly to it. Like a :class:`Method <marshmallow.fields.Method>` field, the function must take a single argument ``obj``.\n\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.String()\n        created_at = fields.DateTime()\n        uppername = fields.Function(lambda obj: obj.name.upper())\n\n`Method` and `Function` field deserialization\n---------------------------------------------\n\nBoth :class:`Function <marshmallow.fields.Function>` and :class:`Method <marshmallow.fields.Method>` receive an optional ``deserialize`` argument which defines how the field should be deserialized. The method or function passed to ``deserialize`` receives the input value for the field.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        # `Method` takes a method name (str), Function takes a callable\n        balance = fields.Method(\"get_balance\", deserialize=\"load_balance\")\n\n        def get_balance(self, obj):\n            return obj.income - obj.debt\n\n        def load_balance(self, value):\n            return float(value)\n\n\n    schema = UserSchema()\n    result = schema.load({\"balance\": \"100.00\"})\n    result[\"balance\"]  # => 100.0\n\n.. _using_context:\n\nUsing context\n-------------\n\nA field may need information about its environment to know how to (de)serialize a value.\n\nYou can use the experimental `Context <marshmallow.experimental.context.Context>` class\nto set and retrieve context.\n\nLet's say your ``UserSchema`` needs to output\nwhether or not a ``User`` is the author of a ``Blog`` or\nwhether a certain word appears in a ``Blog's`` title.\n\n.. code-block:: python\n\n    import typing\n    from dataclasses import dataclass\n\n    from marshmallow import Schema, fields\n    from marshmallow.experimental.context import Context\n\n\n    @dataclass\n    class User:\n        name: str\n\n\n    @dataclass\n    class Blog:\n        title: str\n        author: User\n\n\n    class ContextDict(typing.TypedDict):\n        blog: Blog\n\n\n    class UserSchema(Schema):\n        name = fields.String()\n\n        is_author = fields.Function(\n            lambda user: user == Context[ContextDict].get()[\"blog\"].author\n        )\n        likes_bikes = fields.Method(\"writes_about_bikes\")\n\n        def writes_about_bikes(self, user: User) -> bool:\n            return \"bicycle\" in Context[ContextDict].get()[\"blog\"].title.lower()\n\n.. note::\n    You can use `Context.get <marshmallow.experimental.context.Context.get>`\n    within custom fields, pre-/post-processing methods, and validators.\n\nWhen (de)serializing, set the context by using `Context <marshmallow.experimental.context.Context>` as a context manager.\n\n.. code-block:: python\n\n\n    user = User(\"Freddie Mercury\", \"fred@queen.com\")\n    blog = Blog(\"Bicycle Blog\", author=user)\n\n    schema = UserSchema()\n    with Context({\"blog\": blog}):\n        result = schema.dump(user)\n        print(result[\"is_author\"])  # => True\n        print(result[\"likes_bikes\"])  # => True\n\n\nCustomizing error messages\n--------------------------\n\nValidation error messages for fields can be configured at the class or instance level.\n\nAt the class level, default error messages are defined as a mapping from error codes to error messages.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n\n    class MyDate(fields.Date):\n        default_error_messages = {\"invalid\": \"Please provide a valid date.\"}\n\n.. note::\n    A `Field's` ``default_error_messages`` dictionary gets merged with its parent classes' ``default_error_messages`` dictionaries.\n\nError messages can also be passed to a `Field's` constructor.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class UserSchema(Schema):\n        name = fields.Str(\n            required=True, error_messages={\"required\": \"Please provide a name.\"}\n        )\n\n\nNext steps\n----------\n\n- Need to add schema-level validation, post-processing, or error handling behavior? See the :doc:`extending/index` page.\n- For example applications using marshmallow, check out the :doc:`examples/index` page.\n"
  },
  {
    "path": "docs/dashing.json",
    "content": "{\n  \"name\": \"marshmallow\",\n  \"package\": \"marshmallow\",\n  \"index\": \"_build/index.html\",\n  \"selectors\": {\n    \"dl.class dt\": {\n      \"type\": \"Class\",\n      \"attr\": \"id\"\n    },\n    \"dl.exception dt\": {\n      \"type\": \"Exception\",\n      \"attr\": \"id\"\n    },\n    \"dl.function dt\": {\n      \"type\": \"Function\",\n      \"attr\": \"id\"\n    }\n  },\n  \"icon32x32\": \"\",\n  \"allowJS\": false,\n  \"ExternalURL\": \"\"\n}\n"
  },
  {
    "path": "docs/donate.rst",
    "content": "******\nDonate\n******\n\nIf you find marshmallow useful, please consider supporting the team with a donation:\n\n.. image:: https://opencollective.com/marshmallow/donate/button@2x.png\n   :target: https://opencollective.com/marshmallow\n   :alt: Donate to our Open Collective\n   :height: 50px\n   \nYour donation keeps marshmallow healthy and maintained.\n"
  },
  {
    "path": "docs/examples/index.rst",
    "content": "********\nExamples\n********\n\nThe below examples demonstrate how to use marshmallow in various contexts.\nTo run each example, you will need to have `uv <https://docs.astral.sh/uv/getting-started/installation/>`_ installed.\nThe examples use `PEP 723 inline metadata <https://peps.python.org/pep-0723/>`_\nto declare the dependencies of each script. ``uv`` will install the\ndependencies automatically when running these scripts.\n\n.. toctree::\n  :maxdepth: 1\n\n  validating_package_json\n  quotes_api\n  inflection\n"
  },
  {
    "path": "docs/examples/inflection.rst",
    "content": "*****************************\nInflection (camel-cased keys)\n*****************************\n\nHTTP APIs will often use camel-cased keys for their input and output representations. This example shows how you can use the\n`Schema.on_bind_field <marshmallow.Schema.on_bind_field>` hook to automatically inflect keys.\n\n.. literalinclude:: ../../examples/inflection_example.py\n    :language: python\n\nTo run the example:\n\n.. code-block:: shell-session\n\n    $ uv run examples/inflection_example.py\n    Loaded data:\n    {'first_name': 'David', 'last_name': 'Bowie'}\n    Dumped data:\n    {'firstName': 'David', 'lastName': 'Bowie'}\n"
  },
  {
    "path": "docs/examples/quotes_api.rst",
    "content": "*******************************\nQuotes API (Flask + SQLAlchemy)\n*******************************\n\nBelow 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:\n\n- Custom validation\n- Nesting fields\n- Using ``dump_only=True`` to specify read-only fields\n- Output filtering using the ``only`` parameter\n- Using `@pre_load <marshmallow.decorators.pre_load>` to preprocess input data.\n\n.. literalinclude:: ../../examples/flask_example.py\n    :language: python\n\n\n**Using The API**\n\nRun the app.\n\n.. code-block:: shell-session\n\n    $ uv run examples/flask_example.py\n\nWe'll use the `httpie cli <https://httpie.io/cli>`_ to send requests\nInstall it with ``uv``.\n\n.. code-block:: shell-session\n\n    $ uv tool install httpie\n\nFirst we'll POST some quotes.\n\n.. code-block:: shell-session\n\n    $ http POST :5000/quotes/ author=\"Tim Peters\" content=\"Beautiful is better than ugly.\"\n    $ http POST :5000/quotes/ author=\"Tim Peters\" content=\"Now is better than never.\"\n    $ http POST :5000/quotes/ author=\"Peter Hintjens\" content=\"Simplicity is always better than functionality.\"\n\n\nIf we provide invalid input data, we get 400 error response. Let's omit \"author\" from the input data.\n\n.. code-block:: shell-session\n\n    $ http POST :5000/quotes/ content=\"I have no author\"\n    {\n        \"author\": [\n            \"Data not provided.\"\n        ]\n    }\n\nNow we can GET a list of all the quotes.\n\n.. code-block:: shell-session\n\n    $ http :5000/quotes/\n    {\n        \"quotes\": [\n            {\n                \"content\": \"Beautiful is better than ugly.\",\n                \"id\": 1\n            },\n            {\n                \"content\": \"Now is better than never.\",\n                \"id\": 2\n            },\n            {\n                \"content\": \"Simplicity is always better than functionality.\",\n                \"id\": 3\n            }\n        ]\n    }\n\nWe can also GET the quotes for a single author.\n\n.. code-block:: shell-session\n\n    $ http :5000/authors/1\n    {\n        \"author\": {\n            \"first\": \"Tim\",\n            \"formatted_name\": \"Peters, Tim\",\n            \"id\": 1,\n            \"last\": \"Peters\"\n        },\n        \"quotes\": [\n            {\n                \"content\": \"Beautiful is better than ugly.\",\n                \"id\": 1\n            },\n            {\n                \"content\": \"Now is better than never.\",\n                \"id\": 2\n            }\n        ]\n    }\n"
  },
  {
    "path": "docs/examples/validating_package_json.rst",
    "content": "***************************\nValidating ``package.json``\n***************************\n\nmarshmallow can be used to validate configuration according to a schema.\nBelow is a schema that could be used to validate\n``package.json`` files. This example demonstrates the following features:\n\n\n- Validation and deserialization using `Schema.load <marshmallow.Schema.load>`\n- :doc:`Custom fields <../custom_fields>`\n- Specifying deserialization keys using ``data_key``\n- Including unknown keys using ``unknown = INCLUDE``\n\n.. literalinclude:: ../../examples/package_json_example.py\n    :language: python\n\n\nGiven the following ``package.json`` file...\n\n.. literalinclude:: ../../examples/package.json\n    :language: json\n\n\nWe can validate it using the above script.\n\n.. code-block:: shell-session\n\n    $ uv run examples/package_json_example.py < examples/package.json\n    {'description': 'The Pythonic JavaScript toolkit',\n    'dev_dependencies': {'pest': '^23.4.1'},\n    'license': 'MIT',\n    'main': 'index.js',\n    'name': 'dunderscore',\n    'scripts': {'test': 'pest'},\n    'version': <Version('1.2.3')>}\n\nNotice that our custom field deserialized the version string to a ``Version`` object.\n\nBut if we pass an invalid package.json file...\n\n.. literalinclude:: ../../examples/invalid_package.json\n    :language: json\n\nWe see the corresponding error messages.\n\n.. code-block:: shell-session\n\n    $ uv run examples/package_json_example.py < examples/invalid_package.json\n    ERROR: package.json is invalid\n    {'homepage': ['Not a valid URL.'], 'version': ['Not a valid version.']}\n"
  },
  {
    "path": "docs/extending/custom_error_handling.rst",
    "content": "Custom error handling\n=====================\n\nBy default, `Schema.load <marshmallow.Schema.load>` will raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>` if passed invalid data.\n\nYou 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.\n\n.. code-block:: python\n\n    import logging\n    from marshmallow import Schema, fields\n\n\n    class AppError(Exception):\n        pass\n\n\n    class UserSchema(Schema):\n        email = fields.Email()\n\n        def handle_error(self, exc, data, **kwargs):\n            \"\"\"Log and raise our custom exception when (de)serialization fails.\"\"\"\n            logging.error(exc.messages)\n            raise AppError(\"An error occurred with input: {0}\".format(data))\n\n\n    schema = UserSchema()\n    schema.load({\"email\": \"invalid-email\"})  # raises AppError\n"
  },
  {
    "path": "docs/extending/custom_error_messages.rst",
    "content": "Custom error messages\n=====================\n\nTo 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:\n\n.. code-block:: python\n\n    class MySchema(Schema):\n        error_messages = {\n            \"unknown\": \"Custom unknown field error message.\",\n            \"type\": \"Custom invalid type error message.\",\n        }\n\n\nField-level error message defaults can be set on `Field.default_error_messages <marshmallow.fields.Field.default_error_messages>`.\n\n\n.. code-block:: python\n\n   from marshmallow import Schema, fields\n\n   fields.Field.default_error_messages[\"required\"] = \"You missed something!\"\n\n\n   class ArtistSchema(Schema):\n       name = fields.Str(required=True)\n       label = fields.Str(required=True, error_messages={\"required\": \"Label missing.\"})\n\n\n   print(ArtistSchema().validate({}))\n   # {'label': ['Label missing.'], 'name': ['You missed something!']}\n"
  },
  {
    "path": "docs/extending/custom_options.rst",
    "content": "Custom `class Meta <marshmallow.Schema.Meta>` options\n=====================================================\n\n`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.\n\nYou can add custom `class Meta <marshmallow.Schema.Meta>` options by subclassing `marshmallow.SchemaOpts`.\n\nExample: Enveloping, revisited\n------------------------------\n\nLet's build upon the :ref:`previous enveloping implementation <enveloping_1>` above for adding an envelope to serialized output. \nThis time, we will allow the envelope key to be customizable with `class Meta <marshmallow.Schema.Meta>` options.\n\n::\n\n    # Example outputs\n    {\n        'user': {\n            'name': 'Keith',\n            'email': 'keith@stones.com'\n        }\n    }\n    # List output\n    {\n        'users': [{'name': 'Keith'}, {'name': 'Mick'}]\n    }\n\n\nFirst, we'll add our namespace configuration to a custom options class.\n\n.. code-block:: python\n\n    from marshmallow import Schema, SchemaOpts\n\n\n    class NamespaceOpts(SchemaOpts):\n        \"\"\"Same as the default class Meta options, but adds \"name\" and\n        \"plural_name\" options for enveloping.\n        \"\"\"\n\n        def __init__(self, meta, **kwargs):\n            SchemaOpts.__init__(self, meta, **kwargs)\n            self.name = getattr(meta, \"name\", None)\n            self.plural_name = getattr(meta, \"plural_name\", self.name)\n\n\nThen we create a custom :class:`Schema` that uses our options class.\n\n.. code-block:: python\n\n    class NamespacedSchema(Schema):\n        OPTIONS_CLASS = NamespaceOpts\n\n        @pre_load(pass_many=True)\n        def unwrap_envelope(self, data, many, **kwargs):\n            key = self.opts.plural_name if many else self.opts.name\n            return data[key]\n\n        @post_dump(pass_many=True)\n        def wrap_with_envelope(self, data, many, **kwargs):\n            key = self.opts.plural_name if many else self.opts.name\n            return {key: data}\n\n\nOur application schemas can now inherit from our custom schema class.\n\n.. code-block:: python\n\n    class UserSchema(NamespacedSchema):\n        name = fields.String()\n        email = fields.Email()\n\n        class Meta:\n            name = \"user\"\n            plural_name = \"users\"\n\n\n    ser = UserSchema()\n    user = User(\"Keith\", email=\"keith@stones.com\")\n    result = ser.dump(user)\n    result  # {\"user\": {\"name\": \"Keith\", \"email\": \"keith@stones.com\"}}\n"
  },
  {
    "path": "docs/extending/index.rst",
    "content": "Extending schemas\n=================\n\nThe guides below demonstrate how to extend schemas in various ways.\n\n.. toctree::\n  :maxdepth: 1\n\n  pre_and_post_processing_methods\n  schema_validation\n  using_original_input_data\n  overriding_attribute_access\n  custom_error_handling\n  custom_options\n  custom_error_messages\n"
  },
  {
    "path": "docs/extending/overriding_attribute_access.rst",
    "content": "Overriding how attributes are accessed\n======================================\n\nBy 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.\n\nHowever, if you want to specify how values are accessed from an object, you can override the :meth:`get_attribute <marshmallow.Schema.get_attribute>` method.\n\n.. code-block:: python\n\n    class UserDictSchema(Schema):\n        name = fields.Str()\n        email = fields.Email()\n\n        # If we know we're only serializing dictionaries, we can\n        # use dict.get for all input objects\n        def get_attribute(self, obj, key, default):\n            return obj.get(key, default)\n"
  },
  {
    "path": "docs/extending/pre_and_post_processing_methods.rst",
    "content": "Pre-processing and post-processing methods\n==========================================\n\nDecorator API\n-------------\n\nData pre-processing and post-processing methods can be registered using the `pre_load <marshmallow.decorators.pre_load>`, `post_load <marshmallow.decorators.post_load>`, `pre_dump <marshmallow.decorators.pre_dump>`, and `post_dump <marshmallow.decorators.post_dump>` decorators.\n\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, post_load\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        slug = fields.Str()\n\n        @post_load\n        def slugify_name(self, in_data, **kwargs):\n            in_data[\"slug\"] = in_data[\"slug\"].lower().strip().replace(\" \", \"-\")\n            return in_data\n\n\n    schema = UserSchema()\n    result = schema.load({\"name\": \"Steve\", \"slug\": \"Steve Loria \"})\n    result[\"slug\"]  # => 'steve-loria'\n\nPassing \"many\"\n--------------\n\nBy default, pre- and post-processing methods receive one object/datum at a time, transparently handling the ``many`` parameter passed to the ``Schema``'s `~marshmallow.Schema.dump`/`~marshmallow.Schema.load` method at runtime.\n\nIn cases where your pre- and post-processing methods needs to handle the input collection when processing multiple objects, add ``pass_many=True`` to the method decorators.\n\nYour method will then receive the input data (which may be a single datum or a collection, depending on the dump/load call).\n\n.. _enveloping_1:\n\nExample: Enveloping\n-------------------\n\nOne common use case is to wrap data in a namespace upon serialization and unwrap the data during deserialization.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, pre_load, post_load, post_dump\n\n\n    class BaseSchema(Schema):\n        # Custom options\n        __envelope__ = {\"single\": None, \"many\": None}\n        __model__ = User\n\n        def get_envelope_key(self, many):\n            \"\"\"Helper to get the envelope key.\"\"\"\n            key = self.__envelope__[\"many\"] if many else self.__envelope__[\"single\"]\n            assert key is not None, \"Envelope key undefined\"\n            return key\n\n        @pre_load(pass_many=True)\n        def unwrap_envelope(self, data, many, **kwargs):\n            key = self.get_envelope_key(many)\n            return data[key]\n\n        @post_dump(pass_many=True)\n        def wrap_with_envelope(self, data, many, **kwargs):\n            key = self.get_envelope_key(many)\n            return {key: data}\n\n        @post_load\n        def make_object(self, data, **kwargs):\n            return self.__model__(**data)\n\n\n    class UserSchema(BaseSchema):\n        __envelope__ = {\"single\": \"user\", \"many\": \"users\"}\n        __model__ = User\n        name = fields.Str()\n        email = fields.Email()\n\n\n    user_schema = UserSchema()\n\n    user = User(\"Mick\", email=\"mick@stones.org\")\n    user_data = user_schema.dump(user)\n    # {'user': {'email': 'mick@stones.org', 'name': 'Mick'}}\n\n    users = [\n        User(\"Keith\", email=\"keith@stones.org\"),\n        User(\"Charlie\", email=\"charlie@stones.org\"),\n    ]\n    users_data = user_schema.dump(users, many=True)\n    # {'users': [{'email': 'keith@stones.org', 'name': 'Keith'},\n    #            {'email': 'charlie@stones.org', 'name': 'Charlie'}]}\n\n    user_objs = user_schema.load(users_data, many=True)\n    # [<User(name='Keith Richards')>, <User(name='Charlie Watts')>]\n\nRaising errors in pre-/post-processor methods\n---------------------------------------------\n\nPre- and post-processing methods may raise a `ValidationError <marshmallow.exceptions.ValidationError>`. By default, errors will be stored on the ``\"_schema\"`` key in the errors dictionary.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, ValidationError, pre_load\n\n\n    class BandSchema(Schema):\n        name = fields.Str()\n\n        @pre_load\n        def unwrap_envelope(self, data, **kwargs):\n            if \"data\" not in data:\n                raise ValidationError('Input data must have a \"data\" key.')\n            return data[\"data\"]\n\n\n    sch = BandSchema()\n    try:\n        sch.load({\"name\": \"The Band\"})\n    except ValidationError as err:\n        err.messages\n    # {'_schema': ['Input data must have a \"data\" key.']}\n\nIf you want to store and error on a different key, pass the key name as the second argument to `ValidationError <marshmallow.exceptions.ValidationError>`.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, ValidationError, pre_load\n\n\n    class BandSchema(Schema):\n        name = fields.Str()\n\n        @pre_load\n        def unwrap_envelope(self, data, **kwargs):\n            if \"data\" not in data:\n                raise ValidationError(\n                    'Input data must have a \"data\" key.', \"_preprocessing\"\n                )\n            return data[\"data\"]\n\n\n    sch = BandSchema()\n    try:\n        sch.load({\"name\": \"The Band\"})\n    except ValidationError as err:\n        err.messages\n    # {'_preprocessing': ['Input data must have a \"data\" key.']}\n\nPre-/post-processor invocation order\n------------------------------------\n\nIn summary, the processing pipeline for deserialization is as follows:\n\n1. ``@pre_load(pass_many=True)`` methods\n2. ``@pre_load(pass_many=False)`` methods\n3. ``load(in_data, many)`` (validation and deserialization)\n4. ``@validates`` methods (field validators)\n5. ``@validates_schema`` methods (schema validators)\n6. ``@post_load(pass_many=True)`` methods\n7. ``@post_load(pass_many=False)`` methods\n\nThe pipeline for serialization is similar, except that the ``pass_many=True`` processors are invoked *after* the ``pass_many=False`` processors and there are no validators.\n\n1. ``@pre_dump(pass_many=False)`` methods\n2. ``@pre_dump(pass_many=True)`` methods\n3. ``dump(obj, many)`` (serialization)\n4. ``@post_dump(pass_many=False)`` methods\n5. ``@post_dump(pass_many=True)`` methods\n\n\n.. warning::\n\n    You may register multiple processor methods on a Schema. Keep in mind, however, that **the invocation order of decorated methods of the same type is not guaranteed**. If you need to guarantee order of processing steps, you should put them in the same method.\n\n\n    .. code-block:: python\n\n        from marshmallow import Schema, fields, pre_load\n\n\n        # YES\n        class MySchema(Schema):\n            field_a = fields.Raw()\n\n            @pre_load\n            def preprocess(self, data, **kwargs):\n                step1_data = self.step1(data)\n                step2_data = self.step2(step1_data)\n                return step2_data\n\n            def step1(self, data): ...\n\n            # Depends on step1\n            def step2(self, data): ...\n\n\n        # NO\n        class MySchema(Schema):\n            field_a = fields.Raw()\n\n            @pre_load\n            def step1(self, data, **kwargs): ...\n\n            # Depends on step1\n            @pre_load\n            def step2(self, data, **kwargs): ...\n"
  },
  {
    "path": "docs/extending/schema_validation.rst",
    "content": ".. _schema_validation:\n\nSchema-level validation\n=======================\n\nYou can register schema-level validation functions for a :class:`Schema` using the `marshmallow.validates_schema <marshmallow.decorators.validates_schema>` decorator. By default, schema-level validation errors will be stored on the ``_schema`` key of the errors dictionary.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, validates_schema, ValidationError\n\n\n    class NumberSchema(Schema):\n        field_a = fields.Integer()\n        field_b = fields.Integer()\n\n        @validates_schema\n        def validate_numbers(self, data, **kwargs):\n            if data[\"field_b\"] >= data[\"field_a\"]:\n                raise ValidationError(\"field_a must be greater than field_b\")\n\n\n    schema = NumberSchema()\n    try:\n        schema.load({\"field_a\": 1, \"field_b\": 2})\n    except ValidationError as err:\n        err.messages[\"_schema\"]\n    # => [\"field_a must be greater than field_b\"]\n\nStoring errors on specific fields\n---------------------------------\n\nIt is possible to report errors on fields and subfields using a `dict`.\n\nWhen multiple schema-leval validator return errors, the error structures are merged together in the :exc:`ValidationError <marshmallow.exceptions.ValidationError>` raised at the end of the validation.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, validates_schema, ValidationError\n\n\n    class NumberSchema(Schema):\n        field_a = fields.Integer()\n        field_b = fields.Integer()\n        field_c = fields.Integer()\n        field_d = fields.Integer()\n\n        @validates_schema\n        def validate_lower_bound(self, data, **kwargs):\n            errors = {}\n            if data[\"field_b\"] <= data[\"field_a\"]:\n                errors[\"field_b\"] = [\"field_b must be greater than field_a\"]\n            if data[\"field_c\"] <= data[\"field_a\"]:\n                errors[\"field_c\"] = [\"field_c must be greater than field_a\"]\n            if errors:\n                raise ValidationError(errors)\n\n        @validates_schema\n        def validate_upper_bound(self, data, **kwargs):\n            errors = {}\n            if data[\"field_b\"] >= data[\"field_d\"]:\n                errors[\"field_b\"] = [\"field_b must be lower than field_d\"]\n            if data[\"field_c\"] >= data[\"field_d\"]:\n                errors[\"field_c\"] = [\"field_c must be lower than field_d\"]\n            if errors:\n                raise ValidationError(errors)\n\n\n    schema = NumberSchema()\n    try:\n        schema.load({\"field_a\": 3, \"field_b\": 2, \"field_c\": 1, \"field_d\": 0})\n    except ValidationError as err:\n        err.messages\n    # => {\n    #     'field_b': [\n    #         'field_b must be greater than field_a',\n    #         'field_b must be lower than field_d'\n    #     ],\n    #     'field_c': [\n    #         'field_c must be greater than field_a',\n    #         'field_c must be lower than field_d'\n    #     ]\n    #    }\n"
  },
  {
    "path": "docs/extending/using_original_input_data.rst",
    "content": "Using original input data\n-------------------------\n\nIf you want to use the original, unprocessed input, you can add ``pass_original=True`` to\n`post_load <marshmallow.decorators.post_load>` or `validates_schema <marshmallow.decorators.validates_schema>`.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, post_load, ValidationError\n\n\n    class MySchema(Schema):\n        foo = fields.Int()\n        bar = fields.Int()\n\n        @post_load(pass_original=True)\n        def add_baz_to_bar(self, data, original_data, **kwargs):\n            baz = original_data.get(\"baz\")\n            if baz:\n                data[\"bar\"] = data[\"bar\"] + baz\n            return data\n\n\n    schema = MySchema()\n    schema.load({\"foo\": 1, \"bar\": 2, \"baz\": 3})\n    # {'foo': 1, 'bar': 5}\n\n.. seealso::\n\n   The default behavior for unspecified fields can be controlled with the ``unknown`` option, see :ref:`Handling Unknown Fields <unknown>` for more information.\n"
  },
  {
    "path": "docs/index.rst",
    "content": ".. meta::\n   :description:\n        marshmallow is an ORM/ODM/framework-agnostic library for converting complex datatypes, such as objects, to and from native Python datatypes.\n\n***********\nmarshmallow\n***********\n\n*Object serialization and deserialization, lightweight and fluffy.*\n\nRelease v\\ |version|. (:doc:`changelog`)\n\n----\n\n.. include:: ../README.rst\n    :start-after: .. start elevator-pitch\n    :end-before: .. end elevator-pitch\n\nReady to get started? Go on to the :doc:`quickstart` or check out some :doc:`examples <examples/index>`.\n\nUpgrading from an older version?\n================================\n\nSee the :doc:`upgrading` page for notes on getting your code up-to-date with the latest version.\n\nWhy another library?\n=====================\n\nSee :doc:`this document <why>` to learn about what makes marshmallow unique.\n\nSponsors\n========\n\n.. include:: ../README.rst\n    :start-after: .. start sponsors\n    :end-before: .. end sponsors\n\n.. toctree::\n    :maxdepth: 1\n    :hidden:\n    :titlesonly:\n\n    Home <self>\n\nUsage guide\n===========\n\n.. toctree::\n    :caption: Usage guide\n    :maxdepth: 2\n\n    install\n    quickstart\n    nesting\n    custom_fields\n    extending/index\n    examples/index\n\n\nAPI reference\n=============\n\n.. toctree::\n    :caption: API reference\n    :maxdepth: 1\n\n    api_reference\n\nProject info\n=============\n\n.. toctree::\n    :caption: Project info\n    :maxdepth: 1\n\n    why\n    changelog\n    upgrading\n    whos_using\n    license\n    authors\n    contributing\n    code_of_conduct\n    kudos\n    donate\n\n.. toctree::\n    :hidden:\n    :caption: Useful links\n\n    marshmallow @ PyPI <https://pypi.org/project/marshmallow/>\n    marshmallow @ GitHub <https://github.com/marshmallow-code/marshmallow/>\n    Issue Tracker <https://github.com/marshmallow-code/marshmallow/issues>\n    Ecosystem <https://github.com/marshmallow-code/marshmallow/wiki/Ecosystem>\n"
  },
  {
    "path": "docs/install.rst",
    "content": "Installation\n============\n\nInstalling/upgrading from the PyPI\n----------------------------------\n\nTo install the latest stable version from the PyPI:\n\n.. code-block:: shell-session\n\n    $ pip install -U marshmallow\n\nTo install the latest pre-release version from the PyPI:\n\n.. code-block:: shell-session\n\n    $ pip install -U marshmallow --pre\n\nGet the bleeding edge version\n-----------------------------\n\nTo get the latest development version of marshmallow, run\n\n.. code-block:: shell-session\n\n    $ pip install -U git+https://github.com/marshmallow-code/marshmallow.git@dev\n\n\n.. seealso::\n\n    Need help upgrading to newer releases? See the :doc:`upgrading` page.\n"
  },
  {
    "path": "docs/kudos.rst",
    "content": "*****\nKudos\n*****\n\nA hat tip to `Django Rest Framework`_ , `Flask-RESTful`_, and `colander`_ for ideas and API design.\n\n.. _Flask-RESTful: https://flask-restful.readthedocs.io/en/latest/\n\n.. _Django Rest Framework: https://django-rest-framework.org/\n\n.. _colander: https://docs.pylonsproject.org/projects/colander/en/latest/\n"
  },
  {
    "path": "docs/license.rst",
    "content": "License\n=======\n\n.. literalinclude:: ../LICENSE\n"
  },
  {
    "path": "docs/marshmallow.class_registry.rst",
    "content": "Class registry\n==============\n\n.. automodule:: marshmallow.class_registry\n    :members:\n"
  },
  {
    "path": "docs/marshmallow.decorators.rst",
    "content": "Decorators\n==========\n\n.. automodule:: marshmallow.decorators\n    :members:\n    :autosummary:\n"
  },
  {
    "path": "docs/marshmallow.error_store.rst",
    "content": "Error store\n===========\n\n.. automodule:: marshmallow.error_store\n    :members:\n    :private-members:\n"
  },
  {
    "path": "docs/marshmallow.exceptions.rst",
    "content": "Exceptions\n==========\n\n.. automodule:: marshmallow.exceptions\n    :members:\n"
  },
  {
    "path": "docs/marshmallow.experimental.context.rst",
    "content": "Context (experimental)\n======================\n\n.. automodule:: marshmallow.experimental.context\n    :members:\n"
  },
  {
    "path": "docs/marshmallow.fields.rst",
    "content": ".. _api_fields:\n\nFields\n======\n\nBase Field Class\n----------------\n\n.. autoclass:: marshmallow.fields.Field\n    :private-members:\n\nField subclasses\n----------------\n\n.. automodule:: marshmallow.fields\n    :members:\n    :autosummary:\n    :exclude-members: Field, default_error_messages, mapping_type, num_type, DESERIALIZATION_CLASS\n"
  },
  {
    "path": "docs/marshmallow.schema.rst",
    "content": "Schema\n======\n\n.. autoclass:: marshmallow.schema.Schema\n    :members:\n    :autosummary:\n    :exclude-members: OPTIONS_CLASS\n\n.. autoclass:: marshmallow.schema.SchemaOpts\n"
  },
  {
    "path": "docs/marshmallow.types.rst",
    "content": "Types\n=====\n\n.. automodule:: marshmallow.types\n    :members:\n"
  },
  {
    "path": "docs/marshmallow.utils.rst",
    "content": "Utility functions\n=================\n\n.. automodule:: marshmallow.utils\n    :members:\n"
  },
  {
    "path": "docs/marshmallow.validate.rst",
    "content": ".. _api_validators:\n\nValidators\n==========\n\n.. automodule:: marshmallow.validate\n    :members:\n    :autosummary:\n"
  },
  {
    "path": "docs/nesting.rst",
    "content": "Nesting schemas\n===============\n\nSchemas can be nested to represent relationships between objects (e.g. foreign key relationships). \nFor example, a ``Blog`` may have an author represented by a ``User``.\nAnd a ``User`` may have many friends, each of which is a ``User``.\n\n.. code-block:: python\n\n    from __future__ import annotations  # Enable newer type annotation syntax\n\n    import datetime as dt\n    from dataclasses import dataclass, field\n\n\n    @dataclass\n    class User:\n        name: str\n        email: str\n        created_at: dt.datetime = field(default_factory=dt.datetime.now)\n        friends: list[User] = field(default_factory=list)\n        employer: User | None = None\n\n\n    @dataclass\n    class Blog:\n        title: str\n        author: User\n\nUse a :class:`Nested <marshmallow.fields.Nested>` field to represent the relationship, passing in a nested schema.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.Email()\n        created_at = fields.DateTime()\n\n\n    class BlogSchema(Schema):\n        title = fields.String()\n        author = fields.Nested(UserSchema)\n\nThe serialized blog will have the nested user representation.\n\n.. code-block:: python\n\n    from pprint import pprint\n\n    user = User(name=\"Monty\", email=\"monty@python.org\")\n    blog = Blog(title=\"Something Completely Different\", author=user)\n    result = BlogSchema().dump(blog)\n    pprint(result)\n    # {'title': u'Something Completely Different',\n    #  'author': {'name': u'Monty',\n    #             'email': u'monty@python.org',\n    #             'created_at': '2014-08-17T14:58:57.600623+00:00'}}\n\n.. note::\n    If the field is a collection of nested objects, pass the `Nested <marshmallow.fields.Nested>` field to `List <marshmallow.fields.List>`.\n\n    .. code-block:: python\n\n        collaborators = fields.List(fields.Nested(UserSchema))\n\n.. _specifying-nested-fields:\n\nSpecifying which fields to nest\n-------------------------------\n\nYou can explicitly specify which attributes of the nested objects you want to (de)serialize with the ``only`` argument to the schema.\n\n.. code-block:: python\n\n    class BlogSchema2(Schema):\n        title = fields.String()\n        author = fields.Nested(UserSchema(only=(\"email\",)))\n\n\n    schema = BlogSchema2()\n    result = schema.dump(blog)\n    pprint(result)\n    # {\n    #     'title': u'Something Completely Different',\n    #     'author': {'email': u'monty@python.org'}\n    # }\n\nDotted paths may be passed to ``only`` and ``exclude`` to specify nested attributes.\n\n.. code-block:: python\n\n    class SiteSchema(Schema):\n        blog = fields.Nested(BlogSchema2)\n\n\n    schema = SiteSchema(only=(\"blog.author.email\",))\n    result = schema.dump(site)\n    pprint(result)\n    # {\n    #     'blog': {\n    #         'author': {'email': u'monty@python.org'}\n    #     }\n    # }\n\nYou can replace nested data with a single value (or flat list of values if ``many=True``) using the :class:`Pluck <marshmallow.fields.Pluck>` field.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.Email()\n        friends = fields.Pluck(\"self\", \"name\", many=True)\n\n\n    # ... create ``user`` ...\n    serialized_data = UserSchema().dump(user)\n    pprint(serialized_data)\n    # {\n    #     \"name\": \"Steve\",\n    #     \"email\": \"steve@example.com\",\n    #     \"friends\": [\"Mike\", \"Joe\"]\n    # }\n    deserialized_data = UserSchema().load(result)\n    pprint(deserialized_data)\n    # {\n    #     \"name\": \"Steve\",\n    #     \"email\": \"steve@example.com\",\n    #     \"friends\": [{\"name\": \"Mike\"}, {\"name\": \"Joe\"}]\n    # }\n\n\n.. _partial-loading:\n\nPartial loading\n---------------\n\nNested schemas also inherit the ``partial`` parameter of the parent ``load`` call.\n\n.. code-block:: python\n\n    class UserSchemaStrict(Schema):\n        name = fields.String(required=True)\n        email = fields.Email()\n        created_at = fields.DateTime(required=True)\n\n\n    class BlogSchemaStrict(Schema):\n        title = fields.String(required=True)\n        author = fields.Nested(UserSchemaStrict, required=True)\n\n\n    schema = BlogSchemaStrict()\n    blog = {\"title\": \"Something Completely Different\", \"author\": {}}\n    result = schema.load(blog, partial=True)\n    pprint(result)\n    # {'author': {}, 'title': 'Something Completely Different'}\n\nYou can specify a subset of the fields to allow partial loading using dot delimiters.\n\n.. code-block:: python\n\n    author = {\"name\": \"Monty\"}\n    blog = {\"title\": \"Something Completely Different\", \"author\": author}\n    result = schema.load(blog, partial=(\"title\", \"author.created_at\"))\n    pprint(result)\n    # {'author': {'name': 'Monty'}, 'title': 'Something Completely Different'}\n\n.. _two-way-nesting:\n\nTwo-way nesting\n---------------\n\nIf you have two objects that nest each other, you can pass a callable to `Nested <marshmallow.fields.Nested>`.\nThis allows you to resolve order-of-declaration issues, such as when one schema nests a schema that is declared below it.\n\nFor example, a representation of an ``Author`` model might include the books that have a many-to-one relationship to it.\nCorrespondingly, a representation of a ``Book`` will include its author representation.\n\n.. code-block:: python\n\n    class BookSchema(Schema):\n        id = fields.Int(dump_only=True)\n        title = fields.Str()\n\n        # Make sure to use the 'only' or 'exclude'\n        # to avoid infinite recursion\n        author = fields.Nested(lambda: AuthorSchema(only=(\"id\", \"title\")))\n\n\n    class AuthorSchema(Schema):\n        id = fields.Int(dump_only=True)\n        title = fields.Str()\n\n        books = fields.List(fields.Nested(BookSchema(exclude=(\"author\",))))\n\n\n.. code-block:: python\n\n    from pprint import pprint\n    from mymodels import Author, Book\n\n    author = Author(name=\"William Faulkner\")\n    book = Book(title=\"As I Lay Dying\", author=author)\n    book_result = BookSchema().dump(book)\n    pprint(book_result, indent=2)\n    # {\n    #   \"id\": 124,\n    #   \"title\": \"As I Lay Dying\",\n    #   \"author\": {\n    #     \"id\": 8,\n    #     \"name\": \"William Faulkner\"\n    #   }\n    # }\n\n    author_result = AuthorSchema().dump(author)\n    pprint(author_result, indent=2)\n    # {\n    #   \"id\": 8,\n    #   \"name\": \"William Faulkner\",\n    #   \"books\": [\n    #     {\n    #       \"id\": 124,\n    #       \"title\": \"As I Lay Dying\"\n    #     }\n    #   ]\n    # }\n\nYou can also pass a class name as a string to `Nested <marshmallow.fields.Nested>`.\nThis is useful for avoiding circular imports when your schemas are located in different modules.\n\n.. code-block:: python\n\n    # books.py\n    from marshmallow import Schema, fields\n\n\n    class BookSchema(Schema):\n        id = fields.Int(dump_only=True)\n        title = fields.Str()\n\n        author = fields.Nested(\"AuthorSchema\", only=(\"id\", \"title\"))\n\n.. code-block:: python\n\n    # authors.py\n    from marshmallow import Schema, fields\n\n\n    class AuthorSchema(Schema):\n        id = fields.Int(dump_only=True)\n        title = fields.Str()\n\n        books = fields.List(fields.Nested(\"BookSchema\", exclude=(\"author\",)))\n\n.. note::\n\n    If you have multiple schemas with the same class name, you must pass the full, module-qualified path. ::\n\n        author = fields.Nested(\"authors.BookSchema\", only=(\"id\", \"title\"))\n\n.. _self-nesting:\n\nNesting a schema within itself\n------------------------------\n\nIf the object to be marshalled has a relationship to an object of the same type, you can nest the `Schema <marshmallow.Schema>` within itself by passing a callable that returns an instance of the same schema.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.Email()\n        # Use the 'exclude' argument to avoid infinite recursion\n        employer = fields.Nested(lambda: UserSchema(exclude=(\"employer\",)))\n        friends = fields.List(fields.Nested(lambda: UserSchema()))\n\n\n    user = User(\"Steve\", \"steve@example.com\")\n    user.friends.append(User(\"Mike\", \"mike@example.com\"))\n    user.friends.append(User(\"Joe\", \"joe@example.com\"))\n    user.employer = User(\"Dirk\", \"dirk@example.com\")\n    result = UserSchema().dump(user)\n    pprint(result, indent=2)\n    # {\n    #     \"name\": \"Steve\",\n    #     \"email\": \"steve@example.com\",\n    #     \"friends\": [\n    #         {\n    #             \"name\": \"Mike\",\n    #             \"email\": \"mike@example.com\",\n    #             \"friends\": [],\n    #             \"employer\": null\n    #         },\n    #         {\n    #             \"name\": \"Joe\",\n    #             \"email\": \"joe@example.com\",\n    #             \"friends\": [],\n    #             \"employer\": null\n    #         }\n    #     ],\n    #     \"employer\": {\n    #         \"name\": \"Dirk\",\n    #         \"email\": \"dirk@example.com\",\n    #         \"friends\": []\n    #     }\n    # }\n\nNext steps\n----------\n\n- Want to create your own field type? See the :doc:`custom_fields` page.\n- Need to add schema-level validation, post-processing, or error handling behavior? See the :doc:`extending/index` page.\n- For more detailed usage examples, check out the :doc:`examples/index` page.\n"
  },
  {
    "path": "docs/quickstart.rst",
    "content": "Quickstart\n==========\n\nThis guide will walk you through the basics of creating schemas for serializing and deserializing data.\n\nDeclaring schemas\n-----------------\n\nLet's start with a basic user \"model\".\n\n.. code-block:: python\n\n    from dataclasses import dataclass, field\n    import datetime as dt\n\n\n    @dataclass\n    class User:\n        name: str\n        email: str\n        created_at: dt.datetime = field(default_factory=dt.datetime.now)\n\nCreate a schema by defining a class with variables mapping attribute names to :class:`Field <fields.Field>` objects.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        email = fields.Email()\n        created_at = fields.DateTime()\n\n.. seealso::\n\n    For a full reference on the available field classes, see the `fields module documentation <marshmallow.fields>`.\n\n.. admonition:: Creating schemas from dictionaries\n\n    You can also create a schema from a dictionary of fields using the `from_dict <marshmallow.Schema.from_dict>` method.\n\n    .. code-block:: python\n\n        from marshmallow import Schema, fields\n\n        UserSchema = Schema.from_dict(\n            {\n                \"name\": fields.Str(),\n                \"email\": fields.Email(),\n                \"created_at\": fields.DateTime(),\n            }\n        )\n\n    `from_dict <marshmallow.Schema.from_dict>` is especially useful for generating schemas at runtime.\n\nSerializing objects (\"dumping\")\n-------------------------------\n\nSerialize objects by passing them to your schema's :meth:`dump <marshmallow.Schema.dump>` method, which returns the formatted result.\n\n.. code-block:: python\n\n    from pprint import pprint\n\n    user = User(name=\"Monty\", email=\"monty@python.org\")\n    schema = UserSchema()\n    result = schema.dump(user)\n    pprint(result)\n    # {\"name\": \"Monty\",\n    #  \"email\": \"monty@python.org\",\n    #  \"created_at\": \"2014-08-17T14:54:16.049594+00:00\"}\n\nYou can also serialize to a JSON-encoded string using :meth:`dumps <marshmallow.Schema.dumps>`.\n\n.. code-block:: python\n\n    json_result = schema.dumps(user)\n    print(json_result)\n    # '{\"name\": \"Monty\", \"email\": \"monty@python.org\", \"created_at\": \"2014-08-17T14:54:16.049594+00:00\"}'\n\nFiltering output\n----------------\n\nYou may not need to output all declared fields every time you use a schema. You can specify which fields to output with the ``only`` parameter.\n\n.. code-block:: python\n\n    summary_schema = UserSchema(only=(\"name\", \"email\"))\n    summary_schema.dump(user)\n    # {\"name\": \"Monty\", \"email\": \"monty@python.org\"}\n\nYou can also exclude fields by passing in the ``exclude`` parameter.\n\n\nDeserializing objects (\"loading\")\n---------------------------------\n\nThe reverse of the `dump <Schema.dump>` method is `load <Schema.load>`, which validates and deserializes\nan input dictionary to an application-level data structure.\n\nBy default, :meth:`load <Schema.load>` will return a dictionary of field names mapped to deserialized values (or raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>`\nwith a dictionary of validation errors, which we'll :ref:`revisit later <validation>`).\n\n.. code-block:: python\n\n    from pprint import pprint\n\n    user_data = {\n        \"created_at\": \"2014-08-11T05:26:03.869245\",\n        \"email\": \"ken@yahoo.com\",\n        \"name\": \"Ken\",\n    }\n    schema = UserSchema()\n    result = schema.load(user_data)\n    pprint(result)\n    # {'name': 'Ken',\n    #  'email': 'ken@yahoo.com',\n    #  'created_at': datetime.datetime(2014, 8, 11, 5, 26, 3, 869245)},\n\nNotice that the datetime string was converted to a `datetime` object.\n\nDeserializing to objects\n++++++++++++++++++++++++\n\nIn order to deserialize to an object, define a method of your :class:`Schema` and decorate it with `post_load <marshmallow.decorators.post_load>`. The method receives a dictionary of deserialized data.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, post_load\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        email = fields.Email()\n        created_at = fields.DateTime()\n\n        @post_load\n        def make_user(self, data, **kwargs):\n            return User(**data)\n\nNow, the `load <Schema.load>` method return a ``User`` instance.\n\n.. code-block:: python\n\n    user_data = {\"name\": \"Ronnie\", \"email\": \"ronnie@stones.com\"}\n    schema = UserSchema()\n    result = schema.load(user_data)\n    print(result)  # => <User(name='Ronnie')>\n\nHandling collections of objects\n-------------------------------\n\nSet ``many=True`` when dealing with iterable collections of objects.\n\n.. code-block:: python\n\n    user1 = User(name=\"Mick\", email=\"mick@stones.com\")\n    user2 = User(name=\"Keith\", email=\"keith@stones.com\")\n    users = [user1, user2]\n    schema = UserSchema(many=True)\n    result = schema.dump(users)  # OR UserSchema().dump(users, many=True)\n    pprint(result)\n    # [{'name': u'Mick',\n    #   'email': u'mick@stones.com',\n    #   'created_at': '2014-08-17T14:58:57.600623+00:00'}\n    #  {'name': u'Keith',\n    #   'email': u'keith@stones.com',\n    #   'created_at': '2014-08-17T14:58:57.600623+00:00'}]\n\n\n.. _validation:\n\nValidation\n----------\n\n`Schema.load <marshmallow.Schema.load>` (and its JSON-decoding counterpart, `Schema.loads <marshmallow.Schema.loads>`) raises a :exc:`ValidationError <marshmallow.exceptions.ValidationError>` error when invalid data are passed in. You can access the dictionary of validation errors from the `ValidationError.messages <marshmallow.exceptions.ValidationError.messages>` attribute. The data that were correctly deserialized are accessible in `ValidationError.valid_data <marshmallow.exceptions.ValidationError.valid_data>`. Some fields, such as the :class:`Email <fields.Email>` and :class:`URL <fields.URL>` fields, have built-in validation.\n\n.. code-block:: python\n\n    from marshmallow import ValidationError\n\n    try:\n        result = UserSchema().load({\"name\": \"John\", \"email\": \"foo\"})\n    except ValidationError as err:\n        print(err.messages)  # => {\"email\": ['\"foo\" is not a valid email address.']}\n        print(err.valid_data)  # => {\"name\": \"John\"}\n\n\nWhen validating a collection, the errors dictionary will be keyed on the indices of invalid items.\n\n.. code-block:: python\n\n    from pprint import pprint\n\n    from marshmallow import Schema, fields, ValidationError\n\n\n    class BandMemberSchema(Schema):\n        name = fields.String(required=True)\n        email = fields.Email()\n\n\n    user_data = [\n        {\"email\": \"mick@stones.com\", \"name\": \"Mick\"},\n        {\"email\": \"invalid\", \"name\": \"Invalid\"},  # invalid email\n        {\"email\": \"keith@stones.com\", \"name\": \"Keith\"},\n        {\"email\": \"charlie@stones.com\"},  # missing \"name\"\n    ]\n\n    try:\n        BandMemberSchema(many=True).load(user_data)\n    except ValidationError as err:\n        pprint(err.messages)\n        # {1: {'email': ['Not a valid email address.']},\n        #  3: {'name': ['Missing data for required field.']}}\n\nYou can perform additional validation for a field by passing the ``validate`` argument.\nThere are a number of built-in validators in the :ref:`marshmallow.validate <api_validators>` module.\n\n.. code-block:: python\n\n    from pprint import pprint\n\n    from marshmallow import Schema, fields, validate, ValidationError\n\n\n    class UserSchema(Schema):\n        name = fields.Str(validate=validate.Length(min=1))\n        permission = fields.Str(validate=validate.OneOf([\"read\", \"write\", \"admin\"]))\n        age = fields.Int(validate=validate.Range(min=18, max=40))\n\n\n    in_data = {\"name\": \"\", \"permission\": \"invalid\", \"age\": 71}\n    try:\n        UserSchema().load(in_data)\n    except ValidationError as err:\n        pprint(err.messages)\n        # {'age': ['Must be greater than or equal to 18 and less than or equal to 40.'],\n        #  'name': ['Shorter than minimum length 1.'],\n        #  'permission': ['Must be one of: read, write, admin.']}\n\n\nYou may implement your own validators.\nA validator is a callable that accepts a single argument, the value to validate.\nIf validation fails, the callable should raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>`\nwith an error message.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, ValidationError\n\n\n    def validate_quantity(n):\n        if n < 0:\n            raise ValidationError(\"Quantity must be greater than 0.\")\n        if n > 30:\n            raise ValidationError(\"Quantity must not be greater than 30.\")\n\n\n    class ItemSchema(Schema):\n        quantity = fields.Integer(validate=validate_quantity)\n\n\n    in_data = {\"quantity\": 31}\n    try:\n        result = ItemSchema().load(in_data)\n    except ValidationError as err:\n        print(err.messages)  # => {'quantity': ['Quantity must not be greater than 30.']}\n\nYou may also pass a collection (list, tuple, generator) of callables to ``validate``.\n\n.. warning::\n\n    Validation occurs on deserialization but not on serialization.\n    To improve serialization performance, data passed to `Schema.dump <marshmallow.Schema.dump>`\n    are considered valid.\n\n.. seealso::\n\n    You can register a custom error handler function for a schema by overriding the\n    :func:`handle_error <Schema.handle_error>` method.\n    See the :doc:`extending/custom_error_handling` page for more info.\n\n.. seealso::\n\n    If you need to validate multiple fields within a single validator, see :ref:`schema_validation`.\n\n\nField validators as methods\n+++++++++++++++++++++++++++\n\nIt is sometimes convenient to write validators as methods. Use the `validates <marshmallow.validates>` decorator to register field validator methods.\n\n.. code-block:: python\n\n    from marshmallow import fields, Schema, validates, ValidationError\n\n\n    class ItemSchema(Schema):\n        quantity = fields.Integer()\n\n        @validates(\"quantity\")\n        def validate_quantity(self, value: int, data_key: str) -> None:\n            if value < 0:\n                raise ValidationError(\"Quantity must be greater than 0.\")\n            if value > 30:\n                raise ValidationError(\"Quantity must not be greater than 30.\")\n\n.. note::\n\n    You can pass multiple field names to the `validates <marshmallow.validates>` decorator.\n\n    .. code-block:: python\n\n        from marshmallow import Schema, fields, validates, ValidationError\n\n\n        class UserSchema(Schema):\n            name = fields.Str(required=True)\n            nickname = fields.Str(required=True)\n\n            @validates(\"name\", \"nickname\")\n            def validate_names(self, value: str, data_key: str) -> None:\n                if len(value) < 3:\n                    raise ValidationError(\"Too short\")\n\n\nRequired fields\n---------------\n\nMake a field required by passing ``required=True``. An error will be raised if the the value is missing from the input to `Schema.load <marshmallow.Schema.load>`.\n\nTo customize the error message for required fields, pass a `dict` with a ``required`` key as the ``error_messages`` argument for the field.\n\n.. code-block:: python\n\n    from pprint import pprint\n\n    from marshmallow import Schema, fields, ValidationError\n\n\n    class UserSchema(Schema):\n        name = fields.String(required=True)\n        age = fields.Integer(required=True, error_messages={\"required\": \"Age is required.\"})\n        city = fields.String(\n            required=True,\n            error_messages={\"required\": {\"message\": \"City required\", \"code\": 400}},\n        )\n        email = fields.Email()\n\n\n    try:\n        result = UserSchema().load({\"email\": \"foo@bar.com\"})\n    except ValidationError as err:\n        pprint(err.messages)\n        # {'age': ['Age is required.'],\n        # 'city': {'code': 400, 'message': 'City required'},\n        # 'name': ['Missing data for required field.']}\n\n\nPartial loading\n---------------\n\nWhen using the same schema in multiple places, you may only want to skip ``required``\nvalidation by passing ``partial``.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String(required=True)\n        age = fields.Integer(required=True)\n\n\n    result = UserSchema().load({\"age\": 42}, partial=(\"name\",))\n    # OR UserSchema(partial=('name',)).load({'age': 42})\n    print(result)  # => {'age': 42}\n\nYou can ignore missing fields entirely by setting ``partial=True``.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String(required=True)\n        age = fields.Integer(required=True)\n\n\n    result = UserSchema().load({\"age\": 42}, partial=True)\n    # OR UserSchema(partial=True).load({'age': 42})\n    print(result)  # => {'age': 42}\n\nSpecifying defaults\n-------------------\n\n`load_default` specifies the default deserialization value for a field.\nLikewise, `dump_default` specifies the default serialization value.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        id = fields.UUID(load_default=uuid.uuid1)\n        birthdate = fields.DateTime(dump_default=dt.datetime(2017, 9, 29))\n\n\n    UserSchema().load({})\n    # {'id': UUID('337d946c-32cd-11e8-b475-0022192ed31b')}\n    UserSchema().dump({})\n    # {'birthdate': '2017-09-29T00:00:00+00:00'}\n\n.. _unknown:\n\nHandling unknown fields\n-----------------------\n\nBy default, :meth:`load <Schema.load>` will raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>` if it encounters a key with no matching ``Field`` in the schema.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        email = fields.Email()\n        created_at = fields.DateTime()\n\n\n    UserSchema().load(\n        {\n            \"name\": \"Monty\",\n            \"email\": \"monty@python.org\",\n            \"created_at\": \"2014-08-17T14:54:16.049594+00:00\",\n            \"extra\": \"Not a field\",\n        }\n    )\n    # raises marshmallow.exceptions.ValidationError: {'extra': ['Unknown field.']}\n\nThis behavior can be modified with the ``unknown`` option, which accepts one of the following:\n\n- `RAISE <marshmallow.RAISE>` (default): raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>`\n  if there are any unknown fields\n- `EXCLUDE <marshmallow.EXCLUDE>`: exclude unknown fields\n- `INCLUDE <marshmallow.INCLUDE>`: accept and include the unknown fields\n\nYou can specify `unknown <marshmallow.Schema.Meta.unknown>` in the `class Meta <marshmallow.Schema.Meta>` of your `Schema <marshmallow.Schema>`,\n\n.. code-block:: python\n\n    from pprint import pprint\n    from marshmallow import Schema, fields, INCLUDE\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        email = fields.Email()\n        created_at = fields.DateTime()\n\n        class Meta:\n            unknown = INCLUDE\n\n\n    result = UserSchema().load(\n        {\n            \"name\": \"Monty\",\n            \"email\": \"monty@python.org\",\n            \"created_at\": \"2014-08-17T14:54:16.049594+00:00\",\n            \"extra\": \"Not a field\",\n        }\n    )\n    pprint(result)\n    # {'created_at': datetime.datetime(2014, 8, 17, 14, 54, 16, 49594, tzinfo=datetime.timezone(datetime.timedelta(0), '+0000')),\n    #  'email': 'monty@python.org',\n    #  'extra': 'Not a field',\n    #  'name': 'Monty'}\n\nat instantiation time,\n\n.. code-block:: python\n\n    schema = UserSchema(unknown=INCLUDE)\n\nor when calling :meth:`load <marshmallow.Schema.load>`.\n\n.. code-block:: python\n\n    UserSchema().load(data, unknown=INCLUDE)\n\nThe `unknown <marshmallow.Schema.Meta.unknown>` option value set in `load <marshmallow.Schema.load>`\nwill override the value applied at instantiation time,\nwhich itself will override the value defined in the `class Meta <marshmallow.Schema.Meta>`.\n\nThis order of precedence allows you to change the behavior of a schema for different contexts.\n\n\nValidation without deserialization\n----------------------------------\n\nIf you only need to validate input data (without deserializing to an object), you can use `Schema.validate <marshmallow.Schema.validate>`.\n\n.. code-block:: python\n\n    errors = UserSchema().validate({\"name\": \"Ronnie\", \"email\": \"invalid-email\"})\n    print(errors)  # {'email': ['Not a valid email address.']}\n\n\n\"Read-only\" and \"write-only\" fields\n-----------------------------------\n\nIn the context of a web API, the ``dump_only`` and ``load_only`` parameters are conceptually equivalent to \"read-only\" and \"write-only\" fields, respectively.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        # password is \"write-only\"\n        password = fields.Str(load_only=True)\n        # created_at is \"read-only\"\n        created_at = fields.DateTime(dump_only=True)\n\n.. warning::\n\n    When loading, dump-only fields are considered unknown. If the ``unknown`` option is set to ``INCLUDE``, values with keys corresponding to those fields are therefore loaded with no validation.\n\nSpecifying serialization/deserialization keys\n---------------------------------------------\n\nSchemas will (de)serialize an input dictionary from/to an output dictionary whose keys are identical to the field names.\nIf you are consuming and producing data that does not match your schema, you can specify the output keys via the `data_key` argument.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.Email(data_key=\"emailAddress\")\n\n\n    s = UserSchema()\n\n    data = {\"name\": \"Mike\", \"email\": \"foo@bar.com\"}\n    result = s.dump(data)\n    # {'name': u'Mike',\n    # 'emailAddress': 'foo@bar.com'}\n\n    data = {\"name\": \"Mike\", \"emailAddress\": \"foo@bar.com\"}\n    result = s.load(data)\n    # {'name': u'Mike',\n    # 'email': 'foo@bar.com'}\n\n\nNext steps\n----------\n- Need to represent relationships between objects? See the :doc:`nesting` page.\n- Want to create your own field type? See the :doc:`custom_fields` page.\n- Need to add schema-level validation, post-processing, or error handling behavior? See the :doc:`extending/index` page.\n- For more detailed usage examples, check out the :doc:`examples/index` page.\n"
  },
  {
    "path": "docs/top_level.rst",
    "content": "Top-level API\n=============\n\n.. automodule:: marshmallow\n   :members:\n   :autosummary:\n   :exclude-members: OPTIONS_CLASS\n\n.. Can't use :autodata: here due to Sphinx bug: https://github.com/sphinx-doc/sphinx/issues/6495\n.. data:: missing\n\n   Singleton value that indicates that a field's value is missing from input\n   dict passed to `Schema.load <marshmallow.Schema.load>`. If the field's value is not required,\n   its ``default`` value is used.\n\nConstants for ``unknown``\n-------------------------\n\n.. seealso:: :ref:`unknown`\n\n.. data:: EXCLUDE\n\n   Indicates that fields that are not explicitly declared on a schema should be\n   excluded from the deserialized result.\n\n\n.. data:: INCLUDE\n\n   Indicates that fields that are not explicitly declared on a schema should be\n   included from the deserialized result.\n\n.. data:: RAISE\n\n   Indicates that fields that are not explicitly declared on a schema should\n   result in an error.\n"
  },
  {
    "path": "docs/upgrading.rst",
    "content": "Upgrading to newer releases\n===========================\n\nThis section documents migration paths to new releases.\n\n.. _upgrading_4_0:\n\nUpgrading to 4.0\n++++++++++++++++\n\n``Field`` as a generic class\n****************************\n\n`Field <marshmallow.fields.Field>` is a generic class with a type argument.\nWhen defining a custom field, the type argument should be used to specify the internal type.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n\n    class PinCode(fields.Field[list[int]]):\n        \"\"\"Field that serializes to a string of numbers and deserializes\n        to a list of numbers.\n        \"\"\"\n\n        def _serialize(self, value, attr, obj, **kwargs):\n            if value is None:\n                return \"\"\n            return \"\".join(str(d) for d in value)\n\n        # The inferred return type is list[int]\n        def _deserialize(self, value, attr, data, **kwargs):\n            try:\n                return [int(c) for c in value]\n            except ValueError as error:\n                raise ValidationError(\"Pin codes must contain only digits.\") from error\n\nNew context API\n***************\n\nPassing context to `Schema <marshmallow.schema.Schema>` classes is removed. Use `contextvars.ContextVar` for passing context to\nfields, pre-/post-processing methods, and validators instead.\n\nmarshmallow 4 provides an experimental `Context <marshmallow.experimental.context.Context>`\nwrapper around `contextvars.ContextVar` that can be used to both set and retrieve context.\n\n.. code-block:: python\n\n    # 3.x\n    from marshmallow import Schema, fields\n\n\n    class UserSchema(Schema):\n        name_suffixed = fields.Function(\n            lambda obj, context: obj[\"name\"] + context[\"suffix\"]\n        )\n\n\n    user_schema = UserSchema()\n    user_schema.context = {\"suffix\": \"bar\"}\n    user_schema.dump({\"name\": \"foo\"})\n    # {'name_suffixed': 'foobar'}\n\n    # 4.x\n    import typing\n\n    from marshmallow import Schema, fields\n    from marshmallow.experimental.context import Context\n\n\n    class UserContext(typing.TypedDict):\n        suffix: str\n\n\n    UserSchemaContext = Context[UserContext]\n\n\n    class UserSchema(Schema):\n        name_suffixed = fields.Function(\n            lambda obj: obj[\"name\"] + UserSchemaContext.get()[\"suffix\"]\n        )\n\n\n    with UserSchemaContext({\"suffix\": \"bar\"}):\n        UserSchema().dump({\"name\": \"foo\"})\n        # {'name_suffixed': 'foobar'}\n\nSee :ref:`using_context` for more information.\n\nImplicit field creation is removed\n**********************************\n\nIn marshmallow 3, the ``fields`` and ``additional`` class Meta options allowed fields to be implicitly created via introspection of the data being serialized.\n\nIn marshmallow 4.0, implicit field creation is removed to prevent conflicts with libraries\nthat generate fields dynamically.\n\n.. code-block:: python\n\n    import datetime as dt\n    import dataclasses\n\n    from marshmallow import Schema, fields\n\n\n    @dataclasses.dataclass\n    class User:\n        name: str\n        birthdate: dt.date\n\n\n    # 3.x\n    class UserSchema(Schema):\n        class Meta:\n            fields = (\"name\", \"birthdate\")\n\n\n    # 4.x\n    class UserSchema(Schema):\n        name = fields.String()\n        email = fields.Date()\n\n\nTo automatically generate schema fields from model classes, consider using a separate library, e.g.\n`marshmallow-sqlalchemy <https://github.com/marshmallow-code/marshmallow-sqlalchemy>`_ for SQLAlchemy models.\n\n.. code-block:: python\n\n    from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field\n\n\n    class UserSchema(SQLAlchemySchema):\n        class Meta:\n            model = Author\n\n        name = auto_field()\n        birthdate = auto_field()\n\n`@validates <marshmallow.validates>` accepts multiple field names\n*****************************************************************\n\nThe `@validates <marshmallow.validates>` decorator now accepts multiple field names as arguments.\nDecorated methods receive ``data_key`` as a keyword argument.\n\n.. code-block:: python\n\n    from marshmallow import fields, Schema, validates\n\n\n    # 3.x\n    class UserSchema(Schema):\n        name = fields.Str(required=True)\n        nickname = fields.Str(required=True)\n\n        @validates(\"name\")\n        def validate_name(self, value: str) -> None:\n            if len(value) < 3:\n                raise ValidationError('\"name\" too short')\n\n        @validates(\"nickname\")\n        def validate_nickname(self, value: str) -> None:\n            if len(value) < 3:\n                raise ValidationError('\"nickname\" too short')\n\n\n    # 4.x\n    class UserSchema(Schema):\n        name = fields.Str(required=True)\n        nickname = fields.Str(required=True)\n\n        @validates(\"name\", \"nickname\")\n        def validate_names(self, value: str, data_key: str) -> None:\n            if len(value) < 3:\n                raise ValidationError(f'\"{data_key}\" too short')\n\n\nRemove ``ordered`` from the `SchemaOpts <marshmallow.SchemaOpts>` constructor\n*****************************************************************************\n\nSubclasses of `marshmallow.SchemaOpts` should remove the ``ordered`` argument from the constructor.\n\n.. code-block:: python\n\n    # 3.x\n    class CustomOpts(SchemaOpts):\n        def __init__(self, meta, ordered=False):\n            super().__init__(meta, ordered=ordered)\n            self.custom_option = getattr(meta, \"custom_option\", False)\n\n\n    # 4.x\n    class CustomOpts(SchemaOpts):\n        def __init__(self, meta):\n            super().__init__(meta)\n            self.custom_option = getattr(meta, \"custom_option\", False)\n\n``TimeDelta`` changes\n*********************\n\nThe `TimeDelta <marshmallow.fields.TimeDelta>` field now preserves float values such that\nmicroseconds are included in the resulting `datetime.timedelta` object.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n    field = fields.TimeDelta()\n    value = field.deserialize(12.9)\n\n    # 3.x\n    print(value)  # => datetime.timedelta(seconds=12)\n\n    # 4.x\n    print(value)  # => datetime.timedelta(seconds=12, microseconds=900000)\n\nThe ``serialization_type`` parameter has been removed. Use a custom field or cast the serialized value\nif you need to change the final output type.\n\n``pass_many`` is renamed to ``pass_collection`` in decorators\n*************************************************************\n\nThe ``pass_many`` argument to `pre_load <marshmallow.decorators.pre_load>`,\n`post_load <marshmallow.decorators.post_load>`, `pre_dump <marshmallow.decorators.pre_dump>`,\nand `post_dump <marshmallow.decorators.post_dump>` is renamed to ``pass_collection``.\n\nThe behavior is unchanged.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, post_load\n\n\n    # 3.x\n    class MySchema(Schema):\n        name = fields.Str()\n\n        @post_dump(pass_many=True)\n        def post_dump(self, data, many, **kwargs): ...\n\n\n    # 4.x\n    class MySchema(Schema):\n        name = fields.Str()\n\n        @post_dump(pass_collection=True)\n        def post_dump(self, data, many, **kwargs): ...\n\nRename ``schema`` to ``parent`` in ``_bind_to_schema``\n******************************************************\n\nCustom fields that define a `_bind_to_schema <marshmallow.Fields._bind_to_schema>` method should rename the `schema` argument to `parent`.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n\n    # 3.x\n    class MyField(fields.Field):\n        def _bind_to_schema(self, field_name: str, schema: Schema | Field): ...\n\n\n    # 4.x\n    class MyField(fields.Field[int]):\n        def _bind_to_schema(self, field_name: str, parent: Schema | Field): ...\n\nUse standard library functions to handle RFC 822 and ISO 8601 dates, times, and datetimes\n*****************************************************************************************\n\nISO 8601 and RFC 822 utilities are removed from `marshmallow.utils` in favor\nof using the standard library implementations.\n\n.. code-block:: python\n\n    # 3.x\n    import datetime as dt\n    from marshmallow.utils import (\n        from_iso_date,\n        from_iso_time,\n        from_iso_datetime,\n        to_iso_date,\n        to_iso_time,\n        isoformat,\n        from_rfc,\n        rfc_format,\n    )\n\n    from_iso_date(\"2013-11-10\")\n    from_iso_time(\"01:23:45\")\n    from_iso_datetime(\"2013-11-10T01:23:45\")\n    to_iso_date(dt.date(2013, 11, 10))\n    to_iso_time(dt.time(1, 23, 45))\n    isoformat(dt.datetime(2013, 11, 10, 1, 23, 45))\n    from_rfc(\"Sun, 10 Nov 2013 01:23:45 -0000\")\n    rfc_format(dt.datetime(2013, 11, 10, 1, 23, 45))\n\n    # 4.x\n    import datetime as dt\n    import email.utils\n\n    dt.date.fromisoformat(\"2013-11-10\")\n    dt.time.fromisoformat(\"01:23:45\")\n    dt.datetime.fromisoformat(\"2013-11-10T01:23:45\")\n    dt.date(2013, 11, 10).isoformat()\n    dt.time(1, 23, 45).isoformat()\n    dt.datetime(2013, 11, 10, 1, 23, 45).isoformat()\n    email.utils.parsedate_to_datetime(\"Sun, 10 Nov 2013 01:23:45 -0000\")\n    email.utils.format_datetime(dt.datetime(2013, 11, 10, 1, 23, 45))\n\nUpgrading to 3.26\n+++++++++++++++++\n\n``ordered`` is deprecated\n*************************\n\nThe `ordered <marshmallow.schema.Schema.Meta>` class Meta option is removed, since order is already preserved by default.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.26\n    class MySchema(Schema):\n        id = fields.Integer()\n\n        class Meta:\n            ordered = True\n\n\n    # >=3.26\n    class MySchema(Schema):\n        id = fields.Integer()\n\n.. note::\n\n    You can set `marshmallow.Schema.dict_class` to `collections.OrderedDict` to\n    force the output type of `marshmallow.Schema.dump` to be an `OrderedDict <collections.OrderedDict>`.\n\nUpgrading to 3.24\n+++++++++++++++++\n\n``Field`` usage\n***************\n\n`Field <marshmallow.fields.Field>` is the base class for all fields and should not be used directly within schemas.\nOnly use subclasses of `Field <marshmallow.fields.Field>` in your schemas.\nInstantiating `Field <marshmallow.fields.Field>` will raise a warning in marshmallow>=3.24 and an error in marshmallow 4.0.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.24\n    class UserSchema(Schema):\n        name = fields.Field()\n\n\n    # >=3.24\n    class UserSchema(Schema):\n        name = fields.String()\n\n``Number`` and ``Mapping`` fields as base classes\n*************************************************\n\n`Number <marshmallow.fields.Number>` and `Mapping <marshmallow.fields.Mapping>` are bases classes that should not be used within schemas.\nUse their subclasses instead.\nInstantiating `Number <marshmallow.fields.Number>` or `Mapping <marshmallow.fields.Mapping>`\nwill raise a warning in marshmallow>=3.24 and an error in marshmallow 4.0.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.24\n    class PackageSchema(Schema):\n        revision = fields.Number()\n        dependencies = fields.Mapping()\n\n\n    # >=3.24\n    class PackageSchema(Schema):\n        revision = fields.Integer()\n        dependencies = fields.Dict()\n\nValidators must raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>`\n***************************************************************************************\n\nValidators must raise a :exc:`ValidationError <marshmallow.exceptions.ValidationError>` when the value is invalid.\nReturning `False` from a validator is deprecated and will be removed in marshmallow 4.0.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.24\n    class UserSchema(Schema):\n        password = fields.String(validate=lambda x: x == \"password\")\n\n\n    # >=3.24\n    def validate_password(val):\n        if val != \"password\":\n            raise ValidationError(\"Invalid password.\")\n\n\n    class UserSchema(Schema):\n        password = fields.String(validate=validate_password)\n\n\nIf you want to use anonymous functions, you can use this helper function in your code.\n\n.. code-block:: python\n\n    from typing import Any, Callable\n\n    from marshmallow import Schema, fields\n\n\n    def predicate(\n        func: Callable[[Any], bool],\n    ) -> Callable[[Any], None]:\n        def validate(value: Any) -> None:\n            if func(value) is False:\n                raise ValidationError(\"Invalid value.\")\n\n        return validate\n\n\n    # Usage\n    class UserSchema(Schema):\n        password = fields.String(validate=predicate(lambda x: x == \"password\"))\n\n``context`` is deprecated\n*************************\n\nPassing ``context`` to `Schema <marshmallow.schema.Schema>` classes will raise a warning in marshmallow>=3.24 and will be removed in marshmallow 4.0. Use `contextvars.ContextVar` for passing context to\nfields, :doc:`pre-/post-processing methods <marshmallow.decorators>`, and :doc:`validators <marshmallow.validate>` instead.\n\nUpgrading to 3.13\n+++++++++++++++++\n\n``load_default`` and ``dump_default``\n+++++++++++++++++++++++++++++++++++++\n\nThe ``missing`` and ``default`` parameters of fields are renamed to\n``load_default`` and ``dump_default``, respectively.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # < 3.13\n    class MySchema(Schema):\n        name = fields.Str(missing=\"Monty\")\n        age = fields.Int(default=42)\n\n\n    # >=3.13\n    class MySchema(Schema):\n        name = fields.Str(load_default=\"Monty\")\n        age = fields.Int(dump_default=42)\n\n``load_default`` and ``dump_default`` are passed to the field constructor as keyword arguments.\n\n\nUpgrading to 3.3\n++++++++++++++++\n\nIn 3.3, `fields.Nested <marshmallow.fields.Nested>` may take a callable that returns a schema instance.\nUse this to resolve order-of-declaration issues when schemas nest each other.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.3\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        artist = fields.Nested(\"ArtistSchema\", only=(\"name\",))\n\n\n    class ArtistSchema(Schema):\n        name = fields.Str()\n        albums = fields.List(fields.Nested(AlbumSchema))\n\n\n    # >=3.3\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        artist = fields.Nested(lambda: ArtistSchema(only=(\"name\",)))\n\n\n    class ArtistSchema(Schema):\n        name = fields.Str()\n        albums = fields.List(fields.Nested(AlbumSchema))\n\nA callable should also be used when nesting a schema within itself.\nPassing ``\"self\"`` is deprecated.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # <3.3\n    class PersonSchema(Schema):\n        partner = fields.Nested(\"self\", exclude=(\"partner\",))\n        friends = fields.List(fields.Nested(\"self\"))\n\n\n    # >=3.3\n    class PersonSchema(Schema):\n        partner = fields.Nested(lambda: PersonSchema(exclude=(\"partner\")))\n        friends = fields.List(fields.Nested(lambda: PersonSchema()))\n\n.. _upgrading_3_0:\n\nUpgrading to 3.0\n++++++++++++++++\n\nPython compatibility\n********************\n\nThe marshmallow 3.x series requires Python 3.\n\n\nSchemas are always strict\n*************************\n\nTwo major changes were made to (de)serialization behavior:\n\n- The ``strict`` parameter was removed. Schemas are always strict.\n- `Schema().load <marshmallow.Schema.load>` and `Schema().dump <marshmallow.Schema.dump>` don't return a ``(data, errors)`` tuple any more. Only ``data`` is returned.\n\nIf invalid data are passed, a :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised.\nThe dictionary of validation errors is accessible from the\n`ValidationError.messages <marshmallow.exceptions.ValidationError.messages>` attribute,\nalong with the valid data from the `ValidationError.valid_data\n<marshmallow.exceptions.ValidationError.valid_data>` attribute.\n\n.. code-block:: python\n\n    from marshmallow import ValidationError\n\n    # 2.x\n    schema = UserSchema()\n    data, errors = schema.load({\"name\": \"Monty\", \"email\": \"monty@python.org\"})\n    # OR\n    schema = UserSchema(strict=True)\n    try:\n        data, _ = schema.load({\"name\": \"Monty\", \"email\": \"monty@python.org\"})\n    except ValidationError as err:\n        errors = err.messages\n        valid_data = err.valid_data\n\n    # 3.x\n    schema = UserSchema()\n    # There is only one right way\n    try:\n        data = schema.load({\"name\": \"Monty\", \"email\": \"monty@python.org\"})\n    except ValidationError as err:\n        errors = err.messages\n        valid_data = err.valid_data\n\n`Schema.validate <marshmallow.Schema.validate>` always returns a dictionary of validation errors (same as 2.x with ``strict=False``).\n\n.. code-block:: python\n\n    schema.validate({\"email\": \"invalid\"})\n    # {'email': ['Not a valid email address.']}\n\nSetting the ``strict`` option on `class Meta <marshmallow.Schema.Meta>` has no effect on `Schema <marshmallow.Schema>` behavior.\nPassing ``strict=True`` or ``strict=False`` to the `Schema <marshmallow.Schema>` constructor\nwill raise a :exc:`TypeError`.\n\n\n.. code-block:: python\n\n    # 3.x\n    UserSchema(strict=True)\n    # TypeError: __init__() got an unexpected keyword argument 'strict'\n\n\n.. seealso::\n\n    See GitHub issues :issue:`377` and :issue:`598` for the discussions on\n    this change.\n\n\nDecorated methods and ``handle_error`` receive ``many`` and ``partial``\n***********************************************************************\n\nMethods decorated with\n`pre_load <marshmallow.decorators.pre_load>`, `post_load <marshmallow.decorators.post_load>`,\n`pre_dump <marshmallow.decorators.pre_dump>`, `post_dump <marshmallow.decorators.post_dump>`,\nand `validates_schema <marshmallow.decorators.validates_schema>` receive\n``many`` as a keyword argument. In addition, `pre_load <marshmallow.decorators.pre_load>`, `post_load <marshmallow.decorators.post_load>`,\nand `validates_schema <marshmallow.decorators.validates_schema>` receive\n``partial``. To account for these additional arguments, add ``**kwargs`` to your methods.\n\n.. code-block:: python\n\n    # 2.x\n    class UserSchema(Schema):\n        name = fields.Str()\n        slug = fields.Str()\n\n        @pre_load\n        def slugify_name(self, in_data):\n            in_data[\"slug\"] = in_data[\"slug\"].lower().strip().replace(\" \", \"-\")\n            return in_data\n\n\n    # 3.x\n    class UserSchema(Schema):\n        name = fields.Str()\n        slug = fields.Str()\n\n        @pre_load\n        def slugify_name(self, in_data, **kwargs):\n            in_data[\"slug\"] = in_data[\"slug\"].lower().strip().replace(\" \", \"-\")\n            return in_data\n\n\n`Schema.handle_error <marshmallow.Schema.handle_error>` also receives ``many`` and ``partial`` as keyword arguments.\n\n.. code-block:: python\n\n    # 2.x\n    class UserSchema(Schema):\n        def handle_error(self, exc, data):\n            raise AppError(\"An error occurred with input: {0}\".format(data))\n\n\n    # 3.x\n    class UserSchema(Schema):\n        def handle_error(self, exc, data, **kwargs):\n            raise AppError(\"An error occurred with input: {0}\".format(data))\n\n\nValidation does not occur on serialization\n******************************************\n\n`Schema.dump <marshmallow.Schema.dump>` will no longer validate and collect error messages. You *must* validate\nyour data before serializing it.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, ValidationError\n\n    invalid_data = dict(created_at=\"invalid\")\n\n\n    class WidgetSchema(Schema):\n        created_at = fields.DateTime()\n\n\n    # 2.x\n    WidgetSchema(strict=True).dump(invalid_data)\n    # marshmallow.exceptions.ValidationError: {'created_at': ['\"invalid\" cannot be formatted as a datetime.']}\n\n    # 3.x\n    WidgetSchema().dump(invalid_data)\n    # AttributeError: 'str' object has no attribute 'isoformat'\n\n    # Instead, validate before dumping\n    schema = WidgetSchema()\n    try:\n        widget = schema.load(invalid_data)\n    except ValidationError:\n        print(\"handle errors...\")\n    else:\n        dumped = schema.dump(widget)\n\n\nDeserializing invalid types raises a ``ValidationError``\n********************************************************\n\nNumbers, booleans, strings, and ``None`` are\nconsidered invalid input to `Schema.load\n<marshmallow.Schema.load>`.\n\n.. code-block:: python\n\n    # 2.x\n    # Passes silently\n    schema.load(None)\n    schema.load(False)\n    schema.load(\"pass\")\n\n    # 3.x\n    # marshmallow.exceptions.ValidationError: {'_schema': ['Invalid input type.']}\n    schema.load(None)\n    schema.load(False)\n    schema.load(\"nope\")\n\n\nWhen ``many=True``, non-collection types are also considered invalid.\n\n\n.. code-block:: python\n\n    # 2.x\n    # Passes silently\n    schema.load(None, many=True)\n    schema.load({}, many=True)\n    schema.load(\"pass\", many=True)\n\n    # 3.x\n    # marshmallow.exceptions.ValidationError: {'_schema': ['Invalid input type.']}\n    schema.load(None, many=True)\n    schema.load({}, many=True)\n    schema.load(\"invalid\", many=True)\n\n\n``ValidationError.fields`` is removed\n*************************************\n\n:exc:`ValidationError <marshmallow.exceptions.ValidationError>` no\nlonger stores a list of `Field <marshmallow.fields.Field>` instances\nassociated with the validation errors.\n\nIf you need field instances associated with an error, you can access\nthem from ``schema.fields``.\n\n.. code-block:: python\n\n\n    from marshmallow import Schema, fields, ValidationError\n\n\n    class MySchema(Schema):\n        foo = fields.Int()\n\n\n    schema = MySchema()\n\n    try:\n        schema.load({\"foo\": \"invalid\"})\n    except ValidationError as error:\n        field = schema.fields[\"foo\"]\n        # ...\n\n\n``ValidationError`` expects a single field name\n***********************************************\n\n:exc:`ValidationError <marshmallow.exceptions.ValidationError>` no\nlonger accepts a list of field names. It expects a single field name. If none\nis passed, the error refers to the schema.\n\nTo return an error for several fields at once, a `dict` must be used.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, validates_schema, ValidationError\n\n\n    class NumberSchema(Schema):\n        field_a = fields.Integer()\n        field_b = fields.Integer()\n\n        # 2.x\n        @validates_schema\n        def validate_numbers(self, data):\n            if data[\"field_b\"] >= data[\"field_a\"]:\n                raise ValidationError(\n                    \"field_a must be greater than field_b\", [\"field_a\", \"field_b\"]\n                )\n\n        # 3.x\n        @validates_schema\n        def validate_numbers(self, data):\n            if data[\"field_b\"] >= data[\"field_a\"]:\n                raise ValidationError(\n                    {\n                        \"field_a\": [\"field_a must be greater than field_b\"],\n                        \"field_b\": [\"field_a must be greater than field_b\"],\n                    }\n                )\n\n``ValidationError`` error messages are deep-merged\n**************************************************\n\nWhen multiple :exc:`ValidationError <marshmallow.exceptions.ValidationError>`\nare raised, the error structures are merged in the final :exc:`ValidationError`\nraised at the end of the process.\n\nWhen reporting error messages as `dict`, the keys should refer to subitems\nof the item the message refers to, and the values should be error messages.\n\nSee :doc:`extending/schema_validation` for an example.\npage for an example.\n\nSchemas raise ``ValidationError`` when deserializing data with unknown keys\n***************************************************************************\n\nmarshmallow 3.x schemas can deal with unknown keys in three different ways,\nconfigurable with the ``unknown`` option:\n\n- ``EXCLUDE``: drop those keys (same as marshmallow 2)\n- ``INCLUDE``: pass those keys/values as is, with no validation performed\n- ``RAISE`` (default): raise a ``ValidationError``\n\nThe ``unknown`` option can be passed as a Meta option, on Schema instantiation,\nor at load time.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, EXCLUDE, INCLUDE, RAISE\n\n\n    class MySchema(Schema):\n        foo = fields.Int()\n\n        class Meta:\n            # Pass EXCLUDE as Meta option to keep marshmallow 2 behavior\n            unknown = EXCLUDE\n\n\n    MySchema().load({\"foo\": 42, \"bar\": \"whatever\"})  # => ['foo': 42]\n\n    #  Value passed on instantiation overrides Meta option\n    schema = MySchema(unknown=INCLUDE)\n    schema.load({\"foo\": 42, \"bar\": \"whatever\"})  # => ['foo': 42, 'bar': 'whatever']\n\n    #  Value passed on load overrides instance attribute\n    schema.load({\"foo\": 42, \"bar\": \"whatever\"}, unknown=RAISE)  # => ValidationError\n\nOverriding ``get_attribute``\n****************************\n\nIf your `Schema <marshmallow.Schema>` overrides `get_attribute <marshmallow.Schema.get_attribute>`, you will need to update the method's signature. The positions of the ``attr`` and ``obj`` arguments were switched for consistency with Python builtins, e.g. `getattr`.\n\n.. code-block:: python\n\n    from marshmallow import Schema\n\n\n    # 2.x\n    class MySchema(Schema):\n        def get_attribute(self, attr, obj, default):\n            return getattr(obj, attr, default)\n\n\n    # 3.x\n    class MySchema(Schema):\n        def get_attribute(self, obj, attr, default):\n            return getattr(obj, attr, default)\n\n``pass_original=True`` passes individual items when ``many=True``\n*****************************************************************\n\nWhen ``pass_original=True`` is passed to\n`validates_schema <marshmallow.decorators.validates_schema>`,\n`post_load <marshmallow.decorators.post_load>`, or\n`post_dump <marshmallow.decorators.post_dump>`, the `original_data`\nargument will be a single item corresponding to the (de)serialized\ndatum.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, post_load, EXCLUDE\n\n\n    class ShoeSchema(Schema):\n        size = fields.Int()\n\n        class Meta:\n            unknown = EXCLUDE\n\n        @post_load(pass_original=True)\n        def post_load(self, data, original_data, **kwargs):\n            # original_data has 'width' but\n            # data does not because it's not\n            # in the schema\n            assert \"width\" in original_data\n            assert \"width\" not in data\n            return data\n\n\n    input_data = [{\"size\": 10, \"width\": \"M\"}, {\"size\": 6, \"width\": \"W\"}]\n\n    print(ShoeSchema(many=True).load(input_data))\n    # [{'size': 10}, {'size': 6}]\n\n\n``utils.get_func_args`` no longer returns bound arguments\n*********************************************************\n\nThe `utils.get_func_args <marshmallow.utils.get_func_args>` function will no longer return bound arguments, e.g. `'self'`.\n\n.. code-block:: python\n\n    from marshmallow.utils import get_func_args\n\n\n    class MyCallable:\n        def __call__(self, foo, bar):\n            return 42\n\n\n    callable_obj = MyCallable()\n\n    # 2.x\n    get_func_args(callable_obj)  # => ['self', 'foo', 'bar']\n\n    # 3.x\n    get_func_args(callable_obj)  # => ['foo', 'bar']\n\n\nHandling ``AttributeError`` in ``Method`` and ``Function`` fields\n*****************************************************************\n\nThe `Method <marshmallow.fields.Method>` and `Function <marshmallow.fields.Function>` fields no longer swallow ``AttributeErrors``. Therefore, your methods and functions are responsible for handling inputs such as `None`.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, missing\n\n\n    # 2.x\n    class ShapeSchema(Schema):\n        area = fields.Method(\"get_area\")\n\n        def get_area(self, obj):\n            return obj.height * obj.length\n\n\n    schema = ShapeSchema()\n    # In 2.x, the following would pass without errors\n    # In 3.x, and AttributeError would be raised\n    result = schema.dump(None)\n    result  # => {}\n\n\n    # 3.x\n    class ShapeSchema(Schema):\n        area = fields.Method(\"get_area\")\n\n        def get_area(self, obj):\n            if obj is None:\n                # 'area' will not appear in serialized output\n                return missing\n            return obj.height * obj.length\n\n\n    schema = ShapeSchema()\n    result = schema.dump(None)\n    result  # => {}\n\nAdding additional data to serialized output\n*******************************************\n\nUse a `post_dump <marshmallow.decorators.post_dump>` to add additional data on serialization. The ``extra`` argument on `Schema <marshmallow.Schema>` was removed.\n\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, post_dump\n\n\n    # 2.x\n    class MySchema(Schema):\n        x = fields.Int()\n        y = fields.Int()\n\n\n    schema = MySchema(extra={\"z\": 123})\n    schema.dump({\"x\": 1, \"y\": 2})\n    # => {'z': 123, 'y': 2, 'x': 1}\n\n\n    # 3.x\n    class MySchema(Schema):\n        x = fields.Int()\n        y = fields.Int()\n\n        @post_dump\n        def add_z(self, output):\n            output[\"z\"] = 123\n            return output\n\n\n    schema = MySchema()\n    schema.dump({\"x\": 1, \"y\": 2})\n    # => {'z': 123, 'y': 2, 'x': 1}\n\n\nSchema-level validators are skipped when field validation fails\n***************************************************************\n\nBy default, schema validator methods decorated by `validates_schema <marshmallow.decorators.validates_schema>` won't execute if any of the field validators fails (including ``required=True`` validation).\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, validates_schema, ValidationError\n\n\n    class MySchema(Schema):\n        x = fields.Int(required=True)\n        y = fields.Int(required=True)\n\n        @validates_schema\n        def validate_schema(self, data):\n            if data[\"x\"] <= data[\"y\"]:\n                raise ValidationError(\"x must be greater than y\")\n\n\n    schema = MySchema()\n\n    # 2.x\n    # A KeyError is raised in validate_schema\n    schema.load({\"x\": 2})\n\n    # 3.x\n    # marshmallow.exceptions.ValidationError: {'y': ['Missing data for required field.']}\n    # validate_schema is not run\n    schema.load({\"x\": 2})\n\nIf you want a schema validator to run even if a field validator fails, pass ``skip_on_field_errors=False``. Make sure your code handles cases where fields are missing from the deserialized data (due to validation errors).\n\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, validates_schema, ValidationError\n\n\n    class MySchema(Schema):\n        x = fields.Int(required=True)\n        y = fields.Int(required=True)\n\n        @validates_schema(skip_on_field_errors=False)\n        def validate_schema(self, data):\n            if \"x\" in data and \"y\" in data:\n                if data[\"x\"] <= data[\"y\"]:\n                    raise ValidationError(\"x must be greater than y\")\n\n\n    schema = MySchema()\n    schema.load({\"x\": 2})\n    # marshmallow.exceptions.ValidationError: {'y': ['Missing data for required field.']}\n\n`SchemaOpts` constructor receives ``ordered`` argument\n******************************************************\n\nSubclasses of `SchemaOpts <marshmallow.SchemaOpts>` receive an additional argument, ``ordered``, which is `True` if the `ordered` option is set to `True` on a Schema or one of its parent classes.\n\n.. code-block:: python\n\n    from marshmallow import SchemaOpts\n\n\n    # 2.x\n    class CustomOpts(SchemaOpts):\n        def __init__(self, meta):\n            super().__init__(meta)\n            self.custom_option = getattr(meta, \"meta\", False)\n\n\n    # 3.x\n    class CustomOpts(SchemaOpts):\n        def __init__(self, meta, ordered=False):\n            super().__init__(meta, ordered)\n            self.custom_option = getattr(meta, \"meta\", False)\n\n`ContainsOnly` accepts empty and duplicate values\n*************************************************\n\n`validate.ContainsOnly <marshmallow.validate.ContainsOnly>` now accepts duplicate values in the input value.\n\n\n.. code-block:: python\n\n    from marshmallow import validate\n\n    validator = validate.ContainsOnly([\"red\", \"blue\"])\n\n    # in 2.x the following raises a ValidationError\n    # in 3.x, no error is raised\n    validator([\"red\", \"red\", \"blue\"])\n\n\nIf you don't want to accept duplicates, use a custom validator, like the following.\n\n.. code-block:: python\n\n    from marshmallow import ValidationError\n    from marshmallow.validate import ContainsOnly\n\n\n    class ContainsOnlyNoDuplicates(ContainsOnly):\n        def __call__(self, value):\n            ret = super(ContainsOnlyNoDuplicates, self).__call__(value)\n            if len(set(value)) != len(value):\n                raise ValidationError(\"Duplicate values not allowed\")\n            return ret\n\n.. note::\n\n    If you need to handle unhashable types, you can use the  `implementation of\n    ContainsOnly from marshmallow 2.x <https://github.com/marshmallow-code/marshmallow/blob/2888e6978bc8c409a5fed35da6ece8bdb23384f2/marshmallow/validate.py#L436-L467>`_.\n\n`validate.ContainsOnly <marshmallow.validate.ContainsOnly>` also accepts empty values as valid input.\n\n.. code-block:: python\n\n    from marshmallow import validate\n\n    validator = validate.ContainsOnly([\"red\", \"blue\"])\n\n    # in 2.x the following raises a ValidationError\n    # in 3.x, no error is raised\n    validator([])\n\nTo validate against empty inputs, use `validate.Length(min=1) <marshmallow.validate.Length>`.\n\n\n``json_module`` option is renamed to ``render_module``\n******************************************************\n\nThe ``json_module`` `class Meta <marshmallow.Schema.Meta>` option is deprecated in favor of ``render_module``.\n\n.. code-block:: python\n\n    import ujson\n\n\n    # 2.x\n    class MySchema(Schema):\n        class Meta:\n            json_module = ujson\n\n\n    # 3.x\n    class MySchema(Schema):\n        class Meta:\n            render_module = ujson\n\n\n``missing`` and ``default`` ``Field`` parameters are passed in deserialized form\n********************************************************************************\n\n.. code-block:: python\n\n    # 2.x\n    class UserSchema(Schema):\n        id = fields.UUID(missing=lambda: str(uuid.uuid1()))\n        birthdate = fields.DateTime(default=lambda: dt.datetime(2017, 9, 19).isoformat())\n\n\n    # 3.x\n    class UserSchema(Schema):\n        id = fields.UUID(missing=uuid.uuid1)\n        birthdate = fields.DateTime(default=dt.datetime(2017, 9, 19))\n\n\nPass ``default`` as a keyword argument\n**************************************\n\n`fields.Boolean <marshmallow.fields.Boolean>` now receives additional ``truthy`` and ``falsy`` parameters. Consequently, the ``default`` parameter should always be passed as a keyword argument.\n\n\n.. code-block:: python\n\n    # 2.x\n    fields.Boolean(True)\n\n    # 3.x\n    fields.Boolean(default=True)\n\n\n``Email`` and ``URL`` fields do not validate on serialization\n*************************************************************\n\n`fields.Email <marshmallow.fields.Email>` and `fields.URL <marshmallow.fields.URL>` only validate input upon\ndeserialization. They do not validate on serialization. This makes them\nmore consistent with the other fields and improves serialization\nperformance.\n\n\n``load_from`` and ``dump_to`` are merged into ``data_key``\n**********************************************************\n\nThe same key is used for serialization and deserialization.\n\n.. code-block:: python\n\n    # 2.x\n    class UserSchema(Schema):\n        email = fields.Email(load_from=\"CamelCasedEmail\", dump_to=\"CamelCasedEmail\")\n\n\n    # 3.x\n    class UserSchema(Schema):\n        email = fields.Email(data_key=\"CamelCasedEmail\")\n\nIt is not possible to specify a different key for serialization and deserialization on the same field.\nThis use case is covered by using two different `Schema <marshmallow.Schema>`.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # 2.x\n    class UserSchema(Schema):\n        id = fields.Str()\n        email = fields.Email(load_from=\"CamelCasedEmail\", dump_to=\"snake_case_email\")\n\n\n    # 3.x\n    class BaseUserSchema(Schema):\n        id = fields.Str()\n\n\n    class LoadUserSchema(BaseUserSchema):\n        email = fields.Email(data_key=\"CamelCasedEmail\")\n\n\n    class DumpUserSchema(BaseUserSchema):\n        email = fields.Email(data_key=\"snake_case_email\")\n\n\nAlso, when ``data_key`` is specified on a field, only ``data_key`` is checked in the input data. In marshmallow 2.x the field name is checked if ``load_from`` is missing from the input data.\n\nPre/Post-processors must return modified data\n*********************************************\n\nIn marshmallow 2.x, ``None`` returned by a pre or post-processor is interpreted as \"the data was mutated\". In marshmallow 3.x, the return value is considered as processed data even if it is ``None``.\n\nProcessors that mutate the data should be updated to also return it.\n\n\n.. code-block:: python\n\n    # 2.x\n    class UserSchema(Schema):\n        name = fields.Str()\n        slug = fields.Str()\n\n        @pre_load\n        def slugify_name(self, in_data):\n            # In 2.x, implicitly returning None implied that data were mutated\n            in_data[\"slug\"] = in_data[\"slug\"].lower().strip().replace(\" \", \"-\")\n\n\n    # 3.x\n    class UserSchema(Schema):\n        name = fields.Str()\n        slug = fields.Str()\n\n        @pre_load\n        def slugify_name(self, in_data, **kwargs):\n            # In 3.x, always return the processed data\n            in_data[\"slug\"] = in_data[\"slug\"].lower().strip().replace(\" \", \"-\")\n            return in_data\n\n``Nested`` field no longer supports plucking\n********************************************\n\nIn marshmallow 2.x, when a string was passed to a ``Nested`` field's ```only`` parameter, the field would be plucked. In marshmallow 3.x, the ``Pluck`` field must be used instead.\n\n\n.. code-block:: python\n\n    # 2.x\n    class UserSchema(Schema):\n        name = fields.Str()\n        friends = fields.Nested(\"self\", many=True, only=\"name\")\n\n\n    # 3.x\n    class UserSchema(Schema):\n        name = fields.Str()\n        friends = fields.Pluck(\"self\", \"name\", many=True)\n\n\nAccessing attributes on objects within a list\n*********************************************\n\nIn order to serialize attributes on inner objects within a list, use the\n``Pluck`` field.\n\n.. code-block:: python\n\n    # 2.x\n    class FactorySchema(Schema):\n        widget_ids = fields.List(fields.Int(attribute=\"id\"))\n\n\n    # 3.x\n    class FactorySchema(Schema):\n        widget_ids = fields.List(fields.Pluck(WidgetSchema, \"id\"))\n\n\n``List`` does not wrap single values in a list on serialization\n***************************************************************\n\nIn marshmallow 2.x, ``List`` serializes a single object as a list with a single\nelement. In marshmallow 3.x, the object is assumed to be iterable and passing a\nnon-iterable element results in an error.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        numbers = fields.List(fields.Int())\n\n\n    user = {\"numbers\": 1}\n    UserSchema().dump(user)\n\n    # 2.x\n    # => {'numbers': [1]}\n\n    # 3.x\n    # => TypeError: 'int' object is not iterable\n\n\n``Float`` field takes a new ``allow_nan`` parameter\n***************************************************\n\nIn marshmallow 2.x, ``Float`` field would serialize and deserialize special values such as ``nan``, ``inf`` or ``-inf``. In marshmallow 3, those values trigger a ``ValidationError`` unless ``allow_nan`` is ``True``. ``allow_nan`` defaults to ``False``.\n\n\n.. code-block:: python\n\n    # 2.x\n    class MySchema(Schema):\n        x = fields.Float()\n\n\n    MySchema().load({\"x\": \"nan\"})\n    # => {{'x': nan}}\n\n\n    # 3.x\n    class MySchema(Schema):\n        x = fields.Float()\n        y = fields.Float(allow_nan=True)\n\n\n    MySchema().load({\"x\": 12, \"y\": \"nan\"})\n    # => {{'x': 12.0, 'y': nan}}\n\n    MySchema().load({\"x\": \"nan\"})\n    # marshmallow.exceptions.ValidationError: {'x': ['Special numeric values (nan or infinity) are not permitted.']}\n\n``DateTime`` field ``dateformat`` ``Meta`` option is renamed ``datetimeformat``\n*******************************************************************************\n\nThe ``Meta`` option ``dateformat`` used to pass format to `DateTime <marshmallow.fields.DateTime>` field is renamed as ``datetimeformat``.\n\n`Date <marshmallow.fields.Date>` field gets a new ``format`` parameter to specify the format to use for serialization. ``dateformat`` ``Meta`` option now applies to `Date <marshmallow.fields.Date>` field.\n\n.. code-block:: python\n\n    # 2.x\n    class MySchema(Schema):\n        x = fields.DateTime()\n\n        class Meta:\n            dateformat = \"%Y-%m\"\n\n\n    MySchema().dump({\"x\": dt.datetime(2017, 9, 19)})\n    # => {{'x': '2017-09'}}\n\n\n    # 3.x\n    class MySchema(Schema):\n        x = fields.DateTime()\n        y = fields.Date()\n\n        class Meta:\n            datetimeformat = \"%Y-%m\"\n            dateformat = \"%m-%d\"\n\n\n    MySchema().dump({\"x\": dt.datetime(2017, 9, 19), \"y\": dt.date(2017, 9, 19)})\n    # => {{'x': '2017-09', 'y': '09-19'}}\n\n``DateTime`` leaves timezone information untouched during serialization\n***********************************************************************\n\n``DateTime`` does not convert naive datetimes to UTC on serialization and\n``LocalDateTime`` is removed.\n\n.. code-block:: python\n\n    # 2.x\n    class MySchema(Schema):\n        x = fields.DateTime()\n        y = fields.DateTime()\n        z = fields.LocalDateTime()\n\n\n    MySchema().dump(\n        {\n            \"x\": dt.datetime(2017, 9, 19),\n            \"y\": dt.datetime(2017, 9, 19, tzinfo=dt.timezone(dt.timedelta(hours=2))),\n            \"z\": dt.datetime(2017, 9, 19, tzinfo=dt.timezone(dt.timedelta(hours=2))),\n        }\n    )\n    # => {{'x': '2017-09-19T00:00:00+00:00', 'y': '2017-09-18T22:00:00+00:00', 'z': '2017-09-19T00:00:00+02:00'}}\n\n\n    # 3.x\n    class MySchema(Schema):\n        x = fields.DateTime()\n        y = fields.DateTime()\n\n\n    MySchema().dump(\n        {\n            \"x\": dt.datetime(2017, 9, 19),\n            \"y\": dt.datetime(2017, 9, 19, tzinfo=dt.timezone(dt.timedelta(hours=2))),\n        }\n    )\n    # => {{'x': '2017-09-19T00:00:00', 'y': '2017-09-19T00:00:00+02:00'}}\n\nThe ``prefix`` ``Schema`` parameter is removed\n**********************************************\n\nThe ``prefix`` parameter of ``Schema`` is removed. The same feature can be achieved using a post_dump <marshmallow.decorators.post_dump>` method.\n\n\n.. code-block:: python\n\n    # 2.x\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw()\n\n\n    MySchema(prefix=\"pre_\").dump({\"f1\": \"one\", \"f2\": \"two\"})\n    # {'pre_f1': 'one', '_pre_f2': 'two'}\n\n\n    # 3.x\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw()\n\n        @post_dump\n        def prefix_usr(self, data):\n            return {\"usr_{}\".format(k): v for k, v in iteritems(data)}\n\n\n    MySchema().dump({\"f1\": \"one\", \"f2\": \"two\"})\n    # {'pre_f1': 'one', '_pre_f2': 'two'}\n\n\n``fields.FormattedString`` is removed\n*************************************\n\n``fields.FormattedString`` field is removed. Use `fields.Function\n<marshmallow.fields.Function>` or\n`fields.Method <marshmallow.fields.Method>` instead.\n\n.. code-block:: python\n\n    # 2.x\n    class MySchema(Schema):\n        full_name = fields.FormattedString(\"{first_name} {last_name}\")\n\n\n    # 3.x\n    class MySchema(Schema):\n        full_name = fields.Function(lambda u: f\"{u.first_name} {u.last_name}\")\n\n\n``attribute`` or ``data_key`` collision triggers an exception\n*************************************************************\n\nWhen a `Schema <marshmallow.Schema>` is instantiated, a check is performed and a ``ValueError`` is triggered if\n\n- several fields have the same ``attribute`` value (or field name if ``attribute`` is not passed), excluding ``dump_only`` fields, or\n- several fields have the same ``data_key`` value (or field name if ``data_key`` is not passed), excluding ``load_only`` fields\n\nIn marshmallow 2, it was possible to have multiple fields with the same ``attribute``. It would work provided the ``Schema`` was only used for dumping. When loading, the behaviour was undefined. In marshmallow 3, all but one of those fields must be marked as ``dump_only``. Likewise for ``data_key`` (formerly ``dump_to``) for fields that are not ``load_only``.\n\n.. code-block:: python\n\n    # 2.x\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw(attribute=\"f1\")\n        f3 = fields.Raw(attribute=\"f5\")\n        f4 = fields.Raw(attribute=\"f5\")\n\n\n    MySchema()\n    #  No error\n\n\n    # 3.x\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw(attribute=\"f1\")\n        f3 = fields.Raw(attribute=\"f5\")\n        f4 = fields.Raw(attribute=\"f5\")\n\n\n    MySchema()\n    # ValueError: 'Duplicate attributes: ['f1', 'f5]'\n\n\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw(attribute=\"f1\", dump_only=True)\n        f3 = fields.Raw(attribute=\"f5\")\n        f4 = fields.Raw(attribute=\"f5\", dump_only=True)\n\n\n    MySchema()\n    # No error\n\n\n``Field.fail`` is deprecated in favor of ``Field.make_error``\n*************************************************************\n\n`Field.fail <marshmallow.fields.Field.fail>` is deprecated.\nUse `Field.make_error <marshmallow.fields.Field.fail>`. This allows you to\nre-raise exceptions using ``raise ... from ...``.\n\n.. code-block:: python\n\n    from marshmallow import fields, ValidationError\n    from packaging import version\n\n\n    # 2.x\n    class Version(fields.Field):\n        default_error_messages = {\"invalid\": \"Not a valid version.\"}\n\n        def _deserialize(self, value, *args, **kwargs):\n            try:\n                return version.Version(value)\n            except version.InvalidVersion:\n                self.fail(\"invalid\")\n\n\n    # 3.x\n    class Version(fields.Field):\n        default_error_messages = {\"invalid\": \"Not a valid version.\"}\n\n        def _deserialize(self, value, *args, **kwargs):\n            try:\n                return version.Version(value)\n            except version.InvalidVersion as error:\n                raise self.make_error(\"invalid\") from error\n\n\n``python-dateutil`` recommended dependency is removed\n*****************************************************\n\nIn marshmallow 2, ``python-dateutil`` was used to deserialize RFC or ISO 8601\ndatetimes if it was installed. In marshmallow 3, datetime deserialization is\ndone with no additional dependency.\n\n``python-dateutil`` is no longer used by marshmallow.\n\n\nCustom Fields\n*************\n\nTo make your custom fields compatible with marshmallow 3, ``_deserialize``\nshould accept ``**kwargs``:\n\n.. code-block:: python\n\n    from marshmallow import fields, ValidationError\n    from packaging import version\n\n\n    # 2.x\n    class MyCustomField(fields.Field):\n        def _deserialize(self, value, attr, obj): ...\n\n\n    # 3.x\n    class MyCustomField(fields.Field):\n        def _deserialize(self, value, attr, obj, **kwargs): ...\n\n\nUpgrading to 2.3\n++++++++++++++++\n\nThe ``func`` parameter of `fields.Function <marshmallow.fields.Function>` was renamed to ``serialize``.\n\n\n.. code-block:: python\n\n    # YES\n    lowername = fields.Function(serialize=lambda obj: obj.name.lower())\n    # or\n    lowername = fields.Function(lambda obj: obj.name.lower())\n\n    # NO\n    lowername = fields.Function(func=lambda obj: obj.name.lower())\n\nSimilarly, the ``method_name`` of `fields.Method <marshmallow.fields.Method>` was also renamed to ``serialize``.\n\n.. code-block:: python\n\n    # YES\n    lowername = fields.Method(serialize=\"lowercase\")\n    # or\n    lowername = fields.Method(\"lowercase\")\n\n    # NO\n    lowername = fields.Method(method_name=\"lowercase\")\n\nThe ``func`` parameter is still available for backwards-compatibility. It will be removed in marshmallow 3.0.\n\nBoth `fields.Function <marshmallow.fields.Function>` and `fields.Method <marshmallow.fields.Method>` will allow the serialize parameter to not be passed, in this case use the ``deserialize`` parameter by name.\n\n.. code-block:: python\n\n    lowername = fields.Function(deserialize=lambda name: name.lower())\n    # or\n    lowername = fields.Method(deserialize=\"lowername\")\n\nUpgrading to 2.0\n++++++++++++++++\n\nDeserializing `None`\n********************\n\nIn 2.0, validation/deserialization of `None` is consistent across field types. If ``allow_none`` is `False` (the default), validation fails when the field's value is `None`. If ``allow_none`` is `True`, `None` is considered valid, and the field deserializes to `None`.\n\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n    # In 1.0, deserialization of None was inconsistent\n    fields.Int().deserialize(None)  # 0\n    fields.Str().deserialize(None)  # ''\n    fields.DateTime().deserialize(None)  # error: Could not deserialize None to a datetime.\n\n\n    # In 2.0, validation/deserialization of None is consistent\n    fields.Int().deserialize(None)  # error: Field may not be null.\n    fields.Str().deserialize(None)  # error: Field may not be null.\n    fields.DateTime().deserialize(None)  # error: Field may not be null.\n\n    # allow_none makes None a valid value\n    fields.Int(allow_none=True).deserialize(None)  # None\n\nDefault values\n**************\n\nBefore version 2.0, certain fields (including `String <marshmallow.fields.String>`, `List <marshmallow.fields.List>`, `Nested <marshmallow.fields.Nested>`, and number fields) had implicit default values that would be used if their corresponding input value was `None` or missing.\n\n\nIn 2.0, these implicit defaults are removed.  A `Field's <marshmallow.fields.Field>` ``default`` parameter is only used if you explicitly set it. Otherwise, missing inputs will be excluded from the serialized output.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class MySchema(Schema):\n        str_no_default = fields.Str()\n        int_no_default = fields.Int()\n        list_no_default = fields.List(fields.Str)\n\n\n    schema = MySchema()\n\n    # In 1.0, None was treated as a missing input, so implicit default values were used\n    schema.dump(\n        {\"str_no_default\": None, \"int_no_default\": None, \"list_no_default\": None}\n    ).data\n    # {'str_no_default': '', 'int_no_default': 0, 'list_no_default': []}\n\n    # In 2.0, None serializes to None. No more implicit defaults.\n    schema.dump(\n        {\"str_no_default\": None, \"int_no_default\": None, \"list_no_default\": None}\n    ).data\n    # {'str_no_default': None, 'int_no_default': None, 'list_no_default': None}\n\n\n.. code-block:: python\n\n    # In 1.0, implicit default values were used for missing inputs\n    schema.dump({}).data\n    # {'int_no_default': 0, 'str_no_default': '', 'list_no_default': []}\n\n    # In 2.0, missing inputs are excluded from the serialized output\n    # if no defaults are specified\n    schema.dump({}).data\n    # {}\n\n\nAs a consequence of this new behavior, the ``skip_missing`` `class Meta <marshmallow.Schema.Meta>` option has been removed.\n\n\nPre-processing and post-processing methods\n******************************************\n\nThe pre- and post-processing API was significantly improved for better consistency and flexibility. The `pre_load <marshmallow.decorators.pre_load>`, `post_load <marshmallow.decorators.post_load>`, `pre_dump <marshmallow.decorators.pre_dump>`, and `post_dump <marshmallow.decorators.post_dump>` should be used to define processing hooks. ``Schema.preprocessor`` and ``Schema.data_handler`` are removed.\n\n\n.. code-block:: python\n\n    # 1.0 API\n    from marshmallow import Schema, fields\n\n\n    class ExampleSchema(Schema):\n        field_a = fields.Int()\n\n\n    @ExampleSchema.preprocessor\n    def increment(schema, data):\n        data[\"field_a\"] += 1\n        return data\n\n\n    @ExampleSchema.data_handler\n    def decrement(schema, data, obj):\n        data[\"field_a\"] -= 1\n        return data\n\n\n    # 2.0 API\n    from marshmallow import Schema, fields, pre_load, post_dump\n\n\n    class ExampleSchema(Schema):\n        field_a = fields.Int()\n\n        @pre_load\n        def increment(self, data):\n            data[\"field_a\"] += 1\n            return data\n\n        @post_dump\n        def decrement(self, data):\n            data[\"field_a\"] -= 1\n            return data\n\nSee the :doc:`extending/pre_and_post_processing_methods` page for more information on the ``pre_*`` and ``post_*`` decorators.\n\nSchema validators\n*****************\n\nSimilar to pre-processing and post-processing methods, schema validators are now defined as methods. Decorate schema validators with `validates_schema <marshmallow.decorators.validates_schema>`. ``Schema.validator`` is removed.\n\n.. code-block:: python\n\n    # 1.0 API\n    from marshmallow import Schema, fields, ValidationError\n\n\n    class MySchema(Schema):\n        field_a = fields.Int(required=True)\n        field_b = fields.Int(required=True)\n\n\n    @ExampleSchema.validator\n    def validate_schema(schema, data):\n        if data[\"field_a\"] < data[\"field_b\"]:\n            raise ValidationError(\"field_a must be greater than field_b\")\n\n\n    # 2.0 API\n    from marshmallow import Schema, fields, validates_schema, ValidationError\n\n\n    class MySchema(Schema):\n        field_a = fields.Int(required=True)\n        field_b = fields.Int(required=True)\n\n        @validates_schema\n        def validate_schema(self, data):\n            if data[\"field_a\"] < data[\"field_b\"]:\n                raise ValidationError(\"field_a must be greater than field_b\")\n\nCustom accessors and error handlers\n***********************************\n\nCustom accessors and error handlers are now defined as methods. ``Schema.accessor`` and ``Schema.error_handler`` are deprecated.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    # 1.0 Deprecated API\n    class ExampleSchema(Schema):\n        field_a = fields.Int()\n\n\n    @ExampleSchema.accessor\n    def get_from_dict(schema, attr, obj, default=None):\n        return obj.get(attr, default)\n\n\n    @ExampleSchema.error_handler\n    def handle_errors(schema, errors, obj):\n        raise CustomError(\"Something bad happened\", messages=errors)\n\n\n    # 2.0 API\n    class ExampleSchema(Schema):\n        field_a = fields.Int()\n\n        def get_attribute(self, attr, obj, default):\n            return obj.get(attr, default)\n\n        # handle_error gets passed a ValidationError\n        def handle_error(self, exc, data):\n            raise CustomError(\"Something bad happened\", messages=exc.messages)\n\nUse `post_load <marshmallow.decorators.post_load>` instead of `make_object`\n***************************************************************************\n\nThe `make_object` method was deprecated from the `Schema <marshmallow.Schema>` API (see :issue:`277` for the rationale). In order to deserialize to an object, use a `post_load <marshmallow.decorators.post_load>` method.\n\n.. code-block:: python\n\n    # 1.0\n    from marshmallow import Schema, fields, post_load\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        created_at = fields.DateTime()\n\n        def make_object(self, data):\n            return User(**data)\n\n\n    # 2.0\n    from marshmallow import Schema, fields, post_load\n\n\n    class UserSchema(Schema):\n        name = fields.Str()\n        created_at = fields.DateTime()\n\n        @post_load\n        def make_user(self, data):\n            return User(**data)\n\nError format when ``many=True``\n*******************************\n\nWhen validating a collection (i.e. when calling ``load`` or ``dump`` with ``many=True``), the errors dictionary will be keyed on the indices of invalid items.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class BandMemberSchema(Schema):\n        name = fields.String(required=True)\n        email = fields.Email()\n\n\n    user_data = [\n        {\"email\": \"mick@stones.com\", \"name\": \"Mick\"},\n        {\"email\": \"invalid\", \"name\": \"Invalid\"},  # invalid email\n        {\"email\": \"keith@stones.com\", \"name\": \"Keith\"},\n        {\"email\": \"charlie@stones.com\"},  # missing \"name\"\n    ]\n\n    result = BandMemberSchema(many=True).load(user_data)\n\n    # 1.0\n    result.errors\n    # {'email': ['\"invalid\" is not a valid email address.'],\n    #  'name': ['Missing data for required field.']}\n\n    # 2.0\n    result.errors\n    # {1: {'email': ['\"invalid\" is not a valid email address.']},\n    #  3: {'name': ['Missing data for required field.']}}\n\nYou can still get the pre-2.0 behavior by setting ``index_errors = False`` in a ``Schema's`` `class Meta <marshmallow.Schema.Meta>` options.\n\nUse ``ValidationError`` instead of ``MarshallingError`` and ``UnmarshallingError``\n**********************************************************************************\n\nThe :exc:`MarshallingError` and :exc:`UnmarshallingError` exceptions are deprecated in favor of a single :exc:`ValidationError <marshmallow.exceptions.ValidationError>`. Users who have written custom fields or are using ``strict`` mode will need to change their code accordingly.\n\nHandle ``ValidationError`` in strict mode\n-----------------------------------------\n\nWhen using `strict` mode, you should handle `ValidationErrors` when calling `Schema.dump <marshmallow.Schema.dump>` and `Schema.load <marshmallow.Schema.load>`.\n\n.. code-block:: python\n\n    from marshmallow import exceptions as exc\n\n    schema = BandMemberSchema(strict=True)\n\n    # 1.0\n    try:\n        schema.load({\"email\": \"invalid-email\"})\n    except exc.UnmarshallingError as err:\n        handle_error(err)\n\n    # 2.0\n    try:\n        schema.load({\"email\": \"invalid-email\"})\n    except exc.ValidationError as err:\n        handle_error(err)\n\n\nAccessing error messages in strict mode\n***************************************\n\nIn 2.0, `strict` mode was improved so that you can access all error messages for a schema (rather than failing early) by accessing a `ValidationError's` ``messages`` attribute.\n\n.. code-block:: python\n\n    schema = BandMemberSchema(strict=True)\n\n    try:\n        result = schema.load({\"email\": \"invalid\"})\n    except ValidationMessage as err:\n        print(err.messages)\n    # {\n    #     'email': ['\"invalid\" is not a valid email address.'],\n    #     'name': ['Missing data for required field.']\n    # }\n\n\nCustom fields\n*************\n\nTwo changes must be made to make your custom fields compatible with version 2.0.\n\n- The `_deserialize <marshmallow.fields.Field._deserialize>` method of custom fields now receives ``attr`` (the key corresponding to the value to be deserialized) and the raw input ``data`` as arguments.\n- Custom fields should raise :exc:`ValidationError <marshmallow.exceptions.ValidationError>` in their `_deserialize` and `_serialize` methods when a validation error occurs.\n\n.. code-block:: python\n\n    from marshmallow import fields, ValidationError\n    from marshmallow.exceptions import UnmarshallingError\n\n\n    # In 1.0, an UnmarshallingError was raised\n    class PasswordField(fields.Field):\n        def _deserialize(self, val):\n            if not len(val) >= 6:\n                raise UnmarshallingError(\"Password too short.\")\n            return val\n\n\n    # In 2.0, _deserialize receives attr and data,\n    # and a ValidationError is raised\n    class PasswordField(fields.Field):\n        def _deserialize(self, val, attr, data):\n            if not len(val) >= 6:\n                raise ValidationError(\"Password too short.\")\n            return val\n\n\nTo make a field compatible with both marshmallow 1.x and 2.x, you can pass `*args` and `**kwargs` to the signature.\n\n.. code-block:: python\n\n    class PasswordField(fields.Field):\n        def _deserialize(self, val, *args, **kwargs):\n            if not len(val) >= 6:\n                raise ValidationError(\"Password too short.\")\n            return val\n\nCustom error messages\n*********************\n\nError messages can be customized at the `Field` class or instance level.\n\n\n.. code-block:: python\n\n    # 1.0\n    field = fields.Number(error=\"You passed a bad number\")\n\n    # 2.0\n    # Instance-level\n    field = fields.Number(error_messages={\"invalid\": \"You passed a bad number.\"})\n\n\n    # Class-level\n    class MyNumberField(fields.Number):\n        default_error_messages = {\"invalid\": \"You passed a bad number.\"}\n\nPassing a string to ``required`` is deprecated.\n\n.. code-block:: python\n\n    # 1.0\n    field = fields.Str(required=\"Missing required argument.\")\n\n    # 2.0\n    field = fields.Str(error_messages={\"required\": \"Missing required argument.\"})\n\n\nUse ``OneOf`` instead of ``fields.Select``\n******************************************\n\nThe `fields.Select` field is deprecated in favor of the newly-added `OneOf` validator.\n\n.. code-block:: python\n\n    from marshmallow import fields\n    from marshmallow.validate import OneOf\n\n    # 1.0\n    fields.Select([\"red\", \"blue\"])\n\n    # 2.0\n    fields.Str(validate=OneOf([\"red\", \"blue\"]))\n\nAccessing context from method fields\n************************************\n\nUse ``self.context`` to access a schema's context within a ``Method`` field.\n\n.. code-block:: python\n\n    class UserSchema(Schema):\n        name = fields.String()\n        likes_bikes = fields.Method(\"writes_about_bikes\")\n\n        def writes_about_bikes(self, user):\n            return \"bicycle\" in self.context[\"blog\"].title.lower()\n\n\nValidation error messages\n*************************\n\nThe default error messages for many fields and validators have been changed for better consistency.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, validate\n\n\n    class ValidatingSchema(Schema):\n        foo = fields.Str()\n        bar = fields.Bool()\n        baz = fields.Int()\n        qux = fields.Float()\n        spam = fields.Decimal(2, 2)\n        eggs = fields.DateTime()\n        email = fields.Str(validate=validate.Email())\n        homepage = fields.Str(validate=validate.URL())\n        nums = fields.List(fields.Int())\n\n\n    schema = ValidatingSchema()\n    invalid_data = {\n        \"foo\": 42,\n        \"bar\": 24,\n        \"baz\": \"invalid-integer\",\n        \"qux\": \"invalid-float\",\n        \"spam\": \"invalid-decimal\",\n        \"eggs\": \"invalid-datetime\",\n        \"email\": \"invalid-email\",\n        \"homepage\": \"invalid-url\",\n        \"nums\": \"invalid-list\",\n    }\n    errors = schema.validate(invalid_data)\n    # {\n    #     'foo': ['Not a valid string.'],\n    #     'bar': ['Not a valid boolean.'],\n    #     'baz': ['Not a valid integer.'],\n    #     'qux': ['Not a valid number.'],\n    #     'spam': ['Not a valid number.']\n    #     'eggs': ['Not a valid datetime.'],\n    #     'email': ['Not a valid email address.'],\n    #     'homepage': ['Not a valid URL.'],\n    #     'nums': ['Not a valid list.'],\n    # }\n\nMore\n****\n\nFor a full list of changes in 2.0, see the :doc:`changelog <changelog>`.\n\n\nUpgrading to 1.2\n++++++++++++++++\n\nValidators\n**********\n\nValidators were rewritten as class-based callables, making them easier to use when declaring fields.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n    # 1.2\n    from marshmallow.validate import Range\n\n    age = fields.Int(validate=[Range(min=0, max=999)])\n\n    # Pre-1.2\n    from marshmallow.validate import ranging\n\n    age = fields.Int(validate=[lambda val: ranging(val, min=0, max=999)])\n\n\nThe validator functions from 1.1 are deprecated and will be removed in 2.0.\n\nDeserializing the empty string\n******************************\n\n\nIn version 1.2, deserialization of the empty string (``''``) with `DateTime`, `Date`, `Time`, or `TimeDelta` fields results in consistent error messages, regardless of whether or not `python-dateutil` is installed.\n\n.. code-block:: python\n\n    from marshmallow import fields\n\n    fields.Date().deserialize(\"\")\n    # UnmarshallingError: Could not deserialize '' to a date object.\n\n\nDecimal\n*******\n\nThe `Decimal` field was added to support serialization/deserialization of `decimal.Decimal` numbers. You should use this field when dealing with numbers where precision is critical. The `Fixed`, `Price`, and `Arbitrary` fields are deprecated in favor the `Decimal` field.\n\n\nUpgrading to 1.0\n++++++++++++++++\n\nVersion 1.0 marks the first major release of marshmallow. Many big changes were made from the pre-1.0 releases in order to provide a cleaner API, support object deserialization, and improve field validation.\n\nPerhaps the largest change is in how objects get serialized. Serialization occurs by invoking the :meth:`Schema.dump` method rather than passing the object to the constructor.  Because only configuration options (e.g. the ``many``, ``strict``, and ``only`` parameters) are passed to the constructor, you can more easily reuse serializer instances.  The :meth:`dump <Schema.dump>` method also forms a nice symmetry with the :meth:`Schema.load` method, which is used for deserialization.\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields\n\n\n    class UserSchema(Schema):\n        email = fields.Email()\n        name = fields.String()\n\n\n    user = User(email=\"monty@python.org\", name=\"Monty Python\")\n\n    # 1.0\n    serializer = UserSchema()\n    data, errors = serializer.dump(user)\n    # OR\n    result = serializer.dump(user)\n    result.data  # => serialized result\n    result.errors  # => errors\n\n    # Pre-1.0\n    serialized = UserSchema(user)\n    data = serialized.data\n    errors = serialized.errors\n\n.. note::\n\n    Some crucial parts of the pre-1.0 API have been retained to ease the transition. You can still pass an object to a `Schema <marshmallow.Schema>` constructor and access the `Schema.data` and `Schema.errors` properties. The `is_valid` method, however, has been completely removed. It is recommended that you migrate to the new API to prevent future releases from breaking your code.\n\nThe Fields interface was also reworked in 1.0 to make it easier to define custom fields with their own serialization and deserialization behavior. Custom fields now implement :meth:`Field._serialize` and :meth:`Field._deserialize`.\n\n.. code-block:: python\n\n    from marshmallow import fields, MarshallingError\n\n\n    class PasswordField(fields.Field):\n        def _serialize(self, value, attr, obj):\n            if not value or len(value) < 6:\n                raise MarshallingError(\"Password must be greater than 6 characters.\")\n            return str(value).strip()\n\n        # Similarly, you can override the _deserialize method\n\nAnother major change in 1.0 is that multiple validation errors can be stored for a single field. The ``errors`` dictionary returned by :meth:`Schema.dump` and :meth:`Schema.load` is a list of error messages keyed by field name.\n\n\n.. code-block:: python\n\n    from marshmallow import Schema, fields, ValidationError\n\n\n    def must_have_number(val):\n        if not any(ch.isdigit() for ch in val):\n            raise ValidationError(\"Value must have an number.\")\n\n\n    def validate_length(val):\n        if len(val) < 8:\n            raise ValidationError(\"Value must have 8 or more characters.\")\n\n\n    class ValidatingSchema(Schema):\n        password = fields.String(validate=[must_have_number, validate_length])\n\n\n    result, errors = ValidatingSchema().load({\"password\": \"secure\"})\n    print(errors)\n    # {'password': ['Value must have an number.',\n    #               'Value must have 8 or more characters.']}\n\nOther notable changes:\n\n- Serialized output is no longer an ``OrderedDict`` by default. You must explicitly set the `ordered` `class Meta <marshmallow.Schema.Meta>` option to `True` .\n- ``Serializer`` has been renamed to `Schema <marshmallow.schema.Schema>`, but you can still import ``marshmallow.Serializer`` (which is aliased to `Schema <marshmallow.Schema>`).\n- ``datetime`` objects serialize to ISO8601-formatted strings by default (instead of RFC821 format).\n- The ``fields.validated`` decorator was removed, as it is no longer necessary given the new Fields interface.\n- ``Schema.factory`` class method was removed.\n\n.. seealso::\n\n    See the :doc:`changelog <changelog>` for a more complete listing of added features, bugfixes and breaking changes.\n"
  },
  {
    "path": "docs/whos_using.rst",
    "content": "Who's using marshmallow?\n========================\n\nVisit the link below to see a list of companies using marshmallow.\n\nhttps://github.com/marshmallow-code/marshmallow/wiki/Who's-using-marshmallow%3F\n\nIs your company or organization using marshmallow? Add it to the wiki.\n"
  },
  {
    "path": "docs/why.rst",
    "content": "Why marshmallow?\n================\n\nThe Python ecosystem has many great libraries for data formatting and schema validation.\n\nIn fact, marshmallow was influenced by a number of these libraries. marshmallow is inspired by `Django REST Framework`_, `Flask-RESTful`_, and `colander <https://docs.pylonsproject.org/projects/colander/en/latest/>`_. It borrows a number of implementation and design ideas from these libraries to create a flexible and productive solution for marshalling, unmarshalling, and validating data.\n\nHere are just a few reasons why you might use marshmallow.\n\nAgnostic\n--------\n\nmarshmallow makes no assumption about web frameworks or database layers. It will work with just about any ORM, ODM, or no ORM at all. This gives you the freedom to choose the components that fit your application's needs without having to change your data formatting code. If you wish, you can build integration layers to make marshmallow work more closely with your frameworks and libraries of choice (for examples, see `Flask-Marshmallow <https://github.com/marshmallow-code/flask-marshmallow>`_ and `Django REST Marshmallow <https://github.com/marshmallow-code/django-rest-marshmallow>`_).\n\nConcise, familiar syntax\n------------------------\n\nIf you have used `Django REST Framework`_ or  `WTForms <https://wtforms.readthedocs.io/en/stable/>`_, marshmallow's :class:`Schema <marshmallow.Schema>` syntax will feel familiar to you. Class-level field attributes define the schema for formatting your data. Configuration is added using the `class Meta <marshmallow.Schema.Meta>` paradigm. Configuration options can be overridden at application runtime by passing arguments to the `Schema <marshmallow.Schema>` constructor. The :meth:`dump <marshmallow.Schema.dump>` and :meth:`load <marshmallow.Schema.load>` methods are used for serialization and deserialization (of course!).\n\nClass-based schemas allow for code reuse and configuration\n----------------------------------------------------------\n\nUnlike `Flask-RESTful`_, which uses dictionaries to define output schemas, marshmallow uses classes. This allows for easy code reuse and configuration. It also enables patterns for configuring and extending schemas, such as adding :doc:`post-processing and error handling behavior <extending/index>`.\n\nConsistency meets flexibility\n-----------------------------\n\nmarshmallow makes it easy to modify a schema's output at application runtime. A single :class:`Schema <marshmallow.Schema>` can produce multiple output formats while keeping the individual field outputs consistent.\n\nAs an example, you might have a JSON endpoint for retrieving all information about a video game's state. You then add a low-latency endpoint that only returns a minimal subset of information about game state. Both endpoints can be handled by the same `Schema <marshmallow.Schema>`.\n\n.. code-block:: python\n\n    class GameStateSchema(Schema):\n        _id = fields.UUID(required=True)\n        score = fields.Nested(ScoreSchema)\n        players = fields.List(fields.Nested(PlayerSchema))\n        last_changed = fields.DateTime(format=\"rfc\")\n\n\n    # Serializes full game state\n    full_serializer = GameStateSchema()\n    # Serializes a subset of information, for a low-latency endpoint\n    summary_serializer = GameStateSchema(only=(\"_id\", \"last_changed\"))\n    # Also filter the fields when serializing multiple games\n    gamelist_serializer = GameStateSchema(\n        many=True, only=(\"_id\", \"players\", \"last_changed\")\n    )\n\nIn this example, a single schema produced three different outputs! The dynamic nature of a :class:`Schema` leads to **less code** and **more consistent formatting**.\n\n.. _Django REST Framework: https://www.django-rest-framework.org/\n.. _Flask-RESTful: https://flask-restful.readthedocs.io/\n\nAdvanced schema nesting\n-----------------------\n\nMost serialization libraries provide some means for nesting schemas within each other, but they often fail to meet common use cases in clean way. marshmallow aims to fill these gaps by adding a few nice features for :doc:`nesting schemas <nesting>`:\n\n- You can specify which :ref:`subset of fields <specifying-nested-fields>` to include on nested schemas.\n- :ref:`Two-way nesting <two-way-nesting>`. Two different schemas can nest each other.\n- :ref:`Self-nesting <self-nesting>`. A schema can be nested within itself.\n"
  },
  {
    "path": "examples/flask_example.py",
    "content": "# /// script\n# requires-python = \">=3.10\"\n# dependencies = [\n#     \"flask\",\n#     \"flask-sqlalchemy>=3.1.1\",\n#     \"marshmallow\",\n#     \"sqlalchemy>2.0\",\n# ]\n# ///\nfrom __future__ import annotations\n\nimport datetime\n\nfrom flask import Flask, request\nfrom flask_sqlalchemy import SQLAlchemy\nfrom sqlalchemy.exc import NoResultFound\nfrom sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship\n\nfrom marshmallow import Schema, ValidationError, fields, pre_load\n\napp = Flask(__name__)\napp.config[\"SQLALCHEMY_DATABASE_URI\"] = \"sqlite:////tmp/quotes.db\"\n\n\nclass Base(DeclarativeBase):\n    pass\n\n\ndb = SQLAlchemy(app, model_class=Base)\n\n##### MODELS #####\n\n\nclass Author(db.Model):  # type: ignore[name-defined]\n    id: Mapped[int] = mapped_column(primary_key=True)\n    first: Mapped[str]\n    last: Mapped[str]\n\n\nclass Quote(db.Model):  # type: ignore[name-defined]\n    id: Mapped[int] = mapped_column(primary_key=True)\n    content: Mapped[str] = mapped_column(nullable=False)\n    author_id: Mapped[int] = mapped_column(db.ForeignKey(Author.id))\n    author: Mapped[Author] = relationship(backref=db.backref(\"quotes\", lazy=\"dynamic\"))\n    posted_at: Mapped[datetime.datetime]\n\n\n##### SCHEMAS #####\n\n\nclass AuthorSchema(Schema):\n    id = fields.Int(dump_only=True)\n    first = fields.Str()\n    last = fields.Str()\n    formatted_name = fields.Method(\"format_name\", dump_only=True)\n\n    def format_name(self, author):\n        return f\"{author.last}, {author.first}\"\n\n\n# Custom validator\ndef must_not_be_blank(data):\n    if not data:\n        raise ValidationError(\"Data not provided.\")\n\n\nclass QuoteSchema(Schema):\n    id = fields.Int(dump_only=True)\n    author = fields.Nested(AuthorSchema, validate=must_not_be_blank)\n    content = fields.Str(required=True, validate=must_not_be_blank)\n    posted_at = fields.DateTime(dump_only=True)\n\n    # Allow client to pass author's full name in request body\n    # e.g. {\"author': 'Tim Peters\"} rather than {\"first\": \"Tim\", \"last\": \"Peters\"}\n    @pre_load\n    def process_author(self, data, **kwargs):\n        author_name = data.get(\"author\")\n        if author_name:\n            first, last = author_name.split(\" \")\n            author_dict = {\"first\": first, \"last\": last}\n        else:\n            author_dict = {}\n        data[\"author\"] = author_dict\n        return data\n\n\nauthor_schema = AuthorSchema()\nauthors_schema = AuthorSchema(many=True)\nquote_schema = QuoteSchema()\nquotes_schema = QuoteSchema(many=True, only=(\"id\", \"content\"))\n\n##### API #####\n\n\n@app.route(\"/authors\")\ndef get_authors():\n    authors = Author.query.all()\n    # Serialize the queryset\n    result = authors_schema.dump(authors)\n    return {\"authors\": result}\n\n\n@app.route(\"/authors/<int:pk>\")\ndef get_author(pk):\n    try:\n        author = Author.query.filter(Author.id == pk).one()\n    except NoResultFound:\n        return {\"message\": \"Author could not be found.\"}, 400\n    author_result = author_schema.dump(author)\n    quotes_result = quotes_schema.dump(author.quotes.all())\n    return {\"author\": author_result, \"quotes\": quotes_result}\n\n\n@app.route(\"/quotes/\", methods=[\"GET\"])\ndef get_quotes():\n    quotes = Quote.query.all()\n    result = quotes_schema.dump(quotes, many=True)\n    return {\"quotes\": result}\n\n\n@app.route(\"/quotes/<int:pk>\")\ndef get_quote(pk):\n    try:\n        quote = Quote.query.filter(Quote.id == pk).one()\n    except NoResultFound:\n        return {\"message\": \"Quote could not be found.\"}, 400\n    result = quote_schema.dump(quote)\n    return {\"quote\": result}\n\n\n@app.route(\"/quotes/\", methods=[\"POST\"])\ndef new_quote():\n    json_data = request.get_json()\n    if not json_data:\n        return {\"message\": \"No input data provided\"}, 400\n    # Validate and deserialize input\n    try:\n        data = quote_schema.load(json_data)\n    except ValidationError as err:\n        return err.messages, 422\n    first, last = data[\"author\"][\"first\"], data[\"author\"][\"last\"]\n    author = Author.query.filter_by(first=first, last=last).first()\n    if author is None:\n        # Create a new author\n        author = Author(first=first, last=last)\n        db.session.add(author)\n    # Create new quote\n    quote = Quote(\n        content=data[\"content\"],\n        author=author,\n        posted_at=datetime.datetime.now(datetime.UTC),\n    )\n    db.session.add(quote)\n    db.session.commit()\n    result = quote_schema.dump(Quote.query.get(quote.id))\n    return {\"message\": \"Created new quote.\", \"quote\": result}\n\n\nif __name__ == \"__main__\":\n    with app.app_context():\n        db.create_all()\n    app.run(debug=True, port=5000)\n"
  },
  {
    "path": "examples/inflection_example.py",
    "content": "# /// script\n# requires-python = \">=3.9\"\n# dependencies = [\n#     \"marshmallow\",\n# ]\n# ///\nfrom marshmallow import Schema, fields\n\n\ndef camelcase(s):\n    parts = iter(s.split(\"_\"))\n    return next(parts) + \"\".join(i.title() for i in parts)\n\n\nclass CamelCaseSchema(Schema):\n    \"\"\"Schema that uses camel-case for its external representation\n    and snake-case for its internal representation.\n    \"\"\"\n\n    def on_bind_field(self, field_name, field_obj):\n        field_obj.data_key = camelcase(field_obj.data_key or field_name)\n\n\n# -----------------------------------------------------------------------------\n\n\nclass UserSchema(CamelCaseSchema):\n    first_name = fields.Str(required=True)\n    last_name = fields.Str(required=True)\n\n\nschema = UserSchema()\nloaded = schema.load({\"firstName\": \"David\", \"lastName\": \"Bowie\"})\nprint(\"Loaded data:\")\nprint(loaded)\ndumped = schema.dump(loaded)\nprint(\"Dumped data:\")\nprint(dumped)\n"
  },
  {
    "path": "examples/invalid_package.json",
    "content": "{\n  \"name\": \"dunderscore\",\n  \"version\": \"INVALID\",\n  \"homepage\": \"INVALID\",\n  \"description\": \"The Pythonic JavaScript toolkit\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "examples/package.json",
    "content": "{\n  \"name\": \"dunderscore\",\n  \"version\": \"1.2.3\",\n  \"description\": \"The Pythonic JavaScript toolkit\",\n  \"devDependencies\": {\n    \"pest\": \"^23.4.1\"\n  },\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"pest\"\n  },\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "examples/package_json_example.py",
    "content": "# /// script\n# requires-python = \">=3.10\"\n# dependencies = [\n#     \"marshmallow\",\n#     \"packaging>=17.0\",\n# ]\n# ///\nimport json\nimport sys\nfrom pprint import pprint\n\nfrom packaging import version\n\nfrom marshmallow import INCLUDE, Schema, ValidationError, fields\n\n\nclass Version(fields.Field[version.Version]):\n    \"\"\"Version field that deserializes to a Version object.\"\"\"\n\n    def _deserialize(self, value, *args, **kwargs):\n        try:\n            return version.Version(value)\n        except version.InvalidVersion as e:\n            raise ValidationError(\"Not a valid version.\") from e\n\n    def _serialize(self, value, *args, **kwargs):\n        return str(value)\n\n\nclass PackageSchema(Schema):\n    name = fields.Str(required=True)\n    version = Version(required=True)\n    description = fields.Str(required=True)\n    main = fields.Str(required=False)\n    homepage = fields.URL(required=False)\n    scripts = fields.Dict(keys=fields.Str(), values=fields.Str())\n    license = fields.Str(required=True)\n    dependencies = fields.Dict(keys=fields.Str(), values=fields.Str(), required=False)\n    dev_dependencies = fields.Dict(\n        keys=fields.Str(),\n        values=fields.Str(),\n        required=False,\n        data_key=\"devDependencies\",\n    )\n\n    class Meta:\n        # Include unknown fields in the deserialized output\n        unknown = INCLUDE\n\n\nif __name__ == \"__main__\":\n    pkg = json.load(sys.stdin)\n    try:\n        pprint(PackageSchema().load(pkg))\n    except ValidationError as error:\n        print(\"ERROR: package.json is invalid\")\n        pprint(error.messages)\n        sys.exit(1)\n"
  },
  {
    "path": "performance/benchmark.py",
    "content": "\"\"\"Simple benchmark for marshmallow serialization of a moderately complex object.\n\nUses the `timeit` module to benchmark serializing an object through marshmallow.\n\"\"\"\n\n# ruff: noqa: A002, T201\nimport argparse\nimport cProfile\nimport datetime\nimport gc\nimport timeit\n\nfrom marshmallow import Schema, ValidationError, fields, post_dump\n\n\n# Custom validator\ndef must_not_be_blank(data):\n    if not data:\n        raise ValidationError(\"Data not provided.\")\n\n\nclass AuthorSchema(Schema):\n    id = fields.Int(dump_only=True)\n    first = fields.Str()\n    last = fields.Str()\n    book_count = fields.Float()\n    age = fields.Float()\n    address = fields.Str()\n    full_name = fields.Method(\"get_full_name\")\n\n    def get_full_name(self, author):\n        return f\"{author.last}, {author.first}\"\n\n\nclass QuoteSchema(Schema):\n    id = fields.Int(dump_only=True)\n    author = fields.Nested(AuthorSchema, validate=must_not_be_blank)\n    content = fields.Str(required=True, validate=must_not_be_blank)\n    posted_at = fields.DateTime(dump_only=True)\n    book_name = fields.Str()\n    page_number = fields.Float()\n    line_number = fields.Float()\n    col_number = fields.Float()\n\n    @post_dump\n    def add_full_name(self, data, **kwargs):\n        data[\"author_full\"] = \"{}, {}\".format(\n            data[\"author\"][\"last\"], data[\"author\"][\"first\"]\n        )\n        return data\n\n\nclass Author:\n    def __init__(self, id, first, last, book_count, age, address):\n        self.id = id\n        self.first = first\n        self.last = last\n        self.book_count = book_count\n        self.age = age\n        self.address = address\n\n\nclass Quote:\n    def __init__(\n        self,\n        id,\n        author,\n        content,\n        posted_at,\n        book_name,\n        page_number,\n        line_number,\n        col_number,\n    ):\n        self.id = id\n        self.author = author\n        self.content = content\n        self.posted_at = posted_at\n        self.book_name = book_name\n        self.page_number = page_number\n        self.line_number = line_number\n        self.col_number = col_number\n\n\ndef run_timeit(quotes, iterations, repeat, *, profile=False):\n    quotes_schema = QuoteSchema(many=True)\n    if profile:\n        profile = cProfile.Profile()\n        profile.enable()\n\n    gc.collect()\n    best = min(\n        timeit.repeat(\n            lambda: quotes_schema.dump(quotes),\n            \"gc.enable()\",\n            number=iterations,\n            repeat=repeat,\n        )\n    )\n    if profile:\n        profile.disable()\n        profile.dump_stats(\"marshmallow.pprof\")\n\n    return best * 1e6 / iterations / len(quotes)\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"Runs a benchmark of Marshmallow.\")\n    parser.add_argument(\n        \"--iterations\",\n        type=int,\n        default=1000,\n        help=\"Number of iterations to run per test.\",\n    )\n    parser.add_argument(\n        \"--repeat\",\n        type=int,\n        default=5,\n        help=\"Number of times to repeat the performance test.  The minimum will \"\n        \"be used.\",\n    )\n    parser.add_argument(\n        \"--object-count\", type=int, default=20, help=\"Number of objects to dump.\"\n    )\n    parser.add_argument(\n        \"--profile\",\n        action=\"store_true\",\n        help=\"Whether or not to profile marshmallow while running the benchmark.\",\n    )\n    args = parser.parse_args()\n\n    quotes = [\n        Quote(\n            i,\n            Author(i, \"Foo\", \"Bar\", 42, 66, \"123 Fake St\"),\n            \"Hello World\",\n            datetime.datetime(2019, 7, 4, tzinfo=datetime.timezone.utc),\n            \"The World\",\n            34,\n            3,\n            70,\n        )\n        for i in range(args.object_count)\n    ]\n\n    print(\n        f\"Benchmark Result: {run_timeit(quotes, args.iterations, args.repeat, profile=args.profile):.2f} usec/dump\"\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nname = \"marshmallow\"\nversion = \"4.2.2\"\ndescription = \"A lightweight library for converting complex datatypes to and from native Python datatypes.\"\nreadme = \"README.rst\"\nlicense = { file = \"LICENSE\" }\nauthors = [{ name = \"Steven Loria\", email = \"oss@stevenloria.com\" }]\nmaintainers = [\n  { name = \"Steven Loria\", email = \"oss@stevenloria.com\" },\n  { name = \"Jérôme Lafréchoux\", email = \"jerome@jolimont.fr\" },\n  { name = \"Jared Deckard\", email = \"jared@shademaps.com\" },\n]\nclassifiers = [\n  \"Development Status :: 5 - Production/Stable\",\n  \"Intended Audience :: Developers\",\n  \"License :: OSI Approved :: MIT License\",\n  \"Programming Language :: Python :: 3\",\n  \"Programming Language :: Python :: 3.10\",\n  \"Programming Language :: Python :: 3.11\",\n  \"Programming Language :: Python :: 3.12\",\n  \"Programming Language :: Python :: 3.13\",\n  \"Programming Language :: Python :: 3.14\",\n]\nrequires-python = \">=3.10\"\ndependencies = [\n  \"backports-datetime-fromisoformat; python_version < '3.11'\",\n  \"typing-extensions; python_version < '3.11'\",\n]\n\n[project.urls]\nChangelog = \"https://marshmallow.readthedocs.io/en/latest/changelog.html\"\nFunding = \"https://opencollective.com/marshmallow\"\nIssues = \"https://github.com/marshmallow-code/marshmallow/issues\"\nSource = \"https://github.com/marshmallow-code/marshmallow\"\nTidelift = \"https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=pypi-marshmallow&utm_medium=pypi\"\n\n[project.optional-dependencies]\ndocs = [\n  \"autodocsumm==0.2.14\",\n  \"furo==2025.12.19\",\n  \"sphinx-copybutton==0.5.2\",\n  \"sphinx-issues==6.0.0\",\n  \"sphinx==8.2.3\",\n  \"sphinxext-opengraph==0.13.0\",\n]\ntests = [\"pytest\", \"simplejson\"]\ndev = [\"marshmallow[tests]\", \"tox\", \"pre-commit>=3.5,<5.0\"]\n\n[build-system]\nrequires = [\"flit_core<4\"]\nbuild-backend = \"flit_core.buildapi\"\n\n[tool.flit.sdist]\ninclude = [\n  \"docs/\",\n  \"tests/\",\n  \"CHANGELOG.rst\",\n  \"CONTRIBUTING.rst\",\n  \"SECURITY.md\",\n  \"NOTICE\",\n  \"tox.ini\",\n]\nexclude = [\"docs/_build/\"]\n\n[tool.ruff]\nfix = true\n\n[tool.ruff.format]\ndocstring-code-format = true\n\n[tool.ruff.lint]\n# use all checks available in ruff except the ones explicitly ignored below\nselect = [\"ALL\"]\nignore = [\n  \"A005\",    # \"module {name} shadows a Python standard-library module\"\n  \"ANN\",     # let mypy handle annotation checks\n  \"ARG\",     # unused arguments are common w/ interfaces\n  \"COM\",     # let formatter take care commas\n  \"C901\",    # don't enforce complexity level\n  \"D\",       # don't require docstrings\n  \"DTZ007\",  # ignore false positives due to https://github.com/astral-sh/ruff/issues/1306\n  \"E501\",    # leave line-length enforcement to formatter\n  \"EM\",      # allow string messages in exceptions\n  \"FIX\",     # allow \"FIX\" comments in code\n  \"INP001\",  # allow Python files outside of packages\n  \"N806\",    # allow uppercase variable names for variables that are classes\n  \"PERF203\", # allow try-except within loops\n  \"PLR0913\", # \"Too many arguments\"\n  \"PLR0912\", # \"Too many branches\"\n  \"PLR2004\", # \"Magic value used in comparison\"\n  \"PTH\",     # don't require using pathlib instead of os\n  \"RUF012\",  # allow mutable class variables\n  \"SIM102\",  # Sometimes nested ifs are more readable than if...and...\n  \"SIM105\",  # \"Use `contextlib.suppress(...)` instead of `try`-`except`-`pass`\"\n  \"SIM108\",  # sometimes if-else is more readable than a ternary\n  \"TD\",      # allow TODO comments to be whatever we want\n  \"TRY003\",  # allow long messages passed to exceptions\n  \"TRY004\",  # allow ValueError for invalid argument types\n]\n\n[tool.ruff.lint.per-file-ignores]\n\"tests/*\" = [\n  \"ARG\",     # unused arguments are fine in tests\n  \"C408\",    # allow dict() instead of dict literal\n  \"DTZ\",     # allow naive datetimes\n  \"FBT003\",  # allow boolean positional argument\n  \"N803\",    # fixture names might be uppercase\n  \"PLR0915\", # allow lots of statements\n  \"PT007\",   # ignore false positives due to https://github.com/astral-sh/ruff/issues/14743\n  \"PT011\",   # don't require match when using pytest.raises\n  \"PLW0108\", # allow lambda: MySchema, which is needed in some of the test cases\n  \"RUF043\",  # allow metacharacters in match patterns\n  \"S\",       # allow asserts\n  \"SIM117\",  # allow nested with statements because it's more readable sometimes\n  \"SLF001\",  # allow private attribute access\n]\n\"examples/*\" = [\n  \"S\", # allow asserts\n  \"T\", # allow prints\n]\n\"src/marshmallow/orderedset.py\" = [\n  \"FBT002\", # allow boolean positional argument\n  \"T\",      # allow prints\n]\n\n[tool.mypy]\nfiles = [\"src\", \"tests\", \"examples\"]\nignore_missing_imports = true\nwarn_unreachable = false\nwarn_unused_ignores = true\nwarn_redundant_casts = true\nno_implicit_optional = true\n\n[[tool.mypy.overrides]]\nmodule = \"tests.*\"\ncheck_untyped_defs = true\ndisable_error_code = [\"call-overload\", \"index\"]\n\n[tool.pytest.ini_options]\nnorecursedirs = \".git .ropeproject .tox docs env venv tests/mypy_test_cases\"\n"
  },
  {
    "path": "src/marshmallow/__init__.py",
    "content": "from marshmallow.constants import EXCLUDE, INCLUDE, RAISE, missing\nfrom marshmallow.decorators import (\n    post_dump,\n    post_load,\n    pre_dump,\n    pre_load,\n    validates,\n    validates_schema,\n)\nfrom marshmallow.exceptions import ValidationError\nfrom marshmallow.schema import Schema, SchemaOpts\n\nfrom . import fields\n\n__all__ = [\n    \"EXCLUDE\",\n    \"INCLUDE\",\n    \"RAISE\",\n    \"Schema\",\n    \"SchemaOpts\",\n    \"ValidationError\",\n    \"fields\",\n    \"missing\",\n    \"post_dump\",\n    \"post_load\",\n    \"pre_dump\",\n    \"pre_load\",\n    \"validates\",\n    \"validates_schema\",\n]\n"
  },
  {
    "path": "src/marshmallow/class_registry.py",
    "content": "\"\"\"A registry of :class:`Schema <marshmallow.Schema>` classes. This allows for string\nlookup of schemas, which may be used with\nclass:`fields.Nested <marshmallow.fields.Nested>`.\n\n.. warning::\n\n    This module is treated as private API.\n    Users should not need to use this module directly.\n\"\"\"\n# ruff: noqa: ERA001\n\nfrom __future__ import annotations\n\nimport typing\n\nfrom marshmallow.exceptions import RegistryError\n\nif typing.TYPE_CHECKING:\n    from marshmallow import Schema\n\n    SchemaType = type[Schema]\n\n# {\n#   <class_name>: <list of class objects>\n#   <module_path_to_class>: <list of class objects>\n# }\n_registry = {}  # type: dict[str, list[SchemaType]]\n\n\ndef register(classname: str, cls: SchemaType) -> None:\n    \"\"\"Add a class to the registry of serializer classes. When a class is\n    registered, an entry for both its classname and its full, module-qualified\n    path are added to the registry.\n\n    Example: ::\n\n        class MyClass:\n            pass\n\n\n        register(\"MyClass\", MyClass)\n        # Registry:\n        # {\n        #   'MyClass': [path.to.MyClass],\n        #   'path.to.MyClass': [path.to.MyClass],\n        # }\n\n    \"\"\"\n    # Module where the class is located\n    module = cls.__module__\n    # Full module path to the class\n    # e.g. user.schemas.UserSchema\n    fullpath = f\"{module}.{classname}\"\n    # If the class is already registered; need to check if the entries are\n    # in the same module as cls to avoid having multiple instances of the same\n    # class in the registry\n    if classname in _registry and not any(\n        each.__module__ == module for each in _registry[classname]\n    ):\n        _registry[classname].append(cls)\n    elif classname not in _registry:\n        _registry[classname] = [cls]\n\n    # Also register the full path\n    if fullpath not in _registry:\n        _registry.setdefault(fullpath, []).append(cls)\n    else:\n        # If fullpath does exist, replace existing entry\n        _registry[fullpath] = [cls]\n\n\n@typing.overload\ndef get_class(classname: str, *, all: typing.Literal[False] = ...) -> SchemaType: ...\n\n\n@typing.overload\ndef get_class(\n    classname: str, *, all: typing.Literal[True] = ...\n) -> list[SchemaType]: ...\n\n\ndef get_class(classname: str, *, all: bool = False) -> list[SchemaType] | SchemaType:  # noqa: A002\n    \"\"\"Retrieve a class from the registry.\n\n    :raises: `marshmallow.exceptions.RegistryError` if the class cannot be found\n        or if there are multiple entries for the given class name.\n    \"\"\"\n    try:\n        classes = _registry[classname]\n    except KeyError as error:\n        raise RegistryError(\n            f\"Class with name {classname!r} was not found. You may need \"\n            \"to import the class.\"\n        ) from error\n    if len(classes) > 1:\n        if all:\n            return _registry[classname]\n        raise RegistryError(\n            f\"Multiple classes with name {classname!r} \"\n            \"were found. Please use the full, \"\n            \"module-qualified path.\"\n        )\n    return _registry[classname][0]\n"
  },
  {
    "path": "src/marshmallow/constants.py",
    "content": "import typing\n\nEXCLUDE: typing.Final = \"exclude\"\nINCLUDE: typing.Final = \"include\"\nRAISE: typing.Final = \"raise\"\n\n\nclass _Missing:\n    def __bool__(self):\n        return False\n\n    def __copy__(self):\n        return self\n\n    def __deepcopy__(self, _):\n        return self\n\n    def __repr__(self):\n        return \"<marshmallow.missing>\"\n\n    def __len__(self):\n        return 0\n\n\nmissing: typing.Final = _Missing()\n"
  },
  {
    "path": "src/marshmallow/decorators.py",
    "content": "\"\"\"Decorators for registering schema pre-processing and post-processing methods.\nThese should be imported from the top-level `marshmallow` module.\n\nMethods decorated with\n`pre_load <marshmallow.decorators.pre_load>`, `post_load <marshmallow.decorators.post_load>`,\n`pre_dump <marshmallow.decorators.pre_dump>`, `post_dump <marshmallow.decorators.post_dump>`,\nand `validates_schema <marshmallow.decorators.validates_schema>` receive\n``many`` as a keyword argument. In addition, `pre_load <marshmallow.decorators.pre_load>`,\n`post_load <marshmallow.decorators.post_load>`,\nand `validates_schema <marshmallow.decorators.validates_schema>` receive\n``partial``. If you don't need these arguments, add ``**kwargs`` to your method\nsignature.\n\n\nExample: ::\n\n    from marshmallow import (\n        Schema,\n        pre_load,\n        pre_dump,\n        post_load,\n        validates_schema,\n        validates,\n        fields,\n        ValidationError,\n    )\n\n\n    class UserSchema(Schema):\n        email = fields.Str(required=True)\n        age = fields.Integer(required=True)\n\n        @post_load\n        def lowerstrip_email(self, item, many, **kwargs):\n            item[\"email\"] = item[\"email\"].lower().strip()\n            return item\n\n        @pre_load(pass_collection=True)\n        def remove_envelope(self, data, many, **kwargs):\n            namespace = \"results\" if many else \"result\"\n            return data[namespace]\n\n        @post_dump(pass_collection=True)\n        def add_envelope(self, data, many, **kwargs):\n            namespace = \"results\" if many else \"result\"\n            return {namespace: data}\n\n        @validates_schema\n        def validate_email(self, data, **kwargs):\n            if len(data[\"email\"]) < 3:\n                raise ValidationError(\"Email must be more than 3 characters\", \"email\")\n\n        @validates(\"age\")\n        def validate_age(self, data, **kwargs):\n            if data < 14:\n                raise ValidationError(\"Too young!\")\n\n.. note::\n    These decorators only work with instance methods. Class and static\n    methods are not supported.\n\n.. warning::\n    The invocation order of decorated methods of the same type is not guaranteed.\n    If you need to guarantee order of different processing steps, you should put\n    them in the same processing method.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport functools\nimport typing\nfrom collections import defaultdict\n\nPRE_DUMP = \"pre_dump\"\nPOST_DUMP = \"post_dump\"\nPRE_LOAD = \"pre_load\"\nPOST_LOAD = \"post_load\"\nVALIDATES = \"validates\"\nVALIDATES_SCHEMA = \"validates_schema\"\n\n\nclass MarshmallowHook:\n    __marshmallow_hook__: dict[str, list[tuple[bool, typing.Any]]] | None = None\n\n\ndef validates(*field_names: str) -> typing.Callable[..., typing.Any]:\n    \"\"\"Register a validator method for field(s).\n\n    :param field_names: Names of the fields that the method validates.\n\n    .. versionchanged:: 4.0.0 Accepts multiple field names as positional arguments.\n    .. versionchanged:: 4.0.0 Decorated methods receive ``data_key`` as a keyword argument.\n    \"\"\"\n    return set_hook(None, VALIDATES, field_names=field_names)\n\n\ndef validates_schema(\n    fn: typing.Callable[..., typing.Any] | None = None,\n    *,\n    pass_collection: bool = False,\n    pass_original: bool = False,\n    skip_on_field_errors: bool = True,\n) -> typing.Callable[..., typing.Any]:\n    \"\"\"Register a schema-level validator.\n\n    By default it receives a single object at a time, transparently handling the ``many``\n    argument passed to the `Schema <marshmallow.Schema>`'s :func:`~marshmallow.Schema.validate` call.\n    If ``pass_collection=True``, the raw data (which may be a collection) is passed.\n\n    If ``pass_original=True``, the original data (before unmarshalling) will be passed as\n    an additional argument to the method.\n\n    If ``skip_on_field_errors=True``, this validation method will be skipped whenever\n    validation errors have been detected when validating fields.\n\n    .. versionchanged:: 3.0.0b1 ``skip_on_field_errors`` defaults to `True`.\n    .. versionchanged:: 3.0.0 ``partial`` and ``many`` are always passed as keyword arguments to\n        the decorated method.\n    .. versionchanged:: 4.0.0 ``unknown`` is passed as a keyword argument to the decorated method.\n    .. versionchanged:: 4.0.0 ``pass_many`` is renamed to ``pass_collection``.\n    .. versionchanged:: 4.0.0 ``pass_collection``, ``pass_original``, and ``skip_on_field_errors``\n        are keyword-only arguments.\n    \"\"\"\n    return set_hook(\n        fn,\n        VALIDATES_SCHEMA,\n        many=pass_collection,\n        pass_original=pass_original,\n        skip_on_field_errors=skip_on_field_errors,\n    )\n\n\ndef pre_dump(\n    fn: typing.Callable[..., typing.Any] | None = None,\n    *,\n    pass_collection: bool = False,\n) -> typing.Callable[..., typing.Any]:\n    \"\"\"Register a method to invoke before serializing an object. The method\n    receives the object to be serialized and returns the processed object.\n\n    By default it receives a single object at a time, transparently handling the ``many``\n    argument passed to the `Schema <marshmallow.Schema>`'s :func:`~marshmallow.Schema.dump` call.\n    If ``pass_collection=True``, the raw data (which may be a collection) is passed.\n\n    .. versionchanged:: 3.0.0 ``many`` is always passed as a keyword arguments to the decorated method.\n    .. versionchanged:: 4.0.0 ``pass_many`` is renamed to ``pass_collection``.\n    .. versionchanged:: 4.0.0 ``pass_collection`` is a keyword-only argument.\n    \"\"\"\n    return set_hook(fn, PRE_DUMP, many=pass_collection)\n\n\ndef post_dump(\n    fn: typing.Callable[..., typing.Any] | None = None,\n    *,\n    pass_collection: bool = False,\n    pass_original: bool = False,\n) -> typing.Callable[..., typing.Any]:\n    \"\"\"Register a method to invoke after serializing an object. The method\n    receives the serialized object and returns the processed object.\n\n    By default it receives a single object at a time, transparently handling the ``many``\n    argument passed to the `Schema <marshmallow.Schema>`'s :func:`~marshmallow.Schema.dump` call.\n    If ``pass_collection=True``, the raw data (which may be a collection) is passed.\n\n    If ``pass_original=True``, the original data (before serializing) will be passed as\n    an additional argument to the method.\n\n    .. versionchanged:: 3.0.0 ``many`` is always passed as a keyword arguments to the decorated method.\n    .. versionchanged:: 4.0.0 ``pass_many`` is renamed to ``pass_collection``.\n    .. versionchanged:: 4.0.0 ``pass_collection`` and ``pass_original`` are keyword-only arguments.\n    \"\"\"\n    return set_hook(fn, POST_DUMP, many=pass_collection, pass_original=pass_original)\n\n\ndef pre_load(\n    fn: typing.Callable[..., typing.Any] | None = None,\n    *,\n    pass_collection: bool = False,\n) -> typing.Callable[..., typing.Any]:\n    \"\"\"Register a method to invoke before deserializing an object. The method\n    receives the data to be deserialized and returns the processed data.\n\n    By default it receives a single object at a time, transparently handling the ``many``\n    argument passed to the `Schema <marshmallow.Schema>`'s :func:`~marshmallow.Schema.load` call.\n    If ``pass_collection=True``, the raw data (which may be a collection) is passed.\n\n    .. versionchanged:: 3.0.0 ``partial`` and ``many`` are always passed as keyword arguments to\n        the decorated method.\n    .. versionchanged:: 4.0.0 ``pass_many`` is renamed to ``pass_collection``.\n    .. versionchanged:: 4.0.0 ``pass_collection`` is a keyword-only argument.\n    .. versionchanged:: 4.0.0 ``unknown`` is passed as a keyword argument to the decorated method.\n    \"\"\"\n    return set_hook(fn, PRE_LOAD, many=pass_collection)\n\n\ndef post_load(\n    fn: typing.Callable[..., typing.Any] | None = None,\n    *,\n    pass_collection: bool = False,\n    pass_original: bool = False,\n) -> typing.Callable[..., typing.Any]:\n    \"\"\"Register a method to invoke after deserializing an object. The method\n    receives the deserialized data and returns the processed data.\n\n    By default it receives a single object at a time, transparently handling the ``many``\n    argument passed to the `Schema <marshmallow.Schema>`'s :func:`~marshmallow.Schema.load` call.\n    If ``pass_collection=True``, the raw data (which may be a collection) is passed.\n\n    If ``pass_original=True``, the original data (before deserializing) will be passed as\n    an additional argument to the method.\n\n    .. versionchanged:: 3.0.0 ``partial`` and ``many`` are always passed as keyword arguments to\n        the decorated method.\n    .. versionchanged:: 4.0.0 ``pass_many`` is renamed to ``pass_collection``.\n    .. versionchanged:: 4.0.0 ``pass_collection`` and ``pass_original`` are keyword-only arguments.\n    .. versionchanged:: 4.0.0 ``unknown`` is passed as a keyword argument to the decorated method.\n    \"\"\"\n    return set_hook(fn, POST_LOAD, many=pass_collection, pass_original=pass_original)\n\n\ndef set_hook(\n    fn: typing.Callable[..., typing.Any] | None,\n    tag: str,\n    *,\n    many: bool = False,\n    **kwargs: typing.Any,\n) -> typing.Callable[..., typing.Any]:\n    \"\"\"Mark decorated function as a hook to be picked up later.\n    You should not need to use this method directly.\n\n    .. note::\n        Currently only works with functions and instance methods. Class and\n        static methods are not supported.\n\n    :return: Decorated function if supplied, else this decorator with its args\n        bound.\n    \"\"\"\n    # Allow using this as either a decorator or a decorator factory.\n    if fn is None:\n        return functools.partial(set_hook, tag=tag, many=many, **kwargs)\n\n    # Set a __marshmallow_hook__ attribute instead of wrapping in some class,\n    # because I still want this to end up as a normal (unbound) method.\n    function = typing.cast(\"MarshmallowHook\", fn)\n    try:\n        hook_config = function.__marshmallow_hook__\n    except AttributeError:\n        function.__marshmallow_hook__ = hook_config = defaultdict(list)\n    # Also save the kwargs for the tagged function on\n    # __marshmallow_hook__, keyed by <tag>\n    if hook_config is not None:\n        hook_config[tag].append((many, kwargs))\n\n    return fn\n"
  },
  {
    "path": "src/marshmallow/error_store.py",
    "content": "\"\"\"Utilities for storing collections of error messages.\n\n.. warning::\n\n    This module is treated as private API.\n    Users should not need to use this module directly.\n\"\"\"\n\nfrom marshmallow.exceptions import SCHEMA\n\n\nclass ErrorStore:\n    def __init__(self):\n        #: Dictionary of errors stored during serialization\n        self.errors = {}\n\n    def store_error(self, messages, field_name=SCHEMA, index=None):\n        # field error  -> store/merge error messages under field name key\n        # schema error -> if string or list, store/merge under _schema key\n        #              -> if dict, store/merge with other top-level keys\n        messages = copy_containers(messages)\n        if field_name != SCHEMA or not isinstance(messages, dict):\n            messages = {field_name: messages}\n        if index is not None:\n            messages = {index: messages}\n        self.errors = merge_errors(self.errors, messages)\n\n\ndef copy_containers(errors):\n    if isinstance(errors, list):\n        return [copy_containers(val) for val in errors]\n    if isinstance(errors, dict):\n        return {key: copy_containers(val) for key, val in errors.items()}\n    return errors\n\n\ndef merge_errors(errors1, errors2):  # noqa: PLR0911\n    \"\"\"Deeply merge two error messages.\n\n    The format of ``errors1`` and ``errors2`` matches the ``message``\n    parameter of :exc:`marshmallow.exceptions.ValidationError`.\n    \"\"\"\n    if not errors1:\n        return errors2\n    if not errors2:\n        return errors1\n    if isinstance(errors1, list):\n        if isinstance(errors2, list):\n            errors1.extend(errors2)\n            return errors1\n        if isinstance(errors2, dict):\n            errors2[SCHEMA] = merge_errors(errors1, errors2.get(SCHEMA))\n            return errors2\n        errors1.append(errors2)\n        return errors1\n    if isinstance(errors1, dict):\n        if isinstance(errors2, dict):\n            for key, val in errors2.items():\n                if key in errors1:\n                    errors1[key] = merge_errors(errors1[key], val)\n                else:\n                    errors1[key] = val\n            return errors1\n        errors1[SCHEMA] = merge_errors(errors1.get(SCHEMA), errors2)\n        return errors1\n    if isinstance(errors2, list):\n        return [errors1, *errors2]\n    if isinstance(errors2, dict):\n        errors2[SCHEMA] = merge_errors(errors1, errors2.get(SCHEMA))\n        return errors2\n    return [errors1, errors2]\n"
  },
  {
    "path": "src/marshmallow/exceptions.py",
    "content": "\"\"\"Exception classes for marshmallow-related errors.\"\"\"\n\nfrom __future__ import annotations\n\nimport typing\n\n# Key used for schema-level validation errors\nSCHEMA = \"_schema\"\n\n\nclass MarshmallowError(Exception):\n    \"\"\"Base class for all marshmallow-related errors.\"\"\"\n\n\nclass ValidationError(MarshmallowError):\n    \"\"\"Raised when validation fails on a field or schema.\n\n    Validators and custom fields should raise this exception.\n\n    :param message: An error message, list of error messages, or dict of\n        error messages. If a dict, the keys are subitems and the values are error messages.\n    :param field_name: Field name to store the error on.\n    :param data: Raw input data.\n    :param valid_data: Valid (de)serialized data.\n    \"\"\"\n\n    def __init__(\n        self,\n        message: str | list | dict,\n        field_name: str = SCHEMA,\n        data: typing.Mapping[str, typing.Any]\n        | typing.Iterable[typing.Mapping[str, typing.Any]]\n        | None = None,\n        valid_data: list[typing.Any] | dict[str, typing.Any] | None = None,\n        **kwargs,\n    ):\n        self.messages = [message] if isinstance(message, (str, bytes)) else message\n        self.field_name = field_name\n        self.data = data\n        self.valid_data = valid_data\n        self.kwargs = kwargs\n        super().__init__(message)\n\n    def normalized_messages(self):\n        if self.field_name == SCHEMA and isinstance(self.messages, dict):\n            return self.messages\n        return {self.field_name: self.messages}\n\n    @property\n    def messages_dict(self) -> dict[str, typing.Any]:\n        if not isinstance(self.messages, dict):\n            raise TypeError(\n                \"cannot access 'messages_dict' when 'messages' is of type \"\n                + type(self.messages).__name__\n            )\n        return self.messages\n\n\nclass RegistryError(NameError):\n    \"\"\"Raised when an invalid operation is performed on the serializer\n    class registry.\n    \"\"\"\n\n\nclass StringNotCollectionError(MarshmallowError, TypeError):\n    \"\"\"Raised when a string is passed when a list of strings is expected.\"\"\"\n\n\nclass _FieldInstanceResolutionError(MarshmallowError, TypeError):\n    \"\"\"Raised when an argument is passed to a field class that cannot be resolved to a Field instance.\"\"\"\n"
  },
  {
    "path": "src/marshmallow/experimental/__init__.py",
    "content": "\"\"\"Experimental features.\n\nThe features in this subpackage are experimental. Breaking changes may be\nintroduced in minor marshmallow versions.\n\"\"\"\n"
  },
  {
    "path": "src/marshmallow/experimental/context.py",
    "content": "\"\"\"Helper API for setting serialization/deserialization context.\n\nExample usage:\n\n.. code-block:: python\n\n    import typing\n\n    from marshmallow import Schema, fields\n    from marshmallow.experimental.context import Context\n\n\n    class UserContext(typing.TypedDict):\n        suffix: str\n\n\n    UserSchemaContext = Context[UserContext]\n\n\n    class UserSchema(Schema):\n        name_suffixed = fields.Function(\n            lambda user: user[\"name\"] + UserSchemaContext.get()[\"suffix\"]\n        )\n\n\n    with UserSchemaContext({\"suffix\": \"bar\"}):\n        print(UserSchema().dump({\"name\": \"foo\"}))\n        # {'name_suffixed': 'foobar'}\n\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport contextvars\nimport typing\n\ntry:\n    from types import EllipsisType\nexcept ImportError:  # Python<3.10\n    EllipsisType = type(Ellipsis)  # type: ignore[misc]\n\n_ContextT = typing.TypeVar(\"_ContextT\")\n_DefaultT = typing.TypeVar(\"_DefaultT\")\n_CURRENT_CONTEXT: contextvars.ContextVar = contextvars.ContextVar(\"context\")\n\n\nclass Context(contextlib.AbstractContextManager, typing.Generic[_ContextT]):\n    \"\"\"Context manager for setting and retrieving context.\n\n    :param context: The context to use within the context manager scope.\n    \"\"\"\n\n    def __init__(self, context: _ContextT) -> None:\n        self.context = context\n        self.token: contextvars.Token | None = None\n\n    def __enter__(self) -> Context[_ContextT]:\n        self.token = _CURRENT_CONTEXT.set(self.context)\n        return self\n\n    def __exit__(self, *args, **kwargs) -> None:\n        _CURRENT_CONTEXT.reset(typing.cast(\"contextvars.Token\", self.token))\n\n    @classmethod\n    def get(cls, default: _DefaultT | EllipsisType = ...) -> _ContextT | _DefaultT:\n        \"\"\"Get the current context.\n\n        :param default: Default value to return if no context is set.\n            If not provided and no context is set, a :exc:`LookupError` is raised.\n        \"\"\"\n        if default is not ...:\n            return _CURRENT_CONTEXT.get(default)\n        return _CURRENT_CONTEXT.get()\n"
  },
  {
    "path": "src/marshmallow/fields.py",
    "content": "# ruff: noqa: SLF001\nfrom __future__ import annotations\n\nimport abc\nimport collections\nimport copy\nimport datetime as dt\nimport decimal\nimport email.utils\nimport ipaddress\nimport math\nimport numbers\nimport typing\nimport uuid\nfrom collections.abc import Mapping as _Mapping\nfrom enum import Enum as EnumType\n\ntry:\n    from typing import Unpack\nexcept ImportError:  # Remove when dropping Python 3.10\n    from typing_extensions import Unpack\n\n# Remove when dropping Python 3.10\ntry:\n    from backports.datetime_fromisoformat import MonkeyPatch\nexcept ImportError:\n    pass\nelse:\n    MonkeyPatch.patch_fromisoformat()\n\nfrom marshmallow import class_registry, types, utils, validate\nfrom marshmallow.constants import missing as missing_\nfrom marshmallow.exceptions import (\n    StringNotCollectionError,\n    ValidationError,\n    _FieldInstanceResolutionError,\n)\nfrom marshmallow.validate import And, Length\n\nif typing.TYPE_CHECKING:\n    from marshmallow.schema import Schema, SchemaMeta\n\n\n__all__ = [\n    \"IP\",\n    \"URL\",\n    \"UUID\",\n    \"AwareDateTime\",\n    \"Bool\",\n    \"Boolean\",\n    \"Constant\",\n    \"Date\",\n    \"DateTime\",\n    \"Decimal\",\n    \"Dict\",\n    \"Email\",\n    \"Enum\",\n    \"Field\",\n    \"Float\",\n    \"Function\",\n    \"IPInterface\",\n    \"IPv4\",\n    \"IPv4Interface\",\n    \"IPv6\",\n    \"IPv6Interface\",\n    \"Int\",\n    \"Integer\",\n    \"List\",\n    \"Mapping\",\n    \"Method\",\n    \"NaiveDateTime\",\n    \"Nested\",\n    \"Number\",\n    \"Pluck\",\n    \"Raw\",\n    \"Str\",\n    \"String\",\n    \"Time\",\n    \"TimeDelta\",\n    \"Tuple\",\n    \"Url\",\n]\n\n_InternalT = typing.TypeVar(\"_InternalT\")\n\n\nclass _BaseFieldKwargs(typing.TypedDict, total=False):\n    load_default: typing.Any\n    dump_default: typing.Any\n    data_key: str | None\n    attribute: str | None\n    validate: types.Validator | typing.Iterable[types.Validator] | None\n    required: bool\n    allow_none: bool | None\n    load_only: bool\n    dump_only: bool\n    error_messages: dict[str, str] | None\n    metadata: typing.Mapping[str, typing.Any] | None\n\n\ndef _resolve_field_instance(cls_or_instance: Field | type[Field]) -> Field:\n    \"\"\"Return a Field instance from a Field class or instance.\n\n    :param cls_or_instance: Field class or instance.\n    \"\"\"\n    if isinstance(cls_or_instance, type):\n        if not issubclass(cls_or_instance, Field):\n            raise _FieldInstanceResolutionError\n        return cls_or_instance()\n    if not isinstance(cls_or_instance, Field):\n        raise _FieldInstanceResolutionError\n    return cls_or_instance\n\n\nclass Field(typing.Generic[_InternalT]):\n    \"\"\"Base field from which all other fields inherit.\n    This class should not be used directly within Schemas.\n\n    :param dump_default: If set, this value will be used during serialization if the\n        input value is missing. If not set, the field will be excluded from the\n        serialized output if the input value is missing. May be a value or a callable.\n    :param load_default: Default deserialization value for the field if the field is not\n        found in the input data. May be a value or a callable.\n    :param data_key: The name of the dict key in the external representation, i.e.\n        the input of `load` and the output of `dump`.\n        If `None`, the key will match the name of the field.\n    :param attribute: The name of the key/attribute in the internal representation, i.e.\n        the output of `load` and the input of `dump`.\n        If `None`, the key/attribute will match the name of the field.\n        Note: This should only be used for very specific use cases such as\n        outputting multiple fields for a single attribute, or using keys/attributes\n        that are invalid variable names, unsuitable for field names. In most cases,\n        you should use ``data_key`` instead.\n    :param validate: Validator or collection of validators that are called\n        during deserialization. Validator takes a field's input value as\n        its only parameter and returns a boolean.\n        If it returns `False`, an :exc:`ValidationError` is raised.\n    :param required: Raise a :exc:`ValidationError` if the field value\n        is not supplied during deserialization.\n    :param allow_none: Set this to `True` if `None` should be considered a valid value during\n        validation/deserialization. If set to `False` (the default), `None` is considered invalid input.\n        If ``load_default`` is explicitly set to `None` and ``allow_none`` is unset,\n        `allow_none` is implicitly set to ``True``.\n    :param load_only: If `True` skip this field during serialization, otherwise\n        its value will be present in the serialized data.\n    :param dump_only: If `True` skip this field during deserialization, otherwise\n        its value will be present in the deserialized object. In the context of an\n        HTTP API, this effectively marks the field as \"read-only\".\n    :param error_messages: Overrides for `Field.default_error_messages`.\n    :param metadata: Extra information to be stored as field metadata.\n\n    .. versionchanged:: 3.0.0b8\n        Add ``data_key`` parameter for the specifying the key in the input and\n        output data. This parameter replaced both ``load_from`` and ``dump_to``.\n    .. versionchanged:: 3.13.0\n        Replace ``missing`` and ``default`` parameters with ``load_default`` and ``dump_default``.\n    .. versionchanged:: 3.24.0\n        `Field <marshmallow.fields.Field>` should no longer be used as a field within a `Schema <marshmallow.Schema>`.\n        Use `Raw <marshmallow.fields.Raw>` or another `Field <marshmallow.fields.Field>` subclass instead.\n    .. versionchanged:: 4.0.0\n        Remove ``context`` property.\n    \"\"\"\n\n    # Some fields, such as Method fields and Function fields, are not expected\n    #  to exist as attributes on the objects to serialize. Set this to False\n    #  for those fields\n    _CHECK_ATTRIBUTE = True\n\n    #: Default error messages for various kinds of errors. The keys in this dictionary\n    #: are passed to `Field.make_error`. The values are error messages passed to\n    #: :exc:`marshmallow.exceptions.ValidationError`.\n    default_error_messages: dict[str, str] = {\n        \"required\": \"Missing data for required field.\",\n        \"null\": \"Field may not be null.\",\n        \"validator_failed\": \"Invalid value.\",\n    }\n\n    def __init__(\n        self,\n        *,\n        load_default: typing.Any = missing_,\n        dump_default: typing.Any = missing_,\n        data_key: str | None = None,\n        attribute: str | None = None,\n        validate: types.Validator | typing.Iterable[types.Validator] | None = None,\n        required: bool = False,\n        allow_none: bool | None = None,\n        load_only: bool = False,\n        dump_only: bool = False,\n        error_messages: dict[str, str] | None = None,\n        metadata: typing.Mapping[str, typing.Any] | None = None,\n    ) -> None:\n        self.dump_default = dump_default\n        self.load_default = load_default\n\n        self.attribute = attribute\n        self.data_key = data_key\n        self.validate = validate\n        if validate is None:\n            self.validators = []\n        elif callable(validate):\n            self.validators = [validate]\n        elif utils.is_iterable_but_not_string(validate):\n            self.validators = list(validate)\n        else:\n            raise ValueError(\n                \"The 'validate' parameter must be a callable \"\n                \"or a collection of callables.\"\n            )\n\n        # If allow_none is None and load_default is None\n        # None should be considered valid by default\n        self.allow_none = load_default is None if allow_none is None else allow_none\n        self.load_only = load_only\n        self.dump_only = dump_only\n        if required is True and load_default is not missing_:\n            raise ValueError(\"'load_default' must not be set for required fields.\")\n        self.required = required\n\n        metadata = metadata or {}\n        self.metadata = metadata\n        # Collect default error message from self and parent classes\n        messages: dict[str, str] = {}\n        for cls in reversed(self.__class__.__mro__):\n            messages.update(getattr(cls, \"default_error_messages\", {}))\n        messages.update(error_messages or {})\n        self.error_messages = messages\n\n        self.parent: Field | Schema | None = None\n        self.name: str | None = None\n        self.root: Schema | None = None\n\n    def __repr__(self) -> str:\n        return (\n            f\"<fields.{self.__class__.__name__}(dump_default={self.dump_default!r}, \"\n            f\"attribute={self.attribute!r}, \"\n            f\"validate={self.validate}, required={self.required}, \"\n            f\"load_only={self.load_only}, dump_only={self.dump_only}, \"\n            f\"load_default={self.load_default}, allow_none={self.allow_none}, \"\n            f\"error_messages={self.error_messages})>\"\n        )\n\n    def __deepcopy__(self, memo):\n        return copy.copy(self)\n\n    def get_value(\n        self,\n        obj: typing.Any,\n        attr: str,\n        accessor: (\n            typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None\n        ) = None,\n        default: typing.Any = missing_,\n    ) -> _InternalT:\n        \"\"\"Return the value for a given key from an object.\n\n        :param obj: The object to get the value from.\n        :param attr: The attribute/key in `obj` to get the value from.\n        :param accessor: A callable used to retrieve the value of `attr` from\n            the object `obj`. Defaults to `marshmallow.utils.get_value`.\n        \"\"\"\n        accessor_func = accessor or utils.get_value\n        check_key = attr if self.attribute is None else self.attribute\n        return accessor_func(obj, check_key, default)\n\n    def _validate(self, value: typing.Any) -> None:\n        \"\"\"Perform validation on ``value``. Raise a :exc:`ValidationError` if validation\n        does not succeed.\n        \"\"\"\n        self._validate_all(value)\n\n    @property\n    def _validate_all(self) -> typing.Callable[[typing.Any], None]:\n        return And(*self.validators)\n\n    def make_error(self, key: str, **kwargs) -> ValidationError:\n        \"\"\"Helper method to make a `ValidationError` with an error message\n        from ``self.error_messages``.\n        \"\"\"\n        try:\n            msg = self.error_messages[key]\n        except KeyError as error:\n            class_name = self.__class__.__name__\n            message = (\n                f\"ValidationError raised by `{class_name}`, but error key `{key}` does \"\n                \"not exist in the `error_messages` dictionary.\"\n            )\n            raise AssertionError(message) from error\n        if isinstance(msg, (str, bytes)):\n            msg = msg.format(**kwargs)\n        return ValidationError(msg)\n\n    def _validate_missing(self, value: typing.Any) -> None:\n        \"\"\"Validate missing values. Raise a :exc:`ValidationError` if\n        `value` should be considered missing.\n        \"\"\"\n        if value is missing_ and self.required:\n            raise self.make_error(\"required\")\n        if value is None and not self.allow_none:\n            raise self.make_error(\"null\")\n\n    def serialize(\n        self,\n        attr: str,\n        obj: typing.Any,\n        accessor: (\n            typing.Callable[[typing.Any, str, typing.Any], typing.Any] | None\n        ) = None,\n        **kwargs,\n    ):\n        \"\"\"Pulls the value for the given key from the object, applies the\n        field's formatting and returns the result.\n\n        :param attr: The attribute/key to get from the object.\n        :param obj: The object to access the attribute/key from.\n        :param accessor: Function used to access values from ``obj``.\n        :param kwargs: Field-specific keyword arguments.\n        \"\"\"\n        if self._CHECK_ATTRIBUTE:\n            value = self.get_value(obj, attr, accessor=accessor)\n            if value is missing_:\n                default = self.dump_default\n                value = default() if callable(default) else default\n            if value is missing_:\n                return value\n        else:\n            value = None\n        return self._serialize(value, attr, obj, **kwargs)\n\n    # If value is None, None may be returned\n    @typing.overload\n    def deserialize(\n        self,\n        value: None,\n        attr: str | None = None,\n        data: typing.Mapping[str, typing.Any] | None = None,\n        **kwargs,\n    ) -> None | _InternalT: ...\n\n    # If value is not None, internal type is returned\n    @typing.overload\n    def deserialize(\n        self,\n        value: typing.Any,\n        attr: str | None = None,\n        data: typing.Mapping[str, typing.Any] | None = None,\n        **kwargs,\n    ) -> _InternalT: ...\n\n    def deserialize(\n        self,\n        value: typing.Any,\n        attr: str | None = None,\n        data: typing.Mapping[str, typing.Any] | None = None,\n        **kwargs,\n    ) -> _InternalT | None:\n        \"\"\"Deserialize ``value``.\n\n        :param value: The value to deserialize.\n        :param attr: The attribute/key in `data` to deserialize.\n        :param data: The raw input data passed to `Schema.load <marshmallow.Schema.load>`.\n        :param kwargs: Field-specific keyword arguments.\n        :raise ValidationError: If an invalid value is passed or if a required value\n            is missing.\n        \"\"\"\n        # Validate required fields, deserialize, then validate\n        # deserialized value\n        self._validate_missing(value)\n        if value is missing_:\n            _miss = self.load_default\n            return _miss() if callable(_miss) else _miss\n        if self.allow_none and value is None:\n            return None\n        output = self._deserialize(value, attr, data, **kwargs)\n        self._validate(output)\n        return output\n\n    # Methods for concrete classes to override.\n\n    def _bind_to_schema(self, field_name: str, parent: Schema | Field) -> None:\n        \"\"\"Update field with values from its parent schema. Called by\n                `Schema._bind_field <marshmallow.Schema._bind_field>`.\n\n        :param field_name: Field name set in schema.\n        :param parent: Parent object.\n        \"\"\"\n        self.parent = self.parent or parent\n        self.name = self.name or field_name\n        self.root = self.root or (\n            self.parent.root if isinstance(self.parent, Field) else self.parent\n        )\n\n    def _serialize(\n        self, value: _InternalT | None, attr: str | None, obj: typing.Any, **kwargs\n    ) -> typing.Any:\n        \"\"\"Serializes ``value`` to a basic Python datatype. Noop by default.\n        Concrete :class:`Field` classes should implement this method.\n\n        Example: ::\n\n            class TitleCase(Field):\n                def _serialize(self, value, attr, obj, **kwargs):\n                    if not value:\n                        return \"\"\n                    return str(value).title()\n\n        :param value: The value to be serialized.\n        :param attr: The attribute or key on the object to be serialized.\n        :param obj: The object the value was pulled from.\n        :param kwargs: Field-specific keyword arguments.\n        :return: The serialized value\n        \"\"\"\n        return value\n\n    def _deserialize(\n        self,\n        value: typing.Any,\n        attr: str | None,\n        data: typing.Mapping[str, typing.Any] | None,\n        **kwargs,\n    ) -> _InternalT:\n        \"\"\"Deserialize value. Concrete :class:`Field` classes should implement this method.\n\n        :param value: The value to be deserialized.\n        :param attr: The attribute/key in `data` to be deserialized.\n        :param data: The raw input data passed to the `Schema.load <marshmallow.Schema.load>`.\n        :param kwargs: Field-specific keyword arguments.\n        :raise ValidationError: In case of formatting or validation failure.\n        :return: The deserialized value.\n\n        .. versionchanged:: 3.0.0\n            Added ``**kwargs`` to signature.\n        \"\"\"\n        return value\n\n\nclass Raw(Field[typing.Any]):\n    \"\"\"Field that applies no formatting.\"\"\"\n\n\nclass Nested(Field):\n    \"\"\"Allows you to nest a :class:`Schema <marshmallow.Schema>`\n    inside a field.\n\n    Examples: ::\n\n        class ChildSchema(Schema):\n            id = fields.Str()\n            name = fields.Str()\n            # Use lambda functions when you need two-way nesting or self-nesting\n            parent = fields.Nested(lambda: ParentSchema(only=(\"id\",)), dump_only=True)\n            siblings = fields.List(\n                fields.Nested(lambda: ChildSchema(only=(\"id\", \"name\")))\n            )\n\n\n        class ParentSchema(Schema):\n            id = fields.Str()\n            children = fields.List(\n                fields.Nested(ChildSchema(only=(\"id\", \"parent\", \"siblings\")))\n            )\n            spouse = fields.Nested(lambda: ParentSchema(only=(\"id\",)))\n\n    When passing a `Schema <marshmallow.Schema>` instance as the first argument,\n    the instance's ``exclude``, ``only``, and ``many`` attributes will be respected.\n\n    Therefore, when passing the ``exclude``, ``only``, or ``many`` arguments to `fields.Nested`,\n    you should pass a `Schema <marshmallow.Schema>` class (not an instance) as the first argument.\n\n    ::\n\n        # Yes\n        author = fields.Nested(UserSchema, only=(\"id\", \"name\"))\n\n        # No\n        author = fields.Nested(UserSchema(), only=(\"id\", \"name\"))\n\n    :param nested: `Schema <marshmallow.Schema>` instance, class, class name (string), dictionary, or callable that\n        returns a `Schema <marshmallow.Schema>` or dictionary.\n        Dictionaries are converted with `Schema.from_dict <marshmallow.Schema.from_dict>`.\n    :param exclude: A list or tuple of fields to exclude.\n    :param only: A list or tuple of fields to marshal. If `None`, all fields are marshalled.\n        This parameter takes precedence over ``exclude``.\n    :param many: Whether the field is a collection of objects.\n        If `None` (default), and nested `Schema` instance is provided, ``many`` is not overridden.\n        If `None` (default), and `Schema` subclass is provided, schema instance sets ``many`` as False.\n        If `True | False` nested `[nested_field].schema.many` is overridden.\n    :param unknown: Whether to exclude, include, or raise an error for unknown\n        fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\"type\": \"Invalid type.\"}\n\n    def __init__(\n        self,\n        nested: (\n            Schema\n            | SchemaMeta\n            | str\n            | dict[str, Field]\n            | typing.Callable[[], Schema | SchemaMeta | dict[str, Field]]\n        ),\n        *,\n        only: types.StrSequenceOrSet | None = None,\n        exclude: types.StrSequenceOrSet = (),\n        many: bool | None = None,\n        unknown: types.UnknownOption | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        # Raise error if only or exclude is passed as string, not list of strings\n        if only is not None and not utils.is_sequence_but_not_string(only):\n            raise StringNotCollectionError('\"only\" should be a collection of strings.')\n        if not utils.is_sequence_but_not_string(exclude):\n            raise StringNotCollectionError(\n                '\"exclude\" should be a collection of strings.'\n            )\n        self.nested = nested\n        self.only = only\n        self.exclude = exclude\n        self.many = many\n        self.unknown = unknown\n        self._schema: Schema | None = None  # Cached Schema instance\n        super().__init__(**kwargs)\n\n    @property\n    def schema(self) -> Schema:\n        \"\"\"The nested Schema object.\"\"\"\n        if not self._schema:\n            if callable(self.nested) and not isinstance(self.nested, type):\n                nested = self.nested()\n            else:\n                nested = typing.cast(\"Schema\", self.nested)\n            # defer the import of `marshmallow.schema` to avoid circular imports\n            from marshmallow.schema import Schema  # noqa: PLC0415\n\n            if isinstance(nested, dict):\n                nested = Schema.from_dict(nested)\n\n            if isinstance(nested, Schema):\n                self._schema = copy.copy(nested)\n                # Respect only and exclude and many passed from parent and re-initialize fields\n                set_class = typing.cast(\"type[set]\", self._schema.set_class)\n                if self.only is not None:\n                    if self._schema.only is not None:\n                        original = self._schema.only\n                    else:  # only=None -> all fields\n                        original = self._schema.fields.keys()\n                    self._schema.only = set_class(self.only) & set_class(original)\n                if self.exclude:\n                    original = self._schema.exclude\n                    self._schema.exclude = set_class(self.exclude) | set_class(original)\n                if self.many is not None:\n                    self._schema.many = self.many\n                self._schema._init_fields()\n            else:\n                if isinstance(nested, type) and issubclass(nested, Schema):\n                    schema_class: type[Schema] = nested\n                elif not isinstance(nested, (str, bytes)):\n                    raise ValueError(\n                        \"`Nested` fields must be passed a \"\n                        f\"`Schema`, not {nested.__class__}.\"\n                    )\n                else:\n                    schema_class = class_registry.get_class(nested, all=False)\n                self._schema = schema_class(\n                    many=bool(self.many),\n                    only=self.only,\n                    exclude=self.exclude,\n                    load_only=self._nested_normalized_option(\"load_only\"),\n                    dump_only=self._nested_normalized_option(\"dump_only\"),\n                )\n        return self._schema\n\n    def _nested_normalized_option(self, option_name: str) -> list[str]:\n        nested_field = f\"{self.name}.\"\n        return [\n            field.split(nested_field, 1)[1]\n            for field in getattr(self.root, option_name, set())\n            if field.startswith(nested_field)\n        ]\n\n    def _serialize(self, nested_obj, attr, obj, **kwargs):\n        # Load up the schema first. This allows a RegistryError to be raised\n        # if an invalid schema name was passed\n        schema = self.schema\n        if nested_obj is None:\n            return None\n        many = schema.many or self.many\n        return schema.dump(nested_obj, many=many)\n\n    def _test_collection(self, value: typing.Any) -> None:\n        many = self.schema.many or self.many\n        if many and not utils.is_collection(value):\n            raise self.make_error(\"type\", input=value, type=value.__class__.__name__)\n\n    def _load(\n        self,\n        value: typing.Any,\n        partial: bool | types.StrSequenceOrSet | None = None,  # noqa: FBT001\n    ):\n        try:\n            valid_data = self.schema.load(value, unknown=self.unknown, partial=partial)\n        except ValidationError as error:\n            raise ValidationError(\n                error.messages, valid_data=error.valid_data\n            ) from error\n        return valid_data\n\n    def _deserialize(\n        self,\n        value: typing.Any,\n        attr: str | None,\n        data: typing.Mapping[str, typing.Any] | None,\n        partial: bool | types.StrSequenceOrSet | None = None,  # noqa: FBT001\n        **kwargs,\n    ):\n        \"\"\"Same as :meth:`Field._deserialize` with additional ``partial`` argument.\n\n        :param partial: For nested schemas, the ``partial``\n            parameter passed to `marshmallow.Schema.load`.\n\n        .. versionchanged:: 3.0.0\n            Add ``partial`` parameter.\n        \"\"\"\n        self._test_collection(value)\n        return self._load(value, partial=partial)\n\n\nclass Pluck(Nested):\n    \"\"\"Allows you to replace nested data with one of the data's fields.\n\n    Example: ::\n\n        from marshmallow import Schema, fields\n\n\n        class ArtistSchema(Schema):\n            id = fields.Int()\n            name = fields.Str()\n\n\n        class AlbumSchema(Schema):\n            artist = fields.Pluck(ArtistSchema, \"id\")\n\n\n        in_data = {\"artist\": 42}\n        loaded = AlbumSchema().load(in_data)  # => {'artist': {'id': 42}}\n        dumped = AlbumSchema().dump(loaded)  # => {'artist': 42}\n\n    :param nested: The Schema class or class name (string) to nest\n    :param str field_name: The key to pluck a value from.\n    :param kwargs: The same keyword arguments that :class:`Nested` receives.\n    \"\"\"\n\n    def __init__(\n        self,\n        nested: Schema | SchemaMeta | str | typing.Callable[[], Schema],\n        field_name: str,\n        *,\n        many: bool = False,\n        unknown: types.UnknownOption | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(\n            nested, only=(field_name,), many=many, unknown=unknown, **kwargs\n        )\n        self.field_name = field_name\n\n    @property\n    def _field_data_key(self) -> str:\n        only_field = self.schema.fields[self.field_name]\n        return only_field.data_key or self.field_name\n\n    def _serialize(self, nested_obj, attr, obj, **kwargs):\n        ret = super()._serialize(nested_obj, attr, obj, **kwargs)\n        if ret is None:\n            return None\n        if self.many:\n            return utils.pluck(ret, key=self._field_data_key)\n        return ret[self._field_data_key]\n\n    def _deserialize(self, value, attr, data, partial=None, **kwargs):\n        self._test_collection(value)\n        if self.many:\n            value = [{self._field_data_key: v} for v in value]\n        else:\n            value = {self._field_data_key: value}\n        return self._load(value, partial=partial)\n\n\nclass List(Field[list[_InternalT | None]]):\n    \"\"\"A list field, composed with another `Field` class or\n    instance.\n\n    Example: ::\n\n        numbers = fields.List(fields.Float())\n\n    :param cls_or_instance: A field class or instance.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. versionchanged:: 3.0.0rc9\n        Does not serialize scalar values to single-item lists.\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid list.\"}\n\n    def __init__(\n        self,\n        cls_or_instance: Field[_InternalT] | type[Field[_InternalT]],\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(**kwargs)\n        try:\n            self.inner: Field[_InternalT] = _resolve_field_instance(cls_or_instance)\n        except _FieldInstanceResolutionError as error:\n            raise ValueError(\n                \"The list elements must be a subclass or instance of \"\n                \"marshmallow.fields.Field.\"\n            ) from error\n        if isinstance(self.inner, Nested):\n            self.only = self.inner.only\n            self.exclude = self.inner.exclude\n\n    def _bind_to_schema(self, field_name: str, parent: Schema | Field) -> None:\n        super()._bind_to_schema(field_name, parent)\n        self.inner = copy.deepcopy(self.inner)\n        self.inner._bind_to_schema(field_name, self)\n        if isinstance(self.inner, Nested):\n            self.inner.only = self.only\n            self.inner.exclude = self.exclude\n\n    def _serialize(self, value, attr, obj, **kwargs) -> list[_InternalT] | None:\n        if value is None:\n            return None\n        return [self.inner._serialize(each, attr, obj, **kwargs) for each in value]\n\n    def _deserialize(self, value, attr, data, **kwargs) -> list[_InternalT | None]:\n        if not utils.is_collection(value):\n            raise self.make_error(\"invalid\")\n\n        result = []\n        errors = {}\n        for idx, each in enumerate(value):\n            try:\n                result.append(self.inner.deserialize(each, **kwargs))\n            except ValidationError as error:\n                if error.valid_data is not None:\n                    result.append(typing.cast(\"_InternalT\", error.valid_data))\n                errors.update({idx: error.messages})\n        if errors:\n            raise ValidationError(errors, valid_data=result)\n        return result\n\n\nclass Tuple(Field[tuple]):\n    \"\"\"A tuple field, composed of a fixed number of other `Field` classes or\n    instances\n\n    Example: ::\n\n        row = Tuple((fields.String(), fields.Integer(), fields.Float()))\n\n    .. note::\n        Because of the structured nature of `collections.namedtuple` and\n        `typing.NamedTuple`, using a Schema within a Nested field for them is\n        more appropriate than using a `Tuple` field.\n\n    :param tuple_fields: An iterable of field classes or\n        instances.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. versionadded:: 3.0.0rc4\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid tuple.\"}\n\n    def __init__(\n        self,\n        tuple_fields: typing.Iterable[Field] | typing.Iterable[type[Field]],\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(**kwargs)\n        if not utils.is_collection(tuple_fields):\n            raise ValueError(\n                \"tuple_fields must be an iterable of Field classes or instances.\"\n            )\n\n        try:\n            self.tuple_fields = [\n                _resolve_field_instance(cls_or_instance)\n                for cls_or_instance in tuple_fields\n            ]\n        except _FieldInstanceResolutionError as error:\n            raise ValueError(\n                'Elements of \"tuple_fields\" must be subclasses or '\n                \"instances of marshmallow.fields.Field.\"\n            ) from error\n\n        self.validate_length = Length(equal=len(self.tuple_fields))\n\n    def _bind_to_schema(self, field_name: str, parent: Schema | Field) -> None:\n        super()._bind_to_schema(field_name, parent)\n        new_tuple_fields = []\n        for field in self.tuple_fields:\n            new_field = copy.deepcopy(field)\n            new_field._bind_to_schema(field_name, self)\n            new_tuple_fields.append(new_field)\n\n        self.tuple_fields = new_tuple_fields\n\n    def _serialize(\n        self, value: tuple | None, attr: str | None, obj: typing.Any, **kwargs\n    ) -> tuple | None:\n        if value is None:\n            return None\n\n        return tuple(\n            field._serialize(each, attr, obj, **kwargs)\n            for field, each in zip(self.tuple_fields, value, strict=True)\n        )\n\n    def _deserialize(\n        self,\n        value: typing.Any,\n        attr: str | None,\n        data: typing.Mapping[str, typing.Any] | None,\n        **kwargs,\n    ) -> tuple:\n        if not utils.is_sequence_but_not_string(value):\n            raise self.make_error(\"invalid\")\n\n        self.validate_length(value)\n\n        result = []\n        errors = {}\n\n        for idx, (field, each) in enumerate(zip(self.tuple_fields, value, strict=True)):\n            try:\n                result.append(field.deserialize(each, **kwargs))\n            except ValidationError as error:\n                if error.valid_data is not None:\n                    result.append(error.valid_data)\n                errors.update({idx: error.messages})\n        if errors:\n            raise ValidationError(errors, valid_data=result)\n\n        return tuple(result)\n\n\nclass String(Field[str]):\n    \"\"\"A string field.\n\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\n        \"invalid\": \"Not a valid string.\",\n        \"invalid_utf8\": \"Not a valid utf-8 string.\",\n    }\n\n    def _serialize(self, value, attr, obj, **kwargs) -> str | None:\n        if value is None:\n            return None\n        return utils.ensure_text_type(value)\n\n    def _deserialize(self, value, attr, data, **kwargs) -> str:\n        if not isinstance(value, (str, bytes)):\n            raise self.make_error(\"invalid\")\n        try:\n            return utils.ensure_text_type(value)\n        except UnicodeDecodeError as error:\n            raise self.make_error(\"invalid_utf8\") from error\n\n\nclass UUID(Field[uuid.UUID]):\n    \"\"\"A UUID field.\"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\"invalid_uuid\": \"Not a valid UUID.\"}\n\n    def _validated(self, value) -> uuid.UUID:\n        \"\"\"Format the value or raise a :exc:`ValidationError` if an error occurs.\"\"\"\n        if isinstance(value, uuid.UUID):\n            return value\n        try:\n            if isinstance(value, bytes) and len(value) == 16:\n                return uuid.UUID(bytes=value)\n            return uuid.UUID(value)\n        except (ValueError, AttributeError, TypeError) as error:\n            raise self.make_error(\"invalid_uuid\") from error\n\n    def _serialize(self, value, attr, obj, **kwargs) -> str | None:\n        if value is None:\n            return None\n        return str(value)\n\n    def _deserialize(self, value, attr, data, **kwargs) -> uuid.UUID:\n        return self._validated(value)\n\n\n_NumT = typing.TypeVar(\"_NumT\")\n\n\nclass Number(Field[_NumT]):\n    \"\"\"Base class for number fields. This class should not be used within schemas.\n\n    :param as_string: If `True`, format the serialized value as a string.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. versionchanged:: 3.24.0\n        `Number <marshmallow.fields.Number>` should no longer be used as a field within a `Schema <marshmallow.Schema>`.\n        Use `Integer <marshmallow.fields.Integer>`, `Float <marshmallow.fields.Float>`, or `Decimal <marshmallow.fields.Decimal>` instead.\n    \"\"\"\n\n    num_type: type[_NumT]\n\n    #: Default error messages.\n    default_error_messages = {\n        \"invalid\": \"Not a valid number.\",\n        \"too_large\": \"Number too large.\",\n    }\n\n    def __init__(self, *, as_string: bool = False, **kwargs: Unpack[_BaseFieldKwargs]):\n        self.as_string = as_string\n        super().__init__(**kwargs)\n\n    def _format_num(self, value) -> _NumT:\n        \"\"\"Return the number value for value, given this field's `num_type`.\"\"\"\n        return self.num_type(value)  # type: ignore[call-arg]\n\n    def _validated(self, value: typing.Any) -> _NumT:\n        \"\"\"Format the value or raise a :exc:`ValidationError` if an error occurs.\"\"\"\n        # (value is True or value is False) is ~5x faster than isinstance(value, bool)\n        if value is True or value is False:\n            raise self.make_error(\"invalid\", input=value)\n        try:\n            return self._format_num(value)\n        except (TypeError, ValueError) as error:\n            raise self.make_error(\"invalid\", input=value) from error\n        except OverflowError as error:\n            raise self.make_error(\"too_large\", input=value) from error\n\n    def _to_string(self, value: _NumT) -> str:\n        return str(value)\n\n    def _serialize(self, value, attr, obj, **kwargs) -> str | _NumT | None:\n        \"\"\"Return a string if `self.as_string=True`, otherwise return this field's `num_type`.\"\"\"\n        if value is None:\n            return None\n        ret: _NumT = self._format_num(value)\n        return self._to_string(ret) if self.as_string else ret\n\n    def _deserialize(self, value, attr, data, **kwargs) -> _NumT:\n        return self._validated(value)\n\n\nclass Integer(Number[int]):\n    \"\"\"An integer field.\n\n    :param strict: If `True`, only integer types are valid.\n        Otherwise, any value castable to `int` is valid.\n    :param kwargs: The same keyword arguments that :class:`Number` receives.\n    \"\"\"\n\n    num_type = int\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid integer.\"}\n\n    def __init__(\n        self,\n        *,\n        strict: bool = False,\n        as_string: bool = False,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        self.strict = strict\n        super().__init__(as_string=as_string, **kwargs)\n\n    # override Number\n    def _validated(self, value: typing.Any) -> int:\n        if self.strict and not isinstance(value, numbers.Integral):\n            raise self.make_error(\"invalid\", input=value)\n        return super()._validated(value)\n\n\nclass Float(Number[float]):\n    \"\"\"A double as an IEEE-754 double precision string.\n\n    :param allow_nan: If `True`, `NaN`, `Infinity` and `-Infinity` are allowed,\n        even though they are illegal according to the JSON specification.\n    :param as_string: If `True`, format the value as a string.\n    :param kwargs: The same keyword arguments that :class:`Number` receives.\n    \"\"\"\n\n    num_type = float\n\n    #: Default error messages.\n    default_error_messages = {\n        \"special\": \"Special numeric values (nan or infinity) are not permitted.\"\n    }\n\n    def __init__(\n        self,\n        *,\n        allow_nan: bool = False,\n        as_string: bool = False,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        self.allow_nan = allow_nan\n        super().__init__(as_string=as_string, **kwargs)\n\n    def _validated(self, value: typing.Any) -> float:\n        num = super()._validated(value)\n        if self.allow_nan is False:\n            if math.isnan(num) or num == float(\"inf\") or num == float(\"-inf\"):\n                raise self.make_error(\"special\")\n        return num\n\n\nclass Decimal(Number[decimal.Decimal]):\n    \"\"\"A field that (de)serializes to the Python ``decimal.Decimal`` type.\n    It's safe to use when dealing with money values, percentages, ratios\n    or other numbers where precision is critical.\n\n    .. warning::\n\n        This field serializes to a `decimal.Decimal` object by default. If you need\n        to render your data as JSON, keep in mind that the `json` module from the\n        standard library does not encode `decimal.Decimal`. Therefore, you must use\n        a JSON library that can handle decimals, such as `simplejson`, or serialize\n        to a string by passing ``as_string=True``.\n\n    .. warning::\n\n        If a JSON `float` value is passed to this field for deserialization it will\n        first be cast to its corresponding `string` value before being deserialized\n        to a `decimal.Decimal` object. The default `__str__` implementation of the\n        built-in Python `float` type may apply a destructive transformation upon\n        its input data and therefore cannot be relied upon to preserve precision.\n        To avoid this, you can instead pass a JSON `string` to be deserialized\n        directly.\n\n    :param places: How many decimal places to quantize the value. If `None`, does\n        not quantize the value.\n    :param rounding: How to round the value during quantize, for example\n        `decimal.ROUND_UP`. If `None`, uses the rounding value from\n        the current thread's context.\n    :param allow_nan: If `True`, `NaN`, `Infinity` and `-Infinity` are allowed,\n        even though they are illegal according to the JSON specification.\n    :param as_string: If `True`, serialize to a string instead of a Python\n        `decimal.Decimal` type.\n    :param kwargs: The same keyword arguments that :class:`Number` receives.\n    \"\"\"\n\n    num_type = decimal.Decimal\n\n    #: Default error messages.\n    default_error_messages = {\n        \"special\": \"Special numeric values (nan or infinity) are not permitted.\"\n    }\n\n    def __init__(\n        self,\n        places: int | None = None,\n        rounding: str | None = None,\n        *,\n        allow_nan: bool = False,\n        as_string: bool = False,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        self.places = (\n            decimal.Decimal((0, (1,), -places)) if places is not None else None\n        )\n        self.rounding = rounding\n        self.allow_nan = allow_nan\n        super().__init__(as_string=as_string, **kwargs)\n\n    # override Number\n    def _format_num(self, value):\n        num = decimal.Decimal(str(value))\n        if self.allow_nan:\n            if num.is_nan():\n                return decimal.Decimal(\"NaN\")  # avoid sNaN, -sNaN and -NaN\n        if self.places is not None and num.is_finite():\n            num = num.quantize(self.places, rounding=self.rounding)\n        return num\n\n    # override Number\n    def _validated(self, value: typing.Any) -> decimal.Decimal:\n        try:\n            num = super()._validated(value)\n        except decimal.InvalidOperation as error:\n            raise self.make_error(\"invalid\") from error\n        if not self.allow_nan and (num.is_nan() or num.is_infinite()):\n            raise self.make_error(\"special\")\n        return num\n\n    # override Number\n    def _to_string(self, value: decimal.Decimal) -> str:\n        return format(value, \"f\")\n\n\nclass Boolean(Field[bool]):\n    \"\"\"A boolean field.\n\n    :param truthy: Values that will (de)serialize to `True`. If an empty\n        set, any non-falsy value will deserialize to `True`. If `None`,\n        `marshmallow.fields.Boolean.truthy` will be used.\n    :param falsy: Values that will (de)serialize to `False`. If `None`,\n        `marshmallow.fields.Boolean.falsy` will be used.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n    \"\"\"\n\n    #: Default truthy values.\n    truthy = {\n        \"t\",\n        \"T\",\n        \"true\",\n        \"True\",\n        \"TRUE\",\n        \"on\",\n        \"On\",\n        \"ON\",\n        \"y\",\n        \"Y\",\n        \"yes\",\n        \"Yes\",\n        \"YES\",\n        \"1\",\n        1,\n        # Equal to 1\n        # True,\n    }\n    #: Default falsy values.\n    falsy = {\n        \"f\",\n        \"F\",\n        \"false\",\n        \"False\",\n        \"FALSE\",\n        \"off\",\n        \"Off\",\n        \"OFF\",\n        \"n\",\n        \"N\",\n        \"no\",\n        \"No\",\n        \"NO\",\n        \"0\",\n        0,\n        # Equal to 0\n        # 0.0,\n        # False,\n    }\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid boolean.\"}\n\n    def __init__(\n        self,\n        *,\n        truthy: typing.Iterable | None = None,\n        falsy: typing.Iterable | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(**kwargs)\n\n        if truthy is not None:\n            self.truthy = set(truthy)\n        if falsy is not None:\n            self.falsy = set(falsy)\n\n    def _deserialize(\n        self,\n        value: typing.Any,\n        attr: str | None,\n        data: typing.Mapping[str, typing.Any] | None,\n        **kwargs,\n    ) -> bool:\n        if not self.truthy:\n            return bool(value)\n        try:\n            if value in self.truthy:\n                return True\n            if value in self.falsy:\n                return False\n        except TypeError as error:\n            raise self.make_error(\"invalid\", input=value) from error\n        raise self.make_error(\"invalid\", input=value)\n\n\n_D = typing.TypeVar(\"_D\", dt.datetime, dt.date, dt.time)\n\n\nclass _TemporalField(Field[_D], metaclass=abc.ABCMeta):\n    \"\"\"Base field for date and time related fields including common (de)serialization logic.\"\"\"\n\n    # Subclasses should define each of these class constants\n    SERIALIZATION_FUNCS: dict[str, typing.Callable[[_D], str | float]]\n    DESERIALIZATION_FUNCS: dict[str, typing.Callable[[str], _D]]\n    DEFAULT_FORMAT: str\n    OBJ_TYPE: str\n    SCHEMA_OPTS_VAR_NAME: str\n\n    default_error_messages = {\n        \"invalid\": \"Not a valid {obj_type}.\",\n        \"invalid_awareness\": \"Not a valid {awareness} {obj_type}.\",\n        \"format\": '\"{input}\" cannot be formatted as a {obj_type}.',\n    }\n\n    def __init__(\n        self,\n        format: str | None = None,  # noqa: A002\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ) -> None:\n        super().__init__(**kwargs)\n        # Allow this to be None. It may be set later in the ``_serialize``\n        # or ``_deserialize`` methods. This allows a Schema to dynamically set the\n        # format, e.g. from a Meta option\n        self.format = format\n\n    def _bind_to_schema(self, field_name, parent):\n        super()._bind_to_schema(field_name, parent)\n        self.format = (\n            self.format\n            or getattr(self.root.opts, self.SCHEMA_OPTS_VAR_NAME)\n            or self.DEFAULT_FORMAT\n        )\n\n    def _serialize(self, value: _D | None, attr, obj, **kwargs) -> str | float | None:\n        if value is None:\n            return None\n        data_format = self.format or self.DEFAULT_FORMAT\n        format_func = self.SERIALIZATION_FUNCS.get(data_format)\n        if format_func:\n            return format_func(value)\n        return value.strftime(data_format)\n\n    def _deserialize(self, value, attr, data, **kwargs) -> _D:\n        internal_type: type[_D] = getattr(dt, self.OBJ_TYPE)\n        if isinstance(value, internal_type):\n            return value\n        data_format = self.format or self.DEFAULT_FORMAT\n        func = self.DESERIALIZATION_FUNCS.get(data_format)\n        try:\n            if func:\n                return func(value)\n            return self._make_object_from_format(value, data_format)\n        except (TypeError, AttributeError, ValueError) as error:\n            raise self.make_error(\n                \"invalid\", input=value, obj_type=self.OBJ_TYPE\n            ) from error\n\n    @staticmethod\n    @abc.abstractmethod\n    def _make_object_from_format(value: typing.Any, data_format: str) -> _D: ...\n\n\nclass DateTime(_TemporalField[dt.datetime]):\n    \"\"\"A formatted datetime string.\n\n    Example: ``'2014-12-22T03:12:58.019077+00:00'``\n\n    :param format: Either ``\"rfc\"`` (for RFC822), ``\"iso\"`` (for ISO8601),\n        ``\"timestamp\"``, ``\"timestamp_ms\"`` (for a POSIX timestamp) or a date format string.\n        If `None`, defaults to \"iso\".\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. versionchanged:: 3.0.0rc9\n        Does not modify timezone information on (de)serialization.\n    .. versionchanged:: 3.19\n        Add timestamp as a format.\n    \"\"\"\n\n    SERIALIZATION_FUNCS: dict[str, typing.Callable[[dt.datetime], str | float]] = {\n        \"iso\": dt.datetime.isoformat,\n        \"iso8601\": dt.datetime.isoformat,\n        \"rfc\": email.utils.format_datetime,\n        \"rfc822\": email.utils.format_datetime,\n        \"timestamp\": utils.timestamp,\n        \"timestamp_ms\": utils.timestamp_ms,\n    }\n\n    DESERIALIZATION_FUNCS: dict[str, typing.Callable[[str], dt.datetime]] = {\n        \"iso\": dt.datetime.fromisoformat,\n        \"iso8601\": dt.datetime.fromisoformat,\n        \"rfc\": email.utils.parsedate_to_datetime,\n        \"rfc822\": email.utils.parsedate_to_datetime,\n        \"timestamp\": utils.from_timestamp,\n        \"timestamp_ms\": utils.from_timestamp_ms,\n    }\n\n    DEFAULT_FORMAT = \"iso\"\n\n    OBJ_TYPE = \"datetime\"\n\n    SCHEMA_OPTS_VAR_NAME = \"datetimeformat\"\n\n    @staticmethod\n    def _make_object_from_format(value, data_format) -> dt.datetime:\n        return dt.datetime.strptime(value, data_format)\n\n\nclass NaiveDateTime(DateTime):\n    \"\"\"A formatted naive datetime string.\n\n    :param format: See :class:`DateTime`.\n    :param timezone: Used on deserialization. If `None`,\n        aware datetimes are rejected. If not `None`, aware datetimes are\n        converted to this timezone before their timezone information is\n        removed.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. versionadded:: 3.0.0rc9\n    \"\"\"\n\n    AWARENESS = \"naive\"\n\n    def __init__(\n        self,\n        format: str | None = None,  # noqa: A002\n        *,\n        timezone: dt.timezone | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ) -> None:\n        super().__init__(format=format, **kwargs)\n        self.timezone = timezone\n\n    def _deserialize(self, value, attr, data, **kwargs) -> dt.datetime:\n        ret = super()._deserialize(value, attr, data, **kwargs)\n        if utils.is_aware(ret):\n            if self.timezone is None:\n                raise self.make_error(\n                    \"invalid_awareness\",\n                    awareness=self.AWARENESS,\n                    obj_type=self.OBJ_TYPE,\n                )\n            ret = ret.astimezone(self.timezone).replace(tzinfo=None)\n        return ret\n\n\nclass AwareDateTime(DateTime):\n    \"\"\"A formatted aware datetime string.\n\n    :param format: See :class:`DateTime`.\n    :param default_timezone: Used on deserialization. If `None`, naive\n        datetimes are rejected. If not `None`, naive datetimes are set this\n        timezone.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. versionadded:: 3.0.0rc9\n    \"\"\"\n\n    AWARENESS = \"aware\"\n\n    def __init__(\n        self,\n        format: str | None = None,  # noqa: A002\n        *,\n        default_timezone: dt.tzinfo | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ) -> None:\n        super().__init__(format=format, **kwargs)\n        self.default_timezone = default_timezone\n\n    def _deserialize(self, value, attr, data, **kwargs) -> dt.datetime:\n        ret = super()._deserialize(value, attr, data, **kwargs)\n        if not utils.is_aware(ret):\n            if self.default_timezone is None:\n                raise self.make_error(\n                    \"invalid_awareness\",\n                    awareness=self.AWARENESS,\n                    obj_type=self.OBJ_TYPE,\n                )\n            ret = ret.replace(tzinfo=self.default_timezone)\n        return ret\n\n\nclass Time(_TemporalField[dt.time]):\n    \"\"\"A formatted time string.\n\n    Example: ``'03:12:58.019077'``\n\n    :param format: Either ``\"iso\"`` (for ISO8601) or a date format string.\n        If `None`, defaults to \"iso\".\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n    \"\"\"\n\n    SERIALIZATION_FUNCS = {\n        \"iso\": dt.time.isoformat,\n        \"iso8601\": dt.time.isoformat,\n    }\n\n    DESERIALIZATION_FUNCS = {\n        \"iso\": dt.time.fromisoformat,\n        \"iso8601\": dt.time.fromisoformat,\n    }\n\n    DEFAULT_FORMAT = \"iso\"\n\n    OBJ_TYPE = \"time\"\n\n    SCHEMA_OPTS_VAR_NAME = \"timeformat\"\n\n    @staticmethod\n    def _make_object_from_format(value, data_format):\n        return dt.datetime.strptime(value, data_format).time()\n\n\nclass Date(_TemporalField[dt.date]):\n    \"\"\"ISO8601-formatted date string.\n\n    :param format: Either ``\"iso\"`` (for ISO8601) or a date format string.\n        If `None`, defaults to \"iso\".\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\n        \"invalid\": \"Not a valid date.\",\n        \"format\": '\"{input}\" cannot be formatted as a date.',\n    }\n\n    SERIALIZATION_FUNCS = {\n        \"iso\": dt.date.isoformat,\n        \"iso8601\": dt.date.isoformat,\n    }\n\n    DESERIALIZATION_FUNCS = {\n        \"iso\": dt.date.fromisoformat,\n        \"iso8601\": dt.date.fromisoformat,\n    }\n\n    DEFAULT_FORMAT = \"iso\"\n\n    OBJ_TYPE = \"date\"\n\n    SCHEMA_OPTS_VAR_NAME = \"dateformat\"\n\n    @staticmethod\n    def _make_object_from_format(value, data_format):\n        return dt.datetime.strptime(value, data_format).date()\n\n\nclass TimeDelta(Field[dt.timedelta]):\n    \"\"\"A field that (de)serializes a :class:`datetime.timedelta` object to a `float`.\n    The `float` can represent any time unit that the :class:`datetime.timedelta` constructor\n    supports.\n\n    :param precision: The time unit used for (de)serialization. Must be one of 'weeks',\n        'days', 'hours', 'minutes', 'seconds', 'milliseconds' or 'microseconds'.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    Float Caveats\n    -------------\n    Precision loss may occur when serializing a highly precise :class:`datetime.timedelta`\n    object using a big ``precision`` unit due to floating point arithmetics.\n\n    When necessary, the :class:`datetime.timedelta` constructor rounds `float` inputs\n    to whole microseconds during initialization of the object. As a result, deserializing\n    a `float` might be subject to rounding, regardless of `precision`. For example,\n    ``TimeDelta().deserialize(\"1.1234567\") == timedelta(seconds=1, microseconds=123457)``.\n\n    .. versionchanged:: 3.17.0\n        Allow serialization to `float` through use of a new `serialization_type` parameter.\n        Defaults to `int` for backwards compatibility. Also affects deserialization.\n    .. versionchanged:: 4.0.0\n        Remove `serialization_type` parameter and always serialize to float.\n        Value is cast to a `float` upon deserialization.\n    \"\"\"\n\n    WEEKS = \"weeks\"\n    DAYS = \"days\"\n    HOURS = \"hours\"\n    MINUTES = \"minutes\"\n    SECONDS = \"seconds\"\n    MILLISECONDS = \"milliseconds\"\n    MICROSECONDS = \"microseconds\"\n\n    # cache this mapping on class level for performance\n    _unit_to_microseconds_mapping = {\n        WEEKS: 1000000 * 60 * 60 * 24 * 7,\n        DAYS: 1000000 * 60 * 60 * 24,\n        HOURS: 1000000 * 60 * 60,\n        MINUTES: 1000000 * 60,\n        SECONDS: 1000000,\n        MILLISECONDS: 1000,\n        MICROSECONDS: 1,\n    }\n\n    #: Default error messages.\n    default_error_messages = {\n        \"invalid\": \"Not a valid period of time.\",\n        \"format\": \"{input!r} cannot be formatted as a timedelta.\",\n    }\n\n    def __init__(\n        self,\n        precision: str = SECONDS,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ) -> None:\n        precision = precision.lower()\n\n        if precision not in self._unit_to_microseconds_mapping:\n            units = \", \".join(self._unit_to_microseconds_mapping)\n            msg = f\"The precision must be one of: {units}.\"\n            raise ValueError(msg)\n\n        self.precision = precision\n        super().__init__(**kwargs)\n\n    def _serialize(self, value, attr, obj, **kwargs) -> float | None:\n        if value is None:\n            return None\n\n        # limit float arithmetics to a single division to minimize precision loss\n        microseconds: int = utils.timedelta_to_microseconds(value)\n        microseconds_per_unit: int = self._unit_to_microseconds_mapping[self.precision]\n        return microseconds / microseconds_per_unit\n\n    def _deserialize(self, value, attr, data, **kwargs) -> dt.timedelta:\n        if isinstance(value, dt.timedelta):\n            return value\n        try:\n            value = float(value)\n        except (TypeError, ValueError) as error:\n            raise self.make_error(\"invalid\") from error\n\n        kwargs = {self.precision: value}\n\n        try:\n            return dt.timedelta(**kwargs)\n        except OverflowError as error:\n            raise self.make_error(\"invalid\") from error\n\n\n_MappingT = typing.TypeVar(\"_MappingT\", bound=_Mapping)\n\n\nclass Mapping(Field[_MappingT]):\n    \"\"\"An abstract class for objects with key-value pairs. This class should not be used within schemas.\n\n    :param keys: A field class or instance for dict keys.\n    :param values: A field class or instance for dict values.\n    :param kwargs: The same keyword arguments that :class:`Field` receives.\n\n    .. note::\n        When the structure of nested data is not known, you may omit the\n        `keys` and `values` arguments to prevent content validation.\n\n    .. versionadded:: 3.0.0rc4\n    .. versionchanged:: 3.24.0\n        `Mapping <marshmallow.fields.Mapping>` should no longer be used as a field within a `Schema <marshmallow.Schema>`.\n        Use `Dict <marshmallow.fields.Dict>` instead.\n    \"\"\"\n\n    mapping_type: type[_MappingT]\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid mapping type.\"}\n\n    def __init__(\n        self,\n        keys: Field | type[Field] | None = None,\n        values: Field | type[Field] | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(**kwargs)\n        if keys is None:\n            self.key_field = None\n        else:\n            try:\n                self.key_field = _resolve_field_instance(keys)\n            except _FieldInstanceResolutionError as error:\n                raise ValueError(\n                    '\"keys\" must be a subclass or instance of marshmallow.fields.Field.'\n                ) from error\n\n        if values is None:\n            self.value_field = None\n        else:\n            try:\n                self.value_field = _resolve_field_instance(values)\n            except _FieldInstanceResolutionError as error:\n                raise ValueError(\n                    '\"values\" must be a subclass or instance of '\n                    \"marshmallow.fields.Field.\"\n                ) from error\n            if isinstance(self.value_field, Nested):\n                self.only = self.value_field.only\n                self.exclude = self.value_field.exclude\n\n    def _bind_to_schema(self, field_name, parent):\n        super()._bind_to_schema(field_name, parent)\n        if self.value_field:\n            self.value_field = copy.deepcopy(self.value_field)\n            self.value_field._bind_to_schema(field_name, self)\n        if isinstance(self.value_field, Nested):\n            self.value_field.only = self.only\n            self.value_field.exclude = self.exclude\n        if self.key_field:\n            self.key_field = copy.deepcopy(self.key_field)\n            self.key_field._bind_to_schema(field_name, self)\n\n    def _serialize(self, value, attr, obj, **kwargs):\n        if value is None:\n            return None\n        if not self.value_field and not self.key_field:\n            return self.mapping_type(value)\n\n        # Serialize keys\n        if self.key_field is None:\n            keys = {k: k for k in value}\n        else:\n            keys = {\n                k: self.key_field._serialize(k, None, None, **kwargs) for k in value\n            }\n\n        # Serialize values\n        result = self.mapping_type()\n        if self.value_field is None:\n            for k, v in value.items():\n                if k in keys:\n                    result[keys[k]] = v\n        else:\n            for k, v in value.items():\n                result[keys[k]] = self.value_field._serialize(v, None, None, **kwargs)\n\n        return result\n\n    def _deserialize(self, value, attr, data, **kwargs):\n        if not isinstance(value, _Mapping):\n            raise self.make_error(\"invalid\")\n        if not self.value_field and not self.key_field:\n            return self.mapping_type(value)\n\n        errors = collections.defaultdict(dict)\n\n        # Deserialize keys\n        if self.key_field is None:\n            keys = {k: k for k in value}\n        else:\n            keys = {}\n            for key in value:\n                try:\n                    keys[key] = self.key_field.deserialize(key, **kwargs)\n                except ValidationError as error:\n                    errors[key][\"key\"] = error.messages\n\n        # Deserialize values\n        result = self.mapping_type()\n        if self.value_field is None:\n            for k, v in value.items():\n                if k in keys:\n                    result[keys[k]] = v\n        else:\n            for key, val in value.items():\n                try:\n                    deser_val = self.value_field.deserialize(val, **kwargs)\n                except ValidationError as error:\n                    errors[key][\"value\"] = error.messages\n                    if error.valid_data is not None and key in keys:\n                        result[keys[key]] = error.valid_data\n                else:\n                    if key in keys:\n                        result[keys[key]] = deser_val\n\n        if errors:\n            raise ValidationError(errors, valid_data=result)\n\n        return result\n\n\nclass Dict(Mapping[dict]):\n    \"\"\"A dict field. Supports dicts and dict-like objects\n\n    Example: ::\n\n        numbers = fields.Dict(keys=fields.Str(), values=fields.Float())\n\n    :param kwargs: The same keyword arguments that :class:`Mapping` receives.\n\n    .. versionadded:: 2.1.0\n    \"\"\"\n\n    mapping_type = dict\n\n\nclass Url(String):\n    \"\"\"An URL field.\n\n    :param default: Default value for the field if the attribute is not set.\n    :param relative: Whether to allow relative URLs.\n    :param absolute: Whether to allow absolute URLs.\n    :param require_tld: Whether to reject non-FQDN hostnames.\n    :param schemes: Valid schemes. By default, ``http``, ``https``,\n        ``ftp``, and ``ftps`` are allowed.\n    :param kwargs: The same keyword arguments that :class:`String` receives.\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid URL.\"}\n\n    def __init__(\n        self,\n        *,\n        relative: bool = False,\n        absolute: bool = True,\n        schemes: types.StrSequenceOrSet | None = None,\n        require_tld: bool = True,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(**kwargs)\n\n        self.relative = relative\n        self.absolute = absolute\n        self.require_tld = require_tld\n        # Insert validation into self.validators so that multiple errors can be stored.\n        validator = validate.URL(\n            relative=self.relative,\n            absolute=self.absolute,\n            schemes=schemes,\n            require_tld=self.require_tld,\n            error=self.error_messages[\"invalid\"],\n        )\n        self.validators.insert(0, validator)\n\n\nclass Email(String):\n    \"\"\"An email field.\n\n    :param args: The same positional arguments that :class:`String` receives.\n    :param kwargs: The same keyword arguments that :class:`String` receives.\n    \"\"\"\n\n    #: Default error messages.\n    default_error_messages = {\"invalid\": \"Not a valid email address.\"}\n\n    def __init__(self, **kwargs: Unpack[_BaseFieldKwargs]) -> None:\n        super().__init__(**kwargs)\n        # Insert validation into self.validators so that multiple errors can be stored.\n        validator = validate.Email(error=self.error_messages[\"invalid\"])\n        self.validators.insert(0, validator)\n\n\nclass IP(Field[ipaddress.IPv4Address | ipaddress.IPv6Address]):\n    \"\"\"A IP address field.\n\n    :param exploded: If `True`, serialize ipv6 address in long form, ie. with groups\n        consisting entirely of zeros included.\n\n    .. versionadded:: 3.8.0\n    \"\"\"\n\n    default_error_messages = {\"invalid_ip\": \"Not a valid IP address.\"}\n\n    DESERIALIZATION_CLASS: type | None = None\n\n    def __init__(self, *, exploded: bool = False, **kwargs: Unpack[_BaseFieldKwargs]):\n        super().__init__(**kwargs)\n        self.exploded = exploded\n\n    def _serialize(self, value, attr, obj, **kwargs) -> str | None:\n        if value is None:\n            return None\n        if self.exploded:\n            return value.exploded\n        return value.compressed\n\n    def _deserialize(\n        self, value, attr, data, **kwargs\n    ) -> ipaddress.IPv4Address | ipaddress.IPv6Address:\n        try:\n            return (self.DESERIALIZATION_CLASS or ipaddress.ip_address)(\n                utils.ensure_text_type(value)\n            )\n        except (ValueError, TypeError) as error:\n            raise self.make_error(\"invalid_ip\") from error\n\n\nclass IPv4(IP):\n    \"\"\"A IPv4 address field.\n\n    .. versionadded:: 3.8.0\n    \"\"\"\n\n    default_error_messages = {\"invalid_ip\": \"Not a valid IPv4 address.\"}\n\n    DESERIALIZATION_CLASS = ipaddress.IPv4Address\n\n\nclass IPv6(IP):\n    \"\"\"A IPv6 address field.\n\n    .. versionadded:: 3.8.0\n    \"\"\"\n\n    default_error_messages = {\"invalid_ip\": \"Not a valid IPv6 address.\"}\n\n    DESERIALIZATION_CLASS = ipaddress.IPv6Address\n\n\nclass IPInterface(Field[ipaddress.IPv4Interface | ipaddress.IPv6Interface]):\n    \"\"\"A IPInterface field.\n\n    IP interface is the non-strict form of the IPNetwork type where arbitrary host\n    addresses are always accepted.\n\n    IPAddress and mask e.g. '192.168.0.2/24' or '192.168.0.2/255.255.255.0'\n\n    see https://python.readthedocs.io/en/latest/library/ipaddress.html#interface-objects\n\n    :param exploded: If `True`, serialize ipv6 interface in long form, ie. with groups\n        consisting entirely of zeros included.\n    \"\"\"\n\n    default_error_messages = {\"invalid_ip_interface\": \"Not a valid IP interface.\"}\n\n    DESERIALIZATION_CLASS: type | None = None\n\n    def __init__(self, *, exploded: bool = False, **kwargs: Unpack[_BaseFieldKwargs]):\n        super().__init__(**kwargs)\n        self.exploded = exploded\n\n    def _serialize(self, value, attr, obj, **kwargs) -> str | None:\n        if value is None:\n            return None\n        if self.exploded:\n            return value.exploded\n        return value.compressed\n\n    def _deserialize(\n        self, value, attr, data, **kwargs\n    ) -> ipaddress.IPv4Interface | ipaddress.IPv6Interface:\n        try:\n            return (self.DESERIALIZATION_CLASS or ipaddress.ip_interface)(\n                utils.ensure_text_type(value)\n            )\n        except (ValueError, TypeError) as error:\n            raise self.make_error(\"invalid_ip_interface\") from error\n\n\nclass IPv4Interface(IPInterface):\n    \"\"\"A IPv4 Network Interface field.\"\"\"\n\n    default_error_messages = {\"invalid_ip_interface\": \"Not a valid IPv4 interface.\"}\n\n    DESERIALIZATION_CLASS = ipaddress.IPv4Interface\n\n\nclass IPv6Interface(IPInterface):\n    \"\"\"A IPv6 Network Interface field.\"\"\"\n\n    default_error_messages = {\"invalid_ip_interface\": \"Not a valid IPv6 interface.\"}\n\n    DESERIALIZATION_CLASS = ipaddress.IPv6Interface\n\n\n_EnumT = typing.TypeVar(\"_EnumT\", bound=EnumType)\n\n\nclass Enum(Field[_EnumT]):\n    \"\"\"An Enum field (de)serializing enum members by symbol (name) or by value.\n\n    :param enum: Enum class\n    :param by_value: Whether to (de)serialize by value or by name,\n        or Field class or instance to use to (de)serialize by value. Defaults to False.\n\n    If `by_value` is `False` (default), enum members are (de)serialized by symbol (name).\n    If it is `True`, they are (de)serialized by value using `marshmallow.fields.Raw`.\n    If it is a field instance or class, they are (de)serialized by value using this field.\n\n    .. versionadded:: 3.18.0\n    \"\"\"\n\n    default_error_messages = {\n        \"unknown\": \"Must be one of: {choices}.\",\n    }\n\n    def __init__(\n        self,\n        enum: type[_EnumT],\n        *,\n        by_value: bool | Field | type[Field] = False,\n        **kwargs: Unpack[_BaseFieldKwargs],\n    ):\n        super().__init__(**kwargs)\n        self.enum = enum\n        self.by_value = by_value\n\n        # Serialization by name\n        if by_value is False:\n            self.field: Field = String()\n            self.choices_text = \", \".join(\n                str(self.field._serialize(m, None, None)) for m in enum.__members__\n            )\n        # Serialization by value\n        else:\n            if by_value is True:\n                self.field = Raw()\n            else:\n                try:\n                    self.field = _resolve_field_instance(by_value)\n                except _FieldInstanceResolutionError as error:\n                    raise ValueError(\n                        '\"by_value\" must be either a bool or a subclass or instance of '\n                        \"marshmallow.fields.Field.\"\n                    ) from error\n            self.choices_text = \", \".join(\n                str(self.field._serialize(m.value, None, None)) for m in enum\n            )\n\n    def _serialize(\n        self, value: _EnumT | None, attr: str | None, obj: typing.Any, **kwargs\n    ) -> typing.Any | None:\n        if value is None:\n            return None\n        if self.by_value:\n            val = value.value\n        else:\n            val = value.name\n        return self.field._serialize(val, attr, obj, **kwargs)\n\n    def _deserialize(self, value, attr, data, **kwargs) -> _EnumT:\n        if isinstance(value, self.enum):\n            return value\n        val = self.field._deserialize(value, attr, data, **kwargs)\n        if self.by_value:\n            try:\n                return self.enum(val)\n            except ValueError as error:\n                raise self.make_error(\"unknown\", choices=self.choices_text) from error\n        try:\n            return getattr(self.enum, val)\n        except AttributeError as error:\n            raise self.make_error(\"unknown\", choices=self.choices_text) from error\n\n\nclass Method(Field):\n    \"\"\"A field that takes the value returned by a `Schema <marshmallow.Schema>` method.\n\n    :param serialize: The name of the Schema method from which\n        to retrieve the value. The method must take an argument ``obj``\n        (in addition to self) that is the object to be serialized.\n    :param deserialize: Optional name of the Schema method for deserializing\n        a value The method must take a single argument ``value``, which is the\n        value to deserialize.\n\n    .. versionchanged:: 3.0.0\n        Removed ``method_name`` parameter.\n    \"\"\"\n\n    _CHECK_ATTRIBUTE = False\n\n    def __init__(\n        self,\n        serialize: str | None = None,\n        deserialize: str | None = None,\n        **kwargs: Unpack[_BaseFieldKwargs],  # FIXME: Omit dump_only and load_only\n    ):\n        # Set dump_only and load_only based on arguments\n        kwargs[\"dump_only\"] = bool(serialize) and not bool(deserialize)\n        kwargs[\"load_only\"] = bool(deserialize) and not bool(serialize)\n        super().__init__(**kwargs)\n        self.serialize_method_name = serialize\n        self.deserialize_method_name = deserialize\n        self._serialize_method = None\n        self._deserialize_method = None\n\n    def _bind_to_schema(self, field_name, parent):\n        if self.serialize_method_name:\n            self._serialize_method = utils.callable_or_raise(\n                getattr(parent, self.serialize_method_name)\n            )\n\n        if self.deserialize_method_name:\n            self._deserialize_method = utils.callable_or_raise(\n                getattr(parent, self.deserialize_method_name)\n            )\n\n        super()._bind_to_schema(field_name, parent)\n\n    def _serialize(self, value, attr, obj, **kwargs):\n        if self._serialize_method is not None:\n            return self._serialize_method(obj)\n        return missing_\n\n    def _deserialize(self, value, attr, data, **kwargs):\n        if self._deserialize_method is not None:\n            return self._deserialize_method(value)\n        return value\n\n\nclass Function(Field):\n    \"\"\"A field that takes the value returned by a function.\n\n    :param serialize: A callable from which to retrieve the value.\n        The function must take a single argument ``obj`` which is the object\n        to be serialized.\n        If no callable is provided then the ```load_only``` flag will be set\n        to True.\n    :param deserialize: A callable from which to retrieve the value.\n        The function must take a single argument ``value`` which is the value\n        to be deserialized.\n        If no callable is provided then ```value``` will be passed through\n        unchanged.\n\n    .. versionchanged:: 3.0.0a1\n        Removed ``func`` parameter.\n\n    .. versionchanged:: 4.0.0\n        Don't pass context to serialization and deserialization functions.\n    \"\"\"\n\n    _CHECK_ATTRIBUTE = False\n\n    def __init__(\n        self,\n        serialize: (\n            typing.Callable[[typing.Any], typing.Any]\n            | typing.Callable[[typing.Any, dict], typing.Any]\n            | None\n        ) = None,\n        deserialize: (\n            typing.Callable[[typing.Any], typing.Any]\n            | typing.Callable[[typing.Any, dict], typing.Any]\n            | None\n        ) = None,\n        **kwargs: Unpack[_BaseFieldKwargs],  # FIXME: Omit dump_only and load_only\n    ):\n        # Set dump_only and load_only based on arguments\n        kwargs[\"dump_only\"] = bool(serialize) and not bool(deserialize)\n        kwargs[\"load_only\"] = bool(deserialize) and not bool(serialize)\n        super().__init__(**kwargs)\n        self.serialize_func = serialize and utils.callable_or_raise(serialize)\n        self.deserialize_func = deserialize and utils.callable_or_raise(deserialize)\n\n    def _serialize(self, value, attr, obj, **kwargs):\n        return self.serialize_func(obj)\n\n    def _deserialize(self, value, attr, data, **kwargs):\n        if self.deserialize_func:\n            return self.deserialize_func(value)\n        return value\n\n\n_ContantT = typing.TypeVar(\"_ContantT\")\n\n\nclass Constant(Field[_ContantT]):\n    \"\"\"A field that (de)serializes to a preset constant.  If you only want the\n    constant added for serialization or deserialization, you should use\n    ``dump_only=True`` or ``load_only=True`` respectively.\n\n    :param constant: The constant to return for the field attribute.\n    \"\"\"\n\n    _CHECK_ATTRIBUTE = False\n\n    def __init__(self, constant: _ContantT, **kwargs: Unpack[_BaseFieldKwargs]):\n        kwargs[\"load_default\"] = constant\n        kwargs[\"dump_default\"] = constant\n        super().__init__(**kwargs)\n        self.constant = constant\n\n    def _serialize(self, value, *args, **kwargs) -> _ContantT:\n        return self.constant\n\n    def _deserialize(self, value, *args, **kwargs) -> _ContantT:\n        return self.constant\n\n\n# Aliases\nURL = Url\n\nStr = String\nBool = Boolean\nInt = Integer\n"
  },
  {
    "path": "src/marshmallow/orderedset.py",
    "content": "# OrderedSet\n# Copyright (c) 2009 Raymond Hettinger\n#\n# Permission is hereby granted, free of charge, to any person\n# obtaining a copy of this software and associated documentation files\n# (the \"Software\"), to deal in the Software without restriction,\n# including without limitation the rights to use, copy, modify, merge,\n# publish, distribute, sublicense, and/or sell copies of the Software,\n# and to permit persons to whom the Software is furnished to do so,\n# subject to the following conditions:\n#\n#     The above copyright notice and this permission notice shall be\n#     included in all copies or substantial portions of the Software.\n#\n#     THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n#     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n#     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n#     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n#     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n#     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n#     OTHER DEALINGS IN THE SOFTWARE.\nfrom collections.abc import MutableSet\n\n\nclass OrderedSet(MutableSet):  # noqa: PLW1641\n    def __init__(self, iterable=None):\n        self.end = end = []\n        end += [None, end, end]  # sentinel node for doubly linked list\n        self.map = {}  # key --> [key, prev, next]\n        if iterable is not None:\n            self |= iterable\n\n    def __len__(self):\n        return len(self.map)\n\n    def __contains__(self, key):\n        return key in self.map\n\n    def add(self, key):\n        if key not in self.map:\n            end = self.end\n            curr = end[1]\n            curr[2] = end[1] = self.map[key] = [key, curr, end]\n\n    def discard(self, key):\n        if key in self.map:\n            key, prev, next = self.map.pop(key)  # noqa: A001\n            prev[2] = next\n            next[1] = prev\n\n    def __iter__(self):\n        end = self.end\n        curr = end[2]\n        while curr is not end:\n            yield curr[0]\n            curr = curr[2]\n\n    def __reversed__(self):\n        end = self.end\n        curr = end[1]\n        while curr is not end:\n            yield curr[0]\n            curr = curr[1]\n\n    def pop(self, last=True):\n        if not self:\n            raise KeyError(\"set is empty\")\n        key = self.end[1][0] if last else self.end[2][0]\n        self.discard(key)\n        return key\n\n    def __repr__(self):\n        if not self:\n            return f\"{self.__class__.__name__}()\"\n        return f\"{self.__class__.__name__}({list(self)!r})\"\n\n    def __eq__(self, other):\n        if isinstance(other, OrderedSet):\n            return len(self) == len(other) and list(self) == list(other)\n        return set(self) == set(other)\n\n\nif __name__ == \"__main__\":\n    s = OrderedSet(\"abracadaba\")\n    t = OrderedSet(\"simsalabim\")\n    print(s | t)\n    print(s & t)\n    print(s - t)\n"
  },
  {
    "path": "src/marshmallow/py.typed",
    "content": ""
  },
  {
    "path": "src/marshmallow/schema.py",
    "content": "\"\"\"The `Schema <marshmallow.Schema>` class, including its metaclass and options (`class Meta <marshmallow.Schema.Meta>`).\"\"\"\n\n# ruff: noqa: SLF001\nfrom __future__ import annotations\n\nimport copy\nimport datetime as dt\nimport decimal\nimport functools\nimport inspect\nimport json\nimport operator\nimport typing\nimport uuid\nfrom abc import ABCMeta\nfrom collections import defaultdict\nfrom collections.abc import Mapping, Sequence\nfrom itertools import zip_longest\n\nfrom marshmallow import class_registry, types\nfrom marshmallow import fields as ma_fields\nfrom marshmallow.constants import EXCLUDE, INCLUDE, RAISE, missing\nfrom marshmallow.decorators import (\n    POST_DUMP,\n    POST_LOAD,\n    PRE_DUMP,\n    PRE_LOAD,\n    VALIDATES,\n    VALIDATES_SCHEMA,\n)\nfrom marshmallow.error_store import ErrorStore\nfrom marshmallow.exceptions import SCHEMA, StringNotCollectionError, ValidationError\nfrom marshmallow.orderedset import OrderedSet\nfrom marshmallow.utils import (\n    get_value,\n    is_collection,\n    is_sequence_but_not_string,\n    set_value,\n)\n\nif typing.TYPE_CHECKING:\n    from marshmallow.fields import Field\n\n\ndef _get_fields(attrs) -> list[tuple[str, Field]]:\n    \"\"\"Get fields from a class\n\n    :param attrs: Mapping of class attributes\n    \"\"\"\n    ret = []\n    for field_name, field_value in attrs.items():\n        if isinstance(field_value, type) and issubclass(field_value, ma_fields.Field):\n            raise TypeError(\n                f'Field for \"{field_name}\" must be declared as a '\n                \"Field instance, not a class. \"\n                f'Did you mean \"fields.{field_value.__name__}()\"?'\n            )\n        if isinstance(field_value, ma_fields.Field):\n            ret.append((field_name, field_value))\n    return ret\n\n\n# This function allows Schemas to inherit from non-Schema classes and ensures\n#   inheritance according to the MRO\ndef _get_fields_by_mro(klass: SchemaMeta):\n    \"\"\"Collect fields from a class, following its method resolution order. The\n    class itself is excluded from the search; only its parents are checked. Get\n    fields from ``_declared_fields`` if available, else use ``__dict__``.\n\n    :param klass: Class whose fields to retrieve\n    \"\"\"\n    mro = inspect.getmro(klass)\n    # Combine fields from all parents\n    # functools.reduce(operator.iadd, list_of_lists) is faster than sum(list_of_lists, [])\n    # Loop over mro in reverse to maintain correct order of fields\n    return functools.reduce(\n        operator.iadd,\n        (\n            _get_fields(\n                getattr(base, \"_declared_fields\", base.__dict__),\n            )\n            for base in mro[:0:-1]\n        ),\n        [],\n    )\n\n\nclass SchemaMeta(ABCMeta):\n    \"\"\"Metaclass for the Schema class. Binds the declared fields to\n    a ``_declared_fields`` attribute, which is a dictionary mapping attribute\n    names to field objects. Also sets the ``opts`` class attribute, which is\n    the Schema class's `class Meta <marshmallow.Schema.Meta>` options.\n    \"\"\"\n\n    Meta: type\n    opts: typing.Any\n    OPTIONS_CLASS: type\n    _declared_fields: dict[str, Field]\n\n    def __new__(\n        mcs,\n        name: str,\n        bases: tuple[type, ...],\n        attrs: dict[str, typing.Any],\n    ) -> SchemaMeta:\n        meta = attrs.get(\"Meta\")\n        cls_fields = _get_fields(attrs)\n        # Remove fields from list of class attributes to avoid shadowing\n        # Schema attributes/methods in case of name conflict\n        for field_name, _ in cls_fields:\n            del attrs[field_name]\n        klass = super().__new__(mcs, name, bases, attrs)\n        inherited_fields = _get_fields_by_mro(klass)\n\n        meta = klass.Meta\n        # Set klass.opts in __new__ rather than __init__ so that it is accessible in\n        # get_declared_fields\n        klass.opts = klass.OPTIONS_CLASS(meta)\n        # Add fields specified in the `include` class Meta option\n        cls_fields += list(klass.opts.include.items())\n\n        # Assign _declared_fields on class\n        klass._declared_fields = mcs.get_declared_fields(\n            klass=klass,\n            cls_fields=cls_fields,\n            inherited_fields=inherited_fields,\n            dict_cls=dict,\n        )\n        return klass\n\n    @classmethod\n    def get_declared_fields(\n        mcs,  # noqa: N804\n        klass: SchemaMeta,\n        cls_fields: list[tuple[str, Field]],\n        inherited_fields: list[tuple[str, Field]],\n        dict_cls: type[dict] = dict,\n    ) -> dict[str, Field]:\n        \"\"\"Returns a dictionary of field_name => `Field` pairs declared on the class.\n        This is exposed mainly so that plugins can add additional fields, e.g. fields\n        computed from `class Meta <marshmallow.Schema.Meta>` options.\n\n        :param klass: The class object.\n        :param cls_fields: The fields declared on the class, including those added\n            by the ``include`` `class Meta <marshmallow.Schema.Meta>` option.\n        :param inherited_fields: Inherited fields.\n        :param dict_cls: dict-like class to use for dict output Default to ``dict``.\n        \"\"\"\n        return dict_cls(inherited_fields + cls_fields)\n\n    def __init__(cls, name, bases, attrs):\n        super().__init__(name, bases, attrs)\n        if name and cls.opts.register:\n            class_registry.register(name, cls)\n        cls._hooks = cls.resolve_hooks()\n\n    def resolve_hooks(cls) -> dict[str, list[tuple[str, bool, dict]]]:\n        \"\"\"Add in the decorated processors\n\n        By doing this after constructing the class, we let standard inheritance\n        do all the hard work.\n        \"\"\"\n        mro = inspect.getmro(cls)\n\n        hooks: dict[str, list[tuple[str, bool, dict]]] = defaultdict(list)\n\n        for attr_name in dir(cls):\n            # Need to look up the actual descriptor, not whatever might be\n            # bound to the class. This needs to come from the __dict__ of the\n            # declaring class.\n            for parent in mro:\n                try:\n                    attr = parent.__dict__[attr_name]\n                except KeyError:\n                    continue\n                else:\n                    break\n            else:\n                # In case we didn't find the attribute and didn't break above.\n                # We should never hit this - it's just here for completeness\n                # to exclude the possibility of attr being undefined.\n                continue\n\n            try:\n                hook_config: dict[str, list[tuple[bool, dict]]] = (\n                    attr.__marshmallow_hook__\n                )\n            except AttributeError:\n                pass\n            else:\n                for tag, config in hook_config.items():\n                    # Use name here so we can get the bound method later, in\n                    # case the processor was a descriptor or something.\n                    hooks[tag].extend(\n                        (attr_name, many, kwargs) for many, kwargs in config\n                    )\n\n        return hooks\n\n\nclass SchemaOpts:\n    \"\"\"Defines defaults for `marshmallow.Schema.Meta`.\"\"\"\n\n    def __init__(self, meta: type):\n        self.fields = getattr(meta, \"fields\", ())\n        if not isinstance(self.fields, (list, tuple)):\n            raise ValueError(\"`fields` option must be a list or tuple.\")\n        self.exclude = getattr(meta, \"exclude\", ())\n        if not isinstance(self.exclude, (list, tuple)):\n            raise ValueError(\"`exclude` must be a list or tuple.\")\n        self.dateformat = getattr(meta, \"dateformat\", None)\n        self.datetimeformat = getattr(meta, \"datetimeformat\", None)\n        self.timeformat = getattr(meta, \"timeformat\", None)\n        self.render_module = getattr(meta, \"render_module\", json)\n        self.index_errors = getattr(meta, \"index_errors\", True)\n        self.include = getattr(meta, \"include\", {})\n        self.load_only = getattr(meta, \"load_only\", ())\n        self.dump_only = getattr(meta, \"dump_only\", ())\n        self.unknown = getattr(meta, \"unknown\", RAISE)\n        self.register = getattr(meta, \"register\", True)\n        self.many = getattr(meta, \"many\", False)\n\n\nclass Schema(metaclass=SchemaMeta):\n    \"\"\"Base schema class with which to define schemas.\n\n    Example usage:\n\n    .. code-block:: python\n\n        import datetime as dt\n        from dataclasses import dataclass\n\n        from marshmallow import Schema, fields\n\n\n        @dataclass\n        class Album:\n            title: str\n            release_date: dt.date\n\n\n        class AlbumSchema(Schema):\n            title = fields.Str()\n            release_date = fields.Date()\n\n\n        album = Album(\"Beggars Banquet\", dt.date(1968, 12, 6))\n        schema = AlbumSchema()\n        data = schema.dump(album)\n        data  # {'release_date': '1968-12-06', 'title': 'Beggars Banquet'}\n\n    :param only: Whitelist of the declared fields to select when\n        instantiating the Schema. If None, all fields are used. Nested fields\n        can be represented with dot delimiters.\n    :param exclude: Blacklist of the declared fields to exclude\n        when instantiating the Schema. If a field appears in both `only` and\n        `exclude`, it is not used. Nested fields can be represented with dot\n        delimiters.\n    :param many: Should be set to `True` if ``obj`` is a collection\n        so that the object will be serialized to a list.\n    :param load_only: Fields to skip during serialization (write-only fields)\n    :param dump_only: Fields to skip during deserialization (read-only fields)\n    :param partial: Whether to ignore missing fields and not require\n        any fields declared. Propagates down to ``Nested`` fields as well. If\n        its value is an iterable, only missing fields listed in that iterable\n        will be ignored. Use dot delimiters to specify nested fields.\n    :param unknown: Whether to exclude, include, or raise an error for unknown\n        fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n\n    .. versionchanged:: 3.0.0\n        Remove ``prefix`` parameter.\n\n    .. versionchanged:: 4.0.0\n        Remove ``context`` parameter.\n    \"\"\"\n\n    TYPE_MAPPING: dict[type, type[Field]] = {\n        str: ma_fields.String,\n        bytes: ma_fields.String,\n        dt.datetime: ma_fields.DateTime,\n        float: ma_fields.Float,\n        bool: ma_fields.Boolean,\n        tuple: ma_fields.Raw,\n        list: ma_fields.Raw,\n        set: ma_fields.Raw,\n        int: ma_fields.Integer,\n        uuid.UUID: ma_fields.UUID,\n        dt.time: ma_fields.Time,\n        dt.date: ma_fields.Date,\n        dt.timedelta: ma_fields.TimeDelta,\n        decimal.Decimal: ma_fields.Decimal,\n    }\n    #: Overrides for default schema-level error messages\n    error_messages: dict[str, str] = {}\n\n    _default_error_messages: dict[str, str] = {\n        \"type\": \"Invalid input type.\",\n        \"unknown\": \"Unknown field.\",\n    }\n\n    OPTIONS_CLASS: type = SchemaOpts\n\n    set_class = OrderedSet\n    dict_class: type[dict] = dict\n    \"\"\"`dict` type to return when serializing.\"\"\"\n\n    # These get set by SchemaMeta\n    opts: typing.Any\n    _declared_fields: dict[str, Field] = {}\n    _hooks: dict[str, list[tuple[str, bool, dict]]] = {}\n\n    class Meta:\n        \"\"\"Options object for a Schema.\n\n        Example usage: ::\n\n            from marshmallow import Schema\n\n\n            class MySchema(Schema):\n                class Meta:\n                    fields = (\"id\", \"email\", \"date_created\")\n                    exclude = (\"password\", \"secret_attribute\")\n\n        .. admonition:: A note on type checking\n\n            Type checkers will only check the attributes of the `Meta <marshmallow.Schema.Meta>`\n            class if you explicitly subclass `marshmallow.Schema.Meta`.\n\n            .. code-block:: python\n\n                from marshmallow import Schema\n\n\n                class MySchema(Schema):\n                    # Not checked by type checkers\n                    class Meta:\n                        additional = True\n\n\n                class MySchema2(Schema):\n                    # Type checkers will check attributes\n                    class Meta(Schema.Meta):\n                        additional = True  # Incompatible types in assignment\n\n        .. versionremoved:: 3.0.0b7 Remove ``strict``.\n        .. versionadded:: 3.0.0b12 Add `unknown`.\n        .. versionchanged:: 3.0.0b17 Rename ``dateformat`` to `datetimeformat`.\n        .. versionadded:: 3.9.0 Add `timeformat`.\n        .. versionchanged:: 3.26.0 Deprecate ``ordered``. Field order is preserved by default.\n        .. versionremoved:: 4.0.0 Remove ``ordered``.\n        \"\"\"\n\n        fields: typing.ClassVar[tuple[str, ...] | list[str]]\n        \"\"\"Fields to include in the (de)serialized result\"\"\"\n        additional: typing.ClassVar[tuple[str, ...] | list[str]]\n        \"\"\"Fields to include in addition to the explicitly declared fields.\n        `additional <marshmallow.Schema.Meta.additional>` and `fields <marshmallow.Schema.Meta.fields>`\n        are mutually-exclusive options.\n        \"\"\"\n        include: typing.ClassVar[dict[str, Field]]\n        \"\"\"Dictionary of additional fields to include in the schema. It is\n        usually better to define fields as class variables, but you may need to\n        use this option, e.g., if your fields are Python keywords.\n        \"\"\"\n        exclude: typing.ClassVar[tuple[str, ...] | list[str]]\n        \"\"\"Fields to exclude in the serialized result.\n        Nested fields can be represented with dot delimiters.\n        \"\"\"\n        many: typing.ClassVar[bool]\n        \"\"\"Whether data should be (de)serialized as a collection by default.\"\"\"\n        dateformat: typing.ClassVar[str]\n        \"\"\"Default format for `Date <marshmallow.fields.Date>` fields.\"\"\"\n        datetimeformat: typing.ClassVar[str]\n        \"\"\"Default format for `DateTime <marshmallow.fields.DateTime>` fields.\"\"\"\n        timeformat: typing.ClassVar[str]\n        \"\"\"Default format for `Time <marshmallow.fields.Time>` fields.\"\"\"\n\n        # FIXME: Use a more constrained type here.\n        # ClassVar[RenderModule] doesn't work.\n        render_module: typing.Any\n        \"\"\" Module to use for `loads <marshmallow.Schema.loads>` and `dumps <marshmallow.Schema.dumps>`.\n        Defaults to `json` from the standard library.\n        \"\"\"\n        index_errors: typing.ClassVar[bool]\n        \"\"\"If `True`, errors dictionaries will include the index of invalid items in a collection.\"\"\"\n        load_only: typing.ClassVar[tuple[str, ...] | list[str]]\n        \"\"\"Fields to exclude from serialized results\"\"\"\n        dump_only: typing.ClassVar[tuple[str, ...] | list[str]]\n        \"\"\"Fields to exclude from deserialized results\"\"\"\n        unknown: typing.ClassVar[types.UnknownOption]\n        \"\"\"Whether to exclude, include, or raise an error for unknown fields in the data.\n        Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n        \"\"\"\n        register: typing.ClassVar[bool]\n        \"\"\"Whether to register the `Schema <marshmallow.Schema>` with marshmallow's internal\n        class registry. Must be `True` if you intend to refer to this `Schema <marshmallow.Schema>`\n        by class name in `Nested` fields. Only set this to `False` when memory\n        usage is critical. Defaults to `True`.\n        \"\"\"\n\n    def __init__(\n        self,\n        *,\n        only: types.StrSequenceOrSet | None = None,\n        exclude: types.StrSequenceOrSet = (),\n        many: bool | None = None,\n        load_only: types.StrSequenceOrSet = (),\n        dump_only: types.StrSequenceOrSet = (),\n        partial: bool | types.StrSequenceOrSet | None = None,\n        unknown: types.UnknownOption | None = None,\n    ):\n        # Raise error if only or exclude is passed as string, not list of strings\n        if only is not None and not is_collection(only):\n            raise StringNotCollectionError('\"only\" should be a list of strings')\n        if not is_collection(exclude):\n            raise StringNotCollectionError('\"exclude\" should be a list of strings')\n        # copy declared fields from metaclass\n        self.declared_fields = copy.deepcopy(self._declared_fields)\n        self.many = self.opts.many if many is None else many\n        self.only = only\n        self.exclude: set[typing.Any] | typing.MutableSet[typing.Any] = set(\n            self.opts.exclude\n        ) | set(exclude)\n        self.load_only = set(load_only) or set(self.opts.load_only)\n        self.dump_only = set(dump_only) or set(self.opts.dump_only)\n        self.partial = partial\n        self.unknown: types.UnknownOption = (\n            self.opts.unknown if unknown is None else unknown\n        )\n        self._normalize_nested_options()\n        #: Dictionary mapping field_names -> :class:`Field` objects\n        self.fields: dict[str, Field] = {}\n        self.load_fields: dict[str, Field] = {}\n        self.dump_fields: dict[str, Field] = {}\n        self._init_fields()\n        messages = {}\n        messages.update(self._default_error_messages)\n        for cls in reversed(self.__class__.__mro__):\n            messages.update(getattr(cls, \"error_messages\", {}))\n        messages.update(self.error_messages or {})\n        self.error_messages = messages\n\n    def __repr__(self) -> str:\n        return f\"<{self.__class__.__name__}(many={self.many})>\"\n\n    @classmethod\n    def from_dict(\n        cls,\n        fields: dict[str, Field],\n        *,\n        name: str = \"GeneratedSchema\",\n    ) -> type[Schema]:\n        \"\"\"Generate a `Schema <marshmallow.Schema>` class given a dictionary of fields.\n\n        .. code-block:: python\n\n            from marshmallow import Schema, fields\n\n            PersonSchema = Schema.from_dict({\"name\": fields.Str()})\n            print(PersonSchema().load({\"name\": \"David\"}))  # => {'name': 'David'}\n\n        Generated schemas are not added to the class registry and therefore cannot\n        be referred to by name in `Nested` fields.\n\n\n        :param fields: Dictionary mapping field names to field instances.\n        :param name: Optional name for the class, which will appear in\n            the ``repr`` for the class.\n\n        .. versionadded:: 3.0.0\n        \"\"\"\n        Meta = type(\n            \"GeneratedMeta\", (getattr(cls, \"Meta\", object),), {\"register\": False}\n        )\n        return type(name, (cls,), {**fields.copy(), \"Meta\": Meta})\n\n    ##### Override-able methods #####\n\n    def handle_error(\n        self, error: ValidationError, data: typing.Any, *, many: bool, **kwargs\n    ):\n        \"\"\"Custom error handler function for the schema.\n\n        :param error: The `ValidationError` raised during (de)serialization.\n        :param data: The original input data.\n        :param many: Value of ``many`` on dump or load.\n        :param partial: Value of ``partial`` on load.\n\n        .. versionchanged:: 3.0.0rc9\n            Receives `many` and `partial` (on deserialization) as keyword arguments.\n        \"\"\"\n\n    def get_attribute(self, obj: typing.Any, attr: str, default: typing.Any):\n        \"\"\"Defines how to pull values from an object to serialize.\n\n        .. versionchanged:: 3.0.0a1\n            Changed position of ``obj`` and ``attr``.\n        \"\"\"\n        return get_value(obj, attr, default)\n\n    ##### Serialization/Deserialization API #####\n\n    @staticmethod\n    def _call_and_store(getter_func, data, *, field_name, error_store, index=None):\n        \"\"\"Call ``getter_func`` with ``data`` as its argument, and store any `ValidationErrors`.\n\n        :param getter_func: Function for getting the serialized/deserialized\n            value from ``data``.\n        :param data: The data passed to ``getter_func``.\n        :param field_name: Field name.\n        :param index: Index of the item being validated, if validating a collection,\n            otherwise `None`.\n        \"\"\"\n        try:\n            value = getter_func(data)\n        except ValidationError as error:\n            error_store.store_error(error.messages, field_name, index=index)\n            # When a Nested field fails validation, the marshalled data is stored\n            # on the ValidationError's valid_data attribute\n            return error.valid_data or missing\n        return value\n\n    def _serialize(self, obj: typing.Any, *, many: bool = False):\n        \"\"\"Serialize ``obj``.\n\n        :param obj: The object(s) to serialize.\n        :param many: `True` if ``data`` should be serialized as a collection.\n        :return: A dictionary of the serialized data\n        \"\"\"\n        if many and obj is not None:\n            return [self._serialize(d, many=False) for d in obj]\n        ret = self.dict_class()\n        for attr_name, field_obj in self.dump_fields.items():\n            value = field_obj.serialize(attr_name, obj, accessor=self.get_attribute)\n            if value is missing:\n                continue\n            key = field_obj.data_key if field_obj.data_key is not None else attr_name\n            ret[key] = value\n        return ret\n\n    def dump(self, obj: typing.Any, *, many: bool | None = None):\n        \"\"\"Serialize an object to native Python data types according to this\n        Schema's fields.\n\n        :param obj: The object to serialize.\n        :param many: Whether to serialize `obj` as a collection. If `None`, the value\n            for `self.many` is used.\n        :return: Serialized data\n\n        .. versionchanged:: 3.0.0b7\n            This method returns the serialized data rather than a ``(data, errors)`` tuple.\n            A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised\n            if ``obj`` is invalid.\n        .. versionchanged:: 3.0.0rc9\n            Validation no longer occurs upon serialization.\n        \"\"\"\n        many = self.many if many is None else bool(many)\n        if self._hooks[PRE_DUMP]:\n            processed_obj = self._invoke_dump_processors(\n                PRE_DUMP, obj, many=many, original_data=obj\n            )\n        else:\n            processed_obj = obj\n\n        result = self._serialize(processed_obj, many=many)\n\n        if self._hooks[POST_DUMP]:\n            result = self._invoke_dump_processors(\n                POST_DUMP, result, many=many, original_data=obj\n            )\n\n        return result\n\n    def dumps(self, obj: typing.Any, *args, many: bool | None = None, **kwargs):\n        \"\"\"Same as :meth:`dump`, except return a JSON-encoded string.\n\n        :param obj: The object to serialize.\n        :param many: Whether to serialize `obj` as a collection. If `None`, the value\n            for `self.many` is used.\n        :return: A ``json`` string\n\n        .. versionchanged:: 3.0.0b7\n            This method returns the serialized data rather than a ``(data, errors)`` tuple.\n            A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised\n            if ``obj`` is invalid.\n        \"\"\"\n        serialized = self.dump(obj, many=many)\n        return self.opts.render_module.dumps(serialized, *args, **kwargs)\n\n    def _deserialize(\n        self,\n        data: Mapping[str, typing.Any] | Sequence[Mapping[str, typing.Any]],\n        *,\n        error_store: ErrorStore,\n        many: bool = False,\n        partial=None,\n        unknown: types.UnknownOption = RAISE,\n        index=None,\n    ) -> typing.Any | list[typing.Any]:\n        \"\"\"Deserialize ``data``.\n\n        :param data: The data to deserialize.\n        :param error_store: Structure to store errors.\n        :param many: `True` if ``data`` should be deserialized as a collection.\n        :param partial: Whether to ignore missing fields and not require\n            any fields declared. Propagates down to ``Nested`` fields as well. If\n            its value is an iterable, only missing fields listed in that iterable\n            will be ignored. Use dot delimiters to specify nested fields.\n        :param unknown: Whether to exclude, include, or raise an error for unknown\n            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n        :param index: Index of the item being serialized (for storing errors) if\n            serializing a collection, otherwise `None`.\n        :return: The deserialized data as `dict_class` instance or list of `dict_class`\n        instances if `many` is `True`.\n        \"\"\"\n        index_errors = self.opts.index_errors\n        index = index if index_errors else None\n        if many:\n            if not is_sequence_but_not_string(data):\n                error_store.store_error([self.error_messages[\"type\"]], index=index)\n                ret_l = []\n            else:\n                ret_l = [\n                    self._deserialize(\n                        d,\n                        error_store=error_store,\n                        many=False,\n                        partial=partial,\n                        unknown=unknown,\n                        index=idx,\n                    )\n                    for idx, d in enumerate(data)\n                ]\n            return ret_l\n        ret_d = self.dict_class()\n        # Check data is a dict\n        if not isinstance(data, Mapping):\n            error_store.store_error([self.error_messages[\"type\"]], index=index)\n        else:\n            partial_is_collection = is_collection(partial)\n            for attr_name, field_obj in self.load_fields.items():\n                field_name = (\n                    field_obj.data_key if field_obj.data_key is not None else attr_name\n                )\n                raw_value = data.get(field_name, missing)\n                if raw_value is missing:\n                    # Ignore missing field if we're allowed to.\n                    if partial is True or (\n                        partial_is_collection and attr_name in partial\n                    ):\n                        continue\n                d_kwargs = {}\n                # Allow partial loading of nested schemas.\n                if partial_is_collection:\n                    prefix = field_name + \".\"\n                    len_prefix = len(prefix)\n                    sub_partial = [\n                        f[len_prefix:] for f in partial if f.startswith(prefix)\n                    ]\n                    d_kwargs[\"partial\"] = sub_partial\n                elif partial is not None:\n                    d_kwargs[\"partial\"] = partial\n\n                def getter(\n                    val, field_obj=field_obj, field_name=field_name, d_kwargs=d_kwargs\n                ):\n                    return field_obj.deserialize(\n                        val,\n                        field_name,\n                        data,\n                        **d_kwargs,\n                    )\n\n                value = self._call_and_store(\n                    getter_func=getter,\n                    data=raw_value,\n                    field_name=field_name,\n                    error_store=error_store,\n                    index=index,\n                )\n                if value is not missing:\n                    key = field_obj.attribute or attr_name\n                    set_value(ret_d, key, value)\n            if unknown != EXCLUDE:\n                fields = {\n                    field_obj.data_key if field_obj.data_key is not None else field_name\n                    for field_name, field_obj in self.load_fields.items()\n                }\n                for key in set(data) - fields:\n                    value = data[key]\n                    if unknown == INCLUDE:\n                        ret_d[key] = value\n                    elif unknown == RAISE:\n                        error_store.store_error(\n                            [self.error_messages[\"unknown\"]],\n                            key,\n                            (index if index_errors else None),\n                        )\n        return ret_d\n\n    def load(\n        self,\n        data: Mapping[str, typing.Any] | Sequence[Mapping[str, typing.Any]],\n        *,\n        many: bool | None = None,\n        partial: bool | types.StrSequenceOrSet | None = None,\n        unknown: types.UnknownOption | None = None,\n    ):\n        \"\"\"Deserialize a data structure to an object defined by this Schema's fields.\n\n        :param data: The data to deserialize.\n        :param many: Whether to deserialize `data` as a collection. If `None`, the\n            value for `self.many` is used.\n        :param partial: Whether to ignore missing fields and not require\n            any fields declared. Propagates down to ``Nested`` fields as well. If\n            its value is an iterable, only missing fields listed in that iterable\n            will be ignored. Use dot delimiters to specify nested fields.\n        :param unknown: Whether to exclude, include, or raise an error for unknown\n            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n            If `None`, the value for `self.unknown` is used.\n        :return: Deserialized data\n\n        .. versionchanged:: 3.0.0b7\n            This method returns the deserialized data rather than a ``(data, errors)`` tuple.\n            A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised\n            if invalid data are passed.\n        \"\"\"\n        return self._do_load(\n            data, many=many, partial=partial, unknown=unknown, postprocess=True\n        )\n\n    def loads(\n        self,\n        s: str | bytes | bytearray,\n        /,\n        *,\n        many: bool | None = None,\n        partial: bool | types.StrSequenceOrSet | None = None,\n        unknown: types.UnknownOption | None = None,\n        **kwargs,\n    ):\n        \"\"\"Same as :meth:`load`, except it uses `marshmallow.Schema.Meta.render_module` to deserialize\n        the passed string before passing data to :meth:`load`.\n\n        :param s: A string of the data to deserialize.\n        :param many: Whether to deserialize `obj` as a collection. If `None`, the\n            value for `self.many` is used.\n        :param partial: Whether to ignore missing fields and not require\n            any fields declared. Propagates down to ``Nested`` fields as well. If\n            its value is an iterable, only missing fields listed in that iterable\n            will be ignored. Use dot delimiters to specify nested fields.\n        :param unknown: Whether to exclude, include, or raise an error for unknown\n            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n            If `None`, the value for `self.unknown` is used.\n        :return: Deserialized data\n\n        .. versionchanged:: 3.0.0b7\n            This method returns the deserialized data rather than a ``(data, errors)`` tuple.\n            A :exc:`ValidationError <marshmallow.exceptions.ValidationError>` is raised\n            if invalid data are passed.\n        .. versionchanged:: 4.0.0\n            Rename ``json_module`` parameter to ``s``.\n        \"\"\"\n        data = self.opts.render_module.loads(s, **kwargs)\n        return self.load(data, many=many, partial=partial, unknown=unknown)\n\n    def _run_validator(\n        self,\n        validator_func: types.SchemaValidator,\n        output,\n        *,\n        original_data,\n        error_store: ErrorStore,\n        many: bool,\n        partial: bool | types.StrSequenceOrSet | None,\n        unknown: types.UnknownOption | None,\n        pass_original: bool,\n        index: int | None = None,\n    ):\n        try:\n            if pass_original:  # Pass original, raw data (before unmarshalling)\n                validator_func(\n                    output, original_data, partial=partial, many=many, unknown=unknown\n                )\n            else:\n                validator_func(output, partial=partial, many=many, unknown=unknown)\n        except ValidationError as err:\n            field_name = err.field_name\n            data_key: str\n            if field_name == SCHEMA:\n                data_key = SCHEMA\n            else:\n                field_obj: Field | None = None\n                try:\n                    field_obj = self.fields[field_name]\n                except KeyError:\n                    if field_name in self.declared_fields:\n                        field_obj = self.declared_fields[field_name]\n                if field_obj:\n                    data_key = (\n                        field_obj.data_key\n                        if field_obj.data_key is not None\n                        else field_name\n                    )\n                else:\n                    data_key = field_name\n            error_store.store_error(err.messages, data_key, index=index)\n\n    def validate(\n        self,\n        data: Mapping[str, typing.Any] | Sequence[Mapping[str, typing.Any]],\n        *,\n        many: bool | None = None,\n        partial: bool | types.StrSequenceOrSet | None = None,\n    ) -> dict[str, list[str]]:\n        \"\"\"Validate `data` against the schema, returning a dictionary of\n        validation errors.\n\n        :param data: The data to validate.\n        :param many: Whether to validate `data` as a collection. If `None`, the\n            value for `self.many` is used.\n        :param partial: Whether to ignore missing fields and not require\n            any fields declared. Propagates down to ``Nested`` fields as well. If\n            its value is an iterable, only missing fields listed in that iterable\n            will be ignored. Use dot delimiters to specify nested fields.\n        :return: A dictionary of validation errors.\n        \"\"\"\n        try:\n            self._do_load(data, many=many, partial=partial, postprocess=False)\n        except ValidationError as exc:\n            return typing.cast(\"dict[str, list[str]]\", exc.messages)\n        return {}\n\n    ##### Private Helpers #####\n\n    def _do_load(\n        self,\n        data: (Mapping[str, typing.Any] | Sequence[Mapping[str, typing.Any]]),\n        *,\n        many: bool | None = None,\n        partial: bool | types.StrSequenceOrSet | None = None,\n        unknown: types.UnknownOption | None = None,\n        postprocess: bool = True,\n    ):\n        \"\"\"Deserialize `data`, returning the deserialized result.\n        This method is private API.\n\n        :param data: The data to deserialize.\n        :param many: Whether to deserialize `data` as a collection. If `None`, the\n            value for `self.many` is used.\n        :param partial: Whether to validate required fields. If its\n            value is an iterable, only fields listed in that iterable will be\n            ignored will be allowed missing. If `True`, all fields will be allowed missing.\n            If `None`, the value for `self.partial` is used.\n        :param unknown: Whether to exclude, include, or raise an error for unknown\n            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.\n            If `None`, the value for `self.unknown` is used.\n        :param postprocess: Whether to run post_load methods..\n        :return: Deserialized data\n        \"\"\"\n        error_store = ErrorStore()\n        errors: dict[str, list[str]] = {}\n        many = self.many if many is None else bool(many)\n        unknown = self.unknown if unknown is None else unknown\n        if partial is None:\n            partial = self.partial\n        # Run preprocessors\n        if self._hooks[PRE_LOAD]:\n            try:\n                processed_data = self._invoke_load_processors(\n                    PRE_LOAD,\n                    data,\n                    many=many,\n                    original_data=data,\n                    partial=partial,\n                    unknown=unknown,\n                )\n            except ValidationError as err:\n                errors = err.normalized_messages()\n                result: list | dict | None = None\n        else:\n            processed_data = data\n        if not errors:\n            # Deserialize data\n            result = self._deserialize(\n                processed_data,\n                error_store=error_store,\n                many=many,\n                partial=partial,\n                unknown=unknown,\n            )\n            # Run field-level validation\n            self._invoke_field_validators(\n                error_store=error_store, data=result, many=many\n            )\n            # Run schema-level validation\n            if self._hooks[VALIDATES_SCHEMA]:\n                field_errors = bool(error_store.errors)\n                self._invoke_schema_validators(\n                    error_store=error_store,\n                    pass_collection=True,\n                    data=result,\n                    original_data=data,\n                    many=many,\n                    partial=partial,\n                    unknown=unknown,\n                    field_errors=field_errors,\n                )\n                self._invoke_schema_validators(\n                    error_store=error_store,\n                    pass_collection=False,\n                    data=result,\n                    original_data=data,\n                    many=many,\n                    partial=partial,\n                    unknown=unknown,\n                    field_errors=field_errors,\n                )\n            errors = error_store.errors\n            # Run post processors\n            if not errors and postprocess and self._hooks[POST_LOAD]:\n                try:\n                    result = self._invoke_load_processors(\n                        POST_LOAD,\n                        result,\n                        many=many,\n                        original_data=data,\n                        partial=partial,\n                        unknown=unknown,\n                    )\n                except ValidationError as err:\n                    errors = err.normalized_messages()\n        if errors:\n            exc = ValidationError(errors, data=data, valid_data=result)\n            self.handle_error(exc, data, many=many, partial=partial)\n            raise exc\n\n        return result\n\n    def _normalize_nested_options(self) -> None:\n        \"\"\"Apply then flatten nested schema options.\n        This method is private API.\n        \"\"\"\n        if self.only is not None:\n            # Apply the only option to nested fields.\n            self.__apply_nested_option(\"only\", self.only, \"intersection\")\n            # Remove the child field names from the only option.\n            self.only = self.set_class([field.split(\".\", 1)[0] for field in self.only])\n        if self.exclude:\n            # Apply the exclude option to nested fields.\n            self.__apply_nested_option(\"exclude\", self.exclude, \"union\")\n            # Remove the parent field names from the exclude option.\n            self.exclude = self.set_class(\n                [field for field in self.exclude if \".\" not in field]\n            )\n\n    def __apply_nested_option(self, option_name, field_names, set_operation) -> None:\n        \"\"\"Apply nested options to nested fields\"\"\"\n        # Split nested field names on the first dot.\n        nested_fields = [name.split(\".\", 1) for name in field_names if \".\" in name]\n        # Partition the nested field names by parent field.\n        nested_options = defaultdict(list)  # type: defaultdict\n        for parent, nested_names in nested_fields:\n            nested_options[parent].append(nested_names)\n        # Apply the nested field options.\n        for key, options in iter(nested_options.items()):\n            new_options = self.set_class(options)\n            original_options = getattr(self.declared_fields[key], option_name, ())\n            if original_options:\n                if set_operation == \"union\":\n                    new_options |= self.set_class(original_options)\n                if set_operation == \"intersection\":\n                    new_options &= self.set_class(original_options)\n            setattr(self.declared_fields[key], option_name, new_options)\n\n    def _init_fields(self) -> None:\n        \"\"\"Update self.fields, self.load_fields, and self.dump_fields based on schema options.\n        This method is private API.\n        \"\"\"\n        if self.opts.fields:\n            available_field_names = self.set_class(self.opts.fields)\n        else:\n            available_field_names = self.set_class(self.declared_fields.keys())\n\n        invalid_fields = self.set_class()\n\n        if self.only is not None:\n            # Return only fields specified in only option\n            field_names: typing.AbstractSet[typing.Any] = self.set_class(self.only)\n\n            invalid_fields |= field_names - available_field_names\n        else:\n            field_names = available_field_names\n\n        # If \"exclude\" option or param is specified, remove those fields.\n        if self.exclude:\n            # Note that this isn't available_field_names, since we want to\n            # apply \"only\" for the actual calculation.\n            field_names = field_names - self.exclude\n            invalid_fields |= self.exclude - available_field_names\n\n        if invalid_fields:\n            message = f\"Invalid fields for {self}: {invalid_fields}.\"\n            raise ValueError(message)\n\n        fields_dict = self.dict_class()\n        for field_name in field_names:\n            field_obj = self.declared_fields[field_name]\n            self._bind_field(field_name, field_obj)\n            fields_dict[field_name] = field_obj\n\n        load_fields, dump_fields = self.dict_class(), self.dict_class()\n        for field_name, field_obj in fields_dict.items():\n            if not field_obj.dump_only:\n                load_fields[field_name] = field_obj\n            if not field_obj.load_only:\n                dump_fields[field_name] = field_obj\n\n        dump_data_keys = [\n            field_obj.data_key if field_obj.data_key is not None else name\n            for name, field_obj in dump_fields.items()\n        ]\n        if len(dump_data_keys) != len(set(dump_data_keys)):\n            data_keys_duplicates = {\n                x for x in dump_data_keys if dump_data_keys.count(x) > 1\n            }\n            raise ValueError(\n                \"The data_key argument for one or more fields collides \"\n                \"with another field's name or data_key argument. \"\n                \"Check the following field names and \"\n                f\"data_key arguments: {list(data_keys_duplicates)}\"\n            )\n        load_attributes = [obj.attribute or name for name, obj in load_fields.items()]\n        if len(load_attributes) != len(set(load_attributes)):\n            attributes_duplicates = {\n                x for x in load_attributes if load_attributes.count(x) > 1\n            }\n            raise ValueError(\n                \"The attribute argument for one or more fields collides \"\n                \"with another field's name or attribute argument. \"\n                \"Check the following field names and \"\n                f\"attribute arguments: {list(attributes_duplicates)}\"\n            )\n\n        self.fields = fields_dict\n        self.dump_fields = dump_fields\n        self.load_fields = load_fields\n\n    def on_bind_field(self, field_name: str, field_obj: Field) -> None:\n        \"\"\"Hook to modify a field when it is bound to the `Schema <marshmallow.Schema>`.\n\n        No-op by default.\n        \"\"\"\n        return\n\n    def _bind_field(self, field_name: str, field_obj: Field) -> None:\n        \"\"\"Bind field to the schema, setting any necessary attributes on the\n        field (e.g. parent and name).\n\n        Also set field load_only and dump_only values if field_name was\n        specified in `class Meta <marshmallow.Schema.Meta>`.\n        \"\"\"\n        if field_name in self.load_only:\n            field_obj.load_only = True\n        if field_name in self.dump_only:\n            field_obj.dump_only = True\n        field_obj._bind_to_schema(field_name, self)\n        self.on_bind_field(field_name, field_obj)\n\n    def _invoke_dump_processors(\n        self, tag: str, data, *, many: bool, original_data=None\n    ):\n        # The pass_collection post-dump processors may do things like add an envelope, so\n        # invoke those after invoking the non-pass_collection processors which will expect\n        # to get a list of items.\n        data = self._invoke_processors(\n            tag,\n            pass_collection=False,\n            data=data,\n            many=many,\n            original_data=original_data,\n        )\n        return self._invoke_processors(\n            tag, pass_collection=True, data=data, many=many, original_data=original_data\n        )\n\n    def _invoke_load_processors(\n        self,\n        tag: str,\n        data: Mapping[str, typing.Any] | Sequence[Mapping[str, typing.Any]],\n        *,\n        many: bool,\n        original_data,\n        partial: bool | types.StrSequenceOrSet | None,\n        unknown: types.UnknownOption | None,\n    ):\n        # This has to invert the order of the dump processors, so run the pass_collection\n        # processors first.\n        data = self._invoke_processors(\n            tag,\n            pass_collection=True,\n            data=data,\n            many=many,\n            original_data=original_data,\n            partial=partial,\n            unknown=unknown,\n        )\n        return self._invoke_processors(\n            tag,\n            pass_collection=False,\n            data=data,\n            many=many,\n            original_data=original_data,\n            partial=partial,\n            unknown=unknown,\n        )\n\n    def _invoke_field_validators(self, *, error_store: ErrorStore, data, many: bool):\n        for attr_name, _, validator_kwargs in self._hooks[VALIDATES]:\n            validator = getattr(self, attr_name)\n\n            field_names = validator_kwargs[\"field_names\"]\n\n            for field_name in field_names:\n                try:\n                    field_obj = self.fields[field_name]\n                except KeyError as error:\n                    if field_name in self.declared_fields:\n                        continue\n                    raise ValueError(f'\"{field_name}\" field does not exist.') from error\n\n                data_key = (\n                    field_obj.data_key if field_obj.data_key is not None else field_name\n                )\n                do_validate = functools.partial(validator, data_key=data_key)\n\n                if many:\n                    for idx, item in enumerate(data):\n                        try:\n                            value = item[field_obj.attribute or field_name]\n                        except KeyError:\n                            pass\n                        else:\n                            validated_value = self._call_and_store(\n                                getter_func=do_validate,\n                                data=value,\n                                field_name=data_key,\n                                error_store=error_store,\n                                index=(idx if self.opts.index_errors else None),\n                            )\n                            if validated_value is missing:\n                                item.pop(field_name, None)\n                else:\n                    try:\n                        value = data[field_obj.attribute or field_name]\n                    except KeyError:\n                        pass\n                    else:\n                        validated_value = self._call_and_store(\n                            getter_func=do_validate,\n                            data=value,\n                            field_name=data_key,\n                            error_store=error_store,\n                        )\n                        if validated_value is missing:\n                            data.pop(field_name, None)\n\n    def _invoke_schema_validators(\n        self,\n        *,\n        error_store: ErrorStore,\n        pass_collection: bool,\n        data,\n        original_data,\n        many: bool,\n        partial: bool | types.StrSequenceOrSet | None,\n        field_errors: bool = False,\n        unknown: types.UnknownOption | None,\n    ):\n        for attr_name, hook_many, validator_kwargs in self._hooks[VALIDATES_SCHEMA]:\n            if hook_many != pass_collection:\n                continue\n            validator = getattr(self, attr_name)\n            if field_errors and validator_kwargs[\"skip_on_field_errors\"]:\n                continue\n            pass_original = validator_kwargs.get(\"pass_original\", False)\n\n            if many and not pass_collection:\n                for idx, (item, orig) in enumerate(\n                    zip(data, original_data, strict=True)\n                ):\n                    self._run_validator(\n                        validator,\n                        item,\n                        original_data=orig,\n                        error_store=error_store,\n                        many=many,\n                        partial=partial,\n                        unknown=unknown,\n                        index=idx,\n                        pass_original=pass_original,\n                    )\n            else:\n                self._run_validator(\n                    validator,\n                    data,\n                    original_data=original_data,\n                    error_store=error_store,\n                    many=many,\n                    pass_original=pass_original,\n                    partial=partial,\n                    unknown=unknown,\n                )\n\n    def _invoke_processors(\n        self,\n        tag: str,\n        *,\n        pass_collection: bool,\n        data: Mapping[str, typing.Any] | Sequence[Mapping[str, typing.Any]],\n        many: bool,\n        original_data=None,\n        **kwargs,\n    ):\n        for attr_name, hook_many, processor_kwargs in self._hooks[tag]:\n            if hook_many != pass_collection:\n                continue\n            # This will be a bound method.\n            processor = getattr(self, attr_name)\n            pass_original = processor_kwargs.get(\"pass_original\", False)\n\n            if many and not pass_collection:\n                if pass_original:\n                    data = [\n                        processor(item, original, many=many, **kwargs)\n                        for item, original in zip_longest(data, original_data)\n                    ]\n                else:\n                    data = [processor(item, many=many, **kwargs) for item in data]\n            elif pass_original:\n                data = processor(data, original_data, many=many, **kwargs)\n            else:\n                data = processor(data, many=many, **kwargs)\n        return data\n\n\nBaseSchema = Schema  # for backwards compatibility\n"
  },
  {
    "path": "src/marshmallow/types.py",
    "content": "\"\"\"Type aliases.\n\n.. warning::\n\n    This module is provisional. Types may be modified, added, and removed between minor releases.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport typing\n\n#: A type that can be either a sequence of strings or a set of strings\nStrSequenceOrSet: typing.TypeAlias = typing.Sequence[str] | typing.AbstractSet[str]\n\n#: Type for validator functions\nValidator: typing.TypeAlias = typing.Callable[[typing.Any], typing.Any]\n\n#: A valid option for the ``unknown`` schema option and argument\nUnknownOption: typing.TypeAlias = typing.Literal[\"exclude\", \"include\", \"raise\"]\n\n\nclass SchemaValidator(typing.Protocol):\n    def __call__(\n        self,\n        output: typing.Any,\n        original_data: typing.Any = ...,\n        *,\n        partial: bool | StrSequenceOrSet | None = None,\n        unknown: UnknownOption | None = None,\n        many: bool = False,\n    ) -> None: ...\n\n\nclass RenderModule(typing.Protocol):\n    def dumps(\n        self, obj: typing.Any, *args: typing.Any, **kwargs: typing.Any\n    ) -> str: ...\n\n    def loads(\n        self, s: str | bytes | bytearray, *args: typing.Any, **kwargs: typing.Any\n    ) -> typing.Any: ...\n"
  },
  {
    "path": "src/marshmallow/utils.py",
    "content": "\"\"\"Utility methods for marshmallow.\"\"\"\n\nfrom __future__ import annotations\n\nimport datetime as dt\nimport inspect\nimport typing\nfrom collections.abc import Mapping, Sequence\n\nfrom marshmallow.constants import missing\n\n\ndef is_generator(obj) -> typing.TypeGuard[typing.Generator]:\n    \"\"\"Return True if ``obj`` is a generator\"\"\"\n    return inspect.isgeneratorfunction(obj) or inspect.isgenerator(obj)\n\n\ndef is_iterable_but_not_string(obj) -> typing.TypeGuard[typing.Iterable]:\n    \"\"\"Return True if ``obj`` is an iterable object that isn't a string.\"\"\"\n    return (hasattr(obj, \"__iter__\") and not hasattr(obj, \"strip\")) or is_generator(obj)\n\n\ndef is_sequence_but_not_string(obj) -> typing.TypeGuard[Sequence]:\n    \"\"\"Return True if ``obj`` is a sequence that isn't a string.\"\"\"\n    return isinstance(obj, Sequence) and not isinstance(obj, (str, bytes))\n\n\ndef is_collection(obj) -> typing.TypeGuard[typing.Iterable]:\n    \"\"\"Return True if ``obj`` is a collection type, e.g list, tuple, queryset.\"\"\"\n    return is_iterable_but_not_string(obj) and not isinstance(obj, Mapping)\n\n\n# https://stackoverflow.com/a/27596917\ndef is_aware(datetime: dt.datetime) -> bool:\n    return (\n        datetime.tzinfo is not None and datetime.tzinfo.utcoffset(datetime) is not None\n    )\n\n\ndef from_timestamp(value: typing.Any) -> dt.datetime:\n    if value is True or value is False:\n        raise ValueError(\"Not a valid POSIX timestamp\")\n    value = float(value)\n    if value < 0:\n        raise ValueError(\"Not a valid POSIX timestamp\")\n\n    # Load a timestamp with utc as timezone to prevent using system timezone.\n    # Then set timezone to None, to let the Field handle adding timezone info.\n    try:\n        return dt.datetime.fromtimestamp(value, tz=dt.timezone.utc).replace(tzinfo=None)\n    except OverflowError as exc:\n        raise ValueError(\"Timestamp is too large\") from exc\n    except OSError as exc:\n        raise ValueError(\"Error converting value to datetime\") from exc\n\n\ndef from_timestamp_ms(value: typing.Any) -> dt.datetime:\n    value = float(value)\n    return from_timestamp(value / 1000)\n\n\ndef timestamp(\n    value: dt.datetime,\n) -> float:\n    if not is_aware(value):\n        # When a date is naive, use UTC as zone info to prevent using system timezone.\n        value = value.replace(tzinfo=dt.timezone.utc)\n    return value.timestamp()\n\n\ndef timestamp_ms(value: dt.datetime) -> float:\n    return timestamp(value) * 1000\n\n\ndef ensure_text_type(val: str | bytes) -> str:\n    if isinstance(val, bytes):\n        val = val.decode(\"utf-8\")\n    return str(val)\n\n\ndef pluck(dictlist: list[dict[str, typing.Any]], key: str):\n    \"\"\"Extracts a list of dictionary values from a list of dictionaries.\n    ::\n\n        >>> dlist = [{'id': 1, 'name': 'foo'}, {'id': 2, 'name': 'bar'}]\n        >>> pluck(dlist, 'id')\n        [1, 2]\n    \"\"\"\n    return [d[key] for d in dictlist]\n\n\n# Various utilities for pulling keyed values from objects\n\n\ndef get_value(obj, key: int | str, default=missing):\n    \"\"\"Helper for pulling a keyed value off various types of objects. Fields use\n    this method by default to access attributes of the source object. For object `x`\n    and attribute `i`, this method first tries to access `x[i]`, and then falls back to\n    `x.i` if an exception is raised.\n\n    .. warning::\n        If an object `x` does not raise an exception when `x[i]` does not exist,\n        `get_value` will never check the value `x.i`. Consider overriding\n        `marshmallow.fields.Field.get_value` in this case.\n    \"\"\"\n    if not isinstance(key, int) and \".\" in key:\n        return _get_value_for_keys(obj, key.split(\".\"), default)\n    return _get_value_for_key(obj, key, default)\n\n\ndef _get_value_for_keys(obj, keys, default):\n    if len(keys) == 1:\n        return _get_value_for_key(obj, keys[0], default)\n    return _get_value_for_keys(\n        _get_value_for_key(obj, keys[0], default), keys[1:], default\n    )\n\n\ndef _get_value_for_key(obj, key, default):\n    if not hasattr(obj, \"__getitem__\"):\n        return getattr(obj, key, default)\n\n    try:\n        return obj[key]\n    except (KeyError, IndexError, TypeError, AttributeError):\n        return getattr(obj, key, default)\n\n\ndef set_value(dct: dict[str, typing.Any], key: str, value: typing.Any):\n    \"\"\"Set a value in a dict. If `key` contains a '.', it is assumed\n    be a path (i.e. dot-delimited string) to the value's location.\n\n    ::\n\n        >>> d = {}\n        >>> set_value(d, 'foo.bar', 42)\n        >>> d\n        {'foo': {'bar': 42}}\n    \"\"\"\n    if \".\" in key:\n        head, rest = key.split(\".\", 1)\n        target = dct.setdefault(head, {})\n        if not isinstance(target, dict):\n            raise ValueError(\n                f\"Cannot set {key} in {head} due to existing value: {target}\"\n            )\n        set_value(target, rest, value)\n    else:\n        dct[key] = value\n\n\ndef callable_or_raise(obj):\n    \"\"\"Check that an object is callable, else raise a :exc:`TypeError`.\"\"\"\n    if not callable(obj):\n        raise TypeError(f\"Object {obj!r} is not callable.\")\n    return obj\n\n\ndef timedelta_to_microseconds(value: dt.timedelta) -> int:\n    \"\"\"Compute the total microseconds of a timedelta.\n\n    https://github.com/python/cpython/blob/v3.13.1/Lib/_pydatetime.py#L805-L807\n    \"\"\"\n    return (value.days * (24 * 3600) + value.seconds) * 1000000 + value.microseconds\n"
  },
  {
    "path": "src/marshmallow/validate.py",
    "content": "\"\"\"Validation classes for various types of data.\"\"\"\n\nfrom __future__ import annotations\n\nimport re\nimport typing\nfrom abc import ABC, abstractmethod\nfrom itertools import zip_longest\nfrom operator import attrgetter\n\nfrom marshmallow.exceptions import ValidationError\n\nif typing.TYPE_CHECKING:\n    from marshmallow import types\n\n_T = typing.TypeVar(\"_T\")\n\n\nclass Validator(ABC):\n    \"\"\"Abstract base class for validators.\n\n    .. note::\n        This class does not provide any validation behavior. It is only used to\n        add a useful `__repr__` implementation for validators.\n    \"\"\"\n\n    error: str | None = None\n\n    def __repr__(self) -> str:\n        args = self._repr_args()\n        args = f\"{args}, \" if args else \"\"\n\n        return f\"<{self.__class__.__name__}({args}error={self.error!r})>\"\n\n    def _repr_args(self) -> str:\n        \"\"\"A string representation of the args passed to this validator. Used by\n        `__repr__`.\n        \"\"\"\n        return \"\"\n\n    @abstractmethod\n    def __call__(self, value: typing.Any) -> typing.Any: ...\n\n\nclass And(Validator):\n    \"\"\"Compose multiple validators and combine their error messages.\n\n    Example: ::\n\n        from marshmallow import validate, ValidationError\n\n\n        def is_even(value):\n            if value % 2 != 0:\n                raise ValidationError(\"Not an even value.\")\n\n\n        validator = validate.And(validate.Range(min=0), is_even)\n        validator(-1)\n        # ValidationError: ['Must be greater than or equal to 0.', 'Not an even value.']\n\n    :param validators: Validators to combine.\n    \"\"\"\n\n    def __init__(self, *validators: types.Validator):\n        self.validators = tuple(validators)\n\n    def _repr_args(self) -> str:\n        return f\"validators={self.validators!r}\"\n\n    def __call__(self, value: typing.Any) -> typing.Any:\n        errors: list[str | dict] = []\n        kwargs: dict[str, typing.Any] = {}\n        for validator in self.validators:\n            try:\n                validator(value)\n            except ValidationError as err:\n                kwargs.update(err.kwargs)\n                if isinstance(err.messages, dict):\n                    errors.append(err.messages)\n                else:\n                    errors.extend(err.messages)\n        if errors:\n            raise ValidationError(errors, **kwargs)\n        return value\n\n\nclass URL(Validator):\n    \"\"\"Validate a URL.\n\n    :param relative: Whether to allow relative URLs.\n    :param absolute: Whether to allow absolute URLs.\n    :param error: Error message to raise in case of a validation error.\n        Can be interpolated with `{input}`.\n    :param schemes: Valid schemes. By default, ``http``, ``https``,\n        ``ftp``, and ``ftps`` are allowed.\n    :param require_tld: Whether to reject non-FQDN hostnames.\n    \"\"\"\n\n    class RegexMemoizer:\n        def __init__(self):\n            self._memoized = {}\n\n        def _regex_generator(\n            self, *, relative: bool, absolute: bool, require_tld: bool\n        ) -> typing.Pattern:\n            hostname_variants = [\n                # a normal domain name, expressed in [A-Z0-9] chars with hyphens allowed only in the middle\n                # note that the regex will be compiled with IGNORECASE, so these are upper and lowercase chars\n                (\n                    r\"(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+\"\n                    r\"(?:[A-Z]{2,6}\\.?|[A-Z0-9-]{2,}\\.?)\"\n                ),\n                # or the special string 'localhost'\n                r\"localhost\",\n                # or IPv4\n                r\"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\",\n                # or IPv6\n                r\"\\[[A-F0-9]*:[A-F0-9:]+\\]\",\n            ]\n            if not require_tld:\n                # allow dotless hostnames\n                hostname_variants.append(r\"(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.?)\")\n\n            absolute_part = \"\".join(\n                (\n                    # scheme (e.g. 'https://', 'ftp://', etc)\n                    # this is validated separately against allowed schemes, so in the regex\n                    # we simply want to capture its existence\n                    r\"(?:[a-z0-9\\.\\-\\+]*)://\",\n                    # userinfo, for URLs encoding authentication\n                    # e.g. 'ftp://foo:bar@ftp.example.org/'\n                    r\"(?:(?:[a-z0-9\\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?\",\n                    # netloc, the hostname/domain part of the URL plus the optional port\n                    r\"(?:\",\n                    \"|\".join(hostname_variants),\n                    r\")\",\n                    r\"(?::\\d+)?\",\n                )\n            )\n            relative_part = r\"(?:/?|[/?]\\S+)\\Z\"\n\n            if relative:\n                if absolute:\n                    parts: tuple[str, ...] = (\n                        r\"^(\",\n                        absolute_part,\n                        r\")?\",\n                        relative_part,\n                    )\n                else:\n                    parts = (r\"^\", relative_part)\n            else:\n                parts = (r\"^\", absolute_part, relative_part)\n\n            return re.compile(\"\".join(parts), re.IGNORECASE)\n\n        def __call__(\n            self, *, relative: bool, absolute: bool, require_tld: bool\n        ) -> typing.Pattern:\n            key = (relative, absolute, require_tld)\n            if key not in self._memoized:\n                self._memoized[key] = self._regex_generator(\n                    relative=relative, absolute=absolute, require_tld=require_tld\n                )\n\n            return self._memoized[key]\n\n    _regex = RegexMemoizer()\n\n    default_message = \"Not a valid URL.\"\n    default_schemes = {\"http\", \"https\", \"ftp\", \"ftps\"}\n\n    def __init__(\n        self,\n        *,\n        relative: bool = False,\n        absolute: bool = True,\n        schemes: types.StrSequenceOrSet | None = None,\n        require_tld: bool = True,\n        error: str | None = None,\n    ):\n        if not relative and not absolute:\n            raise ValueError(\n                \"URL validation cannot set both relative and absolute to False.\"\n            )\n        self.relative = relative\n        self.absolute = absolute\n        self.error: str = error or self.default_message\n        self.schemes = {s.lower() for s in schemes} if schemes else self.default_schemes\n        self.require_tld = require_tld\n\n    def _repr_args(self) -> str:\n        return f\"relative={self.relative!r}, absolute={self.absolute!r}\"\n\n    def _format_error(self, value) -> str:\n        return self.error.format(input=value)\n\n    def __call__(self, value: str) -> str:\n        message = self._format_error(value)\n        if not value:\n            raise ValidationError(message)\n\n        # Check first if the scheme is valid\n        scheme = None\n        if \"://\" in value:\n            scheme = value.split(\"://\", maxsplit=1)[0].lower()\n            if scheme not in self.schemes:\n                raise ValidationError(message)\n\n        regex = self._regex(\n            relative=self.relative, absolute=self.absolute, require_tld=self.require_tld\n        )\n\n        # Hostname is optional for file URLS. If absent it means `localhost`.\n        # Fill it in for the validation if needed\n        if scheme == \"file\" and value.lower().startswith(\"file:///\"):\n            matched = regex.search(\"file://localhost/\" + value[8:])\n        else:\n            matched = regex.search(value)\n\n        if not matched:\n            raise ValidationError(message)\n\n        return value\n\n\nclass Email(Validator):\n    \"\"\"Validate an email address.\n\n    :param error: Error message to raise in case of a validation error. Can be\n        interpolated with `{input}`.\n    \"\"\"\n\n    USER_REGEX = re.compile(\n        r\"(^[-!#$%&'*+/=?^`{}|~\\w]+(\\.[-!#$%&'*+/=?^`{}|~\\w]+)*\\Z\"  # dot-atom\n        # quoted-string\n        r'|^\"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]'\n        r'|\\\\[\\001-\\011\\013\\014\\016-\\177])*\"\\Z)',\n        re.IGNORECASE | re.UNICODE,\n    )\n\n    DOMAIN_REGEX = re.compile(\n        # domain\n        r\"(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+\"\n        r\"(?:[A-Z]{2,6}|[A-Z0-9-]{2,})\\Z\"\n        # literal form, ipv4 address (SMTP 4.1.3)\n        r\"|^\\[(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)\"\n        r\"(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\]\\Z\",\n        re.IGNORECASE | re.UNICODE,\n    )\n\n    DOMAIN_WHITELIST = (\"localhost\",)\n\n    default_message = \"Not a valid email address.\"\n\n    def __init__(self, *, error: str | None = None):\n        self.error: str = error or self.default_message\n\n    def _format_error(self, value: str) -> str:\n        return self.error.format(input=value)\n\n    def __call__(self, value: str) -> str:\n        message = self._format_error(value)\n\n        if not value or \"@\" not in value:\n            raise ValidationError(message)\n\n        user_part, domain_part = value.rsplit(\"@\", 1)\n\n        if not self.USER_REGEX.match(user_part):\n            raise ValidationError(message)\n\n        if domain_part not in self.DOMAIN_WHITELIST:\n            if not self.DOMAIN_REGEX.match(domain_part):\n                try:\n                    domain_part = domain_part.encode(\"idna\").decode(\"ascii\")\n                except UnicodeError:\n                    pass\n                else:\n                    if self.DOMAIN_REGEX.match(domain_part):\n                        return value\n                raise ValidationError(message)\n\n        return value\n\n\nclass Range(Validator):\n    \"\"\"Validator which succeeds if the value passed to it is within the specified\n    range. If ``min`` is not specified, or is specified as `None`,\n    no lower bound exists. If ``max`` is not specified, or is specified as `None`,\n    no upper bound exists. The inclusivity of the bounds (if they exist) is configurable.\n    If ``min_inclusive`` is not specified, or is specified as `True`, then\n    the ``min`` bound is included in the range. If ``max_inclusive`` is not specified,\n    or is specified as `True`, then the ``max`` bound is included in the range.\n\n    :param min: The minimum value (lower bound). If not provided, minimum\n        value will not be checked.\n    :param max: The maximum value (upper bound). If not provided, maximum\n        value will not be checked.\n    :param min_inclusive: Whether the `min` bound is included in the range.\n    :param max_inclusive: Whether the `max` bound is included in the range.\n    :param error: Error message to raise in case of a validation error.\n        Can be interpolated with `{input}`, `{min}` and `{max}`.\n    \"\"\"\n\n    message_min = \"Must be {min_op} {{min}}.\"\n    message_max = \"Must be {max_op} {{max}}.\"\n    message_all = \"Must be {min_op} {{min}} and {max_op} {{max}}.\"\n\n    message_gte = \"greater than or equal to\"\n    message_gt = \"greater than\"\n    message_lte = \"less than or equal to\"\n    message_lt = \"less than\"\n\n    def __init__(\n        self,\n        min=None,  # noqa: A002\n        max=None,  # noqa: A002\n        *,\n        min_inclusive: bool = True,\n        max_inclusive: bool = True,\n        error: str | None = None,\n    ):\n        self.min = min\n        self.max = max\n        self.error = error\n        self.min_inclusive = min_inclusive\n        self.max_inclusive = max_inclusive\n\n        # interpolate messages based on bound inclusivity\n        self.message_min = self.message_min.format(\n            min_op=self.message_gte if self.min_inclusive else self.message_gt\n        )\n        self.message_max = self.message_max.format(\n            max_op=self.message_lte if self.max_inclusive else self.message_lt\n        )\n        self.message_all = self.message_all.format(\n            min_op=self.message_gte if self.min_inclusive else self.message_gt,\n            max_op=self.message_lte if self.max_inclusive else self.message_lt,\n        )\n\n    def _repr_args(self) -> str:\n        return f\"min={self.min!r}, max={self.max!r}, min_inclusive={self.min_inclusive!r}, max_inclusive={self.max_inclusive!r}\"\n\n    def _format_error(self, value: _T, message: str) -> str:\n        return (self.error or message).format(input=value, min=self.min, max=self.max)\n\n    def __call__(self, value: _T) -> _T:\n        if self.min is not None and (\n            value < self.min if self.min_inclusive else value <= self.min\n        ):\n            message = self.message_min if self.max is None else self.message_all\n            raise ValidationError(self._format_error(value, message))\n\n        if self.max is not None and (\n            value > self.max if self.max_inclusive else value >= self.max\n        ):\n            message = self.message_max if self.min is None else self.message_all\n            raise ValidationError(self._format_error(value, message))\n\n        return value\n\n\n_SizedT = typing.TypeVar(\"_SizedT\", bound=typing.Sized)\n\n\nclass Length(Validator):\n    \"\"\"Validator which succeeds if the value passed to it has a\n    length between a minimum and maximum. Uses len(), so it\n    can work for strings, lists, or anything with length.\n\n    :param min: The minimum length. If not provided, minimum length\n        will not be checked.\n    :param max: The maximum length. If not provided, maximum length\n        will not be checked.\n    :param equal: The exact length. If provided, maximum and minimum\n        length will not be checked.\n    :param error: Error message to raise in case of a validation error.\n        Can be interpolated with `{input}`, `{min}` and `{max}`.\n    \"\"\"\n\n    message_min = \"Shorter than minimum length {min}.\"\n    message_max = \"Longer than maximum length {max}.\"\n    message_all = \"Length must be between {min} and {max}.\"\n    message_equal = \"Length must be {equal}.\"\n\n    def __init__(\n        self,\n        min: int | None = None,  # noqa: A002\n        max: int | None = None,  # noqa: A002\n        *,\n        equal: int | None = None,\n        error: str | None = None,\n    ):\n        if equal is not None and any([min, max]):\n            raise ValueError(\n                \"The `equal` parameter was provided, maximum or \"\n                \"minimum parameter must not be provided.\"\n            )\n\n        self.min = min\n        self.max = max\n        self.error = error\n        self.equal = equal\n\n    def _repr_args(self) -> str:\n        return f\"min={self.min!r}, max={self.max!r}, equal={self.equal!r}\"\n\n    def _format_error(self, value: _SizedT, message: str) -> str:\n        return (self.error or message).format(\n            input=value, min=self.min, max=self.max, equal=self.equal\n        )\n\n    def __call__(self, value: _SizedT) -> _SizedT:\n        length = len(value)\n\n        if self.equal is not None:\n            if length != self.equal:\n                raise ValidationError(self._format_error(value, self.message_equal))\n            return value\n\n        if self.min is not None and length < self.min:\n            message = self.message_min if self.max is None else self.message_all\n            raise ValidationError(self._format_error(value, message))\n\n        if self.max is not None and length > self.max:\n            message = self.message_max if self.min is None else self.message_all\n            raise ValidationError(self._format_error(value, message))\n\n        return value\n\n\nclass Equal(Validator):\n    \"\"\"Validator which succeeds if the ``value`` passed to it is\n    equal to ``comparable``.\n\n    :param comparable: The object to compare to.\n    :param error: Error message to raise in case of a validation error.\n        Can be interpolated with `{input}` and `{other}`.\n    \"\"\"\n\n    default_message = \"Must be equal to {other}.\"\n\n    def __init__(self, comparable, *, error: str | None = None):\n        self.comparable = comparable\n        self.error: str = error or self.default_message\n\n    def _repr_args(self) -> str:\n        return f\"comparable={self.comparable!r}\"\n\n    def _format_error(self, value: _T) -> str:\n        return self.error.format(input=value, other=self.comparable)\n\n    def __call__(self, value: _T) -> _T:\n        if value != self.comparable:\n            raise ValidationError(self._format_error(value))\n        return value\n\n\nclass Regexp(Validator):\n    \"\"\"Validator which succeeds if the ``value`` matches ``regex``.\n\n    .. note::\n\n        Uses `re.match`, which searches for a match at the beginning of a string.\n\n    :param regex: The regular expression string to use. Can also be a compiled\n        regular expression pattern.\n    :param flags: The regexp flags to use, for example re.IGNORECASE. Ignored\n        if ``regex`` is not a string.\n    :param error: Error message to raise in case of a validation error.\n        Can be interpolated with `{input}` and `{regex}`.\n    \"\"\"\n\n    default_message = \"String does not match expected pattern.\"\n\n    def __init__(\n        self,\n        regex: str | bytes | typing.Pattern,\n        flags: int = 0,\n        *,\n        error: str | None = None,\n    ):\n        self.regex = (\n            re.compile(regex, flags) if isinstance(regex, (str, bytes)) else regex\n        )\n        self.error: str = error or self.default_message\n\n    def _repr_args(self) -> str:\n        return f\"regex={self.regex!r}\"\n\n    def _format_error(self, value: str | bytes) -> str:\n        return self.error.format(input=value, regex=self.regex.pattern)\n\n    @typing.overload\n    def __call__(self, value: str) -> str: ...\n\n    @typing.overload\n    def __call__(self, value: bytes) -> bytes: ...\n\n    def __call__(self, value):\n        if self.regex.match(value) is None:\n            raise ValidationError(self._format_error(value))\n\n        return value\n\n\nclass Predicate(Validator):\n    \"\"\"Call the specified ``method`` of the ``value`` object. The\n    validator succeeds if the invoked method returns an object that\n    evaluates to True in a Boolean context. Any additional keyword\n    argument will be passed to the method.\n\n    :param method: The name of the method to invoke.\n    :param error: Error message to raise in case of a validation error.\n        Can be interpolated with `{input}` and `{method}`.\n    :param kwargs: Additional keyword arguments to pass to the method.\n    \"\"\"\n\n    default_message = \"Invalid input.\"\n\n    def __init__(self, method: str, *, error: str | None = None, **kwargs):\n        self.method = method\n        self.error: str = error or self.default_message\n        self.kwargs = kwargs\n\n    def _repr_args(self) -> str:\n        return f\"method={self.method!r}, kwargs={self.kwargs!r}\"\n\n    def _format_error(self, value: typing.Any) -> str:\n        return self.error.format(input=value, method=self.method)\n\n    def __call__(self, value: _T) -> _T:\n        method = getattr(value, self.method)\n\n        if not method(**self.kwargs):\n            raise ValidationError(self._format_error(value))\n\n        return value\n\n\nclass NoneOf(Validator):\n    \"\"\"Validator which fails if ``value`` is a member of ``iterable``.\n\n    :param iterable: A sequence of invalid values.\n    :param error: Error message to raise in case of a validation error. Can be\n        interpolated using `{input}` and `{values}`.\n    \"\"\"\n\n    default_message = \"Invalid input.\"\n\n    def __init__(self, iterable: typing.Iterable, *, error: str | None = None):\n        self.iterable = iterable\n        self.values_text = \", \".join(str(each) for each in self.iterable)\n        self.error: str = error or self.default_message\n\n    def _repr_args(self) -> str:\n        return f\"iterable={self.iterable!r}\"\n\n    def _format_error(self, value) -> str:\n        return self.error.format(input=value, values=self.values_text)\n\n    def __call__(self, value: typing.Any) -> typing.Any:\n        try:\n            if value in self.iterable:\n                raise ValidationError(self._format_error(value))\n        except TypeError:\n            pass\n\n        return value\n\n\nclass OneOf(Validator):\n    \"\"\"Validator which succeeds if ``value`` is a member of ``choices``.\n\n    :param choices: A sequence of valid values.\n    :param labels: Optional sequence of labels to pair with the choices.\n    :param error: Error message to raise in case of a validation error. Can be\n        interpolated with `{input}`, `{choices}` and `{labels}`.\n    \"\"\"\n\n    default_message = \"Must be one of: {choices}.\"\n\n    def __init__(\n        self,\n        choices: typing.Iterable,\n        labels: typing.Iterable[str] | None = None,\n        *,\n        error: str | None = None,\n    ):\n        self.choices = choices\n        self.choices_text = \", \".join(str(choice) for choice in self.choices)\n        self.labels = labels if labels is not None else []\n        self.labels_text = \", \".join(str(label) for label in self.labels)\n        self.error: str = error or self.default_message\n\n    def _repr_args(self) -> str:\n        return f\"choices={self.choices!r}, labels={self.labels!r}\"\n\n    def _format_error(self, value) -> str:\n        return self.error.format(\n            input=value, choices=self.choices_text, labels=self.labels_text\n        )\n\n    def __call__(self, value: typing.Any) -> typing.Any:\n        try:\n            if value not in self.choices:\n                raise ValidationError(self._format_error(value))\n        except TypeError as error:\n            raise ValidationError(self._format_error(value)) from error\n\n        return value\n\n    def options(\n        self,\n        valuegetter: str | typing.Callable[[typing.Any], typing.Any] = str,\n    ) -> typing.Iterable[tuple[typing.Any, str]]:\n        \"\"\"Return a generator over the (value, label) pairs, where value\n        is a string associated with each choice. This convenience method\n        is useful to populate, for instance, a form select field.\n\n        :param valuegetter: Can be a callable or a string. In the former case, it must\n            be a one-argument callable which returns the value of a\n            choice. In the latter case, the string specifies the name\n            of an attribute of the choice objects. Defaults to `str()`.\n        \"\"\"\n        valuegetter = valuegetter if callable(valuegetter) else attrgetter(valuegetter)\n        pairs = zip_longest(self.choices, self.labels, fillvalue=\"\")\n\n        return ((valuegetter(choice), label) for choice, label in pairs)\n\n\nclass ContainsOnly(OneOf):\n    \"\"\"Validator which succeeds if ``value`` is a sequence and each element\n    in the sequence is also in the sequence passed as ``choices``. Empty input\n    is considered valid.\n\n    :param choices: Same as :class:`OneOf`.\n    :param labels: Same as :class:`OneOf`.\n    :param error: Same as :class:`OneOf`.\n\n    .. versionchanged:: 3.0.0b2\n        Duplicate values are considered valid.\n    .. versionchanged:: 3.0.0b2\n        Empty input is considered valid. Use `validate.Length(min=1) <marshmallow.validate.Length>`\n        to validate against empty inputs.\n    \"\"\"\n\n    default_message = \"One or more of the choices you made was not in: {choices}.\"\n\n    def _format_error(self, value) -> str:\n        value_text = \", \".join(str(val) for val in value)\n        return super()._format_error(value_text)\n\n    def __call__(self, value: typing.Sequence[_T]) -> typing.Sequence[_T]:\n        # We can't use set.issubset because does not handle unhashable types\n        for val in value:\n            if val not in self.choices:\n                raise ValidationError(self._format_error(value))\n        return value\n\n\nclass ContainsNoneOf(NoneOf):\n    \"\"\"Validator which fails if ``value`` is a sequence and any element\n    in the sequence is a member of the sequence passed as ``iterable``. Empty input\n    is considered valid.\n\n    :param iterable: Same as :class:`NoneOf`.\n    :param error: Same as :class:`NoneOf`.\n\n    .. versionadded:: 3.6.0\n    \"\"\"\n\n    default_message = \"One or more of the choices you made was in: {values}.\"\n\n    def _format_error(self, value) -> str:\n        value_text = \", \".join(str(val) for val in value)\n        return super()._format_error(value_text)\n\n    def __call__(self, value: typing.Sequence[_T]) -> typing.Sequence[_T]:\n        for val in value:\n            if val in self.iterable:\n                raise ValidationError(self._format_error(value))\n        return value\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/base.py",
    "content": "\"\"\"Test utilities and fixtures.\"\"\"\n\nimport datetime as dt\nimport functools\nimport typing\nimport uuid\nfrom enum import Enum, IntEnum\nfrom zoneinfo import ZoneInfo\n\nimport simplejson\n\nfrom marshmallow import Schema, fields, missing, post_load, validate\nfrom marshmallow.exceptions import ValidationError\n\ncentral = ZoneInfo(\"America/Chicago\")\n\n\nclass GenderEnum(IntEnum):\n    male = 1\n    female = 2\n    non_binary = 3\n\n\nclass HairColorEnum(Enum):\n    black = \"black hair\"\n    brown = \"brown hair\"\n    blond = \"blond hair\"\n    red = \"red hair\"\n\n\nclass DateEnum(Enum):\n    date_1 = dt.date(2004, 2, 29)\n    date_2 = dt.date(2008, 2, 29)\n    date_3 = dt.date(2012, 2, 29)\n\n\nALL_FIELDS = [\n    fields.String,\n    fields.Integer,\n    fields.Boolean,\n    fields.Float,\n    fields.DateTime,\n    fields.Time,\n    fields.Date,\n    fields.TimeDelta,\n    fields.Dict,\n    fields.Url,\n    fields.Email,\n    fields.UUID,\n    fields.Decimal,\n    fields.IP,\n    fields.IPv4,\n    fields.IPv6,\n    fields.IPInterface,\n    fields.IPv4Interface,\n    fields.IPv6Interface,\n    functools.partial(fields.Enum, GenderEnum),\n    functools.partial(fields.Enum, HairColorEnum, by_value=fields.String),\n    functools.partial(fields.Enum, GenderEnum, by_value=fields.Integer),\n]\n\n\n##### Custom asserts #####\n\n\ndef assert_date_equal(d1: dt.date, d2: dt.date) -> None:\n    assert d1.year == d2.year\n    assert d1.month == d2.month\n    assert d1.day == d2.day\n\n\ndef assert_time_equal(t1: dt.time, t2: dt.time) -> None:\n    assert t1.hour == t2.hour\n    assert t1.minute == t2.minute\n    assert t1.second == t2.second\n    assert t1.microsecond == t2.microsecond\n\n\n##### Validation #####\n\n\ndef predicate(\n    func: typing.Callable[[typing.Any], bool],\n) -> typing.Callable[[typing.Any], None]:\n    def validate(value: typing.Any) -> None:\n        if func(value) is False:\n            raise ValidationError(\"Invalid value.\")\n\n    return validate\n\n\n##### Models #####\n\n\nclass User:\n    SPECIES = \"Homo sapiens\"\n\n    def __init__(\n        self,\n        name,\n        *,\n        age=0,\n        id_=None,\n        homepage=None,\n        email=None,\n        registered=True,\n        time_registered=None,\n        birthdate=None,\n        birthtime=None,\n        balance=100,\n        sex=GenderEnum.male,\n        hair_color=HairColorEnum.black,\n        employer=None,\n        various_data=None,\n    ):\n        self.name = name\n        self.age = age\n        # A naive datetime\n        self.created = dt.datetime(2013, 11, 10, 14, 20, 58)\n        # A TZ-aware datetime\n        self.updated = dt.datetime(2013, 11, 10, 14, 20, 58, tzinfo=central)\n        self.id = id_\n        self.homepage = homepage\n        self.email = email\n        self.balance = balance\n        self.registered = registered\n        self.hair_colors = list(HairColorEnum.__members__)\n        self.sex_choices = list(GenderEnum.__members__)\n        self.finger_count = 10\n        self.uid = uuid.uuid1()\n        self.time_registered = time_registered or dt.time(1, 23, 45, 6789)\n        self.birthdate = birthdate or dt.date(2013, 1, 23)\n        self.birthtime = birthtime or dt.time(0, 1, 2, 3333)\n        self.activation_date = dt.date(2013, 12, 11)\n        self.sex = sex\n        self.hair_color = hair_color\n        self.employer = employer\n        self.relatives = []\n        self.various_data = various_data or {\n            \"pets\": [\"cat\", \"dog\"],\n            \"address\": \"1600 Pennsylvania Ave\\nWashington, DC 20006\",\n        }\n\n    @property\n    def since_created(self):\n        return dt.datetime(2013, 11, 24) - self.created\n\n    def __repr__(self):\n        return f\"<User {self.name}>\"\n\n\nclass Blog:\n    def __init__(self, title, user, collaborators=None, categories=None, id_=None):\n        self.title = title\n        self.user = user\n        self.collaborators = collaborators or []  # List/tuple of users\n        self.categories = categories\n        self.id = id_\n\n    def __contains__(self, item):\n        return item.name in [each.name for each in self.collaborators]\n\n\n###### Schemas #####\n\n\nclass Uppercased(fields.String):\n    \"\"\"Custom field formatting example.\"\"\"\n\n    def _serialize(self, value, attr, obj, **kwargs):\n        if value:\n            return value.upper()\n        return None\n\n\ndef get_lowername(obj):\n    if obj is None:\n        return missing\n    if isinstance(obj, dict):\n        return obj.get(\"name\", \"\").lower()\n    return obj.name.lower()\n\n\nclass UserSchema(Schema):\n    name = fields.String()\n    age: fields.Field = fields.Float()\n    created = fields.DateTime()\n    created_formatted = fields.DateTime(\n        format=\"%Y-%m-%d\", attribute=\"created\", dump_only=True\n    )\n    created_iso = fields.DateTime(format=\"iso\", attribute=\"created\", dump_only=True)\n    updated = fields.DateTime()\n    species = fields.String(attribute=\"SPECIES\")\n    id = fields.String(dump_default=\"no-id\")\n    uppername = Uppercased(attribute=\"name\", dump_only=True)\n    homepage = fields.Url()\n    email = fields.Email()\n    balance = fields.Decimal()\n    is_old: fields.Field = fields.Method(\"get_is_old\")\n    lowername = fields.Function(get_lowername)\n    registered = fields.Boolean()\n    hair_colors = fields.List(fields.Raw)\n    sex_choices = fields.List(fields.Raw)\n    finger_count = fields.Integer()\n    uid = fields.UUID()\n    time_registered = fields.Time()\n    birthdate = fields.Date()\n    birthtime = fields.Time()\n    activation_date = fields.Date()\n    since_created = fields.TimeDelta()\n    sex = fields.Str(validate=validate.OneOf(list(GenderEnum.__members__)))\n    various_data = fields.Dict()\n\n    class Meta:\n        render_module = simplejson\n\n    def get_is_old(self, obj):\n        if obj is None:\n            return missing\n        if isinstance(obj, dict):\n            age = obj.get(\"age\", 0)\n        else:\n            age = obj.age\n        try:\n            return age > 80\n        except TypeError as te:\n            raise ValidationError(str(te)) from te\n\n    @post_load\n    def make_user(self, data, **kwargs):\n        return User(**data)\n\n\nclass UserExcludeSchema(UserSchema):\n    class Meta:\n        exclude = (\"created\", \"updated\")\n\n\nclass UserIntSchema(UserSchema):\n    age = fields.Integer()\n\n\nclass UserFloatStringSchema(UserSchema):\n    age = fields.Float(as_string=True)\n\n\nclass ExtendedUserSchema(UserSchema):\n    is_old = fields.Boolean()\n\n\nclass UserRelativeUrlSchema(UserSchema):\n    homepage = fields.Url(relative=True)\n\n\nclass BlogSchema(Schema):\n    title = fields.String()\n    user = fields.Nested(UserSchema)\n    collaborators = fields.List(fields.Nested(UserSchema()))\n    categories = fields.List(fields.String)\n    id = fields.String()\n\n\nclass BlogOnlySchema(Schema):\n    title = fields.String()\n    user = fields.Nested(UserSchema)\n    collaborators = fields.List(fields.Nested(UserSchema(only=(\"id\",))))\n\n\nclass BlogSchemaExclude(BlogSchema):\n    user = fields.Nested(UserSchema, exclude=(\"uppername\", \"species\"))\n\n\nclass BlogSchemaOnlyExclude(BlogSchema):\n    user = fields.Nested(UserSchema, only=(\"name\",), exclude=(\"name\", \"species\"))\n\n\nclass mockjson:  # noqa: N801\n    @staticmethod\n    def dumps(val):\n        return b\"{'foo': 42}\"\n\n    @staticmethod\n    def loads(val):\n        return {\"foo\": 42}\n"
  },
  {
    "path": "tests/conftest.py",
    "content": "\"\"\"Pytest fixtures that are available in all test modules.\"\"\"\n\nimport pytest\n\nfrom tests.base import Blog, User, UserSchema\n\n\n@pytest.fixture\ndef user():\n    return User(name=\"Monty\", age=42.3, homepage=\"http://monty.python.org/\")\n\n\n@pytest.fixture\ndef blog(user):\n    col1 = User(name=\"Mick\", age=123)\n    col2 = User(name=\"Keith\", age=456)\n    return Blog(\n        \"Monty's blog\",\n        user=user,\n        categories=[\"humor\", \"violence\"],\n        collaborators=[col1, col2],\n    )\n\n\n@pytest.fixture\ndef serialized_user(user):\n    return UserSchema().dump(user)\n"
  },
  {
    "path": "tests/foo_serializer.py",
    "content": "from marshmallow import Schema, fields\n\n\nclass FooSerializer(Schema):\n    _id = fields.Integer()\n"
  },
  {
    "path": "tests/mypy_test_cases/test_class_registry.py",
    "content": "from marshmallow import class_registry\n\n# Works without passing `all`\nclass_registry.get_class(\"MySchema\")\n"
  },
  {
    "path": "tests/mypy_test_cases/test_schema.py",
    "content": "import json\n\nfrom marshmallow import EXCLUDE, Schema\nfrom marshmallow.fields import Integer, String\n\n\n# Test that valid `Meta` class attributes pass type checking\nclass MySchema(Schema):\n    foo = String()\n    bar = Integer()\n\n    class Meta(Schema.Meta):\n        fields = (\"foo\", \"bar\")\n        additional = (\"baz\", \"qux\")\n        include = {\n            \"foo2\": String(),\n        }\n        exclude = (\"bar\", \"baz\")\n        many = True\n        dateformat = \"%Y-%m-%d\"\n        datetimeformat = \"%Y-%m-%dT%H:%M:%S\"\n        timeformat = \"%H:%M:%S\"\n        render_module = json\n        ordered = False\n        index_errors = True\n        load_only = (\"foo\", \"bar\")\n        dump_only = (\"baz\", \"qux\")\n        unknown = EXCLUDE\n        register = False\n"
  },
  {
    "path": "tests/mypy_test_cases/test_validation_error.py",
    "content": "from __future__ import annotations\n\nimport marshmallow as ma\n\n# OK types for 'message'\nma.ValidationError(\"foo\")\nma.ValidationError([\"foo\"])\nma.ValidationError({\"foo\": \"bar\"})\n\n# non-OK types for 'message'\nma.ValidationError(0)  # type: ignore[arg-type]\n\n# 'messages' is a dict|list\nerr = ma.ValidationError(\"foo\")\na: dict | list = err.messages\n# union type can't assign to non-union type\nb: str = err.messages  # type: ignore[assignment]\nc: dict = err.messages  # type: ignore[assignment]\n# 'messages_dict' is a dict, so that it can assign to a dict\nd: dict = err.messages_dict\n"
  },
  {
    "path": "tests/test_context.py",
    "content": "import typing\n\nimport pytest\n\nfrom marshmallow import (\n    Schema,\n    fields,\n    post_dump,\n    post_load,\n    pre_dump,\n    pre_load,\n    validates,\n    validates_schema,\n)\nfrom marshmallow.exceptions import ValidationError\nfrom marshmallow.experimental.context import Context\nfrom tests.base import Blog, User\n\n\nclass UserContextSchema(Schema):\n    is_owner = fields.Method(\"get_is_owner\")\n    is_collab = fields.Function(\n        lambda user: user in Context[dict[str, typing.Any]].get()[\"blog\"]\n    )\n\n    def get_is_owner(self, user):\n        return Context.get()[\"blog\"].user.name == user.name\n\n\nclass TestContext:\n    def test_context_load_dump(self):\n        class ContextField(fields.Integer):\n            def _serialize(self, value, attr, obj, **kwargs):\n                if (context := Context[dict].get(None)) is not None:\n                    value *= context.get(\"factor\", 1)\n                return super()._serialize(value, attr, obj, **kwargs)\n\n            def _deserialize(self, value, attr, data, **kwargs):\n                val = super()._deserialize(value, attr, data, **kwargs)\n                if (context := Context[dict].get(None)) is not None:\n                    val *= context.get(\"factor\", 1)\n                return val\n\n        class ContextSchema(Schema):\n            ctx_fld = ContextField()\n\n        ctx_schema = ContextSchema()\n\n        assert ctx_schema.load({\"ctx_fld\": 1}) == {\"ctx_fld\": 1}\n        assert ctx_schema.dump({\"ctx_fld\": 1}) == {\"ctx_fld\": 1}\n        with Context({\"factor\": 2}):\n            assert ctx_schema.load({\"ctx_fld\": 1}) == {\"ctx_fld\": 2}\n            assert ctx_schema.dump({\"ctx_fld\": 1}) == {\"ctx_fld\": 2}\n\n    def test_context_method(self):\n        owner = User(\"Joe\")\n        blog = Blog(title=\"Joe Blog\", user=owner)\n        serializer = UserContextSchema()\n        with Context({\"blog\": blog}):\n            data = serializer.dump(owner)\n            assert data[\"is_owner\"] is True\n            nonowner = User(\"Fred\")\n            data = serializer.dump(nonowner)\n            assert data[\"is_owner\"] is False\n\n    def test_context_function(self):\n        owner = User(\"Fred\")\n        blog = Blog(\"Killer Queen\", user=owner)\n        collab = User(\"Brian\")\n        blog.collaborators.append(collab)\n        with Context({\"blog\": blog}):\n            serializer = UserContextSchema()\n            data = serializer.dump(collab)\n            assert data[\"is_collab\"] is True\n            noncollab = User(\"Foo\")\n            data = serializer.dump(noncollab)\n            assert data[\"is_collab\"] is False\n\n    def test_function_field_handles_bound_serializer(self):\n        class SerializeA:\n            def __call__(self, value):\n                return \"value\"\n\n        serialize = SerializeA()\n\n        # only has a function field\n        class UserFunctionContextSchema(Schema):\n            is_collab = fields.Function(serialize)\n\n        owner = User(\"Joe\")\n        serializer = UserFunctionContextSchema()\n        data = serializer.dump(owner)\n        assert data[\"is_collab\"] == \"value\"\n\n    def test_nested_fields_inherit_context(self):\n        class InnerSchema(Schema):\n            likes_bikes = fields.Function(lambda obj: \"bikes\" in Context.get()[\"info\"])\n\n        class CSchema(Schema):\n            inner = fields.Nested(InnerSchema)\n\n        ser = CSchema()\n        with Context[dict]({\"info\": \"i like bikes\"}):\n            obj: dict[str, dict] = {\"inner\": {}}\n            result = ser.dump(obj)\n            assert result[\"inner\"][\"likes_bikes\"] is True\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/820\n    def test_nested_list_fields_inherit_context(self):\n        class InnerSchema(Schema):\n            foo = fields.Raw()\n\n            @validates(\"foo\")\n            def validate_foo(self, value, **kwargs):\n                if \"foo_context\" not in Context[dict].get():\n                    raise ValidationError(\"Missing context\")\n\n        class OuterSchema(Schema):\n            bars = fields.List(fields.Nested(InnerSchema()))\n\n        inner = InnerSchema()\n        with Context({\"foo_context\": \"foo\"}):\n            assert inner.load({\"foo\": 42})\n\n        outer = OuterSchema()\n        with Context({\"foo_context\": \"foo\"}):\n            assert outer.load({\"bars\": [{\"foo\": 42}]})\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/820\n    def test_nested_dict_fields_inherit_context(self):\n        class InnerSchema(Schema):\n            foo = fields.Raw()\n\n            @validates(\"foo\")\n            def validate_foo(self, value, **kwargs):\n                if \"foo_context\" not in Context[dict].get():\n                    raise ValidationError(\"Missing context\")\n\n        class OuterSchema(Schema):\n            bars = fields.Dict(values=fields.Nested(InnerSchema()))\n\n        inner = InnerSchema()\n        with Context({\"foo_context\": \"foo\"}):\n            assert inner.load({\"foo\": 42})\n\n        outer = OuterSchema()\n        with Context({\"foo_context\": \"foo\"}):\n            assert outer.load({\"bars\": {\"test\": {\"foo\": 42}}})\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/1404\n    def test_nested_field_with_unpicklable_object_in_context(self):\n        class Unpicklable:\n            def __deepcopy__(self, _):\n                raise NotImplementedError\n\n        class InnerSchema(Schema):\n            foo = fields.Raw()\n\n        class OuterSchema(Schema):\n            inner = fields.Nested(InnerSchema())\n\n        outer = OuterSchema()\n        obj = {\"inner\": {\"foo\": 42}}\n        with Context({\"unp\": Unpicklable()}):\n            assert outer.dump(obj)\n\n    def test_function_field_passed_serialize_with_context(self, user):\n        class Parent(Schema):\n            pass\n\n        field = fields.Function(\n            serialize=lambda obj: obj.name.upper() + Context.get()[\"key\"]\n        )\n        field.parent = Parent()\n        with Context({\"key\": \"BAR\"}):\n            assert field.serialize(\"key\", user) == \"MONTYBAR\"\n\n    def test_function_field_deserialization_with_context(self):\n        class Parent(Schema):\n            pass\n\n        field = fields.Function(\n            lambda x: None,\n            deserialize=lambda val: val.upper() + Context.get()[\"key\"],\n        )\n        field.parent = Parent()\n        with Context({\"key\": \"BAR\"}):\n            assert field.deserialize(\"foo\") == \"FOOBAR\"\n\n    def test_decorated_processors_with_context(self):\n        NumDictContext = Context[dict[int, int]]\n\n        class MySchema(Schema):\n            f_1 = fields.Integer()\n            f_2 = fields.Integer()\n            f_3 = fields.Integer()\n            f_4 = fields.Integer()\n\n            @pre_dump\n            def multiply_f_1(self, item, **kwargs):\n                item[\"f_1\"] *= NumDictContext.get()[1]\n                return item\n\n            @pre_load\n            def multiply_f_2(self, data, **kwargs):\n                data[\"f_2\"] *= NumDictContext.get()[2]\n                return data\n\n            @post_dump\n            def multiply_f_3(self, item, **kwargs):\n                item[\"f_3\"] *= NumDictContext.get()[3]\n                return item\n\n            @post_load\n            def multiply_f_4(self, data, **kwargs):\n                data[\"f_4\"] *= NumDictContext.get()[4]\n                return data\n\n        schema = MySchema()\n\n        with NumDictContext({1: 2, 2: 3, 3: 4, 4: 5}):\n            assert schema.dump({\"f_1\": 1, \"f_2\": 1, \"f_3\": 1, \"f_4\": 1}) == {\n                \"f_1\": 2,\n                \"f_2\": 1,\n                \"f_3\": 4,\n                \"f_4\": 1,\n            }\n            assert schema.load({\"f_1\": 1, \"f_2\": 1, \"f_3\": 1, \"f_4\": 1}) == {\n                \"f_1\": 1,\n                \"f_2\": 3,\n                \"f_3\": 1,\n                \"f_4\": 5,\n            }\n\n    def test_validates_schema_with_context(self):\n        class MySchema(Schema):\n            f_1 = fields.Integer()\n            f_2 = fields.Integer()\n\n            @validates_schema\n            def validate_schema(self, data, **kwargs):\n                if data[\"f_2\"] != data[\"f_1\"] * Context.get():\n                    raise ValidationError(\"Fail\")\n\n        schema = MySchema()\n\n        with Context(2):\n            schema.load({\"f_1\": 1, \"f_2\": 2})\n            with pytest.raises(ValidationError) as excinfo:\n                schema.load({\"f_1\": 1, \"f_2\": 3})\n            assert excinfo.value.messages[\"_schema\"] == [\"Fail\"]\n"
  },
  {
    "path": "tests/test_decorators.py",
    "content": "import pytest\n\nfrom marshmallow import (\n    EXCLUDE,\n    INCLUDE,\n    RAISE,\n    Schema,\n    ValidationError,\n    fields,\n    post_dump,\n    post_load,\n    pre_dump,\n    pre_load,\n    validate,\n    validates,\n    validates_schema,\n)\nfrom tests.base import predicate\n\n\n@pytest.mark.parametrize(\"partial_val\", (True, False))\ndef test_decorated_processors(partial_val):\n    class ExampleSchema(Schema):\n        \"\"\"Includes different ways to invoke decorators and set up methods\"\"\"\n\n        TAG = \"TAG\"\n\n        value = fields.Integer(as_string=True)\n\n        # Implicit default raw, pre dump, static method.\n        @pre_dump\n        def increment_value(self, item, **kwargs):\n            assert \"many\" in kwargs\n            item[\"value\"] += 1\n            return item\n\n        # Implicit default raw, post dump, class method.\n        @post_dump\n        def add_tag(self, item, **kwargs):\n            assert \"many\" in kwargs\n            item[\"value\"] = self.TAG + item[\"value\"]\n            return item\n\n        # Explicitly raw, post dump, instance method.\n        @post_dump(pass_collection=True)\n        def add_envelope(self, data, many, **kwargs):\n            key = self.get_envelope_key(many)\n            return {key: data}\n\n        # Explicitly raw, pre load, instance method.\n        @pre_load(pass_collection=True)\n        def remove_envelope(self, data, many, partial, **kwargs):\n            assert partial is partial_val\n            key = self.get_envelope_key(many)\n            return data[key]\n\n        @staticmethod\n        def get_envelope_key(many):\n            return \"data\" if many else \"datum\"\n\n        # Explicitly not raw, pre load, instance method.\n        @pre_load(pass_collection=False)\n        def remove_tag(self, item, partial, **kwargs):\n            assert partial is partial_val\n            assert \"many\" in kwargs\n            item[\"value\"] = item[\"value\"][len(self.TAG) :]\n            return item\n\n        # Explicit default raw, post load, instance method.\n        @post_load()\n        def decrement_value(self, item, partial, **kwargs):\n            assert partial is partial_val\n            assert \"many\" in kwargs\n            item[\"value\"] -= 1\n            return item\n\n    schema = ExampleSchema(partial=partial_val)\n\n    # Need to re-create these because the processors will modify in place.\n    def make_item():\n        return {\"value\": 3}\n\n    def make_items():\n        return [make_item(), {\"value\": 5}]\n\n    item_dumped = schema.dump(make_item())\n    assert item_dumped == {\"datum\": {\"value\": \"TAG4\"}}\n    item_loaded = schema.load(item_dumped)\n    assert item_loaded == make_item()\n\n    items_dumped = schema.dump(make_items(), many=True)\n    assert items_dumped == {\"data\": [{\"value\": \"TAG4\"}, {\"value\": \"TAG6\"}]}\n    items_loaded = schema.load(items_dumped, many=True)\n    assert items_loaded == make_items()\n\n\n# Regression test for https://github.com/marshmallow-code/marshmallow/issues/347\n@pytest.mark.parametrize(\"unknown\", (EXCLUDE, INCLUDE, RAISE))\ndef test_decorated_processor_returning_none(unknown):\n    class PostSchema(Schema):\n        value = fields.Integer()\n\n        @post_load\n        def load_none(self, item, **kwargs):\n            return None\n\n        @post_dump\n        def dump_none(self, item, **kwargs):\n            return None\n\n    class PreSchema(Schema):\n        value = fields.Integer()\n\n        @pre_load\n        def load_none(self, item, **kwargs):\n            return None\n\n        @pre_dump\n        def dump_none(self, item, **kwargs):\n            return None\n\n    schema = PostSchema(unknown=unknown)\n    assert schema.dump({\"value\": 3}) is None\n    assert schema.load({\"value\": 3}) is None\n    pre_schema = PreSchema(unknown=unknown)\n    assert pre_schema.dump({\"value\": 3}) == {}\n    with pytest.raises(ValidationError) as excinfo:\n        pre_schema.load({\"value\": 3})\n    assert excinfo.value.messages == {\"_schema\": [\"Invalid input type.\"]}\n\n\nclass TestPassOriginal:\n    def test_pass_original_single(self):\n        class MySchema(Schema):\n            foo = fields.Raw()\n\n            @post_load(pass_original=True)\n            def post_load(self, data, original_data, **kwargs):\n                ret = data.copy()\n                ret[\"_post_load\"] = original_data[\"sentinel\"]\n                return ret\n\n            @post_dump(pass_original=True)\n            def post_dump(self, data, obj, **kwargs):\n                ret = data.copy()\n                ret[\"_post_dump\"] = obj[\"sentinel\"]\n                return ret\n\n        schema = MySchema(unknown=EXCLUDE)\n        datum = {\"foo\": 42, \"sentinel\": 24}\n        item_loaded = schema.load(datum)\n        assert item_loaded[\"foo\"] == 42\n        assert item_loaded[\"_post_load\"] == 24\n\n        item_dumped = schema.dump(datum)\n\n        assert item_dumped[\"foo\"] == 42\n        assert item_dumped[\"_post_dump\"] == 24\n\n    def test_pass_original_many(self):\n        class MySchema(Schema):\n            foo = fields.Raw()\n\n            @post_load(pass_collection=True, pass_original=True)\n            def post_load(self, data, original, many, **kwargs):\n                if many:\n                    ret = []\n                    for item, orig_item in zip(data, original, strict=True):\n                        item[\"_post_load\"] = orig_item[\"sentinel\"]\n                        ret.append(item)\n                else:\n                    ret = data.copy()\n                    ret[\"_post_load\"] = original[\"sentinel\"]\n                return ret\n\n            @post_dump(pass_collection=True, pass_original=True)\n            def post_dump(self, data, original, many, **kwargs):\n                if many:\n                    ret = []\n                    for item, orig_item in zip(data, original, strict=True):\n                        item[\"_post_dump\"] = orig_item[\"sentinel\"]\n                        ret.append(item)\n                else:\n                    ret = data.copy()\n                    ret[\"_post_dump\"] = original[\"sentinel\"]\n                return ret\n\n        schema = MySchema(unknown=EXCLUDE)\n        data = [{\"foo\": 42, \"sentinel\": 24}, {\"foo\": 424, \"sentinel\": 242}]\n        items_loaded = schema.load(data, many=True)\n        assert items_loaded == [\n            {\"foo\": 42, \"_post_load\": 24},\n            {\"foo\": 424, \"_post_load\": 242},\n        ]\n        test_values = [e[\"_post_load\"] for e in items_loaded]\n        assert test_values == [24, 242]\n\n        items_dumped = schema.dump(data, many=True)\n        assert items_dumped == [\n            {\"foo\": 42, \"_post_dump\": 24},\n            {\"foo\": 424, \"_post_dump\": 242},\n        ]\n\n        # Also check load/dump of single item\n\n        datum = {\"foo\": 42, \"sentinel\": 24}\n        item_loaded = schema.load(datum, many=False)\n        assert item_loaded == {\"foo\": 42, \"_post_load\": 24}\n\n        item_dumped = schema.dump(datum, many=False)\n        assert item_dumped == {\"foo\": 42, \"_post_dump\": 24}\n\n\ndef test_decorated_processor_inheritance():\n    class ParentSchema(Schema):\n        @post_dump\n        def inherited(self, item, **kwargs):\n            item[\"inherited\"] = \"inherited\"\n            return item\n\n        @post_dump\n        def overridden(self, item, **kwargs):\n            item[\"overridden\"] = \"base\"\n            return item\n\n        @post_dump\n        def deleted(self, item, **kwargs):\n            item[\"deleted\"] = \"retained\"\n            return item\n\n    class ChildSchema(ParentSchema):\n        @post_dump\n        def overridden(self, item, **kwargs):\n            item[\"overridden\"] = \"overridden\"\n            return item\n\n        deleted = None  # type: ignore[assignment]\n\n    parent_dumped = ParentSchema().dump({})\n    assert parent_dumped == {\n        \"inherited\": \"inherited\",\n        \"overridden\": \"base\",\n        \"deleted\": \"retained\",\n    }\n\n    child_dumped = ChildSchema().dump({})\n    assert child_dumped == {\"inherited\": \"inherited\", \"overridden\": \"overridden\"}\n\n\nclass ValidatesSchema(Schema):\n    foo = fields.Int()\n\n    @validates(\"foo\")\n    def validate_foo(self, value, **kwargs):\n        if value != 42:\n            raise ValidationError(\"The answer to life the universe and everything.\")\n\n\nclass TestValidatesDecorator:\n    def test_validates(self):\n        class VSchema(Schema):\n            s = fields.String()\n\n            @validates(\"s\")\n            def validate_string(self, data, **kwargs):\n                raise ValidationError(\"nope\")\n\n        with pytest.raises(ValidationError) as excinfo:\n            VSchema().load({\"s\": \"bar\"})\n\n        assert excinfo.value.messages == {\"s\": [\"nope\"]}\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/350\n    def test_validates_with_attribute(self):\n        class S1(Schema):\n            s = fields.String(attribute=\"string_name\")\n\n            @validates(\"s\")\n            def validate_string(self, data, **kwargs):\n                raise ValidationError(\"nope\")\n\n        with pytest.raises(ValidationError) as excinfo:\n            S1().load({\"s\": \"foo\"})\n        assert excinfo.value.messages == {\"s\": [\"nope\"]}\n\n        with pytest.raises(ValidationError):\n            S1(many=True).load([{\"s\": \"foo\"}])\n\n    def test_validates_decorator(self):\n        schema = ValidatesSchema()\n\n        errors = schema.validate({\"foo\": 41})\n        assert \"foo\" in errors\n        assert errors[\"foo\"][0] == \"The answer to life the universe and everything.\"\n\n        errors = schema.validate({\"foo\": 42})\n        assert errors == {}\n\n        errors = schema.validate([{\"foo\": 42}, {\"foo\": 43}], many=True)\n        assert \"foo\" in errors[1]\n        assert len(errors[1][\"foo\"]) == 1\n        assert errors[1][\"foo\"][0] == \"The answer to life the universe and everything.\"\n\n        errors = schema.validate([{\"foo\": 42}, {\"foo\": 42}], many=True)\n        assert errors == {}\n\n        errors = schema.validate({})\n        assert errors == {}\n\n        with pytest.raises(ValidationError) as excinfo:\n            schema.load({\"foo\": 41})\n        assert excinfo.value.messages\n        result = excinfo.value.valid_data\n        assert result == {}\n\n        with pytest.raises(ValidationError) as excinfo:\n            schema.load([{\"foo\": 42}, {\"foo\": 43}], many=True)\n        error_messages = excinfo.value.messages\n        result = excinfo.value.valid_data\n        assert isinstance(result, list)\n        assert len(result) == 2\n        assert result[0] == {\"foo\": 42}\n        assert result[1] == {}\n        assert 1 in error_messages\n        assert \"foo\" in error_messages[1]\n        assert error_messages[1][\"foo\"] == [\n            \"The answer to life the universe and everything.\"\n        ]\n\n    def test_field_not_present(self):\n        class BadSchema(ValidatesSchema):\n            @validates(\"bar\")\n            def validate_bar(self, value, **kwargs):\n                raise ValidationError(\"Never raised.\")\n\n        schema = BadSchema()\n\n        with pytest.raises(ValueError, match='\"bar\" field does not exist.'):\n            schema.validate({\"foo\": 42})\n\n    def test_precedence(self):\n        class Schema2(ValidatesSchema):\n            foo = fields.Int(validate=predicate(lambda n: n != 42))\n            bar = fields.Int(validate=validate.Equal(1))\n\n            @validates(\"bar\")\n            def validate_bar(self, value, **kwargs):\n                if value != 2:\n                    raise ValidationError(\"Must be 2\")\n\n        schema = Schema2()\n\n        errors = schema.validate({\"foo\": 42})\n        assert \"foo\" in errors\n        assert len(errors[\"foo\"]) == 1\n        assert \"Invalid value.\" in errors[\"foo\"][0]\n\n        errors = schema.validate({\"bar\": 3})\n        assert \"bar\" in errors\n        assert len(errors[\"bar\"]) == 1\n        assert \"Must be equal to 1.\" in errors[\"bar\"][0]\n\n        errors = schema.validate({\"bar\": 1})\n        assert \"bar\" in errors\n        assert len(errors[\"bar\"]) == 1\n        assert errors[\"bar\"][0] == \"Must be 2\"\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/748\n    def test_validates_with_data_key(self):\n        class BadSchema(Schema):\n            foo = fields.String(data_key=\"foo-name\")\n\n            @validates(\"foo\")\n            def validate_string(self, data, **kwargs):\n                raise ValidationError(\"nope\")\n\n        schema = BadSchema()\n        errors = schema.validate({\"foo-name\": \"data\"})\n        assert \"foo-name\" in errors\n        assert errors[\"foo-name\"] == [\"nope\"]\n\n        schema = BadSchema()\n        errors = schema.validate(\n            [{\"foo-name\": \"data\"}, {\"foo-name\": \"data2\"}], many=True\n        )\n        assert errors == {0: {\"foo-name\": [\"nope\"]}, 1: {\"foo-name\": [\"nope\"]}}\n\n    def test_validates_accepts_multiple_fields(self):\n        class BadSchema(Schema):\n            foo = fields.String()\n            bar = fields.String(data_key=\"Bar\")\n\n            @validates(\"foo\", \"bar\")\n            def validate_string(self, data: str, data_key: str):\n                raise ValidationError(f\"'{data}' is invalid for {data_key}.\")\n\n        schema = BadSchema()\n        with pytest.raises(ValidationError) as excinfo:\n            schema.load({\"foo\": \"data\", \"Bar\": \"data2\"})\n        assert excinfo.value.messages == {\n            \"foo\": [\"'data' is invalid for foo.\"],\n            \"Bar\": [\"'data2' is invalid for Bar.\"],\n        }\n\n\nclass TestValidatesSchemaDecorator:\n    def test_validator_nested_many_invalid_data(self):\n        class NestedSchema(Schema):\n            foo = fields.Int(required=True)\n\n        class MySchema(Schema):\n            nested = fields.Nested(NestedSchema, required=True, many=True)\n\n        schema = MySchema()\n        errors = schema.validate({\"nested\": [1]})\n        assert errors\n        assert \"nested\" in errors\n        assert 0 in errors[\"nested\"]\n        assert errors[\"nested\"][0] == {\"_schema\": [\"Invalid input type.\"]}\n\n    def test_validator_nested_many_schema_error(self):\n        class NestedSchema(Schema):\n            foo = fields.Int(required=True)\n\n            @validates_schema\n            def validate_schema(self, data, **kwargs):\n                raise ValidationError(\"This will never work.\")\n\n        class MySchema(Schema):\n            nested = fields.Nested(NestedSchema, required=True, many=True)\n\n        schema = MySchema()\n        errors = schema.validate({\"nested\": [{\"foo\": 1}]})\n        assert errors\n        assert \"nested\" in errors\n        assert 0 in errors[\"nested\"]\n        assert errors[\"nested\"][0] == {\"_schema\": [\"This will never work.\"]}\n\n    def test_validator_nested_many_field_error(self):\n        class NestedSchema(Schema):\n            foo = fields.Int(required=True)\n\n            @validates_schema\n            def validate_schema(self, data, **kwargs):\n                raise ValidationError(\"This will never work.\", \"foo\")\n\n        class MySchema(Schema):\n            nested = fields.Nested(NestedSchema, required=True, many=True)\n\n        schema = MySchema()\n        errors = schema.validate({\"nested\": [{\"foo\": 1}]})\n        assert errors\n        assert \"nested\" in errors\n        assert 0 in errors[\"nested\"]\n        assert errors[\"nested\"][0] == {\"foo\": [\"This will never work.\"]}\n\n    @pytest.mark.parametrize(\"data\", ([{\"foo\": 1, \"bar\": 2}],))\n    @pytest.mark.parametrize(\n        (\"pass_collection\", \"expected_data\", \"expected_original_data\"),\n        (\n            [True, [{\"foo\": 1}], [{\"foo\": 1, \"bar\": 2}]],\n            [False, {\"foo\": 1}, {\"foo\": 1, \"bar\": 2}],\n        ),\n    )\n    def test_validator_nested_many_pass_original_and_pass_collection(\n        self, pass_collection, data, expected_data, expected_original_data\n    ):\n        class NestedSchema(Schema):\n            foo = fields.Int(required=True)\n\n            @validates_schema(pass_collection=pass_collection, pass_original=True)\n            def validate_schema(self, data, original_data, many, **kwargs):\n                assert data == expected_data\n                assert original_data == expected_original_data\n                assert many is True\n                raise ValidationError(\"Method called\")\n\n        class MySchema(Schema):\n            nested = fields.Nested(\n                NestedSchema, required=True, many=True, unknown=EXCLUDE\n            )\n\n        schema = MySchema()\n        errors = schema.validate({\"nested\": data})\n        error = errors[\"nested\"] if pass_collection else errors[\"nested\"][0]\n        assert error[\"_schema\"][0] == \"Method called\"\n\n    def test_decorated_validators(self):\n        class MySchema(Schema):\n            foo = fields.Int()\n            bar = fields.Int()\n\n            @validates_schema\n            def validate_schema(self, data, **kwargs):\n                if data[\"foo\"] <= 3:\n                    raise ValidationError(\"Must be greater than 3\")\n\n            @validates_schema(pass_collection=True)\n            def validate_raw(self, data, many, **kwargs):\n                if many:\n                    assert type(data) is list\n                    if len(data) < 2:\n                        raise ValidationError(\"Must provide at least 2 items\")\n\n            @validates_schema\n            def validate_bar(self, data, **kwargs):\n                if \"bar\" in data and data[\"bar\"] < 0:\n                    raise ValidationError(\"bar must not be negative\", \"bar\")\n\n        schema = MySchema()\n        errors = schema.validate({\"foo\": 3})\n        assert \"_schema\" in errors\n        assert errors[\"_schema\"][0] == \"Must be greater than 3\"\n\n        errors = schema.validate([{\"foo\": 4}], many=True)\n        assert \"_schema\" in errors\n        assert len(errors[\"_schema\"]) == 1\n        assert errors[\"_schema\"][0] == \"Must provide at least 2 items\"\n\n        errors = schema.validate({\"foo\": 4, \"bar\": -1})\n        assert \"bar\" in errors\n        assert len(errors[\"bar\"]) == 1\n        assert errors[\"bar\"][0] == \"bar must not be negative\"\n\n    def test_multiple_validators(self):\n        class MySchema(Schema):\n            foo = fields.Int()\n            bar = fields.Int()\n\n            @validates_schema\n            def validate_schema(self, data, **kwargs):\n                if data[\"foo\"] <= 3:\n                    raise ValidationError(\"Must be greater than 3\")\n\n            @validates_schema\n            def validate_bar(self, data, **kwargs):\n                if \"bar\" in data and data[\"bar\"] < 0:\n                    raise ValidationError(\"bar must not be negative\")\n\n        schema = MySchema()\n        errors = schema.validate({\"foo\": 3, \"bar\": -1})\n        assert type(errors) is dict\n        assert \"_schema\" in errors\n        assert len(errors[\"_schema\"]) == 2\n        assert \"Must be greater than 3\" in errors[\"_schema\"]\n        assert \"bar must not be negative\" in errors[\"_schema\"]\n\n        errors = schema.validate([{\"foo\": 3, \"bar\": -1}, {\"foo\": 3}], many=True)\n        assert type(errors) is dict\n        assert \"_schema\" in errors[0]\n        assert len(errors[0][\"_schema\"]) == 2\n        assert \"Must be greater than 3\" in errors[0][\"_schema\"]\n        assert \"bar must not be negative\" in errors[0][\"_schema\"]\n        assert len(errors[1][\"_schema\"]) == 1\n        assert \"Must be greater than 3\" in errors[0][\"_schema\"]\n\n    def test_multiple_validators_merge_dict_errors(self):\n        class NestedSchema(Schema):\n            foo = fields.Int()\n            bar = fields.Int()\n\n        class MySchema(Schema):\n            nested = fields.Nested(NestedSchema)\n\n            @validates_schema\n            def validate_nested_foo(self, data, **kwargs):\n                raise ValidationError({\"nested\": {\"foo\": [\"Invalid foo\"]}})\n\n            @validates_schema\n            def validate_nested_bar_1(self, data, **kwargs):\n                raise ValidationError({\"nested\": {\"bar\": [\"Invalid bar 1\"]}})\n\n            @validates_schema\n            def validate_nested_bar_2(self, data, **kwargs):\n                raise ValidationError({\"nested\": {\"bar\": [\"Invalid bar 2\"]}})\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"nested\": {\"foo\": 1, \"bar\": 2}})\n\n        assert excinfo.value.messages == {\n            \"nested\": {\n                \"foo\": [\"Invalid foo\"],\n                \"bar\": [\"Invalid bar 1\", \"Invalid bar 2\"],\n            }\n        }\n\n    def test_passing_original_data(self):\n        class MySchema(Schema):\n            foo = fields.Int()\n            bar = fields.Int()\n\n            @validates_schema(pass_original=True)\n            def validate_original(self, data, original_data, partial, **kwargs):\n                if isinstance(original_data, dict) and isinstance(\n                    original_data[\"foo\"], str\n                ):\n                    raise ValidationError(\"foo cannot be a string\")\n\n            @validates_schema(pass_collection=True, pass_original=True)\n            def validate_original_bar(self, data, original_data, many, **kwargs):\n                def check(datum):\n                    if isinstance(datum, dict) and isinstance(datum[\"bar\"], str):\n                        raise ValidationError(\"bar cannot be a string\")\n\n                if many:\n                    for each in original_data:\n                        check(each)\n                else:\n                    check(original_data)\n\n        schema = MySchema()\n\n        errors = schema.validate({\"foo\": \"4\", \"bar\": 12})\n        assert errors[\"_schema\"] == [\"foo cannot be a string\"]\n\n        errors = schema.validate({\"foo\": 4, \"bar\": \"42\"})\n        assert errors[\"_schema\"] == [\"bar cannot be a string\"]\n\n        errors = schema.validate([{\"foo\": 4, \"bar\": \"42\"}], many=True)\n        assert errors[\"_schema\"] == [\"bar cannot be a string\"]\n\n    def test_allow_reporting_field_errors_in_schema_validator(self):\n        class NestedSchema(Schema):\n            baz = fields.Int(required=True)\n\n        class MySchema(Schema):\n            foo = fields.Int(required=True)\n            bar = fields.Nested(NestedSchema, required=True)\n            bam = fields.Int(required=True)\n\n            @validates_schema(skip_on_field_errors=True)\n            def consistency_validation(self, data, **kwargs):\n                errors: dict[str, str | dict] = {}\n                if data[\"bar\"][\"baz\"] != data[\"foo\"]:\n                    errors[\"bar\"] = {\"baz\": \"Non-matching value\"}\n                if data[\"bam\"] > data[\"foo\"]:\n                    errors[\"bam\"] = \"Value should be less than foo\"\n                if errors:\n                    raise ValidationError(errors)\n\n        schema = MySchema()\n        errors = schema.validate({\"foo\": 2, \"bar\": {\"baz\": 5}, \"bam\": 6})\n        assert errors[\"bar\"][\"baz\"] == \"Non-matching value\"\n        assert errors[\"bam\"] == \"Value should be less than foo\"\n\n    # https://github.com/marshmallow-code/marshmallow/issues/273\n    def test_allow_arbitrary_field_names_in_error(self):\n        class MySchema(Schema):\n            @validates_schema\n            def validator(self, data, **kwargs):\n                raise ValidationError(\"Error message\", \"arbitrary_key\")\n\n        errors = MySchema().validate({})\n        assert errors[\"arbitrary_key\"] == [\"Error message\"]\n\n    def test_skip_on_field_errors(self):\n        class MySchema(Schema):\n            foo = fields.Int(required=True, validate=validate.Equal(3))\n            bar = fields.Int(required=True)\n\n            @validates_schema(skip_on_field_errors=True)\n            def validate_schema(self, data, **kwargs):\n                if data[\"foo\"] != data[\"bar\"]:\n                    raise ValidationError(\"Foo and bar must be equal.\")\n\n            @validates_schema(skip_on_field_errors=True, pass_collection=True)\n            def validate_many(self, data, many, **kwargs):\n                if many:\n                    assert type(data) is list\n                    if len(data) < 2:\n                        raise ValidationError(\"Must provide at least 2 items\")\n\n        schema = MySchema()\n        # check that schema errors still occur with no field errors\n        errors = schema.validate({\"foo\": 3, \"bar\": 4})\n        assert \"_schema\" in errors\n        assert errors[\"_schema\"][0] == \"Foo and bar must be equal.\"\n\n        errors = schema.validate([{\"foo\": 3, \"bar\": 3}], many=True)\n        assert \"_schema\" in errors\n        assert errors[\"_schema\"][0] == \"Must provide at least 2 items\"\n\n        # check that schema errors don't occur when field errors do\n        errors = schema.validate({\"foo\": 3, \"bar\": \"not an int\"})\n        assert \"bar\" in errors\n        assert \"_schema\" not in errors\n\n        errors = schema.validate({\"foo\": 2, \"bar\": 2})\n        assert \"foo\" in errors\n        assert \"_schema\" not in errors\n\n        errors = schema.validate([{\"foo\": 3, \"bar\": \"not an int\"}], many=True)\n        assert \"bar\" in errors[0]\n        assert \"_schema\" not in errors\n\n    # https://github.com/marshmallow-code/marshmallow/issues/2170\n    def test_data_key_is_used_in_errors_dict(self):\n        class MySchema(Schema):\n            foo = fields.Int(data_key=\"fooKey\")\n\n            @validates(\"foo\")\n            def validate_foo(self, value, **kwargs):\n                raise ValidationError(\"from validates\")\n\n            @validates_schema(skip_on_field_errors=False)\n            def validate_schema(self, data, **kwargs):\n                raise ValidationError(\"from validates_schema str\", field_name=\"foo\")\n\n            @validates_schema(skip_on_field_errors=False)\n            def validate_schema2(self, data, **kwargs):\n                raise ValidationError({\"fooKey\": \"from validates_schema dict\"})\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"fooKey\": 42})\n        exc = excinfo.value\n        assert exc.messages == {\n            \"fooKey\": [\n                \"from validates\",\n                \"from validates_schema str\",\n                \"from validates_schema dict\",\n            ]\n        }\n\n\ndef test_decorator_error_handling():\n    class ExampleSchema(Schema):\n        foo = fields.Int()\n        bar = fields.Int()\n\n        @pre_load()\n        def pre_load_error1(self, item, **kwargs):\n            if item[\"foo\"] != 0:\n                return item\n            errors = {\"foo\": [\"preloadmsg1\"], \"bar\": [\"preloadmsg2\", \"preloadmsg3\"]}\n            raise ValidationError(errors)\n\n        @pre_load()\n        def pre_load_error2(self, item, **kwargs):\n            if item[\"foo\"] != 4:\n                return item\n            raise ValidationError(\"preloadmsg1\", \"foo\")\n\n        @pre_load()\n        def pre_load_error3(self, item, **kwargs):\n            if item[\"foo\"] != 8:\n                return item\n            raise ValidationError(\"preloadmsg1\")\n\n        @post_load()\n        def post_load_error1(self, item, **kwargs):\n            if item[\"foo\"] != 1:\n                return item\n            errors = {\"foo\": [\"postloadmsg1\"], \"bar\": [\"postloadmsg2\", \"postloadmsg3\"]}\n            raise ValidationError(errors)\n\n        @post_load()\n        def post_load_error2(self, item, **kwargs):\n            if item[\"foo\"] != 5:\n                return item\n            raise ValidationError(\"postloadmsg1\", \"foo\")\n\n    def make_item(foo, bar):\n        data = schema.load({\"foo\": foo, \"bar\": bar})\n        assert data is not None\n        return data\n\n    schema = ExampleSchema()\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"foo\": 0, \"bar\": 1})\n    errors = excinfo.value.messages\n    assert \"foo\" in errors\n    assert len(errors[\"foo\"]) == 1\n    assert errors[\"foo\"][0] == \"preloadmsg1\"\n    assert \"bar\" in errors\n    assert len(errors[\"bar\"]) == 2\n    assert \"preloadmsg2\" in errors[\"bar\"]\n    assert \"preloadmsg3\" in errors[\"bar\"]\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"foo\": 1, \"bar\": 1})\n    errors = excinfo.value.messages\n    assert \"foo\" in errors\n    assert len(errors[\"foo\"]) == 1\n    assert errors[\"foo\"][0] == \"postloadmsg1\"\n    assert \"bar\" in errors\n    assert len(errors[\"bar\"]) == 2\n    assert \"postloadmsg2\" in errors[\"bar\"]\n    assert \"postloadmsg3\" in errors[\"bar\"]\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"foo\": 4, \"bar\": 1})\n    errors = excinfo.value.messages\n    assert len(errors) == 1\n    assert \"foo\" in errors\n    assert len(errors[\"foo\"]) == 1\n    assert errors[\"foo\"][0] == \"preloadmsg1\"\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"foo\": 5, \"bar\": 1})\n    errors = excinfo.value.messages\n    assert len(errors) == 1\n    assert \"foo\" in errors\n    assert len(errors[\"foo\"]) == 1\n    assert errors[\"foo\"][0] == \"postloadmsg1\"\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"foo\": 8, \"bar\": 1})\n    errors = excinfo.value.messages\n    assert len(errors) == 1\n    assert \"_schema\" in errors\n    assert len(errors[\"_schema\"]) == 1\n    assert errors[\"_schema\"][0] == \"preloadmsg1\"\n\n\n@pytest.mark.parametrize(\"decorator\", [pre_load, post_load])\ndef test_decorator_error_handling_with_load(decorator):\n    class ExampleSchema(Schema):\n        @decorator\n        def raise_value_error(self, item, **kwargs):\n            raise ValidationError({\"foo\": \"error\"})\n\n    schema = ExampleSchema()\n    with pytest.raises(ValidationError) as exc:\n        schema.load({})\n    assert exc.value.messages == {\"foo\": \"error\"}\n    schema.dump(object())\n\n\n@pytest.mark.parametrize(\"decorator\", [pre_load, post_load])\ndef test_decorator_error_handling_with_load_dict_error(decorator):\n    class ExampleSchema(Schema):\n        @decorator\n        def raise_value_error(self, item, **kwargs):\n            raise ValidationError({\"foo\": \"error\"}, \"nested_field\")\n\n    schema = ExampleSchema()\n    with pytest.raises(ValidationError) as exc:\n        schema.load({})\n    assert exc.value.messages == {\"nested_field\": {\"foo\": \"error\"}}\n    schema.dump(object())\n\n\n@pytest.mark.parametrize(\"decorator\", [pre_dump, post_dump])\ndef test_decorator_error_handling_with_dump(decorator):\n    class ExampleSchema(Schema):\n        @decorator\n        def raise_value_error(self, item, **kwargs):\n            raise ValidationError({\"foo\": \"error\"})\n\n    schema = ExampleSchema()\n    with pytest.raises(ValidationError) as exc:\n        schema.dump(object())\n    assert exc.value.messages == {\"foo\": \"error\"}\n    schema.load({})\n\n\nclass Nested:\n    def __init__(self, foo):\n        self.foo = foo\n\n\nclass Example:\n    def __init__(self, nested):\n        self.nested = nested\n\n\nexample = Example(nested=[Nested(x) for x in range(1)])\n\n\n@pytest.mark.parametrize(\n    (\"data\", \"expected_data\", \"expected_original_data\"),\n    ([example, {\"foo\": 0}, example.nested[0]],),\n)\ndef test_decorator_post_dump_with_nested_original_and_pass_collection(\n    data, expected_data, expected_original_data\n):\n    class NestedSchema(Schema):\n        foo = fields.Int(required=True)\n\n        @post_dump(pass_collection=False, pass_original=True)\n        def check_pass_original_when_pass_collection_false(\n            self, data, original_data, **kwargs\n        ):\n            assert data == expected_data\n            assert original_data == expected_original_data\n            return data\n\n        @post_dump(pass_collection=True, pass_original=True)\n        def check_pass_original_when_pass_collection_true(\n            self, data, original_data, many, **kwargs\n        ):\n            assert many is True\n            assert data == [expected_data]\n            assert original_data == [expected_original_data]\n            return data\n\n    class ExampleSchema(Schema):\n        nested = fields.Nested(NestedSchema, required=True, many=True)\n\n    schema = ExampleSchema()\n    assert schema.dump(data) == {\"nested\": [{\"foo\": 0}]}\n\n\n@pytest.mark.parametrize(\n    (\"data\", \"expected_data\", \"expected_original_data\"),\n    ([{\"nested\": [{\"foo\": 0}]}, {\"foo\": 0}, {\"foo\": 0}],),\n)\ndef test_decorator_post_load_with_nested_original_and_pass_collection(\n    data, expected_data, expected_original_data\n):\n    class NestedSchema(Schema):\n        foo = fields.Int(required=True)\n\n        @post_load(pass_collection=False, pass_original=True)\n        def check_pass_original_when_pass_collection_false(\n            self, data, original_data, **kwargs\n        ):\n            assert data == expected_data\n            assert original_data == expected_original_data\n            return data\n\n        @post_load(pass_collection=True, pass_original=True)\n        def check_pass_original_when_pass_collection_true(\n            self, data, original_data, many, **kwargs\n        ):\n            assert many is True\n            assert data == [expected_data]\n            assert original_data == [expected_original_data]\n            return data\n\n    class ExampleSchema(Schema):\n        nested = fields.Nested(NestedSchema, required=True, many=True)\n\n    schema = ExampleSchema()\n    assert schema.load(data) == data\n\n\n@pytest.mark.parametrize(\"usage_location\", [\"meta\", \"init\", \"load\"])\n@pytest.mark.parametrize(\"unknown_val\", (EXCLUDE, INCLUDE))\ndef test_load_processors_receive_unknown(usage_location, unknown_val):\n    class ExampleSchema(Schema):\n        foo = fields.Int()\n\n        @validates_schema\n        def check_unknown_validates(self, data, unknown, **kwargs):\n            assert unknown == unknown_val\n\n        @pre_load\n        def check_unknown_pre(self, data, unknown, **kwargs):\n            assert unknown == unknown_val\n            return data\n\n        @post_load\n        def check_unknown_post(self, data, unknown, **kwargs):\n            assert unknown == unknown_val\n            return data\n\n    if usage_location == \"meta\":\n\n        class ExampleSchemaChild(ExampleSchema):\n            class Meta:\n                unknown = unknown_val\n\n        ExampleSchemaChild().load({\"foo\": 42})\n    if usage_location == \"init\":\n        ExampleSchema(unknown=unknown_val).load({\"foo\": 42})\n    else:\n        ExampleSchema().load({\"foo\": 42}, unknown=unknown_val)\n\n\n# https://github.com/marshmallow-code/marshmallow/issues/1755\ndef test_post_load_method_that_appends_to_data():\n    class MySchema(Schema):\n        foo = fields.Int()\n\n        @post_load(pass_collection=True)\n        def append_to_data(self, data, **kwargs):\n            data.append({\"foo\": 42})\n            return data\n\n        @post_load(pass_collection=False, pass_original=True)\n        def noop(self, data, original_data, **kwargs):\n            if original_data is None:  # added item\n                assert data == {\"foo\": 42}\n            else:\n                assert original_data == {\"foo\": 24}\n                assert data == {\"foo\": 24}\n            return data\n\n    schema = MySchema(many=True)\n    assert schema.load([{\"foo\": 24}]) == [{\"foo\": 24}, {\"foo\": 42}]\n"
  },
  {
    "path": "tests/test_deserialization.py",
    "content": "# mypy: disable-error-code=\"arg-type\"\nimport datetime as dt\nimport decimal\nimport ipaddress\nimport math\nimport uuid\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom marshmallow import (\n    EXCLUDE,\n    INCLUDE,\n    RAISE,\n    Schema,\n    fields,\n    missing,\n    validate,\n)\nfrom marshmallow.exceptions import ValidationError\nfrom tests.base import (\n    ALL_FIELDS,\n    DateEnum,\n    GenderEnum,\n    HairColorEnum,\n    assert_date_equal,\n    assert_time_equal,\n    central,\n    predicate,\n)\n\n\nclass MockDateTimeOverflowError(dt.datetime):\n    \"\"\"Used to simulate the possible OverflowError of datetime.fromtimestamp\"\"\"\n\n    def fromtimestamp(self, *args, **kwargs):  # type: ignore[override]\n        raise OverflowError\n\n\nclass MockDateTimeOSError(dt.datetime):\n    \"\"\"Used to simulate the possible OSError of datetime.fromtimestamp\"\"\"\n\n    def fromtimestamp(self, *args, **kwargs):  # type: ignore[override]\n        raise OSError\n\n\nclass TestDeserializingNone:\n    @pytest.mark.parametrize(\"FieldClass\", ALL_FIELDS)\n    def test_fields_allow_none_deserialize_to_none(self, FieldClass):\n        field = FieldClass(allow_none=True)\n        assert field.deserialize(None) is None\n\n    # https://github.com/marshmallow-code/marshmallow/issues/111\n    @pytest.mark.parametrize(\"FieldClass\", ALL_FIELDS)\n    def test_fields_dont_allow_none_by_default(self, FieldClass):\n        field = FieldClass()\n        with pytest.raises(ValidationError, match=\"Field may not be null.\"):\n            field.deserialize(None)\n\n    def test_allow_none_is_true_if_missing_is_true(self):\n        field = fields.Raw(load_default=None)\n        assert field.allow_none is True\n        assert field.deserialize(None) is None\n\n    def test_list_field_deserialize_none_to_none(self):\n        field = fields.List(fields.String(allow_none=True), allow_none=True)\n        assert field.deserialize(None) is None\n\n    def test_tuple_field_deserialize_none_to_none(self):\n        field = fields.Tuple([fields.String()], allow_none=True)\n        assert field.deserialize(None) is None\n\n    def test_list_of_nested_allow_none_deserialize_none_to_none(self):\n        field = fields.List(fields.Nested(Schema(), allow_none=True))\n        assert field.deserialize([None]) == [None]\n\n    def test_list_of_nested_non_allow_none_deserialize_none_to_validation_error(self):\n        field = fields.List(fields.Nested(Schema(), allow_none=False))\n        with pytest.raises(ValidationError):\n            field.deserialize([None])\n\n\nclass TestFieldDeserialization:\n    def test_float_field_deserialization(self):\n        field = fields.Float()\n        assert math.isclose(field.deserialize(\"12.3\"), 12.3)\n        assert math.isclose(field.deserialize(12.3), 12.3)\n\n    @pytest.mark.parametrize(\"in_val\", [\"bad\", \"\", {}, True, False])\n    def test_invalid_float_field_deserialization(self, in_val):\n        field = fields.Float()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_val)\n        assert excinfo.value.args[0] == \"Not a valid number.\"\n\n    def test_float_field_overflow(self):\n        field = fields.Float()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(2**1024)\n        assert excinfo.value.args[0] == \"Number too large.\"\n\n    def test_integer_field_deserialization(self):\n        field = fields.Integer()\n        assert field.deserialize(\"42\") == 42\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"42.0\")\n        assert excinfo.value.args[0] == \"Not a valid integer.\"\n        with pytest.raises(ValidationError):\n            field.deserialize(\"bad\")\n        assert excinfo.value.args[0] == \"Not a valid integer.\"\n        with pytest.raises(ValidationError):\n            field.deserialize({})\n        assert excinfo.value.args[0] == \"Not a valid integer.\"\n\n    def test_strict_integer_field_deserialization(self):\n        field = fields.Integer(strict=True)\n        assert field.deserialize(42) == 42\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(42.0)\n        assert excinfo.value.args[0] == \"Not a valid integer.\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(decimal.Decimal(\"42.0\"))\n        assert excinfo.value.args[0] == \"Not a valid integer.\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"42\")\n        assert excinfo.value.args[0] == \"Not a valid integer.\"\n\n    def test_decimal_field_deserialization(self):\n        m1 = 12\n        m2 = \"12.355\"\n        m3 = decimal.Decimal(1)\n        m4 = 3.14\n        m5 = \"abc\"\n        m6 = [1, 2]\n\n        field = fields.Decimal()\n        assert isinstance(field.deserialize(m1), decimal.Decimal)\n        assert field.deserialize(m1) == decimal.Decimal(12)\n        assert isinstance(field.deserialize(m2), decimal.Decimal)\n        assert field.deserialize(m2) == decimal.Decimal(\"12.355\")\n        assert isinstance(field.deserialize(m3), decimal.Decimal)\n        assert field.deserialize(m3) == decimal.Decimal(1)\n        assert isinstance(field.deserialize(m4), decimal.Decimal)\n        assert field.deserialize(m4).as_tuple() == (0, (3, 1, 4), -2)\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(m5)\n        assert excinfo.value.args[0] == \"Not a valid number.\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(m6)\n        assert excinfo.value.args[0] == \"Not a valid number.\"\n\n    def test_decimal_field_with_places(self):\n        m1 = 12\n        m2 = \"12.355\"\n        m3 = decimal.Decimal(1)\n        m4 = \"abc\"\n        m5 = [1, 2]\n\n        field = fields.Decimal(1)\n        assert isinstance(field.deserialize(m1), decimal.Decimal)\n        assert field.deserialize(m1) == decimal.Decimal(12)\n        assert isinstance(field.deserialize(m2), decimal.Decimal)\n        assert field.deserialize(m2) == decimal.Decimal(\"12.4\")\n        assert isinstance(field.deserialize(m3), decimal.Decimal)\n        assert field.deserialize(m3) == decimal.Decimal(1)\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(m4)\n        assert excinfo.value.args[0] == \"Not a valid number.\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(m5)\n        assert excinfo.value.args[0] == \"Not a valid number.\"\n\n    def test_decimal_field_with_places_and_rounding(self):\n        m1 = 12\n        m2 = \"12.355\"\n        m3 = decimal.Decimal(1)\n        m4 = \"abc\"\n        m5 = [1, 2]\n\n        field = fields.Decimal(1, decimal.ROUND_DOWN)\n        assert isinstance(field.deserialize(m1), decimal.Decimal)\n        assert field.deserialize(m1) == decimal.Decimal(12)\n        assert isinstance(field.deserialize(m2), decimal.Decimal)\n        assert field.deserialize(m2) == decimal.Decimal(\"12.3\")\n        assert isinstance(field.deserialize(m3), decimal.Decimal)\n        assert field.deserialize(m3) == decimal.Decimal(1)\n        with pytest.raises(ValidationError):\n            field.deserialize(m4)\n        with pytest.raises(ValidationError):\n            field.deserialize(m5)\n\n    def test_decimal_field_deserialization_string(self):\n        m1 = 12\n        m2 = \"12.355\"\n        m3 = decimal.Decimal(1)\n        m4 = \"abc\"\n        m5 = [1, 2]\n\n        field = fields.Decimal(as_string=True)\n        assert isinstance(field.deserialize(m1), decimal.Decimal)\n        assert field.deserialize(m1) == decimal.Decimal(12)\n        assert isinstance(field.deserialize(m2), decimal.Decimal)\n        assert field.deserialize(m2) == decimal.Decimal(\"12.355\")\n        assert isinstance(field.deserialize(m3), decimal.Decimal)\n        assert field.deserialize(m3) == decimal.Decimal(1)\n        with pytest.raises(ValidationError):\n            field.deserialize(m4)\n        with pytest.raises(ValidationError):\n            field.deserialize(m5)\n\n    def test_decimal_field_special_values(self):\n        m1 = \"-NaN\"\n        m2 = \"NaN\"\n        m3 = \"-sNaN\"\n        m4 = \"sNaN\"\n        m5 = \"-Infinity\"\n        m6 = \"Infinity\"\n        m7 = \"-0\"\n\n        field = fields.Decimal(places=2, allow_nan=True)\n\n        m1d = field.deserialize(m1)\n        assert isinstance(m1d, decimal.Decimal)\n        assert m1d.is_qnan()\n        assert not m1d.is_signed()\n\n        m2d = field.deserialize(m2)\n        assert isinstance(m2d, decimal.Decimal)\n        assert m2d.is_qnan()\n        assert not m2d.is_signed()\n\n        m3d = field.deserialize(m3)\n        assert isinstance(m3d, decimal.Decimal)\n        assert m3d.is_qnan()\n        assert not m3d.is_signed()\n\n        m4d = field.deserialize(m4)\n        assert isinstance(m4d, decimal.Decimal)\n        assert m4d.is_qnan()\n        assert not m4d.is_signed()\n\n        m5d = field.deserialize(m5)\n        assert isinstance(m5d, decimal.Decimal)\n        assert m5d.is_infinite()\n        assert m5d.is_signed()\n\n        m6d = field.deserialize(m6)\n        assert isinstance(m6d, decimal.Decimal)\n        assert m6d.is_infinite()\n        assert not m6d.is_signed()\n\n        m7d = field.deserialize(m7)\n        assert isinstance(m7d, decimal.Decimal)\n        assert m7d.is_zero()\n        assert m7d.is_signed()\n\n    def test_decimal_field_special_values_not_permitted(self):\n        m1 = \"-NaN\"\n        m2 = \"NaN\"\n        m3 = \"-sNaN\"\n        m4 = \"sNaN\"\n        m5 = \"-Infinity\"\n        m6 = \"Infinity\"\n        m7 = \"-0\"\n\n        field = fields.Decimal(places=2)\n\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(m1)\n        assert str(excinfo.value.args[0]) == (\n            \"Special numeric values (nan or infinity) are not permitted.\"\n        )\n        with pytest.raises(ValidationError):\n            field.deserialize(m2)\n        with pytest.raises(ValidationError):\n            field.deserialize(m3)\n        with pytest.raises(ValidationError):\n            field.deserialize(m4)\n        with pytest.raises(ValidationError):\n            field.deserialize(m5)\n        with pytest.raises(ValidationError):\n            field.deserialize(m6)\n\n        m7d = field.deserialize(m7)\n        assert isinstance(m7d, decimal.Decimal)\n        assert m7d.is_zero()\n        assert m7d.is_signed()\n\n    @pytest.mark.parametrize(\"allow_nan\", (None, False, True))\n    @pytest.mark.parametrize(\"value\", (\"nan\", \"-nan\", \"inf\", \"-inf\"))\n    def test_float_field_allow_nan(self, value, allow_nan):\n        if allow_nan is None:\n            # Test default case is False\n            field = fields.Float()\n        else:\n            field = fields.Float(allow_nan=allow_nan)\n\n        if allow_nan is True:\n            res = field.deserialize(value)\n            assert isinstance(res, float)\n            if value.endswith(\"nan\"):\n                assert math.isnan(res)\n            else:\n                assert res == float(value)\n        else:\n            with pytest.raises(ValidationError) as excinfo:\n                field.deserialize(value)\n            assert str(excinfo.value.args[0]) == (\n                \"Special numeric values (nan or infinity) are not permitted.\"\n            )\n\n    def test_string_field_deserialization(self):\n        field = fields.String()\n        assert field.deserialize(\"foo\") == \"foo\"\n        assert field.deserialize(b\"foo\") == \"foo\"\n\n        # https://github.com/marshmallow-code/marshmallow/issues/231\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(42)\n        assert excinfo.value.args[0] == \"Not a valid string.\"\n\n        with pytest.raises(ValidationError):\n            field.deserialize({})\n\n    def test_boolean_field_deserialization(self):\n        field = fields.Boolean()\n        assert field.deserialize(True) is True\n        assert field.deserialize(False) is False\n        assert field.deserialize(\"True\") is True\n        assert field.deserialize(\"False\") is False\n        assert field.deserialize(\"true\") is True\n        assert field.deserialize(\"false\") is False\n        assert field.deserialize(\"1\") is True\n        assert field.deserialize(\"0\") is False\n        assert field.deserialize(\"on\") is True\n        assert field.deserialize(\"ON\") is True\n        assert field.deserialize(\"On\") is True\n        assert field.deserialize(\"off\") is False\n        assert field.deserialize(\"OFF\") is False\n        assert field.deserialize(\"Off\") is False\n        assert field.deserialize(\"y\") is True\n        assert field.deserialize(\"Y\") is True\n        assert field.deserialize(\"yes\") is True\n        assert field.deserialize(\"YES\") is True\n        assert field.deserialize(\"Yes\") is True\n        assert field.deserialize(\"n\") is False\n        assert field.deserialize(\"N\") is False\n        assert field.deserialize(\"no\") is False\n        assert field.deserialize(\"NO\") is False\n        assert field.deserialize(\"No\") is False\n        assert field.deserialize(1) is True\n        assert field.deserialize(0) is False\n\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({})\n        assert excinfo.value.args[0] == \"Not a valid boolean.\"\n\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(42)\n\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"invalid-string\")\n\n    def test_boolean_field_deserialization_with_custom_truthy_values(self):\n        class MyBoolean(fields.Boolean):\n            truthy = {\"yep\"}\n\n        field = MyBoolean()\n        assert field.deserialize(\"yep\") is True\n\n        field2 = fields.Boolean(truthy=(\"yep\",))\n        assert field2.deserialize(\"yep\") is True\n        assert field2.deserialize(False) is False\n\n    @pytest.mark.parametrize(\"in_val\", [\"notvalid\", 123])\n    def test_boolean_field_deserialization_with_custom_truthy_values_invalid(\n        self, in_val\n    ):\n        class MyBoolean(fields.Boolean):\n            truthy = {\"yep\"}\n\n        field = MyBoolean()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_val)\n        expected_msg = \"Not a valid boolean.\"\n        assert str(excinfo.value.args[0]) == expected_msg\n\n        field2 = fields.Boolean(truthy={\"yep\"})\n        with pytest.raises(ValidationError) as excinfo:\n            field2.deserialize(in_val)\n        expected_msg = \"Not a valid boolean.\"\n        assert str(excinfo.value.args[0]) == expected_msg\n\n        field3 = MyBoolean(error_messages={\"invalid\": \"bad input\"})\n        with pytest.raises(ValidationError) as excinfo:\n            field3.deserialize(in_val)\n        assert str(excinfo.value.args[0]) == \"bad input\"\n\n    def test_boolean_field_deserialization_with_empty_truthy(self):\n        field = fields.Boolean(truthy=set())\n        assert field.deserialize(\"yep\") is True\n        assert field.deserialize(True) is True\n        assert field.deserialize(False) is False\n\n    def test_boolean_field_deserialization_with_custom_falsy_values(self):\n        field = fields.Boolean(falsy=(\"nope\",))\n        assert field.deserialize(\"nope\") is False\n        assert field.deserialize(True) is True\n\n    def test_field_toggle_show_invalid_value_in_error_message(self):\n        error_messages = {\"invalid\": \"Not valid: {input}\"}\n        boolfield = fields.Boolean(error_messages=error_messages)\n        with pytest.raises(ValidationError) as excinfo:\n            boolfield.deserialize(\"notabool\")\n        assert str(excinfo.value.args[0]) == \"Not valid: notabool\"\n\n        numfield = fields.Float(error_messages=error_messages)\n        with pytest.raises(ValidationError) as excinfo:\n            numfield.deserialize(\"notanum\")\n        assert str(excinfo.value.args[0]) == \"Not valid: notanum\"\n\n        intfield = fields.Integer(error_messages=error_messages)\n        with pytest.raises(ValidationError) as excinfo:\n            intfield.deserialize(\"notanint\")\n        assert str(excinfo.value.args[0]) == \"Not valid: notanint\"\n\n        date_error_messages = {\"invalid\": \"Not a valid {obj_type}: {input}\"}\n        datefield = fields.DateTime(error_messages=date_error_messages)\n        with pytest.raises(ValidationError) as excinfo:\n            datefield.deserialize(\"notadate\")\n        assert str(excinfo.value.args[0]) == \"Not a valid datetime: notadate\"\n\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\n            \"not-a-datetime\",\n            42,\n            True,\n            False,\n            0,\n            \"\",\n            [],\n            \"2018\",\n            \"2018-01\",\n            dt.datetime.now().strftime(\"%H:%M:%S %Y-%m-%d\"),\n            dt.datetime.now().strftime(\"%m-%d-%Y %H:%M:%S\"),\n        ],\n    )\n    def test_invalid_datetime_deserialization(self, in_value):\n        field = fields.DateTime()\n        with pytest.raises(ValidationError, match=\"Not a valid datetime.\"):\n            field.deserialize(in_value)\n\n    def test_custom_date_format_datetime_field_deserialization(self):\n        # Datetime string with format \"%H:%M:%S.%f %Y-%m-%d\"\n        datestring = \"10:11:12.123456 2019-01-02\"\n\n        # Deserialization should fail when datestring is not of same format\n        field = fields.DateTime(format=\"%d-%m-%Y %H:%M:%S\")\n        with pytest.raises(ValidationError, match=\"Not a valid datetime.\"):\n            field.deserialize(datestring)\n\n        field = fields.DateTime(format=\"%H:%M:%S.%f %Y-%m-%d\")\n        assert field.deserialize(datestring) == dt.datetime(\n            2019, 1, 2, 10, 11, 12, 123456\n        )\n\n        field = fields.NaiveDateTime(format=\"%H:%M:%S.%f %Y-%m-%d\")\n        assert field.deserialize(datestring) == dt.datetime(\n            2019, 1, 2, 10, 11, 12, 123456\n        )\n\n        field = fields.AwareDateTime(format=\"%H:%M:%S.%f %Y-%m-%d\")\n        with pytest.raises(ValidationError, match=\"Not a valid aware datetime.\"):\n            field.deserialize(datestring)\n\n    @pytest.mark.parametrize(\"fmt\", [\"rfc\", \"rfc822\"])\n    @pytest.mark.parametrize(\n        (\"value\", \"expected\", \"aware\"),\n        [\n            (\n                \"Sun, 10 Nov 2013 01:23:45 -0000\",\n                dt.datetime(2013, 11, 10, 1, 23, 45),\n                False,\n            ),\n            (\n                \"Sun, 10 Nov 2013 01:23:45 +0000\",\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=dt.timezone.utc),\n                True,\n            ),\n            (\n                \"Sun, 10 Nov 2013 01:23:45 -0600\",\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=central),\n                True,\n            ),\n        ],\n    )\n    def test_rfc_datetime_field_deserialization(self, fmt, value, expected, aware):\n        field = fields.DateTime(format=fmt)\n        assert field.deserialize(value) == expected\n        field = fields.NaiveDateTime(format=fmt)\n        if aware:\n            with pytest.raises(ValidationError, match=\"Not a valid naive datetime.\"):\n                field.deserialize(value)\n        else:\n            assert field.deserialize(value) == expected\n        field = fields.AwareDateTime(format=fmt)\n        if not aware:\n            with pytest.raises(ValidationError, match=\"Not a valid aware datetime.\"):\n                field.deserialize(value)\n        else:\n            assert field.deserialize(value) == expected\n\n    @pytest.mark.parametrize(\"fmt\", [\"iso\", \"iso8601\"])\n    @pytest.mark.parametrize(\n        (\"value\", \"expected\", \"aware\"),\n        [\n            (\"2013-11-10T01:23:45\", dt.datetime(2013, 11, 10, 1, 23, 45), False),\n            (\n                \"2013-11-10T01:23:45+00:00\",\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=dt.timezone.utc),\n                True,\n            ),\n            (\n                # Regression test for https://github.com/marshmallow-code/marshmallow/issues/1251\n                \"2013-11-10T01:23:45.123+00:00\",\n                dt.datetime(2013, 11, 10, 1, 23, 45, 123000, tzinfo=dt.timezone.utc),\n                True,\n            ),\n            (\n                \"2013-11-10T01:23:45.123456+00:00\",\n                dt.datetime(2013, 11, 10, 1, 23, 45, 123456, tzinfo=dt.timezone.utc),\n                True,\n            ),\n            (\n                \"2013-11-10T01:23:45-06:00\",\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=central),\n                True,\n            ),\n        ],\n    )\n    def test_iso_datetime_field_deserialization(self, fmt, value, expected, aware):\n        field = fields.DateTime(format=fmt)\n        assert field.deserialize(value) == expected\n        field = fields.NaiveDateTime(format=fmt)\n        if aware:\n            with pytest.raises(ValidationError, match=\"Not a valid naive datetime.\"):\n                field.deserialize(value)\n        else:\n            assert field.deserialize(value) == expected\n        field = fields.AwareDateTime(format=fmt)\n        if not aware:\n            with pytest.raises(ValidationError, match=\"Not a valid aware datetime.\"):\n                field.deserialize(value)\n        else:\n            assert field.deserialize(value) == expected\n\n    @pytest.mark.parametrize(\n        (\"fmt\", \"value\", \"expected\"),\n        [\n            (\"timestamp\", 1384043025, dt.datetime(2013, 11, 10, 0, 23, 45)),\n            (\"timestamp\", \"1384043025\", dt.datetime(2013, 11, 10, 0, 23, 45)),\n            (\"timestamp\", 1384043025.12, dt.datetime(2013, 11, 10, 0, 23, 45, 120000)),\n            (\n                \"timestamp\",\n                1384043025.123456,\n                dt.datetime(2013, 11, 10, 0, 23, 45, 123456),\n            ),\n            (\"timestamp\", 1, dt.datetime(1970, 1, 1, 0, 0, 1)),\n            (\"timestamp_ms\", 1384043025000, dt.datetime(2013, 11, 10, 0, 23, 45)),\n            (\"timestamp_ms\", 1000, dt.datetime(1970, 1, 1, 0, 0, 1)),\n        ],\n    )\n    def test_timestamp_field_deserialization(self, fmt, value, expected):\n        field = fields.DateTime(format=fmt)\n        assert field.deserialize(value) == expected\n\n        # By default, a datetime from a timestamp is never aware.\n        field = fields.NaiveDateTime(format=fmt)\n        assert field.deserialize(value) == expected\n\n        field = fields.AwareDateTime(format=fmt)\n        with pytest.raises(ValidationError, match=\"Not a valid aware datetime.\"):\n            field.deserialize(value)\n\n        # But it can be added by providing a default.\n        field = fields.AwareDateTime(format=fmt, default_timezone=central)\n        expected_aware = expected.replace(tzinfo=central)\n        assert field.deserialize(value) == expected_aware\n\n    @pytest.mark.parametrize(\"fmt\", [\"timestamp\", \"timestamp_ms\"])\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\"\", \"!@#\", -1],\n    )\n    def test_invalid_timestamp_field_deserialization(self, fmt, in_value):\n        field = fields.DateTime(format=fmt)\n        with pytest.raises(ValidationError, match=\"Not a valid datetime.\"):\n            field.deserialize(in_value)\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/pull/2102\n    @pytest.mark.parametrize(\"fmt\", [\"timestamp\", \"timestamp_ms\"])\n    @pytest.mark.parametrize(\n        \"mock_fromtimestamp\", [MockDateTimeOSError, MockDateTimeOverflowError]\n    )\n    def test_oversized_timestamp_field_deserialization(self, fmt, mock_fromtimestamp):\n        with patch(\"datetime.datetime\", mock_fromtimestamp):\n            field = fields.DateTime(format=fmt)\n            with pytest.raises(ValidationError, match=\"Not a valid datetime.\"):\n                field.deserialize(99999999999999999)\n\n    @pytest.mark.parametrize(\n        (\"fmt\", \"timezone\", \"value\", \"expected\"),\n        [\n            (\"iso\", None, \"2013-11-10T01:23:45\", dt.datetime(2013, 11, 10, 1, 23, 45)),\n            (\n                \"iso\",\n                dt.timezone.utc,\n                \"2013-11-10T01:23:45+00:00\",\n                dt.datetime(2013, 11, 10, 1, 23, 45),\n            ),\n            (\n                \"iso\",\n                central,\n                \"2013-11-10T01:23:45-03:00\",\n                dt.datetime(2013, 11, 9, 22, 23, 45),\n            ),\n            (\n                \"rfc\",\n                None,\n                \"Sun, 10 Nov 2013 01:23:45 -0000\",\n                dt.datetime(2013, 11, 10, 1, 23, 45),\n            ),\n            (\n                \"rfc\",\n                dt.timezone.utc,\n                \"Sun, 10 Nov 2013 01:23:45 +0000\",\n                dt.datetime(2013, 11, 10, 1, 23, 45),\n            ),\n            (\n                \"rfc\",\n                central,\n                \"Sun, 10 Nov 2013 01:23:45 -0300\",\n                dt.datetime(2013, 11, 9, 22, 23, 45),\n            ),\n        ],\n    )\n    def test_naive_datetime_with_timezone(self, fmt, timezone, value, expected):\n        field = fields.NaiveDateTime(format=fmt, timezone=timezone)\n        assert field.deserialize(value) == expected\n\n    @pytest.mark.parametrize(\"timezone\", (dt.timezone.utc, central))\n    @pytest.mark.parametrize(\n        (\"fmt\", \"value\"),\n        [(\"iso\", \"2013-11-10T01:23:45\"), (\"rfc\", \"Sun, 10 Nov 2013 01:23:45\")],\n    )\n    def test_aware_datetime_default_timezone(self, fmt, timezone, value):\n        field = fields.AwareDateTime(format=fmt, default_timezone=timezone)\n        assert field.deserialize(value) == dt.datetime(\n            2013, 11, 10, 1, 23, 45, tzinfo=timezone\n        )\n\n    def test_time_field_deserialization(self):\n        field = fields.Time()\n        t = dt.time(1, 23, 45)\n        t_formatted = t.isoformat()\n        result = field.deserialize(t_formatted)\n        assert isinstance(result, dt.time)\n        assert_time_equal(result, t)\n        # With microseconds\n        t2 = dt.time(1, 23, 45, 6789)\n        t2_formatted = t2.isoformat()\n        result2 = field.deserialize(t2_formatted)\n        assert_time_equal(result2, t2)\n\n    @pytest.mark.parametrize(\"in_data\", [\"badvalue\", \"\", [], 42])\n    def test_invalid_time_field_deserialization(self, in_data):\n        field = fields.Time()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_data)\n        assert excinfo.value.args[0] == \"Not a valid time.\"\n\n    def test_custom_time_format_time_field_deserialization(self):\n        # Time string with format \"%f.%S:%M:%H\"\n        timestring = \"123456.12:11:10\"\n\n        # Deserialization should fail when timestring is not of same format\n        field = fields.Time(format=\"%S:%M:%H\")\n        with pytest.raises(ValidationError, match=\"Not a valid time.\"):\n            field.deserialize(timestring)\n\n        field = fields.Time(format=\"%f.%S:%M:%H\")\n        assert field.deserialize(timestring) == dt.time(10, 11, 12, 123456)\n\n    @pytest.mark.parametrize(\"fmt\", [\"iso\", \"iso8601\", None])\n    @pytest.mark.parametrize(\n        (\"value\", \"expected\"),\n        [\n            (\"01:23:45\", dt.time(1, 23, 45)),\n            (\"01:23:45.123\", dt.time(1, 23, 45, 123000)),\n            (\"01:23:45.123456\", dt.time(1, 23, 45, 123456)),\n            (\n                \"01:23:45+01:00\",\n                dt.time(1, 23, 45, tzinfo=dt.timezone(dt.timedelta(seconds=3600))),\n            ),\n        ],\n    )\n    def test_iso_time_field_deserialization(self, fmt, value, expected):\n        if fmt is None:\n            field = fields.Time()\n        else:\n            field = fields.Time(format=fmt)\n        assert field.deserialize(value) == expected\n\n    def test_invalid_timedelta_precision(self):\n        with pytest.raises(ValueError, match=\"The precision must be one of: weeks,\"):\n            fields.TimeDelta(\"invalid\")\n\n    def test_timedelta_field_deserialization(self):\n        field = fields.TimeDelta()\n        result = field.deserialize(\"42\")\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 0\n        assert result.seconds == 42\n        assert result.microseconds == 0\n\n        field = fields.TimeDelta()\n        result = field.deserialize(\"42.9\")\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 0\n        assert result.seconds == 42\n        assert result.microseconds == 900000\n\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        result = field.deserialize(100000)\n        assert result.days == 1\n        assert result.seconds == 13600\n        assert result.microseconds == 0\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        result = field.deserialize(\"-42\")\n        assert isinstance(result, dt.timedelta)\n        assert result.days == -42\n        assert result.seconds == 0\n        assert result.microseconds == 0\n\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        result = field.deserialize(10**6 + 1)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 0\n        assert result.seconds == 1\n        assert result.microseconds == 1\n\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        result = field.deserialize(86400 * 10**6 + 1)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 1\n        assert result.seconds == 0\n        assert result.microseconds == 1\n\n        field = fields.TimeDelta()\n        result = field.deserialize(12.9)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 0\n        assert result.seconds == 12\n        assert result.microseconds == 900000\n\n        field = fields.TimeDelta(fields.TimeDelta.WEEKS)\n        result = field.deserialize(1)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 7\n        assert result.seconds == 0\n        assert result.microseconds == 0\n\n        field = fields.TimeDelta(fields.TimeDelta.HOURS)\n        result = field.deserialize(25)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 1\n        assert result.seconds == 3600\n        assert result.microseconds == 0\n\n        field = fields.TimeDelta(fields.TimeDelta.MINUTES)\n        result = field.deserialize(1441)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 1\n        assert result.seconds == 60\n        assert result.microseconds == 0\n\n        field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)\n        result = field.deserialize(123456)\n        assert isinstance(result, dt.timedelta)\n        assert result.days == 0\n        assert result.seconds == 123\n        assert result.microseconds == 456000\n\n        total_microseconds_value = 322.0\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        result = field.deserialize(total_microseconds_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(microseconds=1).total_seconds()\n        assert math.isclose(\n            result.total_seconds() / unit_value, total_microseconds_value\n        )\n\n        total_microseconds_value = 322.12345\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        result = field.deserialize(total_microseconds_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(microseconds=1).total_seconds()\n        assert math.isclose(\n            result.total_seconds() / unit_value, math.floor(total_microseconds_value)\n        )\n\n        total_milliseconds_value = 322.223\n        field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)\n        result = field.deserialize(total_milliseconds_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(milliseconds=1).total_seconds()\n        assert math.isclose(\n            result.total_seconds() / unit_value, total_milliseconds_value\n        )\n\n        total_seconds_value = 322.223\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        result = field.deserialize(total_seconds_value)\n        assert isinstance(result, dt.timedelta)\n        assert math.isclose(result.total_seconds(), total_seconds_value)\n\n        total_minutes_value = 322.223\n        field = fields.TimeDelta(fields.TimeDelta.MINUTES)\n        result = field.deserialize(total_minutes_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(minutes=1).total_seconds()\n        assert math.isclose(result.total_seconds() / unit_value, total_minutes_value)\n\n        total_hours_value = 322.223\n        field = fields.TimeDelta(fields.TimeDelta.HOURS)\n        result = field.deserialize(total_hours_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(hours=1).total_seconds()\n        assert math.isclose(result.total_seconds() / unit_value, total_hours_value)\n\n        total_days_value = 322.223\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        result = field.deserialize(total_days_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(days=1).total_seconds()\n        assert math.isclose(result.total_seconds() / unit_value, total_days_value)\n\n        total_weeks_value = 322.223\n        field = fields.TimeDelta(fields.TimeDelta.WEEKS)\n        result = field.deserialize(total_weeks_value)\n        assert isinstance(result, dt.timedelta)\n        unit_value = dt.timedelta(weeks=1).total_seconds()\n        assert math.isclose(result.total_seconds() / unit_value, total_weeks_value)\n\n    @pytest.mark.parametrize(\"in_value\", [\"\", \"badvalue\", [], 9999999999])\n    def test_invalid_timedelta_field_deserialization(self, in_value):\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n        assert excinfo.value.args[0] == \"Not a valid period of time.\"\n\n    @pytest.mark.parametrize(\"format\", (None, \"%Y-%m-%d\"))\n    def test_date_field_deserialization(self, format):  # noqa: A002\n        field = fields.Date(format=format)\n        d = dt.date(2014, 8, 21)\n        iso_date = d.isoformat()\n        result = field.deserialize(iso_date)\n        assert type(result) is dt.date\n        assert_date_equal(result, d)\n\n    @pytest.mark.parametrize(\n        \"in_value\", [\"\", 123, [], dt.date(2014, 8, 21).strftime(\"%d-%m-%Y\")]\n    )\n    def test_invalid_date_field_deserialization(self, in_value):\n        field = fields.Date()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n        msg = \"Not a valid date.\"\n        assert excinfo.value.args[0] == msg\n\n    def test_dict_field_deserialization(self):\n        data = {\"foo\": \"bar\"}\n        field = fields.Dict()\n        load = field.deserialize(data)\n        assert load == {\"foo\": \"bar\"}\n        # Check load is a distinct object\n        load[\"foo\"] = \"baz\"\n        assert data[\"foo\"] == \"bar\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"baddict\")\n        assert excinfo.value.args[0] == \"Not a valid mapping type.\"\n\n    def test_structured_dict_value_deserialization(self):\n        field = fields.Dict(values=fields.List(fields.Str))\n        assert field.deserialize({\"foo\": [\"bar\", \"baz\"]}) == {\"foo\": [\"bar\", \"baz\"]}\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({\"foo\": [1, 2], \"bar\": \"baz\", \"ham\": [\"spam\"]})\n        assert excinfo.value.args[0] == {\n            \"foo\": {\"value\": {0: [\"Not a valid string.\"], 1: [\"Not a valid string.\"]}},\n            \"bar\": {\"value\": [\"Not a valid list.\"]},\n        }\n        assert excinfo.value.valid_data == {\"foo\": [], \"ham\": [\"spam\"]}\n\n    def test_structured_dict_key_deserialization(self):\n        field = fields.Dict(keys=fields.Str)\n        assert field.deserialize({\"foo\": \"bar\"}) == {\"foo\": \"bar\"}\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({1: \"bar\", \"foo\": \"baz\"})\n        assert excinfo.value.args[0] == {1: {\"key\": [\"Not a valid string.\"]}}\n        assert excinfo.value.valid_data == {\"foo\": \"baz\"}\n\n    def test_structured_dict_key_value_deserialization(self):\n        field = fields.Dict(\n            keys=fields.Str(\n                validate=[validate.Email(), validate.Regexp(r\".*@test\\.com$\")]\n            ),\n            values=fields.Decimal,\n        )\n        assert field.deserialize({\"foo@test.com\": 1}) == {\n            \"foo@test.com\": decimal.Decimal(1)\n        }\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({1: \"bar\"})\n        assert excinfo.value.args[0] == {\n            1: {\"key\": [\"Not a valid string.\"], \"value\": [\"Not a valid number.\"]}\n        }\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({\"foo@test.com\": \"bar\"})\n        assert excinfo.value.args[0] == {\n            \"foo@test.com\": {\"value\": [\"Not a valid number.\"]}\n        }\n        assert excinfo.value.valid_data == {}\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({1: 1})\n        assert excinfo.value.args[0] == {1: {\"key\": [\"Not a valid string.\"]}}\n        assert excinfo.value.valid_data == {}\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize({\"foo\": \"bar\"})\n        assert excinfo.value.args[0] == {\n            \"foo\": {\n                \"key\": [\n                    \"Not a valid email address.\",\n                    \"String does not match expected pattern.\",\n                ],\n                \"value\": [\"Not a valid number.\"],\n            }\n        }\n        assert excinfo.value.valid_data == {}\n\n    def test_url_field_deserialization(self):\n        field = fields.Url()\n        assert field.deserialize(\"https://duckduckgo.com\") == \"https://duckduckgo.com\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"badurl\")\n        assert excinfo.value.args[0][0] == \"Not a valid URL.\"\n        # Relative URLS not allowed by default\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"/foo/bar\")\n        assert excinfo.value.args[0][0] == \"Not a valid URL.\"\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/issues/1400\n    def test_url_field_non_list_validators(self):\n        field = fields.Url(validate=(validate.Length(min=16),))\n        with pytest.raises(ValidationError, match=\"Shorter than minimum length\"):\n            field.deserialize(\"https://abc.def\")\n\n    def test_relative_url_field_deserialization(self):\n        field = fields.Url(relative=True)\n        assert field.deserialize(\"/foo/bar\") == \"/foo/bar\"\n\n    def test_url_field_schemes_argument(self):\n        field = fields.URL()\n        url = \"ws://test.test\"\n        with pytest.raises(ValidationError):\n            field.deserialize(url)\n        field2 = fields.URL(schemes={\"http\", \"https\", \"ws\"})\n        assert field2.deserialize(url) == url\n\n    def test_email_field_deserialization(self):\n        field = fields.Email()\n        assert field.deserialize(\"foo@bar.com\") == \"foo@bar.com\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"invalidemail\")\n        assert excinfo.value.args[0][0] == \"Not a valid email address.\"\n\n        field = fields.Email(validate=[validate.Length(min=12)])\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"foo@bar.com\")\n        assert excinfo.value.args[0][0] == \"Shorter than minimum length 12.\"\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/issues/1400\n    def test_email_field_non_list_validators(self):\n        field = fields.Email(validate=(validate.Length(min=9),))\n        with pytest.raises(ValidationError, match=\"Shorter than minimum length\"):\n            field.deserialize(\"a@bc.com\")\n\n    def test_function_field_deserialization_is_noop_by_default(self):\n        field = fields.Function(lambda x: None)\n        # Default is noop\n        assert field.deserialize(\"foo\") == \"foo\"\n        assert field.deserialize(42) == 42\n\n    def test_function_field_deserialization_with_callable(self):\n        field = fields.Function(lambda x: None, deserialize=lambda val: val.upper())\n        assert field.deserialize(\"foo\") == \"FOO\"\n\n    def test_function_field_deserialization_missing_with_length_validator(self):\n        field = fields.Function(\n            deserialize=lambda value: value.get(\"some-key\", missing),\n            validate=validate.Length(min=0),\n        )\n        assert field.deserialize({}) is missing\n\n    def test_function_field_passed_deserialize_only_is_load_only(self):\n        field = fields.Function(deserialize=lambda val: val.upper())\n        assert field.load_only is True\n\n    def test_function_field_passed_deserialize_and_serialize_is_not_load_only(self):\n        field = fields.Function(\n            serialize=lambda val: val.lower(), deserialize=lambda val: val.upper()\n        )\n        assert field.load_only is False\n\n    def test_uuid_field_deserialization(self):\n        field = fields.UUID()\n        uuid_str = str(uuid.uuid4())\n        result = field.deserialize(uuid_str)\n        assert isinstance(result, uuid.UUID)\n        assert str(result) == uuid_str\n\n        uuid4 = uuid.uuid4()\n        result = field.deserialize(uuid4)\n        assert isinstance(result, uuid.UUID)\n        assert result == uuid4\n\n        uuid_bytes = b\"]\\xc7wW\\x132O\\xf9\\xa5\\xbe\\x13\\x1f\\x02\\x18\\xda\\xbf\"\n        result = field.deserialize(uuid_bytes)\n        assert isinstance(result, uuid.UUID)\n        assert result.bytes == uuid_bytes\n\n    @pytest.mark.parametrize(\"in_value\", [\"malformed\", 123, [], b\"tooshort\"])\n    def test_invalid_uuid_deserialization(self, in_value):\n        field = fields.UUID()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n\n        assert excinfo.value.args[0] == \"Not a valid UUID.\"\n\n    def test_ip_field_deserialization(self):\n        field = fields.IP()\n        ipv4_str = \"140.82.118.3\"\n        result = field.deserialize(ipv4_str)\n        assert isinstance(result, ipaddress.IPv4Address)\n        assert str(result) == ipv4_str\n\n        ipv6_str = \"2a00:1450:4001:824::200e\"\n        result = field.deserialize(ipv6_str)\n        assert isinstance(result, ipaddress.IPv6Address)\n        assert str(result) == ipv6_str\n\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\"malformed\", 123, b\"\\x01\\x02\\03\", \"192.168\", \"192.168.0.1/24\", \"ff::aa:1::2\"],\n    )\n    def test_invalid_ip_deserialization(self, in_value):\n        field = fields.IP()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n\n        assert excinfo.value.args[0] == \"Not a valid IP address.\"\n\n    def test_ipv4_field_deserialization(self):\n        field = fields.IPv4()\n        ipv4_str = \"140.82.118.3\"\n        result = field.deserialize(ipv4_str)\n        assert isinstance(result, ipaddress.IPv4Address)\n        assert str(result) == ipv4_str\n\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\n            \"malformed\",\n            123,\n            b\"\\x01\\x02\\03\",\n            \"192.168\",\n            \"192.168.0.1/24\",\n            \"2a00:1450:4001:81d::200e\",\n        ],\n    )\n    def test_invalid_ipv4_deserialization(self, in_value):\n        field = fields.IPv4()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n\n        assert excinfo.value.args[0] == \"Not a valid IPv4 address.\"\n\n    def test_ipv6_field_deserialization(self):\n        field = fields.IPv6()\n        ipv6_str = \"2a00:1450:4001:824::200e\"\n        result = field.deserialize(ipv6_str)\n        assert isinstance(result, ipaddress.IPv6Address)\n        assert str(result) == ipv6_str\n\n    def test_ipinterface_field_deserialization(self):\n        field = fields.IPInterface()\n        ipv4interface_str = \"140.82.118.3/24\"\n        result = field.deserialize(ipv4interface_str)\n        assert isinstance(result, ipaddress.IPv4Interface)\n        assert str(result) == ipv4interface_str\n\n        ipv6interface_str = \"2a00:1450:4001:824::200e/128\"\n        result = field.deserialize(ipv6interface_str)\n        assert isinstance(result, ipaddress.IPv6Interface)\n        assert str(result) == ipv6interface_str\n\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\n            \"malformed\",\n            123,\n            b\"\\x01\\x02\\03\",\n            \"192.168\",\n            \"192.168.0.1/33\",\n            \"ff::aa:1::2\",\n            \"2a00:1450:4001:824::200e/129\",\n        ],\n    )\n    def test_invalid_ipinterface_deserialization(self, in_value):\n        field = fields.IPInterface()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n\n        assert excinfo.value.args[0] == \"Not a valid IP interface.\"\n\n    def test_ipv4interface_field_deserialization(self):\n        field = fields.IPv4Interface()\n        ipv4interface_str = \"140.82.118.3/24\"\n        result = field.deserialize(ipv4interface_str)\n        assert isinstance(result, ipaddress.IPv4Interface)\n        assert str(result) == ipv4interface_str\n\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\n            \"malformed\",\n            123,\n            b\"\\x01\\x02\\03\",\n            \"192.168\",\n            \"192.168.0.1/33\",\n            \"2a00:1450:4001:81d::200e\",\n            \"2a00:1450:4001:824::200e/129\",\n        ],\n    )\n    def test_invalid_ipv4interface_deserialization(self, in_value):\n        field = fields.IPv4Interface()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n\n        assert excinfo.value.args[0] == \"Not a valid IPv4 interface.\"\n\n    def test_ipv6interface_field_deserialization(self):\n        field = fields.IPv6Interface()\n        ipv6interface_str = \"2a00:1450:4001:824::200e/128\"\n        result = field.deserialize(ipv6interface_str)\n        assert isinstance(result, ipaddress.IPv6Interface)\n        assert str(result) == ipv6interface_str\n\n    @pytest.mark.parametrize(\n        \"in_value\",\n        [\n            \"malformed\",\n            123,\n            b\"\\x01\\x02\\03\",\n            \"ff::aa:1::2\",\n            \"192.168.0.1\",\n            \"192.168.0.1/24\",\n            \"2a00:1450:4001:824::200e/129\",\n        ],\n    )\n    def test_invalid_ipv6interface_deserialization(self, in_value):\n        field = fields.IPv6Interface()\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(in_value)\n\n        assert excinfo.value.args[0] == \"Not a valid IPv6 interface.\"\n\n    def test_enum_field_by_symbol_deserialization(self):\n        field = fields.Enum(GenderEnum)\n        assert field.deserialize(\"male\") == GenderEnum.male\n\n    def test_enum_field_by_symbol_invalid_value(self):\n        field = fields.Enum(GenderEnum)\n        with pytest.raises(\n            ValidationError, match=\"Must be one of: male, female, non_binary.\"\n        ):\n            field.deserialize(\"dummy\")\n\n    def test_enum_field_by_symbol_not_string(self):\n        field = fields.Enum(GenderEnum)\n        with pytest.raises(ValidationError, match=\"Not a valid string.\"):\n            field.deserialize(12)\n\n    def test_enum_field_by_value_true_deserialization(self):\n        field = fields.Enum(HairColorEnum, by_value=True)\n        assert field.deserialize(\"black hair\") == HairColorEnum.black\n        field2 = fields.Enum(GenderEnum, by_value=True)\n        assert field2.deserialize(1) == GenderEnum.male\n\n    def test_enum_field_by_value_field_deserialization(self):\n        field = fields.Enum(HairColorEnum, by_value=fields.String)\n        assert field.deserialize(\"black hair\") == HairColorEnum.black\n        field2 = fields.Enum(GenderEnum, by_value=fields.Integer)\n        assert field2.deserialize(1) == GenderEnum.male\n        field3 = fields.Enum(DateEnum, by_value=fields.Date(format=\"%d/%m/%Y\"))\n        assert field3.deserialize(\"29/02/2004\") == DateEnum.date_1\n\n    def test_enum_field_by_value_true_invalid_value(self):\n        field = fields.Enum(HairColorEnum, by_value=True)\n        with pytest.raises(\n            ValidationError,\n            match=\"Must be one of: black hair, brown hair, blond hair, red hair.\",\n        ):\n            field.deserialize(\"dummy\")\n        field2 = fields.Enum(GenderEnum, by_value=True)\n        with pytest.raises(ValidationError, match=\"Must be one of: 1, 2, 3.\"):\n            field2.deserialize(12)\n\n    def test_enum_field_by_value_field_invalid_value(self):\n        field = fields.Enum(HairColorEnum, by_value=fields.String)\n        with pytest.raises(\n            ValidationError,\n            match=\"Must be one of: black hair, brown hair, blond hair, red hair.\",\n        ):\n            field.deserialize(\"dummy\")\n        field2 = fields.Enum(GenderEnum, by_value=fields.Integer)\n        with pytest.raises(ValidationError, match=\"Must be one of: 1, 2, 3.\"):\n            field2.deserialize(12)\n        field3 = fields.Enum(DateEnum, by_value=fields.Date(format=\"%d/%m/%Y\"))\n        with pytest.raises(\n            ValidationError, match=\"Must be one of: 29/02/2004, 29/02/2008, 29/02/2012.\"\n        ):\n            field3.deserialize(\"28/02/2004\")\n\n    def test_enum_field_by_value_true_wrong_type(self):\n        field = fields.Enum(HairColorEnum, by_value=True)\n        with pytest.raises(\n            ValidationError,\n            match=\"Must be one of: black hair, brown hair, blond hair, red hair.\",\n        ):\n            field.deserialize(\"dummy\")\n        field = fields.Enum(GenderEnum, by_value=True)\n        with pytest.raises(ValidationError, match=\"Must be one of: 1, 2, 3.\"):\n            field.deserialize(12)\n\n    def test_enum_field_by_value_field_wrong_type(self):\n        field = fields.Enum(HairColorEnum, by_value=fields.String)\n        with pytest.raises(ValidationError, match=\"Not a valid string.\"):\n            field.deserialize(12)\n        field = fields.Enum(GenderEnum, by_value=fields.Integer)\n        with pytest.raises(ValidationError, match=\"Not a valid integer.\"):\n            field.deserialize(\"dummy\")\n        field = fields.Enum(DateEnum, by_value=fields.Date(format=\"%d/%m/%Y\"))\n        with pytest.raises(ValidationError, match=\"Not a valid date.\"):\n            field.deserialize(\"30/02/2004\")\n\n    def test_deserialization_function_must_be_callable(self):\n        with pytest.raises(TypeError):\n            fields.Function(lambda x: None, deserialize=\"notvalid\")\n\n    def test_method_field_deserialization_is_noop_by_default(self):\n        class MiniUserSchema(Schema):\n            uppername = fields.Method(\"uppercase_name\")\n\n            def uppercase_name(self, obj):\n                return obj.upper()\n\n        s = MiniUserSchema()\n        assert s.fields[\"uppername\"].deserialize(\"steve\") == \"steve\"\n\n    def test_deserialization_method(self):\n        class MiniUserSchema(Schema):\n            uppername = fields.Method(\"uppercase_name\", deserialize=\"lowercase_name\")\n\n            def uppercase_name(self, obj):\n                return obj.name.upper()\n\n            def lowercase_name(self, value):\n                return value.lower()\n\n        s = MiniUserSchema()\n        assert s.fields[\"uppername\"].deserialize(\"STEVE\") == \"steve\"\n\n    def test_deserialization_method_must_be_a_method(self):\n        class BadSchema(Schema):\n            uppername = fields.Method(\"uppercase_name\", deserialize=\"lowercase_name\")\n\n        with pytest.raises(AttributeError):\n            BadSchema()\n\n    def test_method_field_deserialize_only(self):\n        class MethodDeserializeOnly(Schema):\n            name = fields.Method(deserialize=\"lowercase_name\")\n\n            def lowercase_name(self, value):\n                return value.lower()\n\n        assert MethodDeserializeOnly().load({\"name\": \"ALEC\"})[\"name\"] == \"alec\"\n\n    def test_datetime_list_field_deserialization(self):\n        dtimes = dt.datetime.now(), dt.datetime.now(), dt.datetime.now(dt.timezone.utc)\n        dstrings = [each.isoformat() for each in dtimes]\n        field = fields.List(fields.DateTime())\n        result = field.deserialize(dstrings)\n        assert all(isinstance(each, dt.datetime) for each in result)\n        for actual, expected in zip(result, dtimes, strict=True):\n            assert_date_equal(actual, expected)\n\n    def test_list_field_deserialize_invalid_item(self):\n        field = fields.List(fields.DateTime)\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([\"badvalue\"])\n        assert excinfo.value.args[0] == {0: [\"Not a valid datetime.\"]}\n\n        field = fields.List(fields.Str())\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([\"good\", 42])\n        assert excinfo.value.args[0] == {1: [\"Not a valid string.\"]}\n\n    def test_list_field_deserialize_multiple_invalid_items(self):\n        field = fields.List(\n            fields.Int(\n                validate=validate.Range(10, 20, error=\"Value {input} not in range\")\n            )\n        )\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([10, 5, 25])\n        assert len(excinfo.value.args[0]) == 2\n        assert excinfo.value.args[0][1] == [\"Value 5 not in range\"]\n        assert excinfo.value.args[0][2] == [\"Value 25 not in range\"]\n\n    @pytest.mark.parametrize(\"value\", [\"notalist\", 42, {}])\n    def test_list_field_deserialize_value_that_is_not_a_list(self, value):\n        field = fields.List(fields.Str())\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(value)\n        assert excinfo.value.args[0] == \"Not a valid list.\"\n\n    def test_datetime_int_tuple_field_deserialization(self):\n        dtime = dt.datetime.now()\n        data = dtime.isoformat(), 42\n        field = fields.Tuple([fields.DateTime(), fields.Integer()])\n        result = field.deserialize(data)\n\n        assert isinstance(result, tuple)\n        assert len(result) == 2\n        for val, type_, true_val in zip(\n            result, (dt.datetime, int), (dtime, 42), strict=True\n        ):\n            assert isinstance(val, type_)\n            assert val == true_val\n\n    def test_tuple_field_deserialize_invalid_item(self):\n        field = fields.Tuple([fields.DateTime])\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([\"badvalue\"])\n        assert excinfo.value.args[0] == {0: [\"Not a valid datetime.\"]}\n\n        field = fields.Tuple([fields.Str(), fields.Integer()])\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([\"good\", \"bad\"])\n        assert excinfo.value.args[0] == {1: [\"Not a valid integer.\"]}\n\n    def test_tuple_field_deserialize_multiple_invalid_items(self):\n        validator = validate.Range(10, 20, error=\"Value {input} not in range\")\n        field = fields.Tuple(\n            [\n                fields.Int(validate=validator),\n                fields.Int(validate=validator),\n                fields.Int(validate=validator),\n            ]\n        )\n\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([10, 5, 25])\n        assert len(excinfo.value.args[0]) == 2\n        assert excinfo.value.args[0][1] == [\"Value 5 not in range\"]\n        assert excinfo.value.args[0][2] == [\"Value 25 not in range\"]\n\n    @pytest.mark.parametrize(\"value\", [\"notalist\", 42, {}])\n    def test_tuple_field_deserialize_value_that_is_not_a_collection(self, value):\n        field = fields.Tuple([fields.Str()])\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(value)\n        assert excinfo.value.args[0] == \"Not a valid tuple.\"\n\n    def test_tuple_field_deserialize_invalid_length(self):\n        field = fields.Tuple([fields.Str(), fields.Str()])\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize([42])\n        assert excinfo.value.args[0] == \"Length must be 2.\"\n\n    def test_constant_field_deserialization(self):\n        field = fields.Constant(\"something\")\n        assert field.deserialize(\"whatever\") == \"something\"\n\n    def test_constant_is_always_included_in_deserialized_data(self):\n        class MySchema(Schema):\n            foo = fields.Constant(42)\n\n        sch = MySchema()\n        assert sch.load({})[\"foo\"] == 42\n        assert sch.load({\"foo\": 24})[\"foo\"] == 42\n\n    def test_constant_none_allows_none_value(self):\n        class MySchema(Schema):\n            foo = fields.Constant(None)\n\n        sch = MySchema()\n        assert sch.load({\"foo\": None})[\"foo\"] is None\n        assert sch.load({})[\"foo\"] is None\n        assert sch.load({\"foo\": \"ignored\"})[\"foo\"] is None\n\n    def test_field_deserialization_with_user_validator_function(self):\n        field = fields.String(validate=predicate(lambda s: s.lower() == \"valid\"))\n        assert field.deserialize(\"Valid\") == \"Valid\"\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"invalid\")\n        assert excinfo.value.args[0][0] == \"Invalid value.\"\n        assert type(excinfo.value) is ValidationError\n\n    def test_field_deserialization_with_user_validator_that_raises_error_with_list(\n        self,\n    ):\n        def validator(val):\n            raise ValidationError([\"err1\", \"err2\"])\n\n        class MySchema(Schema):\n            foo = fields.Raw(validate=validator)\n\n        errors = MySchema().validate({\"foo\": 42})\n        assert errors[\"foo\"] == [\"err1\", \"err2\"]\n\n    def test_field_deserialization_with_validator_with_nonascii_input(self):\n        def validate(val):\n            raise ValidationError(\"oops\")\n\n        field = fields.String(validate=validate)\n        with pytest.raises(ValidationError) as excinfo:\n            field.deserialize(\"привет\")\n        assert type(excinfo.value) is ValidationError\n\n    def test_field_deserialization_with_user_validators(self):\n        validators_gen = (\n            func\n            for func in (\n                predicate(lambda s: s.lower() == \"valid\"),\n                predicate(lambda s: s.lower()[::-1] == \"dilav\"),\n            )\n        )\n\n        m_colletion_type = [\n            fields.String(\n                validate=[\n                    predicate(lambda s: s.lower() == \"valid\"),\n                    predicate(lambda s: s.lower()[::-1] == \"dilav\"),\n                ]\n            ),\n            fields.String(\n                validate=(\n                    predicate(lambda s: s.lower() == \"valid\"),\n                    predicate(lambda s: s.lower()[::-1] == \"dilav\"),\n                )\n            ),\n            fields.String(validate=validators_gen),\n        ]\n\n        for field in m_colletion_type:\n            assert field.deserialize(\"Valid\") == \"Valid\"\n            with pytest.raises(ValidationError, match=\"Invalid value.\"):\n                field.deserialize(\"invalid\")\n\n    @pytest.mark.parametrize(\n        (\"field\", \"value\"),\n        (\n            pytest.param(fields.List(fields.String()), [\"foo\", \"bar\"], id=\"List\"),\n            pytest.param(\n                fields.Tuple((fields.String(), fields.Integer())),\n                (\"foo\", 42),\n                id=\"Tuple\",\n            ),\n            pytest.param(fields.String(), \"valid\", id=\"String\"),\n            pytest.param(fields.UUID(), uuid.uuid4(), id=\"UUID\"),\n            pytest.param(fields.Integer(), 42, id=\"Integer\"),\n            pytest.param(fields.Float(), 42.3, id=\"Float\"),\n            pytest.param(fields.Decimal(), decimal.Decimal(\"42.3\"), id=\"Decimal\"),\n            pytest.param(fields.Boolean(), True, id=\"Boolean\"),\n            pytest.param(fields.DateTime(), dt.datetime(2014, 8, 21), id=\"DateTime\"),\n            pytest.param(fields.Time(), dt.time(10, 15), id=\"Time\"),\n            pytest.param(fields.Date(), dt.date(2014, 8, 21), id=\"Date\"),\n            pytest.param(fields.TimeDelta(), dt.timedelta(days=1), id=\"TimeDelta\"),\n            pytest.param(fields.Dict(), {\"foo\": \"bar\"}, id=\"Dict\"),\n            pytest.param(fields.Url(), \"https://mallow.com\", id=\"Url\"),\n            pytest.param(fields.Email(), \"barbara37@example.net\", id=\"Email\"),\n            pytest.param(fields.IP(), ipaddress.IPv4Address(\"67.60.134.65\"), id=\"IP\"),\n            pytest.param(\n                fields.IPv4(), ipaddress.IPv4Address(\"55.81.158.106\"), id=\"IPv4\"\n            ),\n            pytest.param(\n                fields.IPv6(),\n                ipaddress.IPv6Address(\"89f4:41b6:b97e:ad48:8480:1fda:a811:d1a5\"),\n                id=\"IPv6\",\n            ),\n            pytest.param(fields.Enum(GenderEnum), GenderEnum.non_binary, id=\"Enum\"),\n        ),\n    )\n    def test_fields_accept_internal_types(self, field, value):\n        assert field.deserialize(value) == value\n\n\n# No custom deserialization behavior, so a dict is returned\nclass SimpleUserSchema(Schema):\n    name = fields.String()\n    age = fields.Float()\n\n\nclass Validator(Schema):\n    email = fields.Email()\n    colors = fields.Str(validate=validate.OneOf([\"red\", \"blue\"]))\n    age = fields.Integer(validate=validate.Range(min=0, min_inclusive=False))\n\n\nclass Validators(Schema):\n    email = fields.Email()\n    colors = fields.Str(validate=validate.OneOf([\"red\", \"blue\"]))\n    age = fields.Integer(validate=[validate.Range(1, 99)])\n\n\nclass TestSchemaDeserialization:\n    def test_deserialize_to_dict(self):\n        user_dict = {\"name\": \"Monty\", \"age\": \"42.3\"}\n        result = SimpleUserSchema().load(user_dict)\n        assert result[\"name\"] == \"Monty\"\n        assert math.isclose(result[\"age\"], 42.3)\n\n    def test_deserialize_with_missing_values(self):\n        user_dict = {\"name\": \"Monty\"}\n        result = SimpleUserSchema().load(user_dict)\n        # 'age' is not included in result\n        assert result == {\"name\": \"Monty\"}\n\n    def test_deserialize_many(self):\n        users_data = [{\"name\": \"Mick\", \"age\": \"914\"}, {\"name\": \"Keith\", \"age\": \"8442\"}]\n        result = SimpleUserSchema(many=True).load(users_data)\n        assert isinstance(result, list)\n        user = result[0]\n        assert user[\"age\"] == int(users_data[0][\"age\"])\n\n    def test_exclude(self):\n        schema = SimpleUserSchema(exclude=(\"age\",), unknown=EXCLUDE)\n        result = schema.load({\"name\": \"Monty\", \"age\": 42})\n        assert \"name\" in result\n        assert \"age\" not in result\n\n    def test_nested_single_deserialization_to_dict(self):\n        class SimpleBlogSerializer(Schema):\n            title = fields.String()\n            author = fields.Nested(SimpleUserSchema, unknown=EXCLUDE)\n\n        blog_dict = {\n            \"title\": \"Gimme Shelter\",\n            \"author\": {\"name\": \"Mick\", \"age\": \"914\", \"email\": \"mick@stones.com\"},\n        }\n        result = SimpleBlogSerializer().load(blog_dict)\n        author = result[\"author\"]\n        assert author[\"name\"] == \"Mick\"\n        assert author[\"age\"] == 914\n        assert \"email\" not in author\n\n    def test_nested_list_deserialization_to_dict(self):\n        class SimpleBlogSerializer(Schema):\n            title = fields.String()\n            authors = fields.Nested(SimpleUserSchema, many=True)\n\n        blog_dict = {\n            \"title\": \"Gimme Shelter\",\n            \"authors\": [\n                {\"name\": \"Mick\", \"age\": \"914\"},\n                {\"name\": \"Keith\", \"age\": \"8442\"},\n            ],\n        }\n        result = SimpleBlogSerializer().load(blog_dict)\n        assert isinstance(result[\"authors\"], list)\n        author = result[\"authors\"][0]\n        assert author[\"name\"] == \"Mick\"\n        assert author[\"age\"] == 914\n\n    def test_nested_single_none_not_allowed(self):\n        class PetSchema(Schema):\n            name = fields.Str()\n\n        class OwnerSchema(Schema):\n            pet = fields.Nested(PetSchema(), allow_none=False)\n\n        sch = OwnerSchema()\n        errors = sch.validate({\"pet\": None})\n        assert \"pet\" in errors\n        assert errors[\"pet\"] == [\"Field may not be null.\"]\n\n    def test_nested_many_non_not_allowed(self):\n        class PetSchema(Schema):\n            name = fields.Str()\n\n        class StoreSchema(Schema):\n            pets = fields.Nested(PetSchema, allow_none=False, many=True)\n\n        sch = StoreSchema()\n        errors = sch.validate({\"pets\": None})\n        assert \"pets\" in errors\n        assert errors[\"pets\"] == [\"Field may not be null.\"]\n\n    def test_nested_single_required_missing(self):\n        class PetSchema(Schema):\n            name = fields.Str()\n\n        class OwnerSchema(Schema):\n            pet = fields.Nested(PetSchema(), required=True)\n\n        sch = OwnerSchema()\n        errors = sch.validate({})\n        assert \"pet\" in errors\n        assert errors[\"pet\"] == [\"Missing data for required field.\"]\n\n    def test_nested_many_required_missing(self):\n        class PetSchema(Schema):\n            name = fields.Str()\n\n        class StoreSchema(Schema):\n            pets = fields.Nested(PetSchema, required=True, many=True)\n\n        sch = StoreSchema()\n        errors = sch.validate({})\n        assert \"pets\" in errors\n        assert errors[\"pets\"] == [\"Missing data for required field.\"]\n\n    def test_nested_only_basestring(self):\n        class ANestedSchema(Schema):\n            pk = fields.Str()\n\n        class MainSchema(Schema):\n            pk = fields.Str()\n            child = fields.Pluck(ANestedSchema, \"pk\")\n\n        sch = MainSchema()\n        result = sch.load({\"pk\": \"123\", \"child\": \"456\"})\n        assert result[\"child\"][\"pk\"] == \"456\"\n\n    def test_nested_only_basestring_with_list_data(self):\n        class ANestedSchema(Schema):\n            pk = fields.Str()\n\n        class MainSchema(Schema):\n            pk = fields.Str()\n            children = fields.Pluck(ANestedSchema, \"pk\", many=True)\n\n        sch = MainSchema()\n        result = sch.load({\"pk\": \"123\", \"children\": [\"456\", \"789\"]})\n        assert result[\"children\"][0][\"pk\"] == \"456\"\n        assert result[\"children\"][1][\"pk\"] == \"789\"\n\n    def test_nested_none_deserialization(self):\n        class SimpleBlogSerializer(Schema):\n            title = fields.String()\n            author = fields.Nested(SimpleUserSchema, allow_none=True)\n\n        blog_dict = {\"title\": \"Gimme Shelter\", \"author\": None}\n        result = SimpleBlogSerializer().load(blog_dict)\n        assert result[\"author\"] is None\n        assert result[\"title\"] == blog_dict[\"title\"]\n\n    def test_deserialize_with_attribute_param(self):\n        class AliasingUserSerializer(Schema):\n            username = fields.Email(attribute=\"email\")\n            years = fields.Integer(attribute=\"age\")\n\n        data = {\"username\": \"foo@bar.com\", \"years\": \"42\"}\n        result = AliasingUserSerializer().load(data)\n        assert result[\"email\"] == \"foo@bar.com\"\n        assert result[\"age\"] == 42\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/issues/450\n    def test_deserialize_with_attribute_param_symmetry(self):\n        class MySchema(Schema):\n            foo = fields.Raw(attribute=\"bar.baz\")\n\n        schema = MySchema()\n        dump_data = schema.dump({\"bar\": {\"baz\": 42}})\n        assert dump_data == {\"foo\": 42}\n\n        load_data = schema.load({\"foo\": 42})\n        assert load_data == {\"bar\": {\"baz\": 42}}\n\n    def test_deserialize_with_attribute_param_error_returns_field_name_not_attribute_name(\n        self,\n    ):\n        class AliasingUserSerializer(Schema):\n            username = fields.Email(attribute=\"email\")\n            years = fields.Integer(attribute=\"age\")\n\n        data = {\"username\": \"foobar.com\", \"years\": \"42\"}\n        with pytest.raises(ValidationError) as excinfo:\n            AliasingUserSerializer().load(data)\n        errors = excinfo.value.messages\n        assert errors[\"username\"] == [\"Not a valid email address.\"]\n\n    def test_deserialize_with_attribute_param_error_returns_data_key_not_attribute_name(\n        self,\n    ):\n        class AliasingUserSerializer(Schema):\n            name = fields.String(data_key=\"Name\")\n            username = fields.Email(attribute=\"email\", data_key=\"UserName\")\n            years = fields.Integer(attribute=\"age\", data_key=\"Years\")\n\n        data = {\"Name\": \"Mick\", \"UserName\": \"foobar.com\", \"Years\": \"abc\"}\n        with pytest.raises(ValidationError) as excinfo:\n            AliasingUserSerializer().load(data)\n        errors = excinfo.value.messages\n        assert errors[\"UserName\"] == [\"Not a valid email address.\"]\n        assert errors[\"Years\"] == [\"Not a valid integer.\"]\n\n    def test_deserialize_with_data_key_param(self):\n        class AliasingUserSerializer(Schema):\n            name = fields.String(data_key=\"Name\")\n            username = fields.Email(attribute=\"email\", data_key=\"UserName\")\n            years = fields.Integer(data_key=\"Years\")\n\n        data = {\"Name\": \"Mick\", \"UserName\": \"foo@bar.com\", \"years\": \"42\"}\n        result = AliasingUserSerializer(unknown=EXCLUDE).load(data)\n        assert result[\"name\"] == \"Mick\"\n        assert result[\"email\"] == \"foo@bar.com\"\n        assert \"years\" not in result\n\n    def test_deserialize_with_data_key_as_empty_string(self):\n        class MySchema(Schema):\n            name = fields.Raw(data_key=\"\")\n\n        schema = MySchema()\n        assert schema.load({\"\": \"Grace\"}) == {\"name\": \"Grace\"}\n\n    def test_deserialize_with_dump_only_param(self):\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            years = fields.Integer(dump_only=True)\n            size = fields.Integer(dump_only=True, load_only=True)\n            nicknames = fields.List(fields.Str(), dump_only=True)\n\n        data = {\n            \"name\": \"Mick\",\n            \"years\": \"42\",\n            \"size\": \"12\",\n            \"nicknames\": [\"Your Majesty\", \"Brenda\"],\n        }\n        result = AliasingUserSerializer(unknown=EXCLUDE).load(data)\n        assert result[\"name\"] == \"Mick\"\n        assert \"years\" not in result\n        assert \"size\" not in result\n        assert \"nicknames\" not in result\n\n    def test_deserialize_with_missing_param_value(self):\n        bdate = dt.datetime(2017, 9, 29)\n\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            birthdate = fields.DateTime(load_default=bdate)\n\n        data = {\"name\": \"Mick\"}\n        result = AliasingUserSerializer().load(data)\n        assert result[\"name\"] == \"Mick\"\n        assert result[\"birthdate\"] == bdate\n\n    def test_deserialize_with_missing_param_callable(self):\n        bdate = dt.datetime(2017, 9, 29)\n\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            birthdate = fields.DateTime(load_default=lambda: bdate)\n\n        data = {\"name\": \"Mick\"}\n        result = AliasingUserSerializer().load(data)\n        assert result[\"name\"] == \"Mick\"\n        assert result[\"birthdate\"] == bdate\n\n    def test_deserialize_with_missing_param_none(self):\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            years = fields.Integer(load_default=None, allow_none=True)\n\n        data = {\"name\": \"Mick\"}\n        result = AliasingUserSerializer().load(data)\n        assert result[\"name\"] == \"Mick\"\n        assert result[\"years\"] is None\n\n    def test_deserialization_raises_with_errors(self):\n        bad_data = {\"email\": \"invalid-email\", \"colors\": \"burger\", \"age\": -1}\n        v = Validator()\n        with pytest.raises(ValidationError) as excinfo:\n            v.load(bad_data)\n        errors = excinfo.value.messages\n        assert \"email\" in errors\n        assert \"colors\" in errors\n        assert \"age\" in errors\n\n    def test_deserialization_raises_with_errors_with_multiple_validators(self):\n        bad_data = {\"email\": \"invalid-email\", \"colors\": \"burger\", \"age\": -1}\n        v = Validators()\n        with pytest.raises(ValidationError) as excinfo:\n            v.load(bad_data)\n        errors = excinfo.value.messages\n        assert \"email\" in errors\n        assert \"colors\" in errors\n        assert \"age\" in errors\n\n    def test_deserialization_many_raises_errors(self):\n        bad_data = [\n            {\"email\": \"foo@bar.com\", \"colors\": \"red\", \"age\": 18},\n            {\"email\": \"bad\", \"colors\": \"pizza\", \"age\": -1},\n        ]\n        v = Validator(many=True)\n        with pytest.raises(ValidationError):\n            v.load(bad_data)\n\n    def test_validation_errors_are_stored(self):\n        def validate_field(val):\n            raise ValidationError(\"Something went wrong\")\n\n        class MySchema(Schema):\n            foo = fields.Raw(validate=validate_field)\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"foo\": 42})\n        errors = excinfo.value.messages\n        assert \"Something went wrong\" in errors[\"foo\"]\n\n    def test_multiple_errors_can_be_stored_for_a_field(self):\n        def validate1(n):\n            raise ValidationError(\"error one\")\n\n        def validate2(n):\n            raise ValidationError(\"error two\")\n\n        class MySchema(Schema):\n            foo = fields.Raw(required=True, validate=[validate1, validate2])\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"foo\": \"bar\"})\n        errors = excinfo.value.messages\n\n        assert type(errors[\"foo\"]) is list\n        assert len(errors[\"foo\"]) == 2\n\n    def test_multiple_errors_can_be_stored_for_an_email_field(self):\n        def validate(val):\n            raise ValidationError(\"Invalid value.\")\n\n        class MySchema(Schema):\n            email = fields.Email(validate=[validate])\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"email\": \"foo\"})\n        errors = excinfo.value.messages\n        assert len(errors[\"email\"]) == 2\n        assert \"Not a valid email address.\" in errors[\"email\"][0]\n\n    def test_multiple_errors_can_be_stored_for_a_url_field(self):\n        def validator(val):\n            raise ValidationError(\"Not a valid URL.\")\n\n        class MySchema(Schema):\n            url = fields.Url(validate=[validator])\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"url\": \"foo\"})\n        errors = excinfo.value.messages\n        assert len(errors[\"url\"]) == 2\n        assert \"Not a valid URL.\" in errors[\"url\"][0]\n\n    def test_required_value_only_passed_to_validators_if_provided(self):\n        class MySchema(Schema):\n            foo = fields.Raw(required=True, validate=lambda f: False)\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({})\n        errors = excinfo.value.messages\n        # required value missing\n        assert len(errors[\"foo\"]) == 1\n        assert \"Missing data for required field.\" in errors[\"foo\"]\n\n    @pytest.mark.parametrize(\"partial_schema\", [True, False])\n    def test_partial_deserialization(self, partial_schema):\n        class MySchema(Schema):\n            foo = fields.Raw(required=True)\n            bar = fields.Raw(required=True)\n\n        data = {\"foo\": 3}\n        if partial_schema:\n            result = MySchema(partial=True).load(data)\n        else:\n            result = MySchema().load(data, partial=True)\n\n        assert result[\"foo\"] == 3\n        assert \"bar\" not in result\n\n    def test_partial_fields_deserialization(self):\n        class MySchema(Schema):\n            foo = fields.Raw(required=True)\n            bar = fields.Raw(required=True)\n            baz = fields.Raw(required=True)\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"foo\": 3}, partial=tuple())\n        data, errors = excinfo.value.valid_data, excinfo.value.messages\n        assert data[\"foo\"] == 3\n        assert \"bar\" in errors\n        assert \"baz\" in errors\n\n        data = MySchema().load({\"foo\": 3}, partial=(\"bar\", \"baz\"))\n        assert isinstance(data, dict)\n        assert data[\"foo\"] == 3\n        assert \"bar\" not in data\n        assert \"baz\" not in data\n\n        data = MySchema(partial=True).load({\"foo\": 3}, partial=(\"bar\", \"baz\"))\n        assert isinstance(data, dict)\n        assert data[\"foo\"] == 3\n        assert \"bar\" not in data\n        assert \"baz\" not in data\n\n    def test_partial_fields_validation(self):\n        class MySchema(Schema):\n            foo = fields.Raw(required=True)\n            bar = fields.Raw(required=True)\n            baz = fields.Raw(required=True)\n\n        errors = MySchema().validate({\"foo\": 3}, partial=tuple())\n        assert \"bar\" in errors\n        assert \"baz\" in errors\n\n        errors = MySchema().validate({\"foo\": 3}, partial=(\"bar\", \"baz\"))\n        assert errors == {}\n\n        errors = MySchema(partial=True).validate({\"foo\": 3}, partial=(\"bar\", \"baz\"))\n        assert errors == {}\n\n    def test_unknown_fields_deserialization(self):\n        class MySchema(Schema):\n            foo = fields.Integer()\n\n        data = MySchema(unknown=EXCLUDE).load({\"foo\": 3, \"bar\": 5})\n        assert data[\"foo\"] == 3\n        assert \"bar\" not in data\n\n        data = MySchema(unknown=INCLUDE).load({\"foo\": 3, \"bar\": 5}, unknown=EXCLUDE)\n        assert data[\"foo\"] == 3\n        assert \"bar\" not in data\n\n        data = MySchema(unknown=EXCLUDE).load({\"foo\": 3, \"bar\": 5}, unknown=INCLUDE)\n        assert data[\"foo\"] == 3\n        assert data[\"bar\"]\n\n        data = MySchema(unknown=INCLUDE).load({\"foo\": 3, \"bar\": 5})\n        assert data[\"foo\"] == 3\n        assert data[\"bar\"]\n\n        with pytest.raises(ValidationError, match=\"foo\"):\n            MySchema(unknown=INCLUDE).load({\"foo\": \"asd\", \"bar\": 5})\n\n        data = MySchema(unknown=INCLUDE, many=True).load(\n            [{\"foo\": 1}, {\"foo\": 3, \"bar\": 5}]\n        )\n        assert \"foo\" in data[1]\n        assert \"bar\" in data[1]\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"foo\": 3, \"bar\": 5})\n        err = excinfo.value\n        assert \"bar\" in err.messages\n        assert err.messages[\"bar\"] == [\"Unknown field.\"]\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema(many=True).load([{\"foo\": \"abc\"}, {\"foo\": 3, \"bar\": 5}])\n        err = excinfo.value\n        assert 0 in err.messages\n        assert \"foo\" in err.messages[0]\n        assert err.messages[0][\"foo\"] == [\"Not a valid integer.\"]\n        assert 1 in err.messages\n        assert \"bar\" in err.messages[1]\n        assert err.messages[1][\"bar\"] == [\"Unknown field.\"]\n\n    def test_unknown_fields_deserialization_precedence(self):\n        class MySchema(Schema):\n            class Meta:\n                unknown = INCLUDE\n\n            foo = fields.Integer()\n\n        data = MySchema().load({\"foo\": 3, \"bar\": 5})\n        assert data[\"foo\"] == 3\n        assert data[\"bar\"] == 5\n\n        data = MySchema(unknown=EXCLUDE).load({\"foo\": 3, \"bar\": 5})\n        assert data[\"foo\"] == 3\n        assert \"bar\" not in data\n\n        data = MySchema().load({\"foo\": 3, \"bar\": 5}, unknown=EXCLUDE)\n        assert data[\"foo\"] == 3\n        assert \"bar\" not in data\n\n        with pytest.raises(ValidationError):\n            MySchema(unknown=EXCLUDE).load({\"foo\": 3, \"bar\": 5}, unknown=RAISE)\n\n    def test_unknown_fields_deserialization_with_data_key(self):\n        class MySchema(Schema):\n            foo = fields.Integer(data_key=\"Foo\")\n\n        data = MySchema().load({\"Foo\": 1})\n        assert data[\"foo\"] == 1\n        assert \"Foo\" not in data\n\n        data = MySchema(unknown=RAISE).load({\"Foo\": 1})\n        assert data[\"foo\"] == 1\n        assert \"Foo\" not in data\n\n        with pytest.raises(ValidationError):\n            MySchema(unknown=RAISE).load({\"foo\": 1})\n\n        data = MySchema(unknown=INCLUDE).load({\"Foo\": 1})\n        assert data[\"foo\"] == 1\n        assert \"Foo\" not in data\n\n    def test_unknown_fields_deserialization_with_index_errors_false(self):\n        class MySchema(Schema):\n            foo = fields.Integer()\n\n            class Meta:\n                unknown = RAISE\n                index_errors = False\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema(many=True).load([{\"foo\": \"invalid\"}, {\"foo\": 42, \"bar\": 24}])\n        err = excinfo.value\n        assert 1 not in err.messages\n        assert \"foo\" in err.messages\n        assert \"bar\" in err.messages\n        assert err.messages[\"foo\"] == [\"Not a valid integer.\"]\n        assert err.messages[\"bar\"] == [\"Unknown field.\"]\n\n    def test_dump_only_fields_considered_unknown(self):\n        class MySchema(Schema):\n            foo = fields.Int(dump_only=True)\n\n        with pytest.raises(ValidationError) as excinfo:\n            MySchema().load({\"foo\": 42})\n        err = excinfo.value\n        assert \"foo\" in err.messages\n        assert err.messages[\"foo\"] == [\"Unknown field.\"]\n\n        # When unknown = INCLUDE, dump-only fields are included as unknown\n        # without any validation.\n        data = MySchema(unknown=INCLUDE).load({\"foo\": \"LOL\"})\n        assert data[\"foo\"] == \"LOL\"\n\n    def test_unknown_fields_do_not_unpack_dotted_names(self):\n        class MySchema(Schema):\n            class Meta:\n                unknown = INCLUDE\n\n            foo = fields.Str()\n            bar = fields.Str(data_key=\"bar.baz\")\n\n        # dotted names are still supported\n        data = MySchema().load({\"foo\": \"hi\", \"bar.baz\": \"okay\"})\n        assert data == {\"foo\": \"hi\", \"bar\": \"okay\"}\n\n        # but extra keys included via unknown=INCLUDE are not transformed into nested dicts\n        data = MySchema().load({\"foo\": \"hi\", \"bar.baz\": \"okay\", \"alpha.beta\": \"woah!\"})\n        assert data == {\"foo\": \"hi\", \"bar\": \"okay\", \"alpha.beta\": \"woah!\"}\n\n\nvalidators_gen = (\n    func for func in [predicate(lambda x: x <= 24), predicate(lambda x: x >= 18)]\n)\n\nvalidators_gen_float = (\n    func for func in [predicate(lambda f: f <= 4.1), predicate(lambda f: f >= 1.0)]\n)\n\nvalidators_gen_str = (\n    func\n    for func in [\n        predicate(lambda n: len(n) == 3),\n        predicate(lambda n: n[1].lower() == \"o\"),\n    ]\n)\n\n\nclass TestValidation:\n    def test_integer_with_validator(self):\n        field = fields.Integer(validate=validate.Range(18, 24))\n        out = field.deserialize(\"20\")\n        assert out == 20\n        with pytest.raises(ValidationError):\n            field.deserialize(25)\n\n    @pytest.mark.parametrize(\n        \"field\",\n        [\n            fields.Integer(\n                validate=[predicate(lambda x: x <= 24), predicate(lambda x: x >= 18)]\n            ),\n            fields.Integer(\n                validate=(predicate(lambda x: x <= 24), predicate(lambda x: x >= 18))\n            ),\n            fields.Integer(validate=validators_gen),\n        ],\n    )\n    def test_integer_with_validators(self, field):\n        out = field.deserialize(\"20\")\n        assert out == 20\n        with pytest.raises(ValidationError):\n            field.deserialize(25)\n\n    @pytest.mark.parametrize(\n        \"field\",\n        [\n            fields.Float(\n                validate=[predicate(lambda f: f <= 4.1), predicate(lambda f: f >= 1.0)]\n            ),\n            fields.Float(\n                validate=(predicate(lambda f: f <= 4.1), predicate(lambda f: f >= 1.0))\n            ),\n            fields.Float(validate=validators_gen_float),\n        ],\n    )\n    def test_float_with_validators(self, field):\n        assert field.deserialize(3.14)\n        with pytest.raises(ValidationError):\n            field.deserialize(4.2)\n\n    def test_string_validator(self):\n        field = fields.String(validate=validate.Length(equal=3))\n        assert field.deserialize(\"Joe\") == \"Joe\"\n        with pytest.raises(ValidationError):\n            field.deserialize(\"joseph\")\n\n    def test_function_validator(self):\n        field = fields.Function(\n            lambda d: d.name.upper(), validate=validate.Length(equal=3)\n        )\n        assert field.deserialize(\"joe\")\n        with pytest.raises(ValidationError):\n            field.deserialize(\"joseph\")\n\n    @pytest.mark.parametrize(\n        \"field\",\n        [\n            fields.Function(\n                lambda d: d.name.upper(),\n                validate=[\n                    validate.Length(equal=3),\n                    predicate(lambda n: n[1].lower() == \"o\"),\n                ],\n            ),\n            fields.Function(\n                lambda d: d.name.upper(),\n                validate=(\n                    predicate(lambda n: len(n) == 3),\n                    predicate(lambda n: n[1].lower() == \"o\"),\n                ),\n            ),\n            fields.Function(lambda d: d.name.upper(), validate=validators_gen_str),\n        ],\n    )\n    def test_function_validators(self, field):\n        assert field.deserialize(\"joe\")\n        with pytest.raises(ValidationError):\n            field.deserialize(\"joseph\")\n\n    def test_method_validator(self):\n        class MethodSerializer(Schema):\n            name = fields.Method(\n                \"get_name\", deserialize=\"get_name\", validate=validate.Length(equal=3)\n            )\n\n            def get_name(self, val):\n                return val.upper()\n\n        assert MethodSerializer().load({\"name\": \"joe\"})\n        with pytest.raises(ValidationError, match=\"Length must be 3.\"):\n            MethodSerializer().load({\"name\": \"joseph\"})\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/269\n    def test_nested_data_is_stored_when_validation_fails(self):\n        class SchemaA(Schema):\n            x = fields.Integer()\n            y = fields.Integer(validate=validate.Range(min=1))\n            z = fields.Integer()\n\n        class SchemaB(Schema):\n            w = fields.Integer()\n            n = fields.Nested(SchemaA)\n\n        sch = SchemaB()\n\n        with pytest.raises(ValidationError) as excinfo:\n            sch.load({\"w\": 90, \"n\": {\"x\": 90, \"y\": 89, \"z\": None}})\n        data, errors = excinfo.value.valid_data, excinfo.value.messages\n        assert \"z\" in errors[\"n\"]\n        assert data == {\"w\": 90, \"n\": {\"x\": 90, \"y\": 89}}\n\n        with pytest.raises(ValidationError) as excinfo:\n            sch.load({\"w\": 90, \"n\": {\"x\": 90, \"y\": -1, \"z\": 180}})\n        data, errors = excinfo.value.valid_data, excinfo.value.messages\n        assert \"y\" in errors[\"n\"]\n        assert data == {\"w\": 90, \"n\": {\"x\": 90, \"z\": 180}}\n\n    def test_nested_partial_load(self):\n        class SchemaA(Schema):\n            x = fields.Integer(required=True)\n            y = fields.Integer()\n\n        class SchemaB(Schema):\n            z = fields.Nested(SchemaA)\n\n        b_dict = {\"z\": {\"y\": 42}}\n        # Partial loading shouldn't generate any errors.\n        result = SchemaB().load(b_dict, partial=True)\n        assert result[\"z\"][\"y\"] == 42\n        # Non partial loading should complain about missing values.\n        with pytest.raises(ValidationError) as excinfo:\n            SchemaB().load(b_dict)\n        data, errors = excinfo.value.valid_data, excinfo.value.messages\n        assert data[\"z\"][\"y\"] == 42\n        assert \"z\" in errors\n        assert \"x\" in errors[\"z\"]\n\n    def test_deeply_nested_partial_load(self):\n        class SchemaC(Schema):\n            x = fields.Integer(required=True)\n            y = fields.Integer()\n\n        class SchemaB(Schema):\n            c = fields.Nested(SchemaC)\n\n        class SchemaA(Schema):\n            b = fields.Nested(SchemaB)\n\n        a_dict = {\"b\": {\"c\": {\"y\": 42}}}\n        # Partial loading shouldn't generate any errors.\n        result = SchemaA().load(a_dict, partial=True)\n        assert result[\"b\"][\"c\"][\"y\"] == 42\n        # Non partial loading should complain about missing values.\n        with pytest.raises(ValidationError) as excinfo:\n            SchemaA().load(a_dict)\n        data, errors = excinfo.value.valid_data, excinfo.value.messages\n        assert data[\"b\"][\"c\"][\"y\"] == 42\n        assert \"b\" in errors\n        assert \"c\" in errors[\"b\"]\n        assert \"x\" in errors[\"b\"][\"c\"]\n\n    def test_nested_partial_tuple(self):\n        class SchemaA(Schema):\n            x = fields.Integer(required=True)\n            y = fields.Integer(required=True)\n\n        class SchemaB(Schema):\n            z = fields.Nested(SchemaA)\n\n        b_dict = {\"z\": {\"y\": 42}}\n        # If we ignore the missing z.x, z.y should still load.\n        result = SchemaB().load(b_dict, partial=(\"z.x\",))\n        assert result[\"z\"][\"y\"] == 42\n        # If we ignore a missing z.y we should get a validation error.\n        with pytest.raises(ValidationError):\n            SchemaB().load(b_dict, partial=(\"z.y\",))\n\n    def test_nested_partial_default(self):\n        class SchemaA(Schema):\n            x = fields.Integer(required=True)\n            y = fields.Integer(required=True)\n\n        class SchemaB(Schema):\n            z = fields.Nested(SchemaA(partial=(\"x\",)))\n\n        b_dict = {\"z\": {\"y\": 42}}\n        # Nested partial args should be respected.\n        result = SchemaB().load(b_dict)\n        assert result[\"z\"][\"y\"] == 42\n        with pytest.raises(ValidationError):\n            SchemaB().load({\"z\": {\"x\": 0}})\n\n\n@pytest.mark.parametrize(\"FieldClass\", ALL_FIELDS)\ndef test_required_field_failure(FieldClass):\n    class RequireSchema(Schema):\n        age = FieldClass(required=True)\n\n    user_data = {\"name\": \"Phil\"}\n    with pytest.raises(ValidationError) as excinfo:\n        RequireSchema().load(user_data)\n    errors = excinfo.value.messages\n    assert \"Missing data for required field.\" in errors[\"age\"]\n\n\n@pytest.mark.parametrize(\n    \"message\",\n    [\n        \"My custom required message\",\n        {\"error\": \"something\", \"code\": 400},\n        [\"first error\", \"second error\"],\n    ],\n)\ndef test_required_message_can_be_changed(message):\n    class RequireSchema(Schema):\n        age = fields.Integer(required=True, error_messages={\"required\": message})\n\n    user_data = {\"name\": \"Phil\"}\n    with pytest.raises(ValidationError) as excinfo:\n        RequireSchema().load(user_data)\n    errors = excinfo.value.messages\n    expected = [message] if isinstance(message, str) else message\n    assert expected == errors[\"age\"]\n\n\n@pytest.mark.parametrize(\"unknown\", (EXCLUDE, INCLUDE, RAISE))\n@pytest.mark.parametrize(\"data\", [True, False, 42, None, []])\ndef test_deserialize_raises_exception_if_input_type_is_incorrect(data, unknown):\n    class MySchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n\n    with pytest.raises(ValidationError, match=\"Invalid input type.\") as excinfo:\n        MySchema(unknown=unknown).load(data)\n    exc = excinfo.value\n    assert isinstance(exc.messages, dict)\n    assert list(exc.messages.keys()) == [\"_schema\"]\n"
  },
  {
    "path": "tests/test_error_store.py",
    "content": "from typing import NamedTuple\n\nfrom marshmallow import missing\nfrom marshmallow.error_store import ErrorStore, merge_errors\n\n\ndef test_missing_is_falsy():\n    assert bool(missing) is False\n\n\nclass CustomError(NamedTuple):\n    code: int\n    message: str\n\n\nclass TestMergeErrors:\n    def test_merging_none_and_string(self):\n        assert merge_errors(None, \"error1\") == \"error1\"\n\n    def test_merging_none_and_custom_error(self):\n        assert CustomError(123, \"error1\") == merge_errors(\n            None, CustomError(123, \"error1\")\n        )\n\n    def test_merging_none_and_list(self):\n        assert merge_errors(None, [\"error1\", \"error2\"]) == [\"error1\", \"error2\"]\n\n    def test_merging_none_and_dict(self):\n        assert merge_errors(None, {\"field1\": \"error1\"}) == {\"field1\": \"error1\"}\n\n    def test_merging_string_and_none(self):\n        assert merge_errors(\"error1\", None) == \"error1\"\n\n    def test_merging_custom_error_and_none(self):\n        assert CustomError(123, \"error1\") == merge_errors(\n            CustomError(123, \"error1\"), None\n        )\n\n    def test_merging_list_and_none(self):\n        assert merge_errors([\"error1\", \"error2\"], None) == [\"error1\", \"error2\"]\n\n    def test_merging_dict_and_none(self):\n        assert merge_errors({\"field1\": \"error1\"}, None) == {\"field1\": \"error1\"}\n\n    def test_merging_string_and_string(self):\n        assert merge_errors(\"error1\", \"error2\") == [\"error1\", \"error2\"]\n\n    def test_merging_custom_error_and_string(self):\n        assert [CustomError(123, \"error1\"), \"error2\"] == merge_errors(\n            CustomError(123, \"error1\"), \"error2\"\n        )\n\n    def test_merging_string_and_custom_error(self):\n        assert [\"error1\", CustomError(123, \"error2\")] == merge_errors(\n            \"error1\", CustomError(123, \"error2\")\n        )\n\n    def test_merging_custom_error_and_custom_error(self):\n        assert [CustomError(123, \"error1\"), CustomError(456, \"error2\")] == merge_errors(\n            CustomError(123, \"error1\"), CustomError(456, \"error2\")\n        )\n\n    def test_merging_string_and_list(self):\n        assert merge_errors(\"error1\", [\"error2\"]) == [\"error1\", \"error2\"]\n\n    def test_merging_string_and_dict(self):\n        assert merge_errors(\"error1\", {\"field1\": \"error2\"}) == {\n            \"_schema\": \"error1\",\n            \"field1\": \"error2\",\n        }\n\n    def test_merging_string_and_dict_with_schema_error(self):\n        assert merge_errors(\"error1\", {\"_schema\": \"error2\", \"field1\": \"error3\"}) == {\n            \"_schema\": [\"error1\", \"error2\"],\n            \"field1\": \"error3\",\n        }\n\n    def test_merging_custom_error_and_list(self):\n        assert [CustomError(123, \"error1\"), \"error2\"] == merge_errors(\n            CustomError(123, \"error1\"), [\"error2\"]\n        )\n\n    def test_merging_custom_error_and_dict(self):\n        assert {\n            \"_schema\": CustomError(123, \"error1\"),\n            \"field1\": \"error2\",\n        } == merge_errors(CustomError(123, \"error1\"), {\"field1\": \"error2\"})\n\n    def test_merging_custom_error_and_dict_with_schema_error(self):\n        assert {\n            \"_schema\": [CustomError(123, \"error1\"), \"error2\"],\n            \"field1\": \"error3\",\n        } == merge_errors(\n            CustomError(123, \"error1\"), {\"_schema\": \"error2\", \"field1\": \"error3\"}\n        )\n\n    def test_merging_list_and_string(self):\n        assert merge_errors([\"error1\"], \"error2\") == [\"error1\", \"error2\"]\n\n    def test_merging_list_and_custom_error(self):\n        assert [\"error1\", CustomError(123, \"error2\")] == merge_errors(\n            [\"error1\"], CustomError(123, \"error2\")\n        )\n\n    def test_merging_list_and_list(self):\n        assert merge_errors([\"error1\"], [\"error2\"]) == [\"error1\", \"error2\"]\n\n    def test_merging_list_and_dict(self):\n        assert merge_errors([\"error1\"], {\"field1\": \"error2\"}) == {\n            \"_schema\": [\"error1\"],\n            \"field1\": \"error2\",\n        }\n\n    def test_merging_list_and_dict_with_schema_error(self):\n        assert merge_errors([\"error1\"], {\"_schema\": \"error2\", \"field1\": \"error3\"}) == {\n            \"_schema\": [\"error1\", \"error2\"],\n            \"field1\": \"error3\",\n        }\n\n    def test_merging_dict_and_string(self):\n        assert merge_errors({\"field1\": \"error1\"}, \"error2\") == {\n            \"_schema\": \"error2\",\n            \"field1\": \"error1\",\n        }\n\n    def test_merging_dict_and_custom_error(self):\n        assert {\n            \"_schema\": CustomError(123, \"error2\"),\n            \"field1\": \"error1\",\n        } == merge_errors({\"field1\": \"error1\"}, CustomError(123, \"error2\"))\n\n    def test_merging_dict_and_list(self):\n        assert merge_errors({\"field1\": \"error1\"}, [\"error2\"]) == {\n            \"_schema\": [\"error2\"],\n            \"field1\": \"error1\",\n        }\n\n    def test_merging_dict_and_dict(self):\n        assert merge_errors(\n            {\"field1\": \"error1\", \"field2\": \"error2\"},\n            {\"field2\": \"error3\", \"field3\": \"error4\"},\n        ) == {\n            \"field1\": \"error1\",\n            \"field2\": [\"error2\", \"error3\"],\n            \"field3\": \"error4\",\n        }\n\n    def test_deep_merging_dicts(self):\n        assert merge_errors(\n            {\"field1\": {\"field2\": \"error1\"}}, {\"field1\": {\"field2\": \"error2\"}}\n        ) == {\"field1\": {\"field2\": [\"error1\", \"error2\"]}}\n\n    def test_list_not_changed(self):\n        store = ErrorStore()\n        message = [\"foo\"]\n        store.store_error(message)\n        store.store_error(message)\n        assert message == [\"foo\"]\n        assert store.errors == {\"_schema\": [\"foo\", \"foo\"]}\n\n    def test_dict_not_changed(self):\n        store = ErrorStore()\n        message = {\"foo\": [\"bar\"]}\n        store.store_error(message)\n        store.store_error(message)\n        assert message == {\"foo\": [\"bar\"]}\n        assert store.errors == {\"foo\": [\"bar\", \"bar\"]}\n"
  },
  {
    "path": "tests/test_exceptions.py",
    "content": "import pytest\n\nfrom marshmallow.exceptions import ValidationError\n\n\nclass TestValidationError:\n    def test_stores_message_in_list(self):\n        err = ValidationError(\"foo\")\n        assert err.messages == [\"foo\"]\n\n    def test_can_pass_list_of_messages(self):\n        err = ValidationError([\"foo\", \"bar\"])\n        assert err.messages == [\"foo\", \"bar\"]\n\n    def test_stores_dictionaries(self):\n        messages = {\"user\": {\"email\": [\"email is invalid\"]}}\n        err = ValidationError(messages)\n        assert err.messages == messages\n\n    def test_can_store_field_name(self):\n        err = ValidationError(\"invalid email\", field_name=\"email\")\n        assert err.field_name == \"email\"\n\n    def test_str(self):\n        err = ValidationError(\"invalid email\")\n        assert str(err) == \"invalid email\"\n\n        err2 = ValidationError(\"invalid email\", \"email\")\n        assert str(err2) == \"invalid email\"\n\n    def test_stores_dictionaries_in_messages_dict(self):\n        messages = {\"user\": {\"email\": [\"email is invalid\"]}}\n        err = ValidationError(messages)\n        assert err.messages_dict == messages\n\n    def test_messages_dict_type_error_on_badval(self):\n        err = ValidationError(\"foo\")\n        with pytest.raises(TypeError) as excinfo:\n            err.messages_dict  # noqa: B018\n        assert \"cannot access 'messages_dict' when 'messages' is of type list\" in str(\n            excinfo.value\n        )\n"
  },
  {
    "path": "tests/test_fields.py",
    "content": "import pytest\n\nfrom marshmallow import (\n    EXCLUDE,\n    INCLUDE,\n    RAISE,\n    Schema,\n    ValidationError,\n    fields,\n    missing,\n)\nfrom marshmallow.exceptions import StringNotCollectionError\nfrom marshmallow.orderedset import OrderedSet\nfrom tests.base import ALL_FIELDS\n\n\n@pytest.mark.parametrize(\n    (\"alias\", \"field\"),\n    [\n        (fields.Int, fields.Integer),\n        (fields.Str, fields.String),\n        (fields.Bool, fields.Boolean),\n        (fields.URL, fields.Url),\n    ],\n)\ndef test_field_aliases(alias, field):\n    assert alias is field\n\n\nclass TestField:\n    def test_repr(self):\n        default = \"œ∑´\"  # noqa: RUF001\n        field = fields.Raw(dump_default=default, attribute=None)\n        assert repr(field) == (\n            f\"<fields.Raw(dump_default={default!r}, attribute=None, \"\n            \"validate=None, required=False, \"\n            \"load_only=False, dump_only=False, \"\n            f\"load_default={missing}, allow_none=False, \"\n            f\"error_messages={field.error_messages})>\"\n        )\n        int_field = fields.Integer(validate=lambda x: True)\n        assert \"<fields.Integer\" in repr(int_field)\n\n    def test_error_raised_if_uncallable_validator_passed(self):\n        with pytest.raises(ValueError, match=\"must be a callable\"):\n            fields.Raw(validate=\"notcallable\")  # type: ignore[arg-type]\n\n    def test_error_raised_if_missing_is_set_on_required_field(self):\n        with pytest.raises(\n            ValueError, match=\"'load_default' must not be set for required fields\"\n        ):\n            fields.Raw(required=True, load_default=42)\n\n    def test_custom_field_receives_attr_and_obj(self):\n        class MyField(fields.Field[str]):\n            def _deserialize(self, value, attr, data, **kwargs) -> str:\n                assert attr == \"name\"\n                assert data[\"foo\"] == 42\n                return str(value)\n\n        class MySchema(Schema):\n            name = MyField()\n\n        result = MySchema(unknown=EXCLUDE).load({\"name\": \"Monty\", \"foo\": 42})\n        assert result == {\"name\": \"Monty\"}\n\n    def test_custom_field_receives_data_key_if_set(self):\n        class MyField(fields.Field[str]):\n            def _deserialize(self, value, attr, data, **kwargs):\n                assert attr == \"name\"\n                assert data[\"foo\"] == 42\n                return str(value)\n\n        class MySchema(Schema):\n            Name = MyField(data_key=\"name\")\n\n        result = MySchema(unknown=EXCLUDE).load({\"name\": \"Monty\", \"foo\": 42})\n        assert result == {\"Name\": \"Monty\"}\n\n    def test_custom_field_follows_data_key_if_set(self):\n        class MyField(fields.Field[str]):\n            def _serialize(self, value, attr, obj, **kwargs) -> str:\n                assert attr == \"name\"\n                assert obj[\"foo\"] == 42\n                return str(value)\n\n        class MySchema(Schema):\n            name = MyField(data_key=\"_NaMe\")\n\n        result = MySchema().dump({\"name\": \"Monty\", \"foo\": 42})\n        assert result == {\"_NaMe\": \"Monty\"}\n\n\nclass TestParentAndName:\n    class MySchema(Schema):\n        foo = fields.Raw()\n        bar = fields.List(fields.Str())\n        baz = fields.Tuple((fields.Str(), fields.Int()))\n        bax = fields.Dict(fields.Str(), fields.Int())\n\n    @pytest.fixture\n    def schema(self):\n        return self.MySchema()\n\n    def test_simple_field_parent_and_name(self, schema):\n        assert schema.fields[\"foo\"].parent == schema\n        assert schema.fields[\"foo\"].name == \"foo\"\n        assert schema.fields[\"bar\"].parent == schema\n        assert schema.fields[\"bar\"].name == \"bar\"\n\n    # https://github.com/marshmallow-code/marshmallow/pull/572#issuecomment-275800288\n    def test_unbound_field_root_returns_none(self):\n        field = fields.Str()\n        assert field.root is None\n\n        inner_field = fields.Nested(self.MySchema())\n        outer_field = fields.List(inner_field)\n\n        assert outer_field.root is None\n        assert inner_field.root is None\n\n    def test_list_field_inner_parent_and_name(self, schema):\n        assert schema.fields[\"bar\"].inner.parent == schema.fields[\"bar\"]\n        assert schema.fields[\"bar\"].inner.name == \"bar\"\n\n    def test_tuple_field_inner_parent_and_name(self, schema):\n        for field in schema.fields[\"baz\"].tuple_fields:\n            assert field.parent == schema.fields[\"baz\"]\n            assert field.name == \"baz\"\n\n    def test_mapping_field_inner_parent_and_name(self, schema):\n        assert schema.fields[\"bax\"].value_field.parent == schema.fields[\"bax\"]\n        assert schema.fields[\"bax\"].value_field.name == \"bax\"\n        assert schema.fields[\"bax\"].key_field.parent == schema.fields[\"bax\"]\n        assert schema.fields[\"bax\"].key_field.name == \"bax\"\n\n    def test_simple_field_root(self, schema):\n        assert schema.fields[\"foo\"].root == schema\n        assert schema.fields[\"bar\"].root == schema\n\n    def test_list_field_inner_root(self, schema):\n        assert schema.fields[\"bar\"].inner.root == schema\n\n    def test_tuple_field_inner_root(self, schema):\n        for field in schema.fields[\"baz\"].tuple_fields:\n            assert field.root == schema\n\n    def test_list_root_inheritance(self, schema):\n        class OtherSchema(TestParentAndName.MySchema):\n            pass\n\n        schema2 = OtherSchema()\n\n        bar_field = schema.fields[\"bar\"]\n        assert isinstance(bar_field, fields.List)\n        assert bar_field.inner.root == schema\n\n        bar_field2 = schema2.fields[\"bar\"]\n        assert isinstance(bar_field2, fields.List)\n        assert bar_field2.inner.root == schema2\n\n    def test_dict_root_inheritance(self):\n        class MySchema(Schema):\n            foo = fields.Dict(keys=fields.Str(), values=fields.Int())\n\n        class OtherSchema(MySchema):\n            pass\n\n        schema = MySchema()\n        schema2 = OtherSchema()\n\n        foo_field = schema.fields[\"foo\"]\n        assert isinstance(foo_field, fields.Dict)\n        assert isinstance(foo_field.key_field, fields.Str)\n        assert isinstance(foo_field.value_field, fields.Int)\n        assert foo_field.key_field.root == schema\n        assert foo_field.value_field.root == schema\n\n        foo_field2 = schema2.fields[\"foo\"]\n        assert isinstance(foo_field2, fields.Dict)\n        assert isinstance(foo_field2.key_field, fields.Str)\n        assert isinstance(foo_field2.value_field, fields.Int)\n        assert foo_field2.key_field.root == schema2\n        assert foo_field2.value_field.root == schema2\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/1357\n    def test_datetime_list_inner_format(self, schema):\n        class MySchema(Schema):\n            foo = fields.List(fields.DateTime())\n            bar = fields.Tuple((fields.DateTime(),))\n            baz = fields.List(fields.Date())\n            qux = fields.Tuple((fields.Date(),))\n\n            class Meta:\n                datetimeformat = \"iso8601\"\n                dateformat = \"iso8601\"\n\n        schema = MySchema()\n        for field_name in (\"foo\", \"baz\"):\n            assert schema.fields[field_name].inner.format == \"iso8601\"\n        for field_name in (\"bar\", \"qux\"):\n            assert schema.fields[field_name].tuple_fields[0].format == \"iso8601\"\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/1808\n    def test_field_named_parent_has_root(self, schema):\n        class MySchema(Schema):\n            parent = fields.Raw()\n\n        schema = MySchema()\n        assert schema.fields[\"parent\"].root == schema\n\n\nclass TestMetadata:\n    @pytest.mark.parametrize(\"FieldClass\", ALL_FIELDS)\n    def test_extra_metadata_may_be_added_to_field(self, FieldClass):\n        field = FieldClass(\n            required=True,\n            dump_default=None,\n            validate=lambda v: True,\n            metadata={\"description\": \"foo\", \"widget\": \"select\"},\n        )\n        assert field.metadata == {\"description\": \"foo\", \"widget\": \"select\"}\n\n\nclass TestErrorMessages:\n    class MyField(fields.Field):\n        default_error_messages = {\"custom\": \"Custom error message.\"}\n\n    error_messages = (\n        (\"required\", \"Missing data for required field.\"),\n        (\"null\", \"Field may not be null.\"),\n        (\"custom\", \"Custom error message.\"),\n        (\"validator_failed\", \"Invalid value.\"),\n    )\n\n    def test_default_error_messages_get_merged_with_parent_error_messages_cstm_msg(\n        self,\n    ):\n        field = self.MyField()\n        assert field.error_messages[\"custom\"] == \"Custom error message.\"\n        assert \"required\" in field.error_messages\n\n    def test_default_error_messages_get_merged_with_parent_error_messages(self):\n        field = self.MyField(error_messages={\"passed\": \"Passed error message\"})\n        assert field.error_messages[\"passed\"] == \"Passed error message\"\n\n    @pytest.mark.parametrize((\"key\", \"message\"), error_messages)\n    def test_make_error(self, key, message):\n        field = self.MyField()\n\n        error = field.make_error(key)\n        assert error.args[0] == message\n\n    def test_make_error_key_doesnt_exist(self):\n        with pytest.raises(AssertionError) as excinfo:\n            self.MyField().make_error(\"doesntexist\")\n        assert \"doesntexist\" in excinfo.value.args[0]\n        assert \"MyField\" in excinfo.value.args[0]\n\n\nclass TestNestedField:\n    @pytest.mark.parametrize(\"param\", (\"only\", \"exclude\"))\n    def test_nested_only_and_exclude_as_string(self, param):\n        with pytest.raises(StringNotCollectionError):\n            fields.Nested(Schema, **{param: \"foo\"})  # type: ignore[arg-type]\n\n    @pytest.mark.parametrize(\n        \"nested_value\",\n        [\n            {\"hello\": fields.String()},\n            lambda: {\"hello\": fields.String()},\n        ],\n    )\n    def test_nested_instantiation_from_dict(self, nested_value):\n        class MySchema(Schema):\n            nested = fields.Nested(nested_value)\n\n        schema = MySchema()\n\n        ret = schema.load({\"nested\": {\"hello\": \"world\"}})\n        assert ret == {\"nested\": {\"hello\": \"world\"}}\n\n        with pytest.raises(ValidationError):\n            schema.load({\"nested\": {\"x\": 1}})\n\n    @pytest.mark.parametrize(\"schema_unknown\", (EXCLUDE, INCLUDE, RAISE))\n    @pytest.mark.parametrize(\"field_unknown\", (None, EXCLUDE, INCLUDE, RAISE))\n    def test_nested_unknown_override(self, schema_unknown, field_unknown):\n        class NestedSchema(Schema):\n            class Meta:\n                unknown = schema_unknown\n\n        class MySchema(Schema):\n            nested = fields.Nested(NestedSchema, unknown=field_unknown)\n\n        if field_unknown == EXCLUDE or (\n            schema_unknown == EXCLUDE and not field_unknown\n        ):\n            assert MySchema().load({\"nested\": {\"x\": 1}}) == {\"nested\": {}}\n        elif field_unknown == INCLUDE or (\n            schema_unknown == INCLUDE and not field_unknown\n        ):\n            assert MySchema().load({\"nested\": {\"x\": 1}}) == {\"nested\": {\"x\": 1}}\n        elif field_unknown == RAISE or (schema_unknown == RAISE and not field_unknown):\n            with pytest.raises(ValidationError):\n                MySchema().load({\"nested\": {\"x\": 1}})\n\n    @pytest.mark.parametrize(\n        (\"param\", \"fields_list\"), [(\"only\", [\"foo\"]), (\"exclude\", [\"bar\"])]\n    )\n    def test_nested_schema_only_and_exclude(self, param, fields_list):\n        class NestedSchema(Schema):\n            # We mean to test the use of OrderedSet to specify it explicitly\n            # even if it is default\n            set_class = OrderedSet\n            foo = fields.String()\n            bar = fields.String()\n\n        class MySchema(Schema):\n            nested = fields.Nested(NestedSchema(), **{param: fields_list})\n\n        assert MySchema().dump({\"nested\": {\"foo\": \"baz\", \"bar\": \"bax\"}}) == {\n            \"nested\": {\"foo\": \"baz\"}\n        }\n\n\nclass TestListNested:\n    @pytest.mark.parametrize(\"param\", (\"only\", \"exclude\", \"dump_only\", \"load_only\"))\n    def test_list_nested_only_exclude_dump_only_load_only_propagated_to_nested(\n        self, param\n    ):\n        class Child(Schema):\n            name = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.List(fields.Nested(Child))\n\n        schema = Family(**{param: [\"children.name\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.List)\n        assert isinstance(children_field.inner, fields.Nested)\n        assert getattr(children_field.inner.schema, param) == {\"name\"}\n\n    @pytest.mark.parametrize(\n        (\"param\", \"expected_attribute\", \"expected_dump\"),\n        (\n            (\"only\", {\"name\"}, {\"children\": [{\"name\": \"Lily\"}]}),\n            (\"exclude\", {\"name\", \"surname\", \"age\"}, {\"children\": [{}]}),\n        ),\n    )\n    def test_list_nested_class_only_and_exclude_merged_with_nested(\n        self, param, expected_attribute, expected_dump\n    ):\n        class Child(Schema):\n            name = fields.String()\n            surname = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.List(fields.Nested(Child, **{param: (\"name\", \"surname\")}))  # type: ignore[arg-type]\n\n        schema = Family(**{param: [\"children.name\", \"children.age\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.List)\n        assert getattr(children_field.inner, param) == expected_attribute\n\n        family = {\"children\": [{\"name\": \"Lily\", \"surname\": \"Martinez\", \"age\": 15}]}\n        assert schema.dump(family) == expected_dump\n\n    def test_list_nested_class_multiple_dumps(self):\n        class Child(Schema):\n            name = fields.String()\n            surname = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.List(fields.Nested(Child, only=(\"name\", \"age\")))\n\n        family = {\"children\": [{\"name\": \"Lily\", \"surname\": \"Martinez\", \"age\": 15}]}\n        assert Family(only=(\"children.age\",)).dump(family) == {\n            \"children\": [{\"age\": 15}]\n        }\n        assert Family(only=(\"children.name\",)).dump(family) == {\n            \"children\": [{\"name\": \"Lily\"}]\n        }\n\n    @pytest.mark.parametrize(\n        (\"param\", \"expected_attribute\", \"expected_dump\"),\n        (\n            (\"only\", {\"name\"}, {\"children\": [{\"name\": \"Lily\"}]}),\n            (\"exclude\", {\"name\", \"surname\", \"age\"}, {\"children\": [{}]}),\n        ),\n    )\n    def test_list_nested_instance_only_and_exclude_merged_with_nested(\n        self, param, expected_attribute, expected_dump\n    ):\n        class Child(Schema):\n            name = fields.String()\n            surname = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.List(fields.Nested(Child(**{param: (\"name\", \"surname\")})))  # type: ignore[arg-type]\n\n        schema = Family(**{param: [\"children.name\", \"children.age\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.List)\n        assert isinstance(children_field.inner, fields.Nested)\n        assert getattr(children_field.inner.schema, param) == expected_attribute\n\n        family = {\"children\": [{\"name\": \"Lily\", \"surname\": \"Martinez\", \"age\": 15}]}\n        assert schema.dump(family) == expected_dump\n\n    def test_list_nested_instance_multiple_dumps(self):\n        class Child(Schema):\n            name = fields.String()\n            surname = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.List(fields.Nested(Child(only=(\"name\", \"age\"))))\n\n        family = {\"children\": [{\"name\": \"Lily\", \"surname\": \"Martinez\", \"age\": 15}]}\n        assert Family(only=(\"children.age\",)).dump(family) == {\n            \"children\": [{\"age\": 15}]\n        }\n        assert Family(only=(\"children.name\",)).dump(family) == {\n            \"children\": [{\"name\": \"Lily\"}]\n        }\n\n    @pytest.mark.parametrize(\n        (\"param\", \"expected_attribute\", \"expected_dump\"),\n        (\n            (\"only\", {\"name\"}, {\"children\": [{\"name\": \"Lily\"}]}),\n            (\"exclude\", {\"name\", \"surname\", \"age\"}, {\"children\": [{}]}),\n        ),\n    )\n    def test_list_nested_lambda_only_and_exclude_merged_with_nested(\n        self, param, expected_attribute, expected_dump\n    ):\n        class Child(Schema):\n            name = fields.String()\n            surname = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.List(\n                fields.Nested(lambda: Child(**{param: (\"name\", \"surname\")}))  # type: ignore[arg-type]\n            )\n\n        schema = Family(**{param: [\"children.name\", \"children.age\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.List)\n        assert isinstance(children_field.inner, fields.Nested)\n        assert getattr(children_field.inner.schema, param) == expected_attribute\n\n        family = {\"children\": [{\"name\": \"Lily\", \"surname\": \"Martinez\", \"age\": 15}]}\n        assert schema.dump(family) == expected_dump\n\n    def test_list_nested_partial_propagated_to_nested(self):\n        class Child(Schema):\n            name = fields.String(required=True)\n            age = fields.Integer(required=True)\n\n        class Family(Schema):\n            children = fields.List(fields.Nested(Child))\n\n        payload = {\"children\": [{\"name\": \"Lucette\"}]}\n\n        for val in (True, (\"children.age\",)):\n            result = Family(partial=val).load(payload)\n            assert result[\"children\"][0][\"name\"] == \"Lucette\"\n            result = Family().load(payload, partial=val)\n            assert result[\"children\"][0][\"name\"] == \"Lucette\"\n\n        for val in (False, (\"children.name\",)):\n            with pytest.raises(ValidationError) as excinfo:\n                result = Family(partial=val).load(payload)\n            assert excinfo.value.args[0] == {\n                \"children\": {0: {\"age\": [\"Missing data for required field.\"]}}\n            }\n            with pytest.raises(ValidationError) as excinfo:\n                result = Family().load(payload, partial=val)\n            assert excinfo.value.args[0] == {\n                \"children\": {0: {\"age\": [\"Missing data for required field.\"]}}\n            }\n\n\nclass TestTupleNested:\n    @pytest.mark.parametrize(\"param\", (\"dump_only\", \"load_only\"))\n    def test_tuple_nested_only_exclude_dump_only_load_only_propagated_to_nested(\n        self, param\n    ):\n        class Child(Schema):\n            name = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.Tuple((fields.Nested(Child), fields.Nested(Child)))\n\n        schema = Family(**{param: [\"children.name\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.Tuple)\n        field1, field2 = children_field.tuple_fields\n        assert isinstance(field1, fields.Nested)\n        assert isinstance(field2, fields.Nested)\n        assert getattr(field1.schema, param) == {\"name\"}\n        assert getattr(field2.schema, param) == {\"name\"}\n\n    def test_tuple_nested_partial_propagated_to_nested(self):\n        class Child(Schema):\n            name = fields.String(required=True)\n            age = fields.Integer(required=True)\n\n        class Family(Schema):\n            children = fields.Tuple((fields.Nested(Child),))\n\n        payload = {\"children\": [{\"name\": \"Lucette\"}]}\n\n        for val in (True, (\"children.age\",)):\n            result = Family(partial=val).load(payload)\n            assert result[\"children\"][0][\"name\"] == \"Lucette\"\n            result = Family().load(payload, partial=val)\n            assert result[\"children\"][0][\"name\"] == \"Lucette\"\n\n        for val in (False, (\"children.name\",)):\n            with pytest.raises(ValidationError) as excinfo:\n                result = Family(partial=val).load(payload)\n            assert excinfo.value.args[0] == {\n                \"children\": {0: {\"age\": [\"Missing data for required field.\"]}}\n            }\n            with pytest.raises(ValidationError) as excinfo:\n                result = Family().load(payload, partial=val)\n            assert excinfo.value.args[0] == {\n                \"children\": {0: {\"age\": [\"Missing data for required field.\"]}}\n            }\n\n\nclass TestDictNested:\n    @pytest.mark.parametrize(\"param\", (\"only\", \"exclude\", \"dump_only\", \"load_only\"))\n    def test_dict_nested_only_exclude_dump_only_load_only_propagated_to_nested(\n        self, param\n    ):\n        class Child(Schema):\n            name = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.Dict(values=fields.Nested(Child))\n\n        schema = Family(**{param: [\"children.name\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.Dict)\n        assert isinstance(children_field.value_field, fields.Nested)\n        assert getattr(children_field.value_field.schema, param) == {\"name\"}\n\n    @pytest.mark.parametrize(\n        (\"param\", \"expected\"),\n        ((\"only\", {\"name\"}), (\"exclude\", {\"name\", \"surname\", \"age\"})),\n    )\n    def test_dict_nested_only_and_exclude_merged_with_nested(self, param, expected):\n        class Child(Schema):\n            name = fields.String()\n            surname = fields.String()\n            age = fields.Integer()\n\n        class Family(Schema):\n            children = fields.Dict(\n                values=fields.Nested(Child, **{param: (\"name\", \"surname\")})  # type: ignore[arg-type]\n            )\n\n        schema = Family(**{param: [\"children.name\", \"children.age\"]})  # type: ignore[arg-type]\n        children_field = schema.fields[\"children\"]\n        assert isinstance(children_field, fields.Dict)\n        assert getattr(children_field.value_field, param) == expected\n\n    def test_dict_nested_partial_propagated_to_nested(self):\n        class Child(Schema):\n            name = fields.String(required=True)\n            age = fields.Integer(required=True)\n\n        class Family(Schema):\n            children = fields.Dict(values=fields.Nested(Child))\n\n        payload = {\"children\": {\"daughter\": {\"name\": \"Lucette\"}}}\n\n        for val in (True, (\"children.age\",)):\n            result = Family(partial=val).load(payload)\n            assert result[\"children\"][\"daughter\"][\"name\"] == \"Lucette\"\n            result = Family().load(payload, partial=val)\n            assert result[\"children\"][\"daughter\"][\"name\"] == \"Lucette\"\n\n        for val in (False, (\"children.name\",)):\n            with pytest.raises(ValidationError) as excinfo:\n                result = Family(partial=val).load(payload)\n            assert excinfo.value.args[0] == {\n                \"children\": {\n                    \"daughter\": {\"value\": {\"age\": [\"Missing data for required field.\"]}}\n                }\n            }\n            with pytest.raises(ValidationError) as excinfo:\n                result = Family().load(payload, partial=val)\n            assert excinfo.value.args[0] == {\n                \"children\": {\n                    \"daughter\": {\"value\": {\"age\": [\"Missing data for required field.\"]}}\n                }\n            }\n"
  },
  {
    "path": "tests/test_options.py",
    "content": "import datetime as dt\n\nfrom marshmallow import EXCLUDE, Schema, fields\n\n\nclass UserSchema(Schema):\n    name = fields.String(allow_none=True)\n    email = fields.Email(allow_none=True)\n    age = fields.Integer()\n    created = fields.DateTime()\n    id = fields.Integer(allow_none=True)\n    homepage = fields.Url()\n    birthdate = fields.Date()\n\n\nclass ProfileSchema(Schema):\n    user = fields.Nested(UserSchema)\n\n\nclass TestFieldOrdering:\n    def test_declared_field_order_is_maintained_on_dump(self, user):\n        ser = UserSchema()\n        data = ser.dump(user)\n        keys = list(data)\n        assert keys == [\n            \"name\",\n            \"email\",\n            \"age\",\n            \"created\",\n            \"id\",\n            \"homepage\",\n            \"birthdate\",\n        ]\n\n    def test_declared_field_order_is_maintained_on_load(self, serialized_user):\n        schema = UserSchema(unknown=EXCLUDE)\n        data = schema.load(serialized_user)\n        keys = list(data)\n        assert keys == [\n            \"name\",\n            \"email\",\n            \"age\",\n            \"created\",\n            \"id\",\n            \"homepage\",\n            \"birthdate\",\n        ]\n\n    def test_nested_field_order_with_only_arg_is_maintained_on_dump(self, user):\n        schema = ProfileSchema()\n        data = schema.dump({\"user\": user})\n        user_data = data[\"user\"]\n        keys = list(user_data)\n        assert keys == [\n            \"name\",\n            \"email\",\n            \"age\",\n            \"created\",\n            \"id\",\n            \"homepage\",\n            \"birthdate\",\n        ]\n\n    def test_nested_field_order_with_only_arg_is_maintained_on_load(self):\n        schema = ProfileSchema()\n        data = schema.load(\n            {\n                \"user\": {\n                    \"name\": \"Foo\",\n                    \"email\": \"Foo@bar.com\",\n                    \"age\": 42,\n                    \"created\": dt.datetime.now().isoformat(),\n                    \"id\": 123,\n                    \"homepage\": \"http://foo.com\",\n                    \"birthdate\": dt.datetime.now().date().isoformat(),\n                }\n            }\n        )\n        user_data = data[\"user\"]\n        keys = list(user_data)\n        assert keys == [\n            \"name\",\n            \"email\",\n            \"age\",\n            \"created\",\n            \"id\",\n            \"homepage\",\n            \"birthdate\",\n        ]\n\n    def test_nested_field_order_with_exclude_arg_is_maintained(self, user):\n        class HasNestedExclude(Schema):\n            user = fields.Nested(UserSchema, exclude=(\"birthdate\",))\n\n        ser = HasNestedExclude()\n        data = ser.dump({\"user\": user})\n        user_data = data[\"user\"]\n        keys = list(user_data)\n        assert keys == [\"name\", \"email\", \"age\", \"created\", \"id\", \"homepage\"]\n\n\nclass TestIncludeOption:\n    class AddFieldsSchema(Schema):\n        name = fields.Str()\n\n        class Meta:\n            include = {\"from\": fields.Str()}\n\n    def test_fields_are_added(self):\n        s = self.AddFieldsSchema()\n        in_data = {\"name\": \"Steve\", \"from\": \"Oskosh\"}\n        result = s.load({\"name\": \"Steve\", \"from\": \"Oskosh\"})\n        assert result == in_data\n\n    def test_included_fields_ordered_after_declared_fields(self):\n        class AddFieldsOrdered(Schema):\n            name = fields.Str()\n            email = fields.Str()\n\n            class Meta:\n                include = {\n                    \"from\": fields.Str(),\n                    \"in\": fields.Str(),\n                    \"@at\": fields.Str(),\n                }\n\n        s = AddFieldsOrdered()\n        in_data = {\n            \"name\": \"Steve\",\n            \"from\": \"Oskosh\",\n            \"email\": \"steve@steve.steve\",\n            \"in\": \"VA\",\n            \"@at\": \"Charlottesville\",\n        }\n        # declared fields, then \"included\" fields\n        expected_fields = [\"name\", \"email\", \"from\", \"in\", \"@at\"]\n        assert list(AddFieldsOrdered._declared_fields.keys()) == expected_fields\n\n        result = s.load(in_data)\n        assert list(result.keys()) == expected_fields\n\n    def test_added_fields_are_inherited(self):\n        class AddFieldsChild(self.AddFieldsSchema):  # type: ignore[name-defined]\n            email = fields.Str()\n\n        s = AddFieldsChild()\n        assert \"email\" in s._declared_fields\n        assert \"from\" in s._declared_fields\n        assert isinstance(s._declared_fields[\"from\"], fields.Str)\n\n\nclass TestManyOption:\n    class ManySchema(Schema):\n        foo = fields.Str()\n\n        class Meta:\n            many = True\n\n    def test_many_by_default(self):\n        test = self.ManySchema()\n        assert test.load([{\"foo\": \"bar\"}]) == [{\"foo\": \"bar\"}]\n\n    def test_explicit_single(self):\n        test = self.ManySchema(many=False)\n        assert test.load({\"foo\": \"bar\"}) == {\"foo\": \"bar\"}\n"
  },
  {
    "path": "tests/test_registry.py",
    "content": "import pytest\n\nfrom marshmallow import Schema, class_registry, fields\nfrom marshmallow.exceptions import RegistryError\n\n\ndef test_serializer_has_class_registry():\n    class MySchema(Schema):\n        pass\n\n    class MySubSchema(Schema):\n        pass\n\n    assert \"MySchema\" in class_registry._registry\n    assert \"MySubSchema\" in class_registry._registry\n\n    # by fullpath\n    assert \"tests.test_registry.MySchema\" in class_registry._registry\n    assert \"tests.test_registry.MySubSchema\" in class_registry._registry\n\n\ndef test_register_class_meta_option():\n    class UnregisteredSchema(Schema):\n        class Meta:\n            register = False\n\n    class RegisteredSchema(Schema):\n        class Meta:\n            register = True\n\n    class RegisteredOverrideSchema(UnregisteredSchema):\n        class Meta:\n            register = True\n\n    class UnregisteredOverrideSchema(RegisteredSchema):\n        class Meta:\n            register = False\n\n    assert \"UnregisteredSchema\" not in class_registry._registry\n    assert \"tests.test_registry.UnregisteredSchema\" not in class_registry._registry\n\n    assert \"RegisteredSchema\" in class_registry._registry\n    assert \"tests.test_registry.RegisteredSchema\" in class_registry._registry\n\n    assert \"RegisteredOverrideSchema\" in class_registry._registry\n    assert \"tests.test_registry.RegisteredOverrideSchema\" in class_registry._registry\n\n    assert \"UnregisteredOverrideSchema\" not in class_registry._registry\n    assert (\n        \"tests.test_registry.UnregisteredOverrideSchema\" not in class_registry._registry\n    )\n\n\ndef test_serializer_class_registry_register_same_classname_different_module():\n    reglen = len(class_registry._registry)\n\n    type(\"MyTestRegSchema\", (Schema,), {\"__module__\": \"modA\"})\n\n    assert \"MyTestRegSchema\" in class_registry._registry\n    result = class_registry._registry.get(\"MyTestRegSchema\")\n    assert isinstance(result, list)\n    assert len(result) == 1\n    assert \"modA.MyTestRegSchema\" in class_registry._registry\n    # storing for classname and fullpath\n    assert len(class_registry._registry) == reglen + 2\n\n    type(\"MyTestRegSchema\", (Schema,), {\"__module__\": \"modB\"})\n\n    assert \"MyTestRegSchema\" in class_registry._registry\n    # aggregating classes with same name from different modules\n    result = class_registry._registry.get(\"MyTestRegSchema\")\n    assert isinstance(result, list)\n    assert len(result) == 2\n    assert \"modB.MyTestRegSchema\" in class_registry._registry\n    # storing for same classname (+0) and different module (+1)\n    assert len(class_registry._registry) == reglen + 2 + 1\n\n    type(\"MyTestRegSchema\", (Schema,), {\"__module__\": \"modB\"})\n\n    assert \"MyTestRegSchema\" in class_registry._registry\n    # only the class with matching module has been replaced\n    result = class_registry._registry.get(\"MyTestRegSchema\")\n    assert isinstance(result, list)\n    assert len(result) == 2\n    assert \"modB.MyTestRegSchema\" in class_registry._registry\n    # only the class with matching module has been replaced (+0)\n    assert len(class_registry._registry) == reglen + 2 + 1\n\n\ndef test_serializer_class_registry_override_if_same_classname_same_module():\n    reglen = len(class_registry._registry)\n\n    type(\"MyTestReg2Schema\", (Schema,), {\"__module__\": \"SameModulePath\"})\n\n    assert \"MyTestReg2Schema\" in class_registry._registry\n    result = class_registry._registry.get(\"MyTestReg2Schema\")\n    assert isinstance(result, list)\n    assert len(result) == 1\n    assert \"SameModulePath.MyTestReg2Schema\" in class_registry._registry\n    result = class_registry._registry.get(\"SameModulePath.MyTestReg2Schema\")\n    assert isinstance(result, list)\n    assert len(result) == 1\n    # storing for classname and fullpath\n    assert len(class_registry._registry) == reglen + 2\n\n    type(\"MyTestReg2Schema\", (Schema,), {\"__module__\": \"SameModulePath\"})\n\n    assert \"MyTestReg2Schema\" in class_registry._registry\n    # overriding same class name and same module\n    result = class_registry._registry.get(\"MyTestReg2Schema\")\n    assert isinstance(result, list)\n    assert len(result) == 1\n\n    assert \"SameModulePath.MyTestReg2Schema\" in class_registry._registry\n    # overriding same fullpath\n    result = class_registry._registry.get(\"SameModulePath.MyTestReg2Schema\")\n    assert isinstance(result, list)\n    assert len(result) == 1\n    # overriding for same classname (+0) and different module (+0)\n    assert len(class_registry._registry) == reglen + 2\n\n\nclass A:\n    def __init__(self, _id, b=None):\n        self.id = _id\n        self.b = b\n\n\nclass B:\n    def __init__(self, _id, a=None):\n        self.id = _id\n        self.a = a\n\n\nclass C:\n    def __init__(self, _id, bs=None):\n        self.id = _id\n        self.bs = bs or []\n\n\nclass ASchema(Schema):\n    id = fields.Integer()\n    b = fields.Nested(\"tests.test_registry.BSchema\", exclude=(\"a\",))\n\n\nclass BSchema(Schema):\n    id = fields.Integer()\n    a = fields.Nested(\"tests.test_registry.ASchema\")\n\n\nclass CSchema(Schema):\n    id = fields.Integer()\n    bs = fields.Nested(\"tests.test_registry.BSchema\", many=True)\n\n\ndef test_two_way_nesting():\n    a_obj = A(1)\n    b_obj = B(2, a=a_obj)\n    a_obj.b = b_obj\n\n    a_serialized = ASchema().dump(a_obj)\n    b_serialized = BSchema().dump(b_obj)\n    assert a_serialized[\"b\"][\"id\"] == b_obj.id\n    assert b_serialized[\"a\"][\"id\"] == a_obj.id\n\n\ndef test_nesting_with_class_name_many():\n    c_obj = C(1, bs=[B(2), B(3), B(4)])\n\n    c_serialized = CSchema().dump(c_obj)\n\n    assert len(c_serialized[\"bs\"]) == len(c_obj.bs)\n    assert c_serialized[\"bs\"][0][\"id\"] == c_obj.bs[0].id\n\n\ndef test_invalid_class_name_in_nested_field_raises_error(user):\n    class MySchema(Schema):\n        nf = fields.Nested(\"notfound\")\n\n    sch = MySchema()\n    msg = \"Class with name {!r} was not found\".format(\"notfound\")\n    with pytest.raises(RegistryError, match=msg):\n        sch.dump({\"nf\": None})\n\n\nclass FooSerializer(Schema):\n    _id = fields.Integer()\n\n\ndef test_multiple_classes_with_same_name_raises_error():\n    # Import a class with the same name\n    from .foo_serializer import FooSerializer as FooSerializer1  # noqa: PLC0415, F401\n\n    class MySchema(Schema):\n        foo = fields.Nested(\"FooSerializer\")\n\n    # Using a nested field with the class name fails because there are\n    # two defined classes with the same name\n    sch = MySchema()\n    msg = \"Multiple classes with name {!r} were found.\".format(\"FooSerializer\")\n    with pytest.raises(RegistryError, match=msg):\n        sch.dump({\"foo\": {\"_id\": 1}})\n\n\ndef test_multiple_classes_with_all():\n    # Import a class with the same name\n    from .foo_serializer import FooSerializer as FooSerializer1  # noqa: PLC0415, F401\n\n    classes = class_registry.get_class(\"FooSerializer\", all=True)\n    assert len(classes) == 2\n\n\ndef test_can_use_full_module_path_to_class():\n    from .foo_serializer import FooSerializer as FooSerializer1  # noqa: PLC0415, F401\n\n    # Using full paths is ok\n\n    class Schema1(Schema):\n        foo = fields.Nested(\"tests.foo_serializer.FooSerializer\")\n\n    sch = Schema1()\n\n    # Note: The arguments here don't matter. What matters is that no\n    # error is raised\n    assert sch.dump({\"foo\": {\"_id\": 42}})\n\n    class Schema2(Schema):\n        foo = fields.Nested(\"tests.test_registry.FooSerializer\")\n\n    sch2 = Schema2()\n    assert sch2.dump({\"foo\": {\"_id\": 42}})\n"
  },
  {
    "path": "tests/test_schema.py",
    "content": "import datetime as dt\nimport math\nimport random\nfrom collections import OrderedDict\nfrom typing import NamedTuple, cast\n\nimport pytest\nimport simplejson as json\n\nfrom marshmallow import (\n    EXCLUDE,\n    INCLUDE,\n    RAISE,\n    Schema,\n    class_registry,\n    fields,\n    validate,\n    validates,\n    validates_schema,\n)\nfrom marshmallow.exceptions import (\n    RegistryError,\n    StringNotCollectionError,\n    ValidationError,\n)\nfrom tests.base import (\n    Blog,\n    BlogOnlySchema,\n    BlogSchema,\n    BlogSchemaExclude,\n    ExtendedUserSchema,\n    User,\n    UserExcludeSchema,\n    UserFloatStringSchema,\n    UserIntSchema,\n    UserRelativeUrlSchema,\n    UserSchema,\n    mockjson,\n)\n\nrandom.seed(1)\n\n\ndef test_serializing_basic_object(user):\n    s = UserSchema()\n    data = s.dump(user)\n    assert data[\"name\"] == user.name\n    assert math.isclose(data[\"age\"], 42.3)\n    assert data[\"registered\"]\n\n\ndef test_serializer_dump(user):\n    s = UserSchema()\n    result = s.dump(user)\n    assert result[\"name\"] == user.name\n\n\ndef test_load_resets_errors():\n    class MySchema(Schema):\n        email = fields.Email()\n\n    schema = MySchema()\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"name\": \"Joe\", \"email\": \"notvalid\"})\n    errors = excinfo.value.messages\n    assert len(errors[\"email\"]) == 1\n    assert \"Not a valid email address.\" in errors[\"email\"][0]\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"name\": \"Joe\", \"email\": \"__invalid\"})\n    errors = excinfo.value.messages\n    assert len(errors[\"email\"]) == 1\n    assert \"Not a valid email address.\" in errors[\"email\"][0]\n\n\ndef test_load_validation_error_stores_input_data_and_valid_data():\n    def validator(val):\n        raise ValidationError(\"oops\")\n\n    class MySchema(Schema):\n        always_valid = fields.DateTime()\n        always_invalid = fields.Raw(validate=[validator])\n\n    schema = MySchema()\n    input_data = {\n        \"always_valid\": dt.datetime.now(dt.timezone.utc).isoformat(),\n        \"always_invalid\": 24,\n    }\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load(input_data)\n    err = excinfo.value\n    # err.data is the raw input data\n    assert err.data == input_data\n    assert isinstance(err.valid_data, dict)\n    assert \"always_valid\" in err.valid_data\n    # err.valid_data contains valid, deserialized data\n    assert isinstance(err.valid_data[\"always_valid\"], dt.datetime)\n    # excludes invalid data\n    assert \"always_invalid\" not in err.valid_data\n\n\ndef test_load_resets_error_fields():\n    class MySchema(Schema):\n        email = fields.Email()\n        name = fields.Str()\n\n    schema = MySchema()\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"name\": \"Joe\", \"email\": \"not-valid\"})\n    exc = excinfo.value\n    assert isinstance(exc.messages, dict)\n    assert len(exc.messages.keys()) == 1\n\n    with pytest.raises(ValidationError) as excinfo:\n        schema.load({\"name\": 12, \"email\": \"mick@stones.com\"})\n    exc = excinfo.value\n\n\ndef test_errored_fields_do_not_appear_in_output():\n    class MyField(fields.Field[int]):\n        # Make sure validation fails during serialization\n        def _serialize(self, value, attr, obj, **kwargs):\n            raise ValidationError(\"oops\")\n\n    def validator(val):\n        raise ValidationError(\"oops\")\n\n    class MySchema(Schema):\n        foo = MyField(validate=validator)\n\n    sch = MySchema()\n    with pytest.raises(ValidationError) as excinfo:\n        sch.load({\"foo\": 2})\n    data, errors = excinfo.value.valid_data, excinfo.value.messages\n\n    assert \"foo\" in errors\n    assert isinstance(data, dict)\n    assert \"foo\" not in data\n\n\ndef test_load_many_stores_error_indices():\n    s = UserSchema()\n    data = [\n        {\"name\": \"Mick\", \"email\": \"mick@stones.com\"},\n        {\"name\": \"Keith\", \"email\": \"invalid-email\", \"homepage\": \"invalid-homepage\"},\n    ]\n    with pytest.raises(ValidationError) as excinfo:\n        s.load(data, many=True)\n    errors = excinfo.value.messages\n    assert 0 not in errors\n    assert 1 in errors\n    assert \"email\" in errors[1]\n    assert \"homepage\" in errors[1]\n\n\ndef test_dump_many():\n    s = UserSchema()\n    u1, u2 = User(\"Mick\"), User(\"Keith\")\n    data = s.dump([u1, u2], many=True)\n    assert len(data) == 2\n    assert data[0] == s.dump(u1)\n\n\ndef test_multiple_errors_can_be_stored_for_a_given_index():\n    class MySchema(Schema):\n        foo = fields.Str(validate=validate.Length(min=4))\n        bar = fields.Int(validate=validate.Range(min=4))\n\n    sch = MySchema()\n    valid = {\"foo\": \"loll\", \"bar\": 42}\n    invalid = {\"foo\": \"lol\", \"bar\": 3}\n    errors = sch.validate([valid, invalid], many=True)\n\n    assert 1 in errors\n    assert len(errors[1]) == 2\n    assert \"foo\" in errors[1]\n    assert \"bar\" in errors[1]\n\n\ndef test_dump_returns_a_dict(user):\n    s = UserSchema()\n    result = s.dump(user)\n    assert type(result) is dict\n\n\ndef test_dumps_returns_a_string(user):\n    s = UserSchema()\n    result = s.dumps(user)\n    assert type(result) is str\n\n\ndef test_dumping_single_object_with_collection_schema(user):\n    s = UserSchema(many=True)\n    result = s.dump(user, many=False)\n    assert type(result) is dict\n    assert result == UserSchema().dump(user)\n\n\ndef test_loading_single_object_with_collection_schema():\n    s = UserSchema(many=True)\n    in_data = {\"name\": \"Mick\", \"email\": \"mick@stones.com\"}\n    result = s.load(in_data, many=False)\n    assert type(result) is User\n    assert result.name == UserSchema().load(in_data).name\n\n\ndef test_dumps_many():\n    s = UserSchema()\n    u1, u2 = User(\"Mick\"), User(\"Keith\")\n    json_result = s.dumps([u1, u2], many=True)\n    data = json.loads(json_result)\n    assert len(data) == 2\n    assert data[0] == s.dump(u1)\n\n\ndef test_load_returns_an_object():\n    s = UserSchema()\n    result = s.load({\"name\": \"Monty\"})\n    assert type(result) is User\n\n\ndef test_load_many():\n    s = UserSchema()\n    in_data = [{\"name\": \"Mick\"}, {\"name\": \"Keith\"}]\n    result = s.load(in_data, many=True)\n    assert type(result) is list\n    assert type(result[0]) is User\n    assert result[0].name == \"Mick\"\n\n\n@pytest.mark.parametrize(\"val\", (None, False, 1, 1.2, object(), [], set(), \"lol\"))\ndef test_load_invalid_input_type(val):\n    class Sch(Schema):\n        name = fields.Str()\n\n    with pytest.raises(ValidationError) as e:\n        Sch().load(val)\n    assert e.value.messages == {\"_schema\": [\"Invalid input type.\"]}\n    assert e.value.valid_data == {}\n\n\n# regression test for https://github.com/marshmallow-code/marshmallow/issues/906\n@pytest.mark.parametrize(\"val\", (None, False, 1, 1.2, object(), {}, {\"1\": 2}, \"lol\"))\ndef test_load_many_invalid_input_type(val):\n    class Sch(Schema):\n        name = fields.Str()\n\n    with pytest.raises(ValidationError) as e:\n        Sch(many=True).load(val)\n    assert e.value.messages == {\"_schema\": [\"Invalid input type.\"]}\n    assert e.value.valid_data == []\n\n\n@pytest.mark.parametrize(\"val\", ([], tuple()))\ndef test_load_many_empty_collection(val):\n    class Sch(Schema):\n        name = fields.Str()\n\n    assert Sch(many=True).load(val) == []\n\n\n@pytest.mark.parametrize(\"val\", (False, 1, 1.2, object(), {}, {\"1\": 2}, \"lol\"))\ndef test_load_many_in_nested_invalid_input_type(val):\n    class Inner(Schema):\n        name = fields.String()\n\n    class Outer(Schema):\n        list1 = fields.List(fields.Nested(Inner))\n        list2 = fields.Nested(Inner, many=True)\n\n    with pytest.raises(ValidationError) as e:\n        Outer().load({\"list1\": val, \"list2\": val})\n    # TODO: Error messages should be identical (#779)\n    assert e.value.messages == {\n        \"list1\": [\"Not a valid list.\"],\n        \"list2\": [\"Invalid type.\"],\n    }\n\n\n@pytest.mark.parametrize(\"val\", ([], tuple()))\ndef test_load_many_in_nested_empty_collection(val):\n    class Inner(Schema):\n        name = fields.String()\n\n    class Outer(Schema):\n        list1 = fields.List(fields.Nested(Inner))\n        list2 = fields.Nested(Inner, many=True)\n\n    assert Outer().load({\"list1\": val, \"list2\": val}) == {\"list1\": [], \"list2\": []}\n\n\ndef test_loads_returns_a_user():\n    s = UserSchema()\n    result = s.loads(json.dumps({\"name\": \"Monty\"}))\n    assert type(result) is User\n\n\ndef test_loads_many():\n    s = UserSchema()\n    in_data = [{\"name\": \"Mick\"}, {\"name\": \"Keith\"}]\n    in_json_data = json.dumps(in_data)\n    result = s.loads(in_json_data, many=True)\n    assert type(result) is list\n    assert result[0].name == \"Mick\"\n\n\ndef test_loads_deserializes_from_json():\n    user_dict = {\"name\": \"Monty\", \"age\": \"42.3\"}\n    user_json = json.dumps(user_dict)\n    result = UserSchema().loads(user_json)\n    assert isinstance(result, User)\n    assert result.name == \"Monty\"\n    assert math.isclose(result.age, 42.3)\n\n\ndef test_serializing_none():\n    class MySchema(Schema):\n        id = fields.Str(dump_default=\"no-id\")\n        num = fields.Int()\n        name = fields.Str()\n\n    data = UserSchema().dump(None)\n    assert data == {\"id\": \"no-id\"}\n\n\ndef test_default_many_symmetry():\n    \"\"\"The dump/load(s) methods should all default to the many value of the schema.\"\"\"\n    s_many = UserSchema(many=True, only=(\"name\",))\n    s_single = UserSchema(only=(\"name\",))\n    u1, u2 = User(\"King Arthur\"), User(\"Sir Lancelot\")\n    s_single.load(s_single.dump(u1))\n    s_single.loads(s_single.dumps(u1))\n    s_many.load(s_many.dump([u1, u2]))\n    s_many.loads(s_many.dumps([u1, u2]))\n\n\ndef test_on_bind_field_hook():\n    class MySchema(Schema):\n        foo = fields.Str()\n\n        def on_bind_field(self, field_name, field_obj):\n            assert field_obj.parent is self\n            field_obj.metadata[\"fname\"] = field_name\n\n    schema = MySchema()\n    assert schema.fields[\"foo\"].metadata[\"fname\"] == \"foo\"\n\n\ndef test_nested_on_bind_field_hook():\n    class MySchema(Schema):\n        class NestedSchema(Schema):\n            bar = fields.Str()\n\n            def on_bind_field(self, field_name, field_obj):\n                assert field_obj.parent is self\n                field_obj.metadata[\"fname\"] = field_name\n\n        foo = fields.Nested(NestedSchema)\n\n    schema = MySchema()\n    foo_field = schema.fields[\"foo\"]\n    assert isinstance(foo_field, fields.Nested)\n    assert foo_field.schema.fields[\"bar\"].metadata[\"fname\"] == \"bar\"\n\n\nclass TestValidate:\n    def test_validate_raises_with_errors_dict(self):\n        s = UserSchema()\n        errors = s.validate({\"email\": \"bad-email\", \"name\": \"Valid Name\"})\n        assert type(errors) is dict\n        assert \"email\" in errors\n        assert \"name\" not in errors\n\n        valid_data = {\"name\": \"Valid Name\", \"email\": \"valid@email.com\"}\n        errors = s.validate(valid_data)\n        assert errors == {}\n\n    def test_validate_many(self):\n        s = UserSchema(many=True)\n        in_data = [\n            {\"name\": \"Valid Name\", \"email\": \"validemail@hotmail.com\"},\n            {\"name\": \"Valid Name2\", \"email\": \"invalid\"},\n        ]\n        errors = s.validate(in_data, many=True)\n        assert 1 in errors\n        assert \"email\" in errors[1]\n\n    def test_validate_many_doesnt_store_index_if_index_errors_option_is_false(self):\n        class NoIndex(Schema):\n            email = fields.Email()\n\n            class Meta:\n                index_errors = False\n\n        s = NoIndex()\n        in_data = [\n            {\"name\": \"Valid Name\", \"email\": \"validemail@hotmail.com\"},\n            {\"name\": \"Valid Name2\", \"email\": \"invalid\"},\n        ]\n        errors = s.validate(in_data, many=True)\n        assert 1 not in errors\n        assert \"email\" in errors\n\n    def test_validate(self):\n        s = UserSchema()\n        errors = s.validate({\"email\": \"bad-email\"})\n        assert errors == {\"email\": [\"Not a valid email address.\"]}\n\n    def test_validate_required(self):\n        class MySchema(Schema):\n            foo = fields.Raw(required=True)\n\n        s = MySchema()\n        errors = s.validate({\"bar\": 42})\n        assert \"foo\" in errors\n        assert \"required\" in errors[\"foo\"][0]\n\n\ndef test_fields_are_not_copies():\n    s = UserSchema()\n    s2 = UserSchema()\n    assert s.fields is not s2.fields\n\n\ndef test_dumps_returns_json(user):\n    ser = UserSchema()\n    serialized = ser.dump(user)\n    json_data = ser.dumps(user)\n    assert type(json_data) is str\n    expected = json.dumps(serialized)\n    assert json_data == expected\n\n\ndef test_naive_datetime_field(user, serialized_user):\n    expected = user.created.isoformat()\n    assert serialized_user[\"created\"] == expected\n\n\ndef test_datetime_formatted_field(user, serialized_user):\n    result = serialized_user[\"created_formatted\"]\n    assert result == user.created.strftime(\"%Y-%m-%d\")\n\n\ndef test_datetime_iso_field(user, serialized_user):\n    assert serialized_user[\"created_iso\"] == user.created.isoformat()\n\n\ndef test_tz_datetime_field(user, serialized_user):\n    # Datetime is corrected back to GMT\n    expected = user.updated.isoformat()\n    assert serialized_user[\"updated\"] == expected\n\n\ndef test_class_variable(serialized_user):\n    assert serialized_user[\"species\"] == \"Homo sapiens\"\n\n\ndef test_serialize_many():\n    user1 = User(name=\"Mick\", age=123)\n    user2 = User(name=\"Keith\", age=456)\n    users = [user1, user2]\n    serialized = UserSchema(many=True).dump(users)\n    assert len(serialized) == 2\n    assert serialized[0][\"name\"] == \"Mick\"\n    assert serialized[1][\"name\"] == \"Keith\"\n\n\ndef test_inheriting_schema(user):\n    sch = ExtendedUserSchema()\n    result = sch.dump(user)\n    assert result[\"name\"] == user.name\n    user.is_old = True\n    result = sch.dump(user)\n    assert result[\"is_old\"] is True\n\n\ndef test_custom_field(serialized_user, user):\n    assert serialized_user[\"uppername\"] == user.name.upper()\n\n\ndef test_url_field(serialized_user, user):\n    assert serialized_user[\"homepage\"] == user.homepage\n\n\ndef test_relative_url_field():\n    u = {\"name\": \"John\", \"homepage\": \"/foo\"}\n    UserRelativeUrlSchema().load(u)\n\n\ndef test_stores_invalid_url_error():\n    user = {\"name\": \"Steve\", \"homepage\": \"www.foo.com\"}\n    with pytest.raises(ValidationError) as excinfo:\n        UserSchema().load(user)\n    errors = excinfo.value.messages\n    assert \"homepage\" in errors\n    expected = [\"Not a valid URL.\"]\n    assert errors[\"homepage\"] == expected\n\n\ndef test_email_field():\n    u = User(\"John\", email=\"john@example.com\")\n    s = UserSchema().dump(u)\n    assert s[\"email\"] == \"john@example.com\"\n\n\ndef test_stored_invalid_email():\n    u = {\"name\": \"John\", \"email\": \"johnexample.com\"}\n    with pytest.raises(ValidationError) as excinfo:\n        UserSchema().load(u)\n    errors = excinfo.value.messages\n    assert \"email\" in errors\n    assert errors[\"email\"][0] == \"Not a valid email address.\"\n\n\ndef test_integer_field():\n    u = User(\"John\", age=42.3)\n    serialized = UserIntSchema().dump(u)\n    assert type(serialized[\"age\"]) is int\n    assert serialized[\"age\"] == 42\n\n\ndef test_as_string():\n    u = User(\"John\", age=42.3)\n    serialized = UserFloatStringSchema().dump(u)\n    assert type(serialized[\"age\"]) is str\n    assert math.isclose(float(serialized[\"age\"]), 42.3)\n\n\ndef test_method_field(serialized_user):\n    assert serialized_user[\"is_old\"] is False\n    u = User(\"Joe\", age=81)\n    assert UserSchema().dump(u)[\"is_old\"] is True\n\n\ndef test_function_field(serialized_user, user):\n    assert serialized_user[\"lowername\"] == user.name.lower()\n\n\ndef test_fields_must_be_declared_as_instances(user):\n    with pytest.raises(\n        TypeError, match='Field for \"name\" must be declared as a Field instance'\n    ):\n\n        class BadUserSchema(Schema):\n            name = fields.String\n\n\n# regression test\ndef test_bind_field_does_not_swallow_typeerror():\n    class MySchema(Schema):\n        name = fields.Str()\n\n        def on_bind_field(self, field_name, field_obj):\n            raise TypeError(\"boom\")\n\n    with pytest.raises(TypeError, match=\"boom\"):\n        MySchema()\n\n\ndef test_serializing_generator():\n    users = [User(\"Foo\"), User(\"Bar\")]\n    user_gen = (u for u in users)\n    s = UserSchema(many=True).dump(user_gen)\n    assert len(s) == 2\n    assert s[0] == UserSchema().dump(users[0])\n\n\ndef test_serializing_empty_list_returns_empty_list():\n    assert UserSchema(many=True).dump([]) == []\n\n\ndef test_serializing_dict():\n    user = {\n        \"name\": \"foo\",\n        \"email\": \"foo@bar.com\",\n        \"age\": 42,\n        \"various_data\": {\"foo\": \"bar\"},\n    }\n    data = UserSchema().dump(user)\n    assert data[\"name\"] == \"foo\"\n    assert data[\"age\"] == 42\n    assert data[\"various_data\"] == {\"foo\": \"bar\"}\n\n\ndef test_exclude_in_init(user):\n    s = UserSchema(exclude=(\"age\", \"homepage\")).dump(user)\n    assert \"homepage\" not in s\n    assert \"age\" not in s\n    assert \"name\" in s\n\n\ndef test_only_in_init(user):\n    s = UserSchema(only=(\"name\", \"age\")).dump(user)\n    assert \"homepage\" not in s\n    assert \"name\" in s\n    assert \"age\" in s\n\n\ndef test_invalid_only_param(user):\n    with pytest.raises(ValueError):\n        UserSchema(only=(\"_invalid\", \"name\")).dump(user)\n\n\ndef test_can_serialize_uuid(serialized_user, user):\n    assert serialized_user[\"uid\"] == str(user.uid)\n\n\ndef test_can_serialize_time(user, serialized_user):\n    expected = user.time_registered.isoformat()[:15]\n    assert serialized_user[\"time_registered\"] == expected\n\n\ndef test_render_module():\n    class UserJSONSchema(Schema):\n        name = fields.String()\n\n        class Meta:\n            render_module = mockjson\n\n    user = User(\"Joe\")\n    s = UserJSONSchema()\n    result = s.dumps(user)\n    assert result == mockjson.dumps(\"val\")\n\n\ndef test_custom_error_message():\n    class ErrorSchema(Schema):\n        email = fields.Email(error_messages={\"invalid\": \"Invalid email\"})\n        homepage = fields.Url(error_messages={\"invalid\": \"Bad homepage.\"})\n        balance = fields.Decimal(error_messages={\"invalid\": \"Bad balance.\"})\n\n    u = {\"email\": \"joe.net\", \"homepage\": \"joe@example.com\", \"balance\": \"blah\"}\n    s = ErrorSchema()\n    with pytest.raises(ValidationError) as excinfo:\n        s.load(u)\n    errors = excinfo.value.messages\n    assert \"Bad balance.\" in errors[\"balance\"]\n    assert \"Bad homepage.\" in errors[\"homepage\"]\n    assert \"Invalid email\" in errors[\"email\"]\n\n\ndef test_custom_unknown_error_message():\n    custom_message = \"custom error message.\"\n\n    class ErrorSchema(Schema):\n        error_messages = {\"unknown\": custom_message}\n        name = fields.String()\n\n    s = ErrorSchema()\n    u = {\"name\": \"Joe\", \"age\": 13}\n    with pytest.raises(ValidationError) as excinfo:\n        s.load(u)\n    errors = excinfo.value.messages\n    assert custom_message in errors[\"age\"]\n\n\ndef test_custom_type_error_message():\n    custom_message = \"custom error message.\"\n\n    class ErrorSchema(Schema):\n        error_messages = {\"type\": custom_message}\n        name = fields.String()\n\n    s = ErrorSchema()\n    u = [\"Joe\"]\n    with pytest.raises(ValidationError) as excinfo:\n        s.load(u)  # type: ignore[arg-type]\n    errors = excinfo.value.messages\n    assert custom_message in errors[\"_schema\"]\n\n\ndef test_custom_type_error_message_with_many():\n    custom_message = \"custom error message.\"\n\n    class ErrorSchema(Schema):\n        error_messages = {\"type\": custom_message}\n        name = fields.String()\n\n    s = ErrorSchema(many=True)\n    u = {\"name\": \"Joe\"}\n    with pytest.raises(ValidationError) as excinfo:\n        s.load(u)\n    errors = excinfo.value.messages\n    assert custom_message in errors[\"_schema\"]\n\n\ndef test_custom_error_messages_with_inheritance():\n    parent_type_message = \"parent type error message.\"\n    parent_unknown_message = \"parent unknown error message.\"\n    child_type_message = \"child type error message.\"\n\n    class ParentSchema(Schema):\n        error_messages = {\n            \"type\": parent_type_message,\n            \"unknown\": parent_unknown_message,\n        }\n        name = fields.String()\n\n    class ChildSchema(ParentSchema):\n        error_messages = {\"type\": child_type_message}\n\n    unknown_user = {\"name\": \"Eleven\", \"age\": 12}\n\n    parent_schema = ParentSchema()\n    with pytest.raises(ValidationError) as excinfo:\n        parent_schema.load(unknown_user)\n    assert parent_unknown_message in excinfo.value.messages[\"age\"]\n    with pytest.raises(ValidationError) as excinfo:\n        parent_schema.load(11)  # type: ignore[arg-type]\n    assert parent_type_message in excinfo.value.messages[\"_schema\"]\n\n    child_schema = ChildSchema()\n    with pytest.raises(ValidationError) as excinfo:\n        child_schema.load(unknown_user)\n    assert parent_unknown_message in excinfo.value.messages[\"age\"]\n    with pytest.raises(ValidationError) as excinfo:\n        child_schema.load(11)  # type: ignore[arg-type]\n    assert child_type_message in excinfo.value.messages[\"_schema\"]\n\n\ndef test_load_errors_with_many():\n    class ErrorSchema(Schema):\n        email = fields.Email()\n\n    data = [\n        {\"email\": \"bademail\"},\n        {\"email\": \"goo@email.com\"},\n        {\"email\": \"anotherbademail\"},\n    ]\n\n    with pytest.raises(ValidationError) as excinfo:\n        ErrorSchema(many=True).load(data)\n    errors = excinfo.value.messages\n    assert 0 in errors\n    assert 2 in errors\n    assert \"Not a valid email address.\" in errors[0][\"email\"][0]\n    assert \"Not a valid email address.\" in errors[2][\"email\"][0]\n\n\ndef test_error_raised_if_fields_option_is_not_list():\n    with pytest.raises(ValueError):\n\n        class BadSchema(Schema):\n            name = fields.String()\n\n            class Meta:\n                fields = \"name\"\n\n\ndef test_nested_custom_set_in_exclude_reusing_schema():\n    class CustomSet:\n        # This custom set is to allow the obj check in BaseSchema.__filter_fields\n        # to pass, since it'll be a valid instance, and this class overrides\n        # getitem method to allow the hasattr check to pass too, which will try\n        # to access the first obj index and will simulate a IndexError throwing.\n        # e.g. SqlAlchemy.Query is a valid use case for this 'obj'.\n\n        def __getitem__(self, item):\n            return [][item]\n\n    class ChildSchema(Schema):\n        foo = fields.Raw(required=True)\n        bar = fields.Raw()\n\n        class Meta:\n            only = (\"bar\",)\n\n    class ParentSchema(Schema):\n        child = fields.Nested(ChildSchema, many=True, exclude=(\"foo\",))\n\n    sch = ParentSchema()\n    obj = dict(child=CustomSet())\n    sch.dumps(obj)\n    data = dict(child=[{\"bar\": 1}])\n    sch.load(data, partial=True)\n\n\ndef test_nested_only():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema)\n\n    sch = ParentSchema(only=(\"bla\", \"blubb.foo\", \"blubb.bar\"))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n\n\ndef test_nested_only_inheritance():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema, only=(\"foo\", \"bar\"))\n\n    sch = ParentSchema(only=(\"blubb.foo\", \"blubb.baz\"))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" not in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" in child\n    assert \"bar\" not in child\n    assert \"baz\" not in child\n\n\ndef test_nested_only_empty_inheritance():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema, only=(\"bar\",))\n\n    sch = ParentSchema(only=(\"blubb.foo\",))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" not in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" not in child\n    assert \"baz\" not in child\n\n\ndef test_nested_exclude():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema)\n\n    sch = ParentSchema(exclude=(\"bli\", \"blubb.baz\"))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n\n\ndef test_nested_exclude_inheritance():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema, exclude=(\"baz\",))\n\n    sch = ParentSchema(exclude=(\"blubb.foo\",))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n\n\ndef test_nested_only_and_exclude():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema)\n\n    sch = ParentSchema(only=(\"bla\", \"blubb.foo\", \"blubb.bar\"), exclude=(\"blubb.foo\",))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n\n\ndef test_nested_only_then_exclude_inheritance():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema, only=(\"foo\", \"bar\"))\n\n    sch = ParentSchema(exclude=(\"blubb.foo\",))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n\n\ndef test_nested_exclude_then_only_inheritance():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema, exclude=(\"foo\",))\n\n    sch = ParentSchema(only=(\"blubb.bar\",))\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" not in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n\n\ndef test_nested_exclude_and_only_inheritance():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n        ban = fields.Raw()\n        fuu = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(\n            ChildSchema, only=(\"foo\", \"bar\", \"baz\", \"ban\"), exclude=(\"foo\",)\n        )\n\n    sch = ParentSchema(\n        only=(\"blubb.foo\", \"blubb.bar\", \"blubb.baz\"), exclude=(\"blubb.baz\",)\n    )\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n    result = sch.dump(data)\n    assert \"bla\" not in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" not in child\n    assert \"ban\" not in child\n    assert \"fuu\" not in child\n\n\n# https://github.com/marshmallow-code/marshmallow/issues/1160\ndef test_nested_instance_many():\n    class BookSchema(Schema):\n        id = fields.Int()\n        title = fields.String()\n\n    class UserSchema(Schema):\n        id = fields.Int()\n        name = fields.String()\n        books = fields.Nested(BookSchema(many=True))\n\n    books = [{\"id\": 1, \"title\": \"First book\"}, {\"id\": 2, \"title\": \"Second book\"}]\n    user = {\"id\": 1, \"name\": \"Peter\", \"books\": books}\n\n    assert cast(\"fields.Nested\", UserSchema().fields[\"books\"]).schema.many\n\n    user_dump = UserSchema().dump(user)\n    assert user_dump[\"books\"] == books\n\n    user_load = UserSchema().load(user_dump)\n    assert user_load == user\n\n\ndef test_nested_many_should_override_schema_many_case1():\n    class BookSchema(Schema):\n        id = fields.Int()\n        title = fields.String()\n\n    class UserSchema(Schema):\n        id = fields.Int()\n        name = fields.String()\n        books = fields.Nested(BookSchema(), many=True)\n\n    books = [{\"id\": 1, \"title\": \"First book\"}, {\"id\": 2, \"title\": \"Second book\"}]\n    user = {\"id\": 1, \"name\": \"Peter\", \"books\": books}\n\n    assert cast(\"fields.Nested\", UserSchema().fields[\"books\"]).schema.many\n\n    user_dump = UserSchema().dump(user)\n    assert user_dump[\"books\"] == books\n\n    user_load = UserSchema().load(user_dump)\n    assert user_load == user\n\n\ndef test_nested_many_should_override_schema_many_case2():\n    class BookSchema(Schema):\n        id = fields.Int()\n        title = fields.String()\n\n    class UserSchema(Schema):\n        id = fields.Int()\n        name = fields.String()\n        book = fields.Nested(BookSchema(many=True), many=False)\n\n    book = {\"id\": 1, \"title\": \"First book\"}\n    user = {\"id\": 1, \"name\": \"Peter\", \"book\": book}\n\n    assert not cast(\"fields.Nested\", UserSchema().fields[\"book\"]).schema.many\n\n    user_dump = UserSchema().dump(user)\n    assert user_dump[\"book\"] == book\n\n    user_load = UserSchema().load(user_dump)\n    assert user_load == user\n\n\ndef test_nested_instance_only():\n    class ArtistSchema(Schema):\n        first = fields.Str()\n        last = fields.Str()\n\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        artist = fields.Nested(ArtistSchema(), only=(\"last\",))\n\n    schema = AlbumSchema()\n    album = {\"title\": \"Hunky Dory\", \"artist\": {\"last\": \"Bowie\"}}\n    loaded = schema.load(album)\n    assert loaded == album\n    full_album = {\"title\": \"Hunky Dory\", \"artist\": {\"first\": \"David\", \"last\": \"Bowie\"}}\n    assert schema.dump(full_album) == album\n\n\ndef test_nested_instance_exclude():\n    class ArtistSchema(Schema):\n        first = fields.Str()\n        last = fields.Str()\n\n    class AlbumSchema(Schema):\n        title = fields.Str()\n        artist = fields.Nested(ArtistSchema(), exclude=(\"first\",))\n\n    schema = AlbumSchema()\n    album = {\"title\": \"Hunky Dory\", \"artist\": {\"last\": \"Bowie\"}}\n    loaded = schema.load(album)\n    assert loaded == album\n    full_album = {\"title\": \"Hunky Dory\", \"artist\": {\"first\": \"David\", \"last\": \"Bowie\"}}\n    assert schema.dump(full_album) == album\n\n\ndef test_meta_nested_exclude():\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema)\n\n        class Meta:\n            exclude = (\"blubb.foo\",)\n\n    data = dict(bla=1, bli=2, blubb=dict(foo=42, bar=24, baz=242))\n\n    sch = ParentSchema()\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" in child\n\n    # Test fields with dot notations in Meta.exclude on multiple instantiations\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/1212\n    sch = ParentSchema()\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" in result\n    child = result[\"blubb\"]\n    assert \"foo\" not in child\n    assert \"bar\" in child\n    assert \"baz\" in child\n\n\ndef test_nested_custom_set_not_implementing_getitem():\n    # This test checks that marshmallow can serialize implementations of\n    # :mod:`collections.abc.MutableSequence`, with ``__getitem__`` arguments\n    # that are not integers.\n\n    class ListLikeParent:\n        \"\"\"\n        Implements a list-like object that can get children using a\n        non-integer key\n        \"\"\"\n\n        def __init__(self, required_key, child):\n            \"\"\"\n            :param required_key: The key to use in ``__getitem__`` in order\n                to successfully get the ``child``\n            :param child: The return value of the ``child`` if\n            ``__getitem__`` succeeds\n            \"\"\"\n            self.children = {required_key: child}\n\n    class Child:\n        \"\"\"\n        Implements an object with some attribute\n        \"\"\"\n\n        def __init__(self, attribute: str):\n            \"\"\"\n            :param attribute: The attribute to initialize\n            \"\"\"\n            self.attribute = attribute\n\n    class ChildSchema(Schema):\n        \"\"\"\n        The marshmallow schema for the child\n        \"\"\"\n\n        attribute = fields.Str()\n\n    class ParentSchema(Schema):\n        \"\"\"\n        The schema for the parent\n        \"\"\"\n\n        children = fields.Nested(ChildSchema, many=True)\n\n    attribute = \"Foo\"\n    required_key = \"key\"\n    child = Child(attribute)\n\n    parent = ListLikeParent(required_key, child)\n\n    ParentSchema().dump(parent)\n\n\ndef test_deeply_nested_only_and_exclude():\n    class GrandChildSchema(Schema):\n        goo = fields.Raw()\n        gah = fields.Raw()\n        bah = fields.Raw()\n\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        flubb = fields.Nested(GrandChildSchema)\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(ChildSchema)\n\n    sch = ParentSchema(\n        only=(\"bla\", \"blubb.foo\", \"blubb.flubb.goo\", \"blubb.flubb.gah\"),\n        exclude=(\"blubb.flubb.goo\",),\n    )\n    data = dict(bla=1, bli=2, blubb=dict(foo=3, bar=4, flubb=dict(goo=5, gah=6, bah=7)))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" in child\n    assert \"flubb\" in child\n    assert \"bar\" not in child\n    grand_child = child[\"flubb\"]\n    assert \"gah\" in grand_child\n    assert \"goo\" not in grand_child\n    assert \"bah\" not in grand_child\n\n\ndef test_nested_lambda():\n    class ChildSchema(Schema):\n        id = fields.Str()\n        name = fields.Str()\n        parent = fields.Nested(lambda: ParentSchema(only=(\"id\",)), dump_only=True)\n        siblings = fields.List(fields.Nested(lambda: ChildSchema(only=(\"id\", \"name\"))))\n\n    class ParentSchema(Schema):\n        id = fields.Str()\n        spouse = fields.Nested(lambda: ParentSchema(only=(\"id\",)))\n        children = fields.List(\n            fields.Nested(lambda: ChildSchema(only=(\"id\", \"parent\", \"siblings\")))\n        )\n\n    sch = ParentSchema()\n    data_to_load = {\n        \"id\": \"p1\",\n        \"spouse\": {\"id\": \"p2\"},\n        \"children\": [{\"id\": \"c1\", \"siblings\": [{\"id\": \"c2\", \"name\": \"sis\"}]}],\n    }\n    loaded = sch.load(data_to_load)\n    assert loaded == data_to_load\n\n    data_to_dump = dict(\n        id=\"p2\",\n        spouse=dict(id=\"p2\"),\n        children=[\n            dict(\n                id=\"c1\",\n                name=\"bar\",\n                parent=dict(id=\"p2\"),\n                siblings=[dict(id=\"c2\", name=\"sis\")],\n            )\n        ],\n    )\n    dumped = sch.dump(data_to_dump)\n    assert dumped == {\n        \"id\": \"p2\",\n        \"spouse\": {\"id\": \"p2\"},\n        \"children\": [\n            {\n                \"id\": \"c1\",\n                \"parent\": {\"id\": \"p2\"},\n                \"siblings\": [{\"id\": \"c2\", \"name\": \"sis\"}],\n            }\n        ],\n    }\n\n\n@pytest.mark.parametrize(\"data_key\", (\"f1\", \"f5\", None))\ndef test_data_key_collision(data_key):\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw(data_key=data_key)\n        f3 = fields.Raw(data_key=\"f5\")\n        f4 = fields.Raw(data_key=\"f1\", load_only=True)\n\n    if data_key is None:\n        MySchema()\n    else:\n        with pytest.raises(ValueError, match=data_key):\n            MySchema()\n\n\n@pytest.mark.parametrize(\"attribute\", (\"f1\", \"f5\", None))\ndef test_attribute_collision(attribute):\n    class MySchema(Schema):\n        f1 = fields.Raw()\n        f2 = fields.Raw(attribute=attribute)\n        f3 = fields.Raw(attribute=\"f5\")\n        f4 = fields.Raw(attribute=\"f1\", dump_only=True)\n\n    if attribute is None:\n        MySchema()\n    else:\n        with pytest.raises(ValueError, match=attribute):\n            MySchema()\n\n\nclass TestDeeplyNestedLoadOnly:\n    @pytest.fixture\n    def schema(self):\n        class GrandChildSchema(Schema):\n            str_dump_only = fields.String()\n            str_load_only = fields.String()\n            str_regular = fields.String()\n\n        class ChildSchema(Schema):\n            str_dump_only = fields.String()\n            str_load_only = fields.String()\n            str_regular = fields.String()\n            grand_child = fields.Nested(GrandChildSchema, unknown=EXCLUDE)\n\n        class ParentSchema(Schema):\n            str_dump_only = fields.String()\n            str_load_only = fields.String()\n            str_regular = fields.String()\n            child = fields.Nested(ChildSchema, unknown=EXCLUDE)\n\n        return ParentSchema(\n            dump_only=(\n                \"str_dump_only\",\n                \"child.str_dump_only\",\n                \"child.grand_child.str_dump_only\",\n            ),\n            load_only=(\n                \"str_load_only\",\n                \"child.str_load_only\",\n                \"child.grand_child.str_load_only\",\n            ),\n        )\n\n    @pytest.fixture\n    def data(self):\n        return dict(\n            str_dump_only=\"Dump Only\",\n            str_load_only=\"Load Only\",\n            str_regular=\"Regular String\",\n            child=dict(\n                str_dump_only=\"Dump Only\",\n                str_load_only=\"Load Only\",\n                str_regular=\"Regular String\",\n                grand_child=dict(\n                    str_dump_only=\"Dump Only\",\n                    str_load_only=\"Load Only\",\n                    str_regular=\"Regular String\",\n                ),\n            ),\n        )\n\n    def test_load_only(self, schema, data):\n        result = schema.dump(data)\n        assert \"str_load_only\" not in result\n        assert \"str_dump_only\" in result\n        assert \"str_regular\" in result\n        child = result[\"child\"]\n        assert \"str_load_only\" not in child\n        assert \"str_dump_only\" in child\n        assert \"str_regular\" in child\n        grand_child = child[\"grand_child\"]\n        assert \"str_load_only\" not in grand_child\n        assert \"str_dump_only\" in grand_child\n        assert \"str_regular\" in grand_child\n\n    def test_dump_only(self, schema, data):\n        result = schema.load(data, unknown=EXCLUDE)\n        assert \"str_dump_only\" not in result\n        assert \"str_load_only\" in result\n        assert \"str_regular\" in result\n        child = result[\"child\"]\n        assert \"str_dump_only\" not in child\n        assert \"str_load_only\" in child\n        assert \"str_regular\" in child\n        grand_child = child[\"grand_child\"]\n        assert \"str_dump_only\" not in grand_child\n        assert \"str_load_only\" in grand_child\n        assert \"str_regular\" in grand_child\n\n\nclass TestDeeplyNestedListLoadOnly:\n    @pytest.fixture\n    def schema(self):\n        class ChildSchema(Schema):\n            str_dump_only = fields.String()\n            str_load_only = fields.String()\n            str_regular = fields.String()\n\n        class ParentSchema(Schema):\n            str_dump_only = fields.String()\n            str_load_only = fields.String()\n            str_regular = fields.String()\n            child = fields.List(fields.Nested(ChildSchema, unknown=EXCLUDE))\n\n        return ParentSchema(\n            dump_only=(\"str_dump_only\", \"child.str_dump_only\"),\n            load_only=(\"str_load_only\", \"child.str_load_only\"),\n        )\n\n    @pytest.fixture\n    def data(self):\n        return dict(\n            str_dump_only=\"Dump Only\",\n            str_load_only=\"Load Only\",\n            str_regular=\"Regular String\",\n            child=[\n                dict(\n                    str_dump_only=\"Dump Only\",\n                    str_load_only=\"Load Only\",\n                    str_regular=\"Regular String\",\n                )\n            ],\n        )\n\n    def test_load_only(self, schema, data):\n        result = schema.dump(data)\n        assert \"str_load_only\" not in result\n        assert \"str_dump_only\" in result\n        assert \"str_regular\" in result\n        child = result[\"child\"][0]\n        assert \"str_load_only\" not in child\n        assert \"str_dump_only\" in child\n        assert \"str_regular\" in child\n\n    def test_dump_only(self, schema, data):\n        result = schema.load(data, unknown=EXCLUDE)\n        assert \"str_dump_only\" not in result\n        assert \"str_load_only\" in result\n        assert \"str_regular\" in result\n        child = result[\"child\"][0]\n        assert \"str_dump_only\" not in child\n        assert \"str_load_only\" in child\n        assert \"str_regular\" in child\n\n\ndef test_nested_constructor_only_and_exclude():\n    class GrandChildSchema(Schema):\n        goo = fields.Raw()\n        gah = fields.Raw()\n        bah = fields.Raw()\n\n    class ChildSchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        flubb = fields.Nested(GrandChildSchema)\n\n    class ParentSchema(Schema):\n        bla = fields.Raw()\n        bli = fields.Raw()\n        blubb = fields.Nested(\n            ChildSchema, only=(\"foo\", \"flubb.goo\", \"flubb.gah\"), exclude=(\"flubb.goo\",)\n        )\n\n    sch = ParentSchema(only=(\"bla\", \"blubb\"))\n    data = dict(bla=1, bli=2, blubb=dict(foo=3, bar=4, flubb=dict(goo=5, gah=6, bah=7)))\n    result = sch.dump(data)\n    assert \"bla\" in result\n    assert \"blubb\" in result\n    assert \"bli\" not in result\n    child = result[\"blubb\"]\n    assert \"foo\" in child\n    assert \"flubb\" in child\n    assert \"bar\" not in child\n    grand_child = child[\"flubb\"]\n    assert \"gah\" in grand_child\n    assert \"goo\" not in grand_child\n    assert \"bah\" not in grand_child\n\n\ndef test_only_and_exclude():\n    class MySchema(Schema):\n        foo = fields.Raw()\n        bar = fields.Raw()\n        baz = fields.Raw()\n\n    sch = MySchema(only=(\"foo\", \"bar\"), exclude=(\"bar\",))\n    data = dict(foo=42, bar=24, baz=242)\n    result = sch.dump(data)\n    assert \"foo\" in result\n    assert \"bar\" not in result\n\n\ndef test_invalid_only_and_exclude_with_fields():\n    class MySchema(Schema):\n        foo = fields.Raw()\n\n        class Meta:\n            fields = (\"bar\", \"baz\")\n\n    with pytest.raises(ValueError) as excinfo:\n        MySchema(only=(\"foo\", \"par\"), exclude=(\"ban\",))\n\n    assert \"foo\" in str(excinfo.value)\n    assert \"par\" in str(excinfo.value)\n    assert \"ban\" in str(excinfo.value)\n\n\ndef test_exclude_invalid_attribute():\n    class MySchema(Schema):\n        foo = fields.Raw()\n\n    with pytest.raises(ValueError, match=\"'bar'\"):\n        MySchema(exclude=(\"bar\",))\n\n\ndef test_only_bounded_by_fields():\n    class MySchema(Schema):\n        class Meta:\n            fields = (\"foo\",)\n\n    with pytest.raises(ValueError, match=\"'baz'\"):\n        MySchema(only=(\"baz\",))\n\n\ndef test_only_bounded_by_additional():\n    class MySchema(Schema):\n        class Meta:\n            additional = (\"b\",)\n\n    with pytest.raises(ValueError):\n        MySchema(only=(\"c\",)).dump({\"c\": 3})\n\n\ndef test_only_empty():\n    class MySchema(Schema):\n        foo = fields.Raw()\n\n    sch = MySchema(only=())\n    assert \"foo\" not in sch.dump({\"foo\": \"bar\"})\n\n\n@pytest.mark.parametrize(\"param\", (\"only\", \"exclude\"))\ndef test_only_and_exclude_as_string(param):\n    class MySchema(Schema):\n        foo = fields.Raw()\n\n    with pytest.raises(StringNotCollectionError):\n        MySchema(**{param: \"foo\"})  # type: ignore[arg-type]\n\n\ndef test_nested_with_sets():\n    class Inner(Schema):\n        foo = fields.Raw()\n\n    class Outer(Schema):\n        inners = fields.Nested(Inner, many=True)\n\n    sch = Outer()\n\n    class Thing(NamedTuple):\n        foo: int\n\n    data = dict(inners={Thing(42), Thing(2)})\n    result = sch.dump(data)\n    assert len(result[\"inners\"]) == 2\n\n\ndef test_meta_field_not_on_obj_raises_attribute_error(user):\n    class BadUserSchema(Schema):\n        class Meta:\n            fields = (\"name\",)\n            exclude = (\"notfound\",)\n\n    with pytest.raises(ValueError, match=\"'notfound'\"):\n        BadUserSchema().dump(user)\n\n\ndef test_exclude_fields(user):\n    s = UserExcludeSchema().dump(user)\n    assert \"created\" not in s\n    assert \"updated\" not in s\n    assert \"name\" in s\n\n\ndef test_fields_option_must_be_list_or_tuple():\n    with pytest.raises(ValueError):\n\n        class BadFields(Schema):\n            class Meta:\n                fields = \"name\"\n\n\ndef test_exclude_option_must_be_list_or_tuple():\n    with pytest.raises(ValueError):\n\n        class BadExclude(Schema):\n            class Meta:\n                exclude = \"name\"\n\n\ndef test_datetimeformat_option(user):\n    meta_fmt = \"%Y-%m\"\n    field_fmt = \"%m-%d\"\n\n    class DateTimeFormatSchema(Schema):\n        created = fields.DateTime()\n        updated = fields.DateTime(field_fmt)\n\n        class Meta:\n            datetimeformat = meta_fmt\n\n    serialized = DateTimeFormatSchema().dump(user)\n    assert serialized[\"created\"] == user.created.strftime(meta_fmt)\n    assert serialized[\"updated\"] == user.updated.strftime(field_fmt)\n\n\ndef test_dateformat_option(user):\n    fmt = \"%Y-%m\"\n    field_fmt = \"%m-%d\"\n\n    class DateFormatSchema(Schema):\n        birthdate = fields.Date(field_fmt)\n        activation_date = fields.Date()\n\n        class Meta:\n            dateformat = fmt\n\n    serialized = DateFormatSchema().dump(user)\n    assert serialized[\"birthdate\"] == user.birthdate.strftime(field_fmt)\n    assert serialized[\"activation_date\"] == user.activation_date.strftime(fmt)\n\n\ndef test_timeformat_option(user):\n    fmt = \"%H:%M:%S\"\n    field_fmt = \"%H:%M\"\n\n    class TimeFormatSchema(Schema):\n        birthtime = fields.Time(field_fmt)\n        time_registered = fields.Time()\n\n        class Meta:\n            timeformat = fmt\n\n    serialized = TimeFormatSchema().dump(user)\n    assert serialized[\"birthtime\"] == user.birthtime.strftime(field_fmt)\n    assert serialized[\"time_registered\"] == user.time_registered.strftime(fmt)\n\n\ndef test_default_dateformat(user):\n    class DateFormatSchema(Schema):\n        created = fields.DateTime()\n        updated = fields.DateTime(format=\"%m-%d\")\n\n    serialized = DateFormatSchema().dump(user)\n    assert serialized[\"created\"] == user.created.isoformat()\n    assert serialized[\"updated\"] == user.updated.strftime(\"%m-%d\")\n\n\nclass CustomError(Exception):\n    pass\n\n\nclass MySchema(Schema):\n    name = fields.String()\n    email = fields.Email()\n    age = fields.Integer()\n\n    def handle_error(self, error, data, *args, **kwargs):\n        raise CustomError(\"Something bad happened\")\n\n    def test_load_with_custom_error_handler(self):\n        in_data = {\"email\": \"invalid\"}\n\n        class MySchema3(Schema):\n            email = fields.Email()\n\n            def handle_error(self, error, data, **kwargs):\n                assert type(error) is ValidationError\n                assert \"email\" in error.messages\n                assert isinstance(error.messages, dict)\n                assert list(error.messages.keys()) == [\"email\"]\n                assert data == in_data\n                raise CustomError(\"Something bad happened\")\n\n        with pytest.raises(CustomError):\n            MySchema3().load(in_data)\n\n    def test_load_with_custom_error_handler_and_partially_valid_data(self):\n        in_data = {\"email\": \"invalid\", \"url\": \"http://valid.com\"}\n\n        class MySchema(Schema):\n            email = fields.Email()\n            url = fields.URL()\n\n            def handle_error(self, error, data, **kwargs):\n                assert type(error) is ValidationError\n                assert \"email\" in error.messages\n                assert isinstance(error.messages, dict)\n                assert list(error.messages.keys()) == [\"email\"]\n                assert data == in_data\n                raise CustomError(\"Something bad happened\")\n\n        with pytest.raises(CustomError):\n            MySchema().load(in_data)\n\n    def test_custom_error_handler_with_validates_decorator(self):\n        in_data = {\"num\": -1}\n\n        class MySchema(Schema):\n            num = fields.Int()\n\n            @validates(\"num\")\n            def validate_num(self, value):\n                if value < 0:\n                    raise ValidationError(\"Must be greater than 0.\")\n\n            def handle_error(self, error, data, **kwargs):\n                assert type(error) is ValidationError\n                assert \"num\" in error.messages\n                assert isinstance(error.messages, dict)\n                assert list(error.messages.keys()) == [\"num\"]\n                assert data == in_data\n                raise CustomError(\"Something bad happened\")\n\n        with pytest.raises(CustomError):\n            MySchema().load(in_data)\n\n    def test_custom_error_handler_with_validates_schema_decorator(self):\n        in_data = {\"num\": -1}\n\n        class MySchema(Schema):\n            num = fields.Int()\n\n            @validates_schema\n            def validates_schema(self, data, **kwargs):\n                raise ValidationError(\"Invalid schema!\")\n\n            def handle_error(self, error, data, **kwargs):\n                assert type(error) is ValidationError\n                assert isinstance(error.messages, dict)\n                assert list(error.messages.keys()) == [\"_schema\"]\n                assert data == in_data\n                raise CustomError(\"Something bad happened\")\n\n        with pytest.raises(CustomError):\n            MySchema().load(in_data)\n\n    def test_validate_with_custom_error_handler(self):\n        with pytest.raises(CustomError):\n            MySchema().validate({\"age\": \"notvalid\", \"email\": \"invalid\"})\n\n\nclass TestFieldValidation:\n    def test_errors_are_cleared_after_loading_collection(self):\n        def always_fail(val):\n            raise ValidationError(\"lol\")\n\n        class MySchema(Schema):\n            foo = fields.Str(validate=always_fail)\n\n        schema = MySchema()\n        with pytest.raises(ValidationError) as excinfo:\n            schema.load([{\"foo\": \"bar\"}, {\"foo\": \"baz\"}], many=True)\n        errors = excinfo.value.messages\n        assert len(errors[0][\"foo\"]) == 1\n        assert len(errors[1][\"foo\"]) == 1\n        with pytest.raises(ValidationError) as excinfo:\n            schema.load({\"foo\": \"bar\"})\n        errors = excinfo.value.messages\n        assert len(errors[\"foo\"]) == 1\n\n    def test_raises_error_with_list(self):\n        def validator(val):\n            raise ValidationError([\"err1\", \"err2\"])\n\n        class MySchema(Schema):\n            foo = fields.Raw(validate=validator)\n\n        s = MySchema()\n        errors = s.validate({\"foo\": 42})\n        assert errors[\"foo\"] == [\"err1\", \"err2\"]\n\n    # https://github.com/marshmallow-code/marshmallow/issues/110\n    def test_raises_error_with_dict(self):\n        def validator(val):\n            raise ValidationError({\"code\": \"invalid_foo\"})\n\n        class MySchema(Schema):\n            foo = fields.Raw(validate=validator)\n\n        s = MySchema()\n        errors = s.validate({\"foo\": 42})\n        assert errors[\"foo\"] == [{\"code\": \"invalid_foo\"}]\n\n    def test_ignored_if_not_in_only(self):\n        class MySchema(Schema):\n            a = fields.Raw()\n            b = fields.Raw()\n\n            @validates(\"a\")\n            def validate_a(self, val, **kwargs):\n                raise ValidationError({\"code\": \"invalid_a\"})\n\n            @validates(\"b\")\n            def validate_b(self, val, **kwargs):\n                raise ValidationError({\"code\": \"invalid_b\"})\n\n        s = MySchema(only=(\"b\",))\n        errors = s.validate({\"b\": \"data\"})\n        assert errors == {\"b\": {\"code\": \"invalid_b\"}}\n\n\ndef test_schema_repr():\n    class MySchema(Schema):\n        name = fields.String()\n\n    ser = MySchema(many=True)\n    rep = repr(ser)\n    assert \"MySchema\" in rep\n    assert \"many=True\" in rep\n\n\nclass TestNestedSchema:\n    @pytest.fixture\n    def user(self):\n        return User(name=\"Monty\", age=81)\n\n    @pytest.fixture\n    def blog(self, user):\n        col1 = User(name=\"Mick\", age=123)\n        col2 = User(name=\"Keith\", age=456)\n        return Blog(\n            \"Monty's blog\",\n            user=user,\n            categories=[\"humor\", \"violence\"],\n            collaborators=[col1, col2],\n        )\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/issues/64\n    def test_nested_many_with_missing_attribute(self, user):\n        class SimpleBlogSchema(Schema):\n            title = fields.Str()\n            wat = fields.Nested(UserSchema, many=True)\n\n        blog = Blog(\"Simple blog\", user=user, collaborators=None)\n        schema = SimpleBlogSchema()\n        result = schema.dump(blog)\n        assert \"wat\" not in result\n\n    def test_nested_with_attribute_none(self):\n        class InnerSchema(Schema):\n            bar = fields.Raw()\n\n        class MySchema(Schema):\n            foo = fields.Nested(InnerSchema)\n\n        class MySchema2(Schema):\n            foo = fields.Nested(InnerSchema)\n\n        s = MySchema()\n        result = s.dump({\"foo\": None})\n        assert result[\"foo\"] is None\n\n        s2 = MySchema2()\n        result2 = s2.dump({\"foo\": None})\n        assert result2[\"foo\"] is None\n\n    def test_nested_field_does_not_validate_required(self):\n        class BlogRequiredSchema(Schema):\n            user = fields.Nested(UserSchema, required=True)\n\n        b = Blog(\"Authorless blog\", user=None)\n        BlogRequiredSchema().dump(b)\n\n    def test_nested_none(self):\n        class BlogDefaultSchema(Schema):\n            user = fields.Nested(UserSchema, dump_default=0)\n\n        b = Blog(\"Just the default blog\", user=None)\n        data = BlogDefaultSchema().dump(b)\n        assert data[\"user\"] is None\n\n    def test_nested(self, user, blog):\n        blog_serializer = BlogSchema()\n        serialized_blog = blog_serializer.dump(blog)\n        user_serializer = UserSchema()\n        serialized_user = user_serializer.dump(user)\n        assert serialized_blog[\"user\"] == serialized_user\n\n        with pytest.raises(ValidationError, match=\"email\"):\n            BlogSchema().load(\n                {\"title\": \"Monty's blog\", \"user\": {\"name\": \"Monty\", \"email\": \"foo\"}}\n            )\n\n    def test_nested_many_fields(self, blog):\n        serialized_blog = BlogSchema().dump(blog)\n        expected = [UserSchema().dump(col) for col in blog.collaborators]\n        assert serialized_blog[\"collaborators\"] == expected\n\n    def test_nested_only(self, blog):\n        col1 = User(name=\"Mick\", age=123, id_=\"abc\")\n        col2 = User(name=\"Keith\", age=456, id_=\"def\")\n        blog.collaborators = [col1, col2]\n        serialized_blog = BlogOnlySchema().dump(blog)\n        assert serialized_blog[\"collaborators\"] == [{\"id\": col1.id}, {\"id\": col2.id}]\n\n    def test_exclude(self, blog):\n        serialized = BlogSchemaExclude().dump(blog)\n        assert \"uppername\" not in serialized[\"user\"]\n\n    def test_list_field(self, blog):\n        serialized = BlogSchema().dump(blog)\n        assert serialized[\"categories\"] == [\"humor\", \"violence\"]\n\n    def test_nested_load_many(self):\n        in_data = {\n            \"title\": \"Shine A Light\",\n            \"collaborators\": [\n                {\"name\": \"Mick\", \"email\": \"mick@stones.com\"},\n                {\"name\": \"Keith\", \"email\": \"keith@stones.com\"},\n            ],\n        }\n        data = BlogSchema().load(in_data)\n        collabs = data[\"collaborators\"]\n        assert len(collabs) == 2\n        assert all(type(each) is User for each in collabs)\n        assert collabs[0].name == in_data[\"collaborators\"][0][\"name\"]\n\n    def test_nested_errors(self):\n        with pytest.raises(ValidationError) as excinfo:\n            BlogSchema().load(\n                {\"title\": \"Monty's blog\", \"user\": {\"name\": \"Monty\", \"email\": \"foo\"}}\n            )\n        errors = excinfo.value.messages\n        assert \"email\" in errors[\"user\"]\n        assert len(errors[\"user\"][\"email\"]) == 1\n        assert \"Not a valid email address.\" in errors[\"user\"][\"email\"][0]\n        # No problems with collaborators\n        assert \"collaborators\" not in errors\n\n    def test_nested_method_field(self, blog):\n        data = BlogSchema().dump(blog)\n        assert data[\"user\"][\"is_old\"]\n        assert data[\"collaborators\"][0][\"is_old\"]\n\n    def test_nested_function_field(self, blog, user):\n        data = BlogSchema().dump(blog)\n        assert data[\"user\"][\"lowername\"] == user.name.lower()\n        expected = blog.collaborators[0].name.lower()\n        assert data[\"collaborators\"][0][\"lowername\"] == expected\n\n    def test_nested_fields_must_be_passed_a_serializer(self, blog):\n        class BadNestedFieldSchema(BlogSchema):\n            user = fields.Nested(fields.String)  # type: ignore[arg-type]\n\n        with pytest.raises(ValueError):\n            BadNestedFieldSchema().dump(blog)\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/issues/188\n    def test_invalid_type_passed_to_nested_field(self):\n        class InnerSchema(Schema):\n            foo = fields.Raw()\n\n        class MySchema(Schema):\n            inner = fields.Nested(InnerSchema, many=True)\n\n        sch = MySchema()\n\n        sch.load({\"inner\": [{\"foo\": 42}]})\n\n        with pytest.raises(ValidationError) as excinfo:\n            sch.load({\"inner\": \"invalid\"})\n        errors = excinfo.value.messages\n        assert \"inner\" in errors\n        assert errors[\"inner\"] == [\"Invalid type.\"]\n\n        class OuterSchema(Schema):\n            inner = fields.Nested(InnerSchema)\n\n        schema = OuterSchema()\n        with pytest.raises(ValidationError) as excinfo:\n            schema.load({\"inner\": 1})\n        errors = excinfo.value.messages\n        assert errors[\"inner\"][\"_schema\"] == [\"Invalid input type.\"]\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/issues/298\n    def test_all_errors_on_many_nested_field_with_validates_decorator(self):\n        class Inner(Schema):\n            req = fields.Raw(required=True)\n\n        class Outer(Schema):\n            inner = fields.Nested(Inner, many=True)\n\n            @validates(\"inner\")\n            def validates_inner(self, data, **kwargs):\n                raise ValidationError(\"not a chance\")\n\n        outer = Outer()\n        with pytest.raises(ValidationError) as excinfo:\n            outer.load({\"inner\": [{}]})\n        errors = excinfo.value.messages\n        assert \"inner\" in errors\n        assert \"_schema\" in errors[\"inner\"]\n\n    @pytest.mark.parametrize(\"unknown\", (None, RAISE, INCLUDE, EXCLUDE))\n    def test_nested_unknown_validation(self, unknown):\n        class ChildSchema(Schema):\n            num = fields.Int()\n\n        class ParentSchema(Schema):\n            child = fields.Nested(ChildSchema, unknown=unknown)\n\n        data = {\"child\": {\"num\": 1, \"extra\": 1}}\n        if unknown is None or unknown == RAISE:\n            with pytest.raises(ValidationError) as excinfo:\n                ParentSchema().load(data)\n            exc = excinfo.value\n            assert exc.messages == {\"child\": {\"extra\": [\"Unknown field.\"]}}\n        else:\n            output = {\n                INCLUDE: {\"child\": {\"num\": 1, \"extra\": 1}},\n                EXCLUDE: {\"child\": {\"num\": 1}},\n            }[unknown]\n            assert ParentSchema().load(data) == output\n\n\nclass TestPluckSchema:\n    @pytest.mark.parametrize(\"user_schema\", [UserSchema, UserSchema()])\n    def test_pluck(self, user_schema, blog):\n        class FlatBlogSchema(Schema):\n            user = fields.Pluck(user_schema, \"name\")\n            collaborators = fields.Pluck(user_schema, \"name\", many=True)\n\n        s = FlatBlogSchema()\n        data = s.dump(blog)\n        assert data[\"user\"] == blog.user.name\n        for i, name in enumerate(data[\"collaborators\"]):\n            assert name == blog.collaborators[i].name\n\n    def test_pluck_none(self, blog):\n        class FlatBlogSchema(Schema):\n            user = fields.Pluck(UserSchema, \"name\")\n            collaborators = fields.Pluck(UserSchema, \"name\", many=True)\n\n        col1 = User(name=\"Mick\", age=123)\n        col2 = User(name=\"Keith\", age=456)\n        blog = Blog(title=\"Unowned Blog\", user=None, collaborators=[col1, col2])\n        s = FlatBlogSchema()\n        data = s.dump(blog)\n        assert data[\"user\"] == blog.user\n        for i, name in enumerate(data[\"collaborators\"]):\n            assert name == blog.collaborators[i].name\n\n    # Regression test for https://github.com/marshmallow-code/marshmallow/issues/800\n    def test_pluck_with_data_key(self, blog):\n        class UserSchema(Schema):\n            name = fields.String(data_key=\"username\")\n            age = fields.Int()\n\n        class FlatBlogSchema(Schema):\n            user = fields.Pluck(UserSchema, \"name\")\n            collaborators = fields.Pluck(UserSchema, \"name\", many=True)\n\n        s = FlatBlogSchema()\n        data = s.dump(blog)\n        assert data[\"user\"] == blog.user.name\n        for i, name in enumerate(data[\"collaborators\"]):\n            assert name == blog.collaborators[i].name\n        assert s.load(data) == {\n            \"user\": {\"name\": \"Monty\"},\n            \"collaborators\": [{\"name\": \"Mick\"}, {\"name\": \"Keith\"}],\n        }\n\n\nclass TestSelfReference:\n    @pytest.fixture\n    def employer(self):\n        return User(name=\"Joe\", age=59)\n\n    @pytest.fixture\n    def user(self, employer):\n        return User(name=\"Tom\", employer=employer, age=28)\n\n    def test_nesting_schema_by_passing_lambda(self, user, employer):\n        class SelfReferencingSchema(Schema):\n            name = fields.Str()\n            age = fields.Int()\n            employer = fields.Nested(\n                lambda: SelfReferencingSchema(exclude=(\"employer\",))\n            )\n\n        data = SelfReferencingSchema().dump(user)\n        assert data[\"name\"] == user.name\n        assert data[\"employer\"][\"name\"] == employer.name\n        assert data[\"employer\"][\"age\"] == employer.age\n\n    def test_nesting_schema_by_passing_class_name(self, user, employer):\n        class SelfReferencingSchema(Schema):\n            name = fields.Str()\n            age = fields.Int()\n            employer = fields.Nested(\"SelfReferencingSchema\", exclude=(\"employer\",))\n\n        data = SelfReferencingSchema().dump(user)\n        assert data[\"name\"] == user.name\n        assert data[\"employer\"][\"name\"] == employer.name\n        assert data[\"employer\"][\"age\"] == employer.age\n\n    def test_nesting_within_itself_exclude(self, user, employer):\n        class SelfSchema(Schema):\n            name = fields.String()\n            age = fields.Integer()\n            employer = fields.Nested(lambda: SelfSchema(exclude=(\"employer\",)))\n\n        data = SelfSchema().dump(user)\n        assert data[\"name\"] == user.name\n        assert data[\"age\"] == user.age\n        assert data[\"employer\"][\"name\"] == employer.name\n        assert data[\"employer\"][\"age\"] == employer.age\n\n    def test_nested_self_with_only_param(self, user, employer):\n        class SelfSchema(Schema):\n            name = fields.String()\n            age = fields.Integer()\n            employer = fields.Nested(lambda: SelfSchema(only=(\"name\",)))\n\n        data = SelfSchema().dump(user)\n        assert data[\"employer\"][\"name\"] == employer.name\n        assert \"age\" not in data[\"employer\"]\n\n    def test_multiple_pluck_self_lambda(self, user):\n        class MultipleSelfSchema(Schema):\n            name = fields.String()\n            emp = fields.Pluck(\n                lambda: MultipleSelfSchema(), \"name\", attribute=\"employer\"\n            )\n            rels = fields.Pluck(\n                lambda: MultipleSelfSchema(), \"name\", many=True, attribute=\"relatives\"\n            )\n\n        schema = MultipleSelfSchema()\n        user.relatives = [User(name=\"Bar\", age=12), User(name=\"Baz\", age=34)]\n        data = schema.dump(user)\n        assert len(data[\"rels\"]) == len(user.relatives)\n        relative = data[\"rels\"][0]\n        assert relative == user.relatives[0].name\n\n    def test_nested_self_many_lambda(self):\n        class SelfManySchema(Schema):\n            relatives = fields.Nested(lambda: SelfManySchema(), many=True)\n            name = fields.String()\n            age = fields.Integer()\n\n        person = User(name=\"Foo\")\n        person.relatives = [User(name=\"Bar\", age=12), User(name=\"Baz\", age=34)]\n        data = SelfManySchema().dump(person)\n        assert data[\"name\"] == person.name\n        assert len(data[\"relatives\"]) == len(person.relatives)\n        assert data[\"relatives\"][0][\"name\"] == person.relatives[0].name\n        assert data[\"relatives\"][0][\"age\"] == person.relatives[0].age\n\n    def test_nested_self_list(self):\n        class SelfListSchema(Schema):\n            relatives = fields.List(fields.Nested(lambda: SelfListSchema()))\n            name = fields.String()\n            age = fields.Integer()\n\n        person = User(name=\"Foo\")\n        person.relatives = [User(name=\"Bar\", age=12), User(name=\"Baz\", age=34)]\n        data = SelfListSchema().dump(person)\n        assert data[\"name\"] == person.name\n        assert len(data[\"relatives\"]) == len(person.relatives)\n        assert data[\"relatives\"][0][\"name\"] == person.relatives[0].name\n        assert data[\"relatives\"][0][\"age\"] == person.relatives[0].age\n\n\nclass RequiredUserSchema(Schema):\n    name = fields.Raw(required=True)\n\n\ndef test_serialization_with_required_field():\n    user = User(name=None)\n    RequiredUserSchema().dump(user)\n\n\ndef test_deserialization_with_required_field():\n    with pytest.raises(ValidationError) as excinfo:\n        RequiredUserSchema().load({})\n    data, errors = excinfo.value.valid_data, excinfo.value.messages\n    assert \"name\" in errors\n    assert \"Missing data for required field.\" in errors[\"name\"]\n    assert isinstance(data, dict)\n    # field value should also not be in output data\n    assert \"name\" not in data\n\n\ndef test_deserialization_with_required_field_and_custom_validator():\n    def validator(val):\n        if val.lower() not in {\"red\", \"blue\"}:\n            raise ValidationError(\"Color must be red or blue\")\n\n    class ValidatingSchema(Schema):\n        color = fields.String(\n            required=True,\n            validate=validator,\n        )\n\n    with pytest.raises(ValidationError) as excinfo:\n        ValidatingSchema().load({\"name\": \"foo\"})\n    errors = excinfo.value.messages\n    assert errors\n    assert \"color\" in errors\n    assert \"Missing data for required field.\" in errors[\"color\"]\n\n    with pytest.raises(ValidationError) as excinfo:\n        ValidatingSchema().load({\"color\": \"green\"})\n    errors = excinfo.value.messages\n    assert \"color\" in errors\n    assert \"Color must be red or blue\" in errors[\"color\"]\n\n\ndef test_serializer_can_specify_nested_object_as_attribute(blog):\n    class BlogUsernameSchema(Schema):\n        author_name = fields.String(attribute=\"user.name\")\n\n    ser = BlogUsernameSchema()\n    result = ser.dump(blog)\n    assert result[\"author_name\"] == blog.user.name\n\n\nclass TestFieldInheritance:\n    def test_inherit_fields_from_schema_subclass(self):\n        expected = {\n            \"field_a\": fields.Integer(),\n            \"field_b\": fields.Integer(),\n        }\n\n        class SerializerA(Schema):\n            field_a = expected[\"field_a\"]\n\n        class SerializerB(SerializerA):\n            field_b = expected[\"field_b\"]\n\n        assert SerializerB._declared_fields == expected\n\n    def test_inherit_fields_from_non_schema_subclass(self):\n        expected = {\n            \"field_a\": fields.Integer(),\n            \"field_b\": fields.Integer(),\n        }\n\n        class PlainBaseClass:\n            field_a = expected[\"field_a\"]\n\n        class SerializerB1(Schema, PlainBaseClass):\n            field_b = expected[\"field_b\"]\n\n        class SerializerB2(PlainBaseClass, Schema):\n            field_b = expected[\"field_b\"]\n\n        assert SerializerB1._declared_fields == expected\n        assert SerializerB2._declared_fields == expected\n\n    def test_inheritance_follows_mro(self):\n        expected = {\n            \"field_a\": fields.String(),\n            \"field_b\": fields.String(),\n            \"field_c\": fields.String(),\n            \"field_d\": fields.String(),\n        }\n        # Diamond inheritance graph\n        # MRO: D -> B -> C -> A\n\n        class SerializerA(Schema):\n            field_a = expected[\"field_a\"]\n\n        class SerializerB(SerializerA):\n            field_b = expected[\"field_b\"]\n\n        class SerializerC(SerializerA):\n            field_c = expected[\"field_c\"]\n\n        class SerializerD(SerializerB, SerializerC):\n            field_d = expected[\"field_d\"]\n\n        assert SerializerD._declared_fields == expected\n\n\ndef get_from_dict(schema, obj, key, default=None):\n    return obj.get(\"_\" + key, default)\n\n\nclass TestGetAttribute:\n    def test_get_attribute_is_used(self):\n        class UserDictSchema(Schema):\n            name = fields.Str()\n            email = fields.Email()\n\n            def get_attribute(self, obj, attr, default):\n                return get_from_dict(self, obj, attr, default)\n\n        user_dict = {\"_name\": \"joe\", \"_email\": \"joe@shmoe.com\"}\n        schema = UserDictSchema()\n        result = schema.dump(user_dict)\n        assert result[\"name\"] == user_dict[\"_name\"]\n        assert result[\"email\"] == user_dict[\"_email\"]\n        # can't serialize User object\n        user = User(name=\"joe\", email=\"joe@shmoe.com\")\n        with pytest.raises(AttributeError):\n            schema.dump(user)\n\n    def test_get_attribute_with_many(self):\n        class UserDictSchema(Schema):\n            name = fields.Str()\n            email = fields.Email()\n\n            def get_attribute(self, obj, attr, default):\n                return get_from_dict(self, obj, attr, default)\n\n        user_dicts = [\n            {\"_name\": \"joe\", \"_email\": \"joe@shmoe.com\"},\n            {\"_name\": \"jane\", \"_email\": \"jane@shmane.com\"},\n        ]\n        schema = UserDictSchema(many=True)\n        results = schema.dump(user_dicts)\n        for result, user_dict in zip(results, user_dicts, strict=True):\n            assert result[\"name\"] == user_dict[\"_name\"]\n            assert result[\"email\"] == user_dict[\"_email\"]\n        # can't serialize User object\n        users = [\n            User(name=\"joe\", email=\"joe@shmoe.com\"),\n            User(name=\"jane\", email=\"jane@shmane.com\"),\n        ]\n        with pytest.raises(AttributeError):\n            schema.dump(users)\n\n\nclass TestRequiredFields:\n    class StringSchema(Schema):\n        required_field = fields.Str(required=True)\n        allow_none_field = fields.Str(allow_none=True)\n        allow_none_required_field = fields.Str(required=True, allow_none=True)\n\n    @pytest.fixture\n    def string_schema(self):\n        return self.StringSchema()\n\n    @pytest.fixture\n    def data(self):\n        return dict(\n            required_field=\"foo\",\n            allow_none_field=\"bar\",\n            allow_none_required_field=\"one\",\n        )\n\n    def test_required_string_field_missing(self, string_schema, data):\n        del data[\"required_field\"]\n        errors = string_schema.validate(data)\n        assert errors[\"required_field\"] == [\"Missing data for required field.\"]\n\n    def test_required_string_field_failure(self, string_schema, data):\n        data[\"required_field\"] = None\n        errors = string_schema.validate(data)\n        assert errors[\"required_field\"] == [\"Field may not be null.\"]\n\n    def test_allow_none_param(self, string_schema, data):\n        data[\"allow_none_field\"] = None\n        errors = string_schema.validate(data)\n        assert errors == {}\n\n        data[\"allow_none_required_field\"] = None\n        string_schema.validate(data)\n\n        del data[\"allow_none_required_field\"]\n        errors = string_schema.validate(data)\n        assert \"allow_none_required_field\" in errors\n\n    def test_allow_none_custom_message(self, data):\n        class MySchema(Schema):\n            allow_none_field = fields.Raw(\n                allow_none=False, error_messages={\"null\": \"<custom>\"}\n            )\n\n        schema = MySchema()\n        errors = schema.validate({\"allow_none_field\": None})\n        assert errors[\"allow_none_field\"][0] == \"<custom>\"\n\n\nclass TestDefaults:\n    class MySchema(Schema):\n        int_no_default = fields.Int(allow_none=True)\n        str_no_default = fields.Str(allow_none=True)\n        list_no_default = fields.List(fields.Str, allow_none=True)\n        nested_no_default = fields.Nested(UserSchema, many=True, allow_none=True)\n\n        int_with_default = fields.Int(allow_none=True, dump_default=42)\n        str_with_default = fields.Str(allow_none=True, dump_default=\"foo\")\n\n    @pytest.fixture\n    def schema(self):\n        return self.MySchema()\n\n    @pytest.fixture\n    def data(self):\n        return dict(\n            int_no_default=None,\n            str_no_default=None,\n            list_no_default=None,\n            nested_no_default=None,\n            int_with_default=None,\n            str_with_default=None,\n        )\n\n    def test_missing_inputs_are_excluded_from_dump_output(self, schema, data):\n        for key in [\n            \"int_no_default\",\n            \"str_no_default\",\n            \"list_no_default\",\n            \"nested_no_default\",\n        ]:\n            d = data.copy()\n            del d[key]\n            result = schema.dump(d)\n            # the missing key is not in the serialized result\n            assert key not in result\n            # the rest of the keys are in the result\n            assert all(k in result for k in d)\n\n    def test_none_is_serialized_to_none(self, schema, data):\n        errors = schema.validate(data)\n        assert errors == {}\n        result = schema.dump(data)\n        for key in data:\n            msg = f\"result[{key!r}] should be None\"\n            assert result[key] is None, msg\n\n    def test_default_and_value_missing(self, schema, data):\n        del data[\"int_with_default\"]\n        del data[\"str_with_default\"]\n        result = schema.dump(data)\n        assert result[\"int_with_default\"] == 42\n        assert result[\"str_with_default\"] == \"foo\"\n\n    def test_loading_none(self, schema, data):\n        result = schema.load(data)\n        for key in data:\n            assert result[key] is None\n\n    def test_missing_inputs_are_excluded_from_load_output(self, schema, data):\n        for key in [\n            \"int_no_default\",\n            \"str_no_default\",\n            \"list_no_default\",\n            \"nested_no_default\",\n        ]:\n            d = data.copy()\n            del d[key]\n            result = schema.load(d)\n            # the missing key is not in the deserialized result\n            assert key not in result\n            # the rest of the keys are in the result\n            assert all(k in result for k in d)\n\n\nclass TestLoadOnly:\n    class MySchema(Schema):\n        class Meta:\n            load_only = (\"str_load_only\",)\n            dump_only = (\"str_dump_only\",)\n\n        str_dump_only = fields.String()\n        str_load_only = fields.String()\n        str_regular = fields.String()\n\n    @pytest.fixture\n    def schema(self):\n        return self.MySchema()\n\n    @pytest.fixture\n    def data(self):\n        return dict(\n            str_dump_only=\"Dump Only\",\n            str_load_only=\"Load Only\",\n            str_regular=\"Regular String\",\n        )\n\n    def test_load_only(self, schema, data):\n        result = schema.dump(data)\n        assert \"str_load_only\" not in result\n        assert \"str_dump_only\" in result\n        assert \"str_regular\" in result\n\n    def test_dump_only(self, schema, data):\n        result = schema.load(data, unknown=EXCLUDE)\n        assert \"str_dump_only\" not in result\n        assert \"str_load_only\" in result\n        assert \"str_regular\" in result\n\n    # regression test for https://github.com/marshmallow-code/marshmallow/pull/765\n    def test_url_field_requre_tld_false(self):\n        class NoTldTestSchema(Schema):\n            url = fields.Url(require_tld=False, schemes=[\"marshmallow\"])\n\n        schema = NoTldTestSchema()\n        data_with_no_top_level_domain = {\"url\": \"marshmallow://app/discounts\"}\n        result = schema.load(data_with_no_top_level_domain)\n        assert result == data_with_no_top_level_domain\n\n\nclass TestFromDict:\n    def test_generates_schema(self):\n        MySchema = Schema.from_dict({\"foo\": fields.Str()})\n        assert issubclass(MySchema, Schema)\n\n    def test_name(self):\n        MySchema = Schema.from_dict({\"foo\": fields.Str()})\n        assert \"GeneratedSchema\" in repr(MySchema)\n        SchemaWithName = Schema.from_dict(\n            {\"foo\": fields.Int()}, name=\"MyGeneratedSchema\"\n        )\n        assert \"MyGeneratedSchema\" in repr(SchemaWithName)\n\n    def test_generated_schemas_are_not_registered(self):\n        n_registry_entries = len(class_registry._registry)\n        Schema.from_dict({\"foo\": fields.Str()})\n        Schema.from_dict({\"bar\": fields.Str()}, name=\"MyGeneratedSchema\")\n        assert len(class_registry._registry) == n_registry_entries\n        with pytest.raises(RegistryError):\n            class_registry.get_class(\"GeneratedSchema\")\n        with pytest.raises(RegistryError):\n            class_registry.get_class(\"MyGeneratedSchema\")\n\n    def test_meta_options_are_applied(self):\n        class OrderedSchema(Schema):\n            class Meta:\n                load_only = (\"bar\",)\n\n        OSchema = OrderedSchema.from_dict({\"foo\": fields.Int(), \"bar\": fields.Int()})\n        dumped = OSchema().dump({\"foo\": 42, \"bar\": 24})\n        assert \"bar\" not in dumped\n\n\ndef test_class_registry_returns_schema_type():\n    class DefinitelyUniqueSchema(Schema):\n        \"\"\"\n        Just a schema\n        \"\"\"\n\n    SchemaClass = class_registry.get_class(DefinitelyUniqueSchema.__name__)\n    assert SchemaClass is DefinitelyUniqueSchema\n\n\n@pytest.mark.parametrize(\"dict_cls\", (dict, OrderedDict))\ndef test_set_dict_class(dict_cls):\n    \"\"\"Demonstrate how to specify dict_class as class attribute\"\"\"\n\n    class MySchema(Schema):\n        dict_class = dict_cls\n        foo = fields.String()\n\n    result = MySchema().dump({\"foo\": \"bar\"})\n    assert result == {\"foo\": \"bar\"}\n    assert isinstance(result, dict_cls)\n"
  },
  {
    "path": "tests/test_serialization.py",
    "content": "\"\"\"Tests for field serialization.\"\"\"\n\nimport datetime as dt\nimport decimal\nimport ipaddress\nimport itertools\nimport math\nimport uuid\nfrom collections import OrderedDict\nfrom typing import NamedTuple\n\nimport pytest\n\nfrom marshmallow import Schema, fields\nfrom marshmallow import missing as missing_\nfrom tests.base import ALL_FIELDS, DateEnum, GenderEnum, HairColorEnum, User, central\n\n\nclass Point(NamedTuple):\n    x: int\n    y: int\n\n\nclass DateTimeList:\n    def __init__(self, dtimes):\n        self.dtimes = dtimes\n\n\nclass IntegerList:\n    def __init__(self, ints):\n        self.ints = ints\n\n\nclass DateTimeIntegerTuple:\n    def __init__(self, dtime_int):\n        self.dtime_int = dtime_int\n\n\nclass TestFieldSerialization:\n    @pytest.fixture\n    def user(self):\n        return User(\"Foo\", email=\"foo@bar.com\", age=42)\n\n    def test_function_field_passed_func(self, user):\n        field = fields.Function(lambda obj: obj.name.upper())\n        assert field.serialize(\"key\", user) == \"FOO\"\n\n    def test_function_field_passed_serialize_only_is_dump_only(self, user):\n        field = fields.Function(serialize=lambda obj: obj.name.upper())\n        assert field.dump_only is True\n\n    def test_function_field_passed_deserialize_and_serialize_is_not_dump_only(self):\n        field = fields.Function(\n            serialize=lambda val: val.lower(), deserialize=lambda val: val.upper()\n        )\n        assert field.dump_only is False\n\n    def test_function_field_passed_serialize(self, user):\n        field = fields.Function(serialize=lambda obj: obj.name.upper())\n        assert field.serialize(\"key\", user) == \"FOO\"\n\n    # https://github.com/marshmallow-code/marshmallow/issues/395\n    def test_function_field_does_not_swallow_attribute_error(self, user):\n        def raise_error(obj):\n            raise AttributeError\n\n        field = fields.Function(serialize=raise_error)\n        with pytest.raises(AttributeError):\n            field.serialize(\"key\", user)\n\n    def test_serialize_with_load_only_param(self):\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            years = fields.Integer(load_only=True)\n            size = fields.Integer(dump_only=True, load_only=True)\n            nicknames = fields.List(fields.Str(), load_only=True)\n\n        data = {\n            \"name\": \"Mick\",\n            \"years\": \"42\",\n            \"size\": \"12\",\n            \"nicknames\": [\"Your Majesty\", \"Brenda\"],\n        }\n        result = AliasingUserSerializer().dump(data)\n        assert result[\"name\"] == \"Mick\"\n        assert \"years\" not in result\n        assert \"size\" not in result\n        assert \"nicknames\" not in result\n\n    def test_function_field_load_only(self):\n        field = fields.Function(deserialize=lambda obj: None)\n        assert field.load_only\n\n    def test_function_field_passed_uncallable_object(self):\n        with pytest.raises(TypeError):\n            fields.Function(\"uncallable\")  # type: ignore[arg-type]\n\n    def test_integer_field(self, user):\n        field = fields.Integer()\n        assert field.serialize(\"age\", user) == 42\n\n    def test_integer_as_string_field(self, user):\n        field = fields.Integer(as_string=True)\n        assert field.serialize(\"age\", user) == \"42\"\n\n    def test_integer_field_default(self, user):\n        user.age = None\n        field = fields.Integer(dump_default=0)\n        assert field.serialize(\"age\", user) is None\n        # missing\n        assert field.serialize(\"age\", {}) == 0\n\n    def test_integer_field_default_set_to_none(self, user):\n        user.age = None\n        field = fields.Integer(dump_default=None)\n        assert field.serialize(\"age\", user) is None\n\n    def test_uuid_field(self, user):\n        user.uuid1 = uuid.UUID(\"12345678123456781234567812345678\")\n        user.uuid2 = None\n\n        field = fields.UUID()\n        assert isinstance(field.serialize(\"uuid1\", user), str)\n        assert field.serialize(\"uuid1\", user) == \"12345678-1234-5678-1234-567812345678\"\n        assert field.serialize(\"uuid2\", user) is None\n\n    def test_ip_address_field(self, user):\n        ipv4_string = \"192.168.0.1\"\n        ipv6_string = \"ffff::ffff\"\n        ipv6_exploded_string = ipaddress.ip_address(\"ffff::ffff\").exploded\n\n        user.ipv4 = ipaddress.ip_address(ipv4_string)\n        user.ipv6 = ipaddress.ip_address(ipv6_string)\n        user.empty_ip = None\n\n        field_compressed = fields.IP()\n        assert isinstance(field_compressed.serialize(\"ipv4\", user), str)\n        assert field_compressed.serialize(\"ipv4\", user) == ipv4_string\n        assert isinstance(field_compressed.serialize(\"ipv6\", user), str)\n        assert field_compressed.serialize(\"ipv6\", user) == ipv6_string\n        assert field_compressed.serialize(\"empty_ip\", user) is None\n\n        field_exploded = fields.IP(exploded=True)\n        assert isinstance(field_exploded.serialize(\"ipv6\", user), str)\n        assert field_exploded.serialize(\"ipv6\", user) == ipv6_exploded_string\n\n    def test_ipv4_address_field(self, user):\n        ipv4_string = \"192.168.0.1\"\n\n        user.ipv4 = ipaddress.ip_address(ipv4_string)\n        user.empty_ip = None\n\n        field = fields.IPv4()\n        assert isinstance(field.serialize(\"ipv4\", user), str)\n        assert field.serialize(\"ipv4\", user) == ipv4_string\n        assert field.serialize(\"empty_ip\", user) is None\n\n    def test_ipv6_address_field(self, user):\n        ipv6_string = \"ffff::ffff\"\n        ipv6_exploded_string = ipaddress.ip_address(\"ffff::ffff\").exploded\n\n        user.ipv6 = ipaddress.ip_address(ipv6_string)\n        user.empty_ip = None\n\n        field_compressed = fields.IPv6()\n        assert isinstance(field_compressed.serialize(\"ipv6\", user), str)\n        assert field_compressed.serialize(\"ipv6\", user) == ipv6_string\n        assert field_compressed.serialize(\"empty_ip\", user) is None\n\n        field_exploded = fields.IPv6(exploded=True)\n        assert isinstance(field_exploded.serialize(\"ipv6\", user), str)\n        assert field_exploded.serialize(\"ipv6\", user) == ipv6_exploded_string\n\n    def test_ip_interface_field(self, user):\n        ipv4interface_string = \"192.168.0.1/24\"\n        ipv6interface_string = \"ffff::ffff/128\"\n        ipv6interface_exploded_string = ipaddress.ip_interface(\n            \"ffff::ffff/128\"\n        ).exploded\n\n        user.ipv4interface = ipaddress.ip_interface(ipv4interface_string)\n        user.ipv6interface = ipaddress.ip_interface(ipv6interface_string)\n        user.empty_ipinterface = None\n\n        field_compressed = fields.IPInterface()\n        assert isinstance(field_compressed.serialize(\"ipv4interface\", user), str)\n        assert field_compressed.serialize(\"ipv4interface\", user) == ipv4interface_string\n        assert isinstance(field_compressed.serialize(\"ipv6interface\", user), str)\n        assert field_compressed.serialize(\"ipv6interface\", user) == ipv6interface_string\n        assert field_compressed.serialize(\"empty_ipinterface\", user) is None\n\n        field_exploded = fields.IPInterface(exploded=True)\n        assert isinstance(field_exploded.serialize(\"ipv6interface\", user), str)\n        assert (\n            field_exploded.serialize(\"ipv6interface\", user)\n            == ipv6interface_exploded_string\n        )\n\n    def test_ipv4_interface_field(self, user):\n        ipv4interface_string = \"192.168.0.1/24\"\n\n        user.ipv4interface = ipaddress.ip_interface(ipv4interface_string)\n        user.empty_ipinterface = None\n\n        field = fields.IPv4Interface()\n        assert isinstance(field.serialize(\"ipv4interface\", user), str)\n        assert field.serialize(\"ipv4interface\", user) == ipv4interface_string\n        assert field.serialize(\"empty_ipinterface\", user) is None\n\n    def test_ipv6_interface_field(self, user):\n        ipv6interface_string = \"ffff::ffff/128\"\n        ipv6interface_exploded_string = ipaddress.ip_interface(\n            \"ffff::ffff/128\"\n        ).exploded\n\n        user.ipv6interface = ipaddress.ip_interface(ipv6interface_string)\n        user.empty_ipinterface = None\n\n        field_compressed = fields.IPv6Interface()\n        assert isinstance(field_compressed.serialize(\"ipv6interface\", user), str)\n        assert field_compressed.serialize(\"ipv6interface\", user) == ipv6interface_string\n        assert field_compressed.serialize(\"empty_ipinterface\", user) is None\n\n        field_exploded = fields.IPv6Interface(exploded=True)\n        assert isinstance(field_exploded.serialize(\"ipv6interface\", user), str)\n        assert (\n            field_exploded.serialize(\"ipv6interface\", user)\n            == ipv6interface_exploded_string\n        )\n\n    def test_enum_field_by_symbol_serialization(self, user):\n        user.sex = GenderEnum.male\n        field = fields.Enum(GenderEnum)\n        assert field.serialize(\"sex\", user) == \"male\"\n\n    def test_enum_field_by_value_true_serialization(self, user):\n        user.hair_color = HairColorEnum.black\n        field = fields.Enum(HairColorEnum, by_value=True)\n        assert field.serialize(\"hair_color\", user) == \"black hair\"\n        user.sex = GenderEnum.male\n        field2 = fields.Enum(GenderEnum, by_value=True)\n        assert field2.serialize(\"sex\", user) == 1\n        user.some_date = DateEnum.date_1\n\n    def test_enum_field_by_value_field_serialization(self, user):\n        user.hair_color = HairColorEnum.black\n        field = fields.Enum(HairColorEnum, by_value=fields.String)\n        assert field.serialize(\"hair_color\", user) == \"black hair\"\n        user.sex = GenderEnum.male\n        field2 = fields.Enum(GenderEnum, by_value=fields.Integer)\n        assert field2.serialize(\"sex\", user) == 1\n        user.some_date = DateEnum.date_1\n        field3 = fields.Enum(DateEnum, by_value=fields.Date(format=\"%d/%m/%Y\"))\n        assert field3.serialize(\"some_date\", user) == \"29/02/2004\"\n\n    def test_decimal_field(self, user):\n        user.m1 = 12\n        user.m2 = \"12.355\"\n        user.m3 = decimal.Decimal(1)\n        user.m4 = None\n\n        field = fields.Decimal()\n        assert isinstance(field.serialize(\"m1\", user), decimal.Decimal)\n        assert field.serialize(\"m1\", user) == decimal.Decimal(12)\n        assert isinstance(field.serialize(\"m2\", user), decimal.Decimal)\n        assert field.serialize(\"m2\", user) == decimal.Decimal(\"12.355\")\n        assert isinstance(field.serialize(\"m3\", user), decimal.Decimal)\n        assert field.serialize(\"m3\", user) == decimal.Decimal(1)\n        assert field.serialize(\"m4\", user) is None\n\n        field = fields.Decimal(1)\n        assert isinstance(field.serialize(\"m1\", user), decimal.Decimal)\n        assert field.serialize(\"m1\", user) == decimal.Decimal(12)\n        assert isinstance(field.serialize(\"m2\", user), decimal.Decimal)\n        assert field.serialize(\"m2\", user) == decimal.Decimal(\"12.4\")\n        assert isinstance(field.serialize(\"m3\", user), decimal.Decimal)\n        assert field.serialize(\"m3\", user) == decimal.Decimal(1)\n        assert field.serialize(\"m4\", user) is None\n\n        field = fields.Decimal(1, decimal.ROUND_DOWN)\n        assert isinstance(field.serialize(\"m1\", user), decimal.Decimal)\n        assert field.serialize(\"m1\", user) == decimal.Decimal(12)\n        assert isinstance(field.serialize(\"m2\", user), decimal.Decimal)\n        assert field.serialize(\"m2\", user) == decimal.Decimal(\"12.3\")\n        assert isinstance(field.serialize(\"m3\", user), decimal.Decimal)\n        assert field.serialize(\"m3\", user) == decimal.Decimal(1)\n        assert field.serialize(\"m4\", user) is None\n\n    def test_decimal_field_string(self, user):\n        user.m1 = 12\n        user.m2 = \"12.355\"\n        user.m3 = decimal.Decimal(1)\n        user.m4 = None\n\n        field = fields.Decimal(as_string=True)\n        assert isinstance(field.serialize(\"m1\", user), str)\n        assert field.serialize(\"m1\", user) == \"12\"\n        assert isinstance(field.serialize(\"m2\", user), str)\n        assert field.serialize(\"m2\", user) == \"12.355\"\n        assert isinstance(field.serialize(\"m3\", user), str)\n        assert field.serialize(\"m3\", user) == \"1\"\n        assert field.serialize(\"m4\", user) is None\n\n        field = fields.Decimal(1, as_string=True)\n        assert isinstance(field.serialize(\"m1\", user), str)\n        assert field.serialize(\"m1\", user) == \"12.0\"\n        assert isinstance(field.serialize(\"m2\", user), str)\n        assert field.serialize(\"m2\", user) == \"12.4\"\n        assert isinstance(field.serialize(\"m3\", user), str)\n        assert field.serialize(\"m3\", user) == \"1.0\"\n        assert field.serialize(\"m4\", user) is None\n\n        field = fields.Decimal(1, decimal.ROUND_DOWN, as_string=True)\n        assert isinstance(field.serialize(\"m1\", user), str)\n        assert field.serialize(\"m1\", user) == \"12.0\"\n        assert isinstance(field.serialize(\"m2\", user), str)\n        assert field.serialize(\"m2\", user) == \"12.3\"\n        assert isinstance(field.serialize(\"m3\", user), str)\n        assert field.serialize(\"m3\", user) == \"1.0\"\n        assert field.serialize(\"m4\", user) is None\n\n    def test_decimal_field_special_values(self, user):\n        user.m1 = \"-NaN\"\n        user.m2 = \"NaN\"\n        user.m3 = \"-sNaN\"\n        user.m4 = \"sNaN\"\n        user.m5 = \"-Infinity\"\n        user.m6 = \"Infinity\"\n        user.m7 = \"-0\"\n\n        field = fields.Decimal(places=2, allow_nan=True)\n\n        m1s = field.serialize(\"m1\", user)\n        assert isinstance(m1s, decimal.Decimal)\n        assert m1s.is_qnan()\n        assert not m1s.is_signed()\n\n        m2s = field.serialize(\"m2\", user)\n        assert isinstance(m2s, decimal.Decimal)\n        assert m2s.is_qnan()\n        assert not m2s.is_signed()\n\n        m3s = field.serialize(\"m3\", user)\n        assert isinstance(m3s, decimal.Decimal)\n        assert m3s.is_qnan()\n        assert not m3s.is_signed()\n\n        m4s = field.serialize(\"m4\", user)\n        assert isinstance(m4s, decimal.Decimal)\n        assert m4s.is_qnan()\n        assert not m4s.is_signed()\n\n        m5s = field.serialize(\"m5\", user)\n        assert isinstance(m5s, decimal.Decimal)\n        assert m5s.is_infinite()\n        assert m5s.is_signed()\n\n        m6s = field.serialize(\"m6\", user)\n        assert isinstance(m6s, decimal.Decimal)\n        assert m6s.is_infinite()\n        assert not m6s.is_signed()\n\n        m7s = field.serialize(\"m7\", user)\n        assert isinstance(m7s, decimal.Decimal)\n        assert m7s.is_zero()\n        assert m7s.is_signed()\n\n        field = fields.Decimal(as_string=True, allow_nan=True)\n\n        m2s = field.serialize(\"m2\", user)\n        assert isinstance(m2s, str)\n        assert m2s == user.m2\n\n        m5s = field.serialize(\"m5\", user)\n        assert isinstance(m5s, str)\n        assert m5s == user.m5\n\n        m6s = field.serialize(\"m6\", user)\n        assert isinstance(m6s, str)\n        assert m6s == user.m6\n\n    def test_decimal_field_special_values_not_permitted(self, user):\n        user.m7 = \"-0\"\n\n        field = fields.Decimal(places=2)\n\n        m7s = field.serialize(\"m7\", user)\n        assert isinstance(m7s, decimal.Decimal)\n        assert m7s.is_zero()\n        assert m7s.is_signed()\n\n    def test_decimal_field_fixed_point_representation(self, user):\n        \"\"\"\n        Test we get fixed-point string representation for a Decimal number that would normally\n        output in engineering notation.\n        \"\"\"\n        user.m1 = \"0.00000000100000000\"\n\n        field = fields.Decimal()\n        s = field.serialize(\"m1\", user)\n        assert isinstance(s, decimal.Decimal)\n        assert s == decimal.Decimal(\"1.00000000E-9\")\n\n        field = fields.Decimal(as_string=True)\n        s = field.serialize(\"m1\", user)\n        assert isinstance(s, str)\n        assert s == user.m1\n\n        field = fields.Decimal(as_string=True, places=2)\n        s = field.serialize(\"m1\", user)\n        assert isinstance(s, str)\n        assert s == \"0.00\"\n\n    def test_email_field_serialize_none(self, user):\n        user.email = None\n        field = fields.Email()\n        assert field.serialize(\"email\", user) is None\n\n    def test_dict_field_serialize_none(self, user):\n        user.various_data = None\n        field = fields.Dict()\n        assert field.serialize(\"various_data\", user) is None\n\n    def test_dict_field_serialize(self, user):\n        user.various_data = {\"foo\": \"bar\"}\n        field = fields.Dict()\n        dump = field.serialize(\"various_data\", user)\n        assert dump == {\"foo\": \"bar\"}\n        # Check dump is a distinct object\n        dump[\"foo\"] = \"baz\"\n        assert user.various_data[\"foo\"] == \"bar\"\n\n    def test_dict_field_serialize_ordereddict(self, user):\n        user.various_data = OrderedDict([(\"foo\", \"bar\"), (\"bar\", \"baz\")])\n        field = fields.Dict()\n        assert field.serialize(\"various_data\", user) == OrderedDict(\n            [(\"foo\", \"bar\"), (\"bar\", \"baz\")]\n        )\n\n    def test_structured_dict_value_serialize(self, user):\n        user.various_data = {\"foo\": decimal.Decimal(1)}\n        field = fields.Dict(values=fields.Decimal)\n        assert field.serialize(\"various_data\", user) == {\"foo\": 1}\n\n    def test_structured_dict_key_serialize(self, user):\n        user.various_data = {1: \"bar\"}\n        field = fields.Dict(keys=fields.Str)\n        assert field.serialize(\"various_data\", user) == {\"1\": \"bar\"}\n\n    def test_structured_dict_key_value_serialize(self, user):\n        user.various_data = {1: decimal.Decimal(1)}\n        field = fields.Dict(keys=fields.Str, values=fields.Decimal)\n        assert field.serialize(\"various_data\", user) == {\"1\": 1}\n\n    def test_url_field_serialize_none(self, user):\n        user.homepage = None\n        field = fields.Url()\n        assert field.serialize(\"homepage\", user) is None\n\n    def test_method_field_with_method_missing(self):\n        class BadSerializer(Schema):\n            bad_field = fields.Method(\"invalid\")\n\n        with pytest.raises(AttributeError):\n            BadSerializer()\n\n    def test_method_field_passed_serialize_only_is_dump_only(self, user):\n        field = fields.Method(serialize=\"method\")\n        assert field.dump_only is True\n        assert field.load_only is False\n\n    def test_method_field_passed_deserialize_only_is_load_only(self):\n        field = fields.Method(deserialize=\"somemethod\")\n        assert field.load_only is True\n        assert field.dump_only is False\n\n    def test_method_field_with_uncallable_attribute(self):\n        class BadSerializer(Schema):\n            foo = \"not callable\"\n            bad_field = fields.Method(\"foo\")\n\n        with pytest.raises(TypeError):\n            BadSerializer()\n\n    # https://github.com/marshmallow-code/marshmallow/issues/395\n    def test_method_field_does_not_swallow_attribute_error(self):\n        class MySchema(Schema):\n            mfield = fields.Method(\"raise_error\")\n\n            def raise_error(self, obj):\n                raise AttributeError\n\n        with pytest.raises(AttributeError):\n            MySchema().dump({})\n\n    def test_method_with_no_serialize_is_missing(self):\n        m = fields.Method()\n        m.parent = Schema()\n\n        assert m.serialize(\"\", \"\", None) is missing_\n\n    def test_serialize_with_data_key_param(self):\n        class DumpToSchema(Schema):\n            name = fields.String(data_key=\"NamE\")\n            years = fields.Integer(data_key=\"YearS\")\n\n        data = {\"name\": \"Richard\", \"years\": 11}\n        result = DumpToSchema().dump(data)\n        assert result == {\"NamE\": \"Richard\", \"YearS\": 11}\n\n    def test_serialize_with_data_key_as_empty_string(self):\n        class MySchema(Schema):\n            name = fields.Raw(data_key=\"\")\n\n        schema = MySchema()\n        assert schema.dump({\"name\": \"Grace\"}) == {\"\": \"Grace\"}\n\n    def test_serialize_with_attribute_and_data_key_uses_data_key(self):\n        class ConfusedDumpToAndAttributeSerializer(Schema):\n            name = fields.String(data_key=\"FullName\")\n            username = fields.String(attribute=\"uname\", data_key=\"UserName\")\n            years = fields.Integer(attribute=\"le_wild_age\", data_key=\"Years\")\n\n        data = {\"name\": \"Mick\", \"uname\": \"mick_the_awesome\", \"le_wild_age\": 999}\n        result = ConfusedDumpToAndAttributeSerializer().dump(data)\n\n        assert result == {\n            \"FullName\": \"Mick\",\n            \"UserName\": \"mick_the_awesome\",\n            \"Years\": 999,\n        }\n\n    @pytest.mark.parametrize(\"fmt\", [\"rfc\", \"rfc822\"])\n    @pytest.mark.parametrize(\n        (\"value\", \"expected\"),\n        [\n            (dt.datetime(2013, 11, 10, 1, 23, 45), \"Sun, 10 Nov 2013 01:23:45 -0000\"),\n            (\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=dt.timezone.utc),\n                \"Sun, 10 Nov 2013 01:23:45 +0000\",\n            ),\n            (\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=central),\n                \"Sun, 10 Nov 2013 01:23:45 -0600\",\n            ),\n        ],\n    )\n    def test_datetime_field_rfc822(self, fmt, value, expected):\n        field = fields.DateTime(format=fmt)\n        assert field.serialize(\"d\", {\"d\": value}) == expected\n\n    @pytest.mark.parametrize(\n        (\"fmt\", \"value\", \"expected\"),\n        [\n            (\"timestamp\", dt.datetime(1970, 1, 1), 0),\n            (\"timestamp\", dt.datetime(2013, 11, 10, 0, 23, 45), 1384043025),\n            (\n                \"timestamp\",\n                dt.datetime(2013, 11, 10, 0, 23, 45, tzinfo=dt.timezone.utc),\n                1384043025,\n            ),\n            (\n                \"timestamp\",\n                dt.datetime(2013, 11, 10, 0, 23, 45, tzinfo=central),\n                1384064625,\n            ),\n            (\"timestamp_ms\", dt.datetime(2013, 11, 10, 0, 23, 45), 1384043025000),\n            (\n                \"timestamp_ms\",\n                dt.datetime(2013, 11, 10, 0, 23, 45, tzinfo=dt.timezone.utc),\n                1384043025000,\n            ),\n            (\n                \"timestamp_ms\",\n                dt.datetime(2013, 11, 10, 0, 23, 45, tzinfo=central),\n                1384064625000,\n            ),\n        ],\n    )\n    def test_datetime_field_timestamp(self, fmt, value, expected):\n        field = fields.DateTime(format=fmt)\n        assert field.serialize(\"d\", {\"d\": value}) == expected\n\n    @pytest.mark.parametrize(\"fmt\", [\"iso\", \"iso8601\", None])\n    @pytest.mark.parametrize(\n        (\"value\", \"expected\"),\n        [\n            (dt.datetime(2013, 11, 10, 1, 23, 45), \"2013-11-10T01:23:45\"),\n            (\n                dt.datetime(2013, 11, 10, 1, 23, 45, 123456, tzinfo=dt.timezone.utc),\n                \"2013-11-10T01:23:45.123456+00:00\",\n            ),\n            (\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=dt.timezone.utc),\n                \"2013-11-10T01:23:45+00:00\",\n            ),\n            (\n                dt.datetime(2013, 11, 10, 1, 23, 45, tzinfo=central),\n                \"2013-11-10T01:23:45-06:00\",\n            ),\n        ],\n    )\n    def test_datetime_field_iso8601(self, fmt, value, expected):\n        if fmt is None:\n            # Test default is ISO\n            field = fields.DateTime()\n        else:\n            field = fields.DateTime(format=fmt)\n        assert field.serialize(\"d\", {\"d\": value}) == expected\n\n    def test_datetime_field_format(self, user):\n        datetimeformat = \"%Y-%m-%d\"\n        field = fields.DateTime(format=datetimeformat)\n        assert field.serialize(\"created\", user) == user.created.strftime(datetimeformat)\n\n    def test_string_field(self):\n        field = fields.String()\n        user = User(name=b\"foo\")\n        assert field.serialize(\"name\", user) == \"foo\"\n        field = fields.String(allow_none=True)\n        user.name = None\n        assert field.serialize(\"name\", user) is None\n\n    def test_string_field_default_to_empty_string(self, user):\n        field = fields.String(dump_default=\"\")\n        assert field.serialize(\"notfound\", {}) == \"\"\n\n    def test_time_field(self, user):\n        field = fields.Time()\n        expected = user.time_registered.isoformat()[:15]\n        assert field.serialize(\"time_registered\", user) == expected\n\n        user.time_registered = None\n        assert field.serialize(\"time_registered\", user) is None\n\n    @pytest.mark.parametrize(\"fmt\", [\"iso\", \"iso8601\", None])\n    @pytest.mark.parametrize(\n        (\"value\", \"expected\"),\n        [\n            (dt.time(1, 23, 45), \"01:23:45\"),\n            (dt.time(1, 23, 45, 123000), \"01:23:45.123000\"),\n            (dt.time(1, 23, 45, 123456), \"01:23:45.123456\"),\n        ],\n    )\n    def test_time_field_iso8601(self, fmt, value, expected):\n        if fmt is None:\n            # Test default is ISO\n            field = fields.Time()\n        else:\n            field = fields.Time(format=fmt)\n        assert field.serialize(\"d\", {\"d\": value}) == expected\n\n    def test_time_field_format(self, user):\n        fmt = \"%H:%M:%S\"\n        field = fields.Time(format=fmt)\n        assert field.serialize(\"birthtime\", user) == user.birthtime.strftime(fmt)\n\n    def test_date_field(self, user):\n        field = fields.Date()\n        assert field.serialize(\"birthdate\", user) == user.birthdate.isoformat()\n\n        user.birthdate = None\n        assert field.serialize(\"birthdate\", user) is None\n\n    def test_timedelta_field(self, user):\n        user.d1 = dt.timedelta(days=1, seconds=1, microseconds=1)\n        user.d2 = dt.timedelta(days=0, seconds=86401, microseconds=1)\n        user.d3 = dt.timedelta(days=0, seconds=0, microseconds=86401000001)\n        user.d4 = dt.timedelta(days=0, seconds=0, microseconds=0)\n        user.d5 = dt.timedelta(days=-1, seconds=0, microseconds=0)\n        user.d6 = dt.timedelta(\n            days=1,\n            seconds=1,\n            microseconds=1,\n            milliseconds=1,\n            minutes=1,\n            hours=1,\n            weeks=1,\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        assert field.serialize(\"d1\", user) == 1.0000115740856481\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d1\", user) == 86401.000001\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        assert field.serialize(\"d1\", user) == 86401000001\n        field = fields.TimeDelta(fields.TimeDelta.HOURS)\n        assert field.serialize(\"d1\", user) == 24.000277778055555\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        assert field.serialize(\"d2\", user) == 1.0000115740856481\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d2\", user) == 86401.000001\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        assert field.serialize(\"d2\", user) == 86401000001\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        assert field.serialize(\"d3\", user) == 1.0000115740856481\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d3\", user) == 86401.000001\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        assert field.serialize(\"d3\", user) == 86401000001\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        assert field.serialize(\"d4\", user) == 0\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d4\", user) == 0\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        assert field.serialize(\"d4\", user) == 0\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        assert field.serialize(\"d5\", user) == -1\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d5\", user) == -86400\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        assert field.serialize(\"d5\", user) == -86400000000\n\n        field = fields.TimeDelta(fields.TimeDelta.WEEKS)\n        assert field.serialize(\"d6\", user) == 1.1489103852529763\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        assert field.serialize(\"d6\", user) == 8.042372696770833\n        field = fields.TimeDelta(fields.TimeDelta.HOURS)\n        assert field.serialize(\"d6\", user) == 193.0169447225\n        field = fields.TimeDelta(fields.TimeDelta.MINUTES)\n        assert field.serialize(\"d6\", user) == 11581.01668335\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d6\", user) == 694861.001001\n        field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)\n        assert field.serialize(\"d6\", user) == 694861001.001\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        assert field.serialize(\"d6\", user) == 694861001001\n\n        user.d7 = None\n        assert field.serialize(\"d7\", user) is None\n\n        user.d8 = dt.timedelta(milliseconds=345)\n        field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)\n        assert field.serialize(\"d8\", user) == 345\n\n        user.d9 = dt.timedelta(milliseconds=1999)\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert field.serialize(\"d9\", user) == 1.999\n\n        user.d10 = dt.timedelta(\n            weeks=1,\n            days=6,\n            hours=2,\n            minutes=5,\n            seconds=51,\n            milliseconds=10,\n            microseconds=742,\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.MICROSECONDS)\n        unit_value = dt.timedelta(microseconds=1).total_seconds()\n        assert math.isclose(\n            field.serialize(\"d10\", user), user.d10.total_seconds() / unit_value\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.MILLISECONDS)\n        unit_value = dt.timedelta(milliseconds=1).total_seconds()\n        assert math.isclose(\n            field.serialize(\"d10\", user), user.d10.total_seconds() / unit_value\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.SECONDS)\n        assert math.isclose(field.serialize(\"d10\", user), user.d10.total_seconds())\n\n        field = fields.TimeDelta(fields.TimeDelta.MINUTES)\n        unit_value = dt.timedelta(minutes=1).total_seconds()\n        assert math.isclose(\n            field.serialize(\"d10\", user), user.d10.total_seconds() / unit_value\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.HOURS)\n        unit_value = dt.timedelta(hours=1).total_seconds()\n        assert math.isclose(\n            field.serialize(\"d10\", user), user.d10.total_seconds() / unit_value\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.DAYS)\n        unit_value = dt.timedelta(days=1).total_seconds()\n        assert math.isclose(\n            field.serialize(\"d10\", user), user.d10.total_seconds() / unit_value\n        )\n\n        field = fields.TimeDelta(fields.TimeDelta.WEEKS)\n        unit_value = dt.timedelta(weeks=1).total_seconds()\n        assert math.isclose(\n            field.serialize(\"d10\", user), user.d10.total_seconds() / unit_value\n        )\n\n    def test_datetime_list_field(self):\n        obj = DateTimeList([dt.datetime.now(dt.timezone.utc), dt.datetime.now()])\n        field = fields.List(fields.DateTime)\n        result = field.serialize(\"dtimes\", obj)\n        assert all(type(each) is str for each in result)\n\n    def test_list_field_serialize_none_returns_none(self):\n        obj = DateTimeList(None)\n        field = fields.List(fields.DateTime)\n        assert field.serialize(\"dtimes\", obj) is None\n\n    def test_list_field_work_with_generator_single_value(self):\n        def custom_generator():\n            yield dt.datetime.now(dt.timezone.utc)\n\n        obj = DateTimeList(custom_generator())\n        field = fields.List(fields.DateTime)\n        result = field.serialize(\"dtimes\", obj)\n        assert len(result) == 1\n\n    def test_list_field_work_with_generators_multiple_values(self):\n        def custom_generator():\n            yield from [dt.datetime.now(dt.timezone.utc), dt.datetime.now()]\n\n        obj = DateTimeList(custom_generator())\n        field = fields.List(fields.DateTime)\n        result = field.serialize(\"dtimes\", obj)\n        assert len(result) == 2\n\n    def test_list_field_work_with_generators_empty_generator_returns_none_for_every_non_returning_yield_statement(\n        self,\n    ):\n        def custom_generator():\n            yield\n            yield\n\n        obj = DateTimeList(custom_generator())\n        field = fields.List(fields.DateTime, allow_none=True)\n        result = field.serialize(\"dtimes\", obj)\n        assert len(result) == 2\n        assert result[0] is None\n        assert result[1] is None\n\n    def test_list_field_work_with_set(self):\n        custom_set = {1, 2, 3}\n        obj = IntegerList(custom_set)\n        field = fields.List(fields.Int)\n        result = field.serialize(\"ints\", obj)\n        assert len(result) == 3\n        assert 1 in result\n        assert 2 in result\n        assert 3 in result\n\n    def test_list_field_work_with_custom_class_with_iterator_protocol(self):\n        class IteratorSupportingClass:\n            def __init__(self, iterable):\n                self.iterable = iterable\n\n            def __iter__(self):\n                return iter(self.iterable)\n\n        ints = IteratorSupportingClass([1, 2, 3])\n        obj = IntegerList(ints)\n        field = fields.List(fields.Int)\n        result = field.serialize(\"ints\", obj)\n        assert len(result) == 3\n        assert result[0] == 1\n        assert result[1] == 2\n        assert result[2] == 3\n\n    def test_bad_list_field(self):\n        class ASchema(Schema):\n            id = fields.Int()\n\n        with pytest.raises(ValueError):\n            fields.List(\"string\")  # type: ignore[arg-type]\n        expected_msg = (\n            \"The list elements must be a subclass or instance of \"\n            \"marshmallow.fields.Field\"\n        )\n        with pytest.raises(ValueError, match=expected_msg):\n            fields.List(ASchema)  # type: ignore[arg-type]\n\n    def test_datetime_integer_tuple_field(self):\n        obj = DateTimeIntegerTuple((dt.datetime.now(dt.timezone.utc), 42))\n        field = fields.Tuple([fields.DateTime, fields.Integer])\n        result = field.serialize(\"dtime_int\", obj)\n        assert type(result[0]) is str\n        assert type(result[1]) is int\n\n    def test_tuple_field_serialize_none_returns_none(self):\n        obj = DateTimeIntegerTuple(None)\n        field = fields.Tuple([fields.DateTime, fields.Integer])\n        assert field.serialize(\"dtime_int\", obj) is None\n\n    def test_bad_tuple_field(self):\n        class ASchema(Schema):\n            id = fields.Int()\n\n        with pytest.raises(ValueError):\n            fields.Tuple([\"string\"])  # type: ignore[arg-type]\n        with pytest.raises(ValueError):\n            fields.Tuple(fields.String)  # type: ignore[arg-type]\n        expected_msg = (\n            'Elements of \"tuple_fields\" must be subclasses or '\n            \"instances of marshmallow.fields.Field.\"\n        )\n        with pytest.raises(ValueError, match=expected_msg):\n            fields.Tuple([ASchema])  # type: ignore[arg-type]\n\n    def test_serialize_does_not_apply_validators(self, user):\n        field = fields.Raw(validate=lambda x: False)\n        # No validation error raised\n        assert field.serialize(\"age\", user) == user.age\n\n    def test_constant_field_serialization(self, user):\n        field = fields.Constant(\"something\")\n        assert field.serialize(\"whatever\", user) == \"something\"\n\n    def test_constant_is_always_included_in_serialized_data(self):\n        class MySchema(Schema):\n            foo = fields.Constant(42)\n\n        sch = MySchema()\n        assert sch.dump({\"bar\": 24})[\"foo\"] == 42\n        assert sch.dump({\"foo\": 24})[\"foo\"] == 42\n\n    def test_constant_field_serialize_when_omitted(self):\n        class MiniUserSchema(Schema):\n            name = fields.Constant(\"bill\")\n\n        s = MiniUserSchema()\n        assert s.dump({})[\"name\"] == \"bill\"\n\n    @pytest.mark.parametrize(\"FieldClass\", ALL_FIELDS)\n    def test_all_fields_serialize_none_to_none(self, FieldClass):\n        field = FieldClass(allow_none=True)\n        res = field.serialize(\"foo\", {\"foo\": None})\n        assert res is None\n\n\nclass TestSchemaSerialization:\n    def test_serialize_with_missing_param_value(self):\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            birthdate = fields.DateTime(dump_default=dt.datetime(2017, 9, 29))\n\n        data = {\"name\": \"Mick\"}\n        result = AliasingUserSerializer().dump(data)\n        assert result[\"name\"] == \"Mick\"\n        assert result[\"birthdate\"] == \"2017-09-29T00:00:00\"\n\n    def test_serialize_with_missing_param_callable(self):\n        class AliasingUserSerializer(Schema):\n            name = fields.String()\n            birthdate = fields.DateTime(dump_default=lambda: dt.datetime(2017, 9, 29))\n\n        data = {\"name\": \"Mick\"}\n        result = AliasingUserSerializer().dump(data)\n        assert result[\"name\"] == \"Mick\"\n        assert result[\"birthdate\"] == \"2017-09-29T00:00:00\"\n\n\ndef test_serializing_named_tuple():\n    field = fields.Raw()\n\n    p = Point(x=4, y=2)\n\n    assert field.serialize(\"x\", p) == 4\n\n\ndef test_serializing_named_tuple_with_meta():\n    p = Point(x=4, y=2)\n\n    class PointSerializer(Schema):\n        x = fields.Int()\n        y = fields.Int()\n\n    serialized = PointSerializer().dump(p)\n    assert serialized[\"x\"] == 4\n    assert serialized[\"y\"] == 2\n\n\ndef test_serializing_slice():\n    values = [{\"value\": value} for value in range(5)]\n    sliced = itertools.islice(values, None)\n\n    class ValueSchema(Schema):\n        value = fields.Int()\n\n    serialized = ValueSchema(many=True).dump(sliced)\n    assert serialized == values\n\n\n# https://github.com/marshmallow-code/marshmallow/issues/1163\ndef test_nested_field_many_serializing_generator():\n    class MySchema(Schema):\n        name = fields.Str()\n\n    class OtherSchema(Schema):\n        objects = fields.Nested(MySchema, many=True)\n\n    def gen():\n        yield {\"name\": \"foo\"}\n        yield {\"name\": \"bar\"}\n\n    obj = {\"objects\": gen()}\n    data = OtherSchema().dump(obj)\n\n    assert data.get(\"objects\") == [{\"name\": \"foo\"}, {\"name\": \"bar\"}]\n"
  },
  {
    "path": "tests/test_utils.py",
    "content": "from __future__ import annotations\n\nimport datetime as dt\nfrom copy import copy, deepcopy\nfrom typing import NamedTuple\n\nimport pytest\n\nfrom marshmallow import Schema, fields, utils\n\n\ndef test_missing_singleton_copy():\n    assert copy(utils.missing) is utils.missing\n    assert deepcopy(utils.missing) is utils.missing\n\n\nclass PointNT(NamedTuple):\n    x: int | None\n    y: int | None\n\n\nclass PointClass:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n\nclass PointDict(dict):\n    def __init__(self, x, y):\n        super().__init__({\"x\": x})\n        self.y = y\n\n\n@pytest.mark.parametrize(\n    \"obj\", [PointNT(24, 42), PointClass(24, 42), PointDict(24, 42), {\"x\": 24, \"y\": 42}]\n)\ndef test_get_value_from_object(obj):\n    assert utils.get_value(obj, \"x\") == 24\n    assert utils.get_value(obj, \"y\") == 42\n\n\ndef test_get_value_from_namedtuple_with_default():\n    p = PointNT(x=42, y=None)\n    # Default is only returned if key is not found\n    assert utils.get_value(p, \"z\", default=123) == 123\n    # since 'y' is an attribute, None is returned instead of the default\n    assert utils.get_value(p, \"y\", default=123) is None\n\n\nclass Triangle:\n    def __init__(self, p1, p2, p3):\n        self.p1 = p1\n        self.p2 = p2\n        self.p3 = p3\n        self.points = [p1, p2, p3]\n\n\ndef test_get_value_for_nested_object():\n    tri = Triangle(p1=PointClass(1, 2), p2=PointNT(3, 4), p3={\"x\": 5, \"y\": 6})\n    assert utils.get_value(tri, \"p1.x\") == 1\n    assert utils.get_value(tri, \"p2.x\") == 3\n    assert utils.get_value(tri, \"p3.x\") == 5\n\n\n# regression test for https://github.com/marshmallow-code/marshmallow/issues/62\ndef test_get_value_from_dict():\n    d = dict(items=[\"foo\", \"bar\"], keys=[\"baz\", \"quux\"])\n    assert utils.get_value(d, \"items\") == [\"foo\", \"bar\"]\n    assert utils.get_value(d, \"keys\") == [\"baz\", \"quux\"]\n\n\ndef test_get_value():\n    lst = [1, 2, 3]\n    assert utils.get_value(lst, 1) == 2\n\n    class MyInt(int):\n        pass\n\n    assert utils.get_value(lst, MyInt(1)) == 2\n\n\ndef test_set_value():\n    d: dict[str, int | dict] = {}\n    utils.set_value(d, \"foo\", 42)\n    assert d == {\"foo\": 42}\n\n    d = {}\n    utils.set_value(d, \"foo.bar\", 42)\n    assert d == {\"foo\": {\"bar\": 42}}\n\n    d = {\"foo\": {}}\n    utils.set_value(d, \"foo.bar\", 42)\n    assert d == {\"foo\": {\"bar\": 42}}\n\n    d = {\"foo\": 42}\n    with pytest.raises(ValueError):\n        utils.set_value(d, \"foo.bar\", 42)\n\n\ndef test_is_collection():\n    assert utils.is_collection([1, \"foo\", {}]) is True\n    assert utils.is_collection((\"foo\", 2.3)) is True\n    assert utils.is_collection({\"foo\": \"bar\"}) is False\n\n\n@pytest.mark.parametrize(\n    (\"value\", \"expected\"),\n    [\n        (1676386740, dt.datetime(2023, 2, 14, 14, 59, 00)),\n        (1676386740.58, dt.datetime(2023, 2, 14, 14, 59, 00, 580000)),\n    ],\n)\ndef test_from_timestamp(value, expected):\n    result = utils.from_timestamp(value)\n    assert type(result) is dt.datetime\n    assert result == expected\n\n\ndef test_from_timestamp_with_negative_value():\n    value = -10\n    with pytest.raises(ValueError, match=r\"Not a valid POSIX timestamp\"):\n        utils.from_timestamp(value)\n\n\ndef test_from_timestamp_with_overflow_value():\n    value = 9223372036854775\n    with pytest.raises(ValueError, match=r\"out of range|year must be in 1\\.\\.9999\"):\n        utils.from_timestamp(value)\n\n\n# Regression test for https://github.com/marshmallow-code/marshmallow/issues/540\ndef test_function_field_using_type_annotation():\n    def get_split_words(value: str):\n        return value.split(\";\")\n\n    class MySchema(Schema):\n        friends = fields.Function(deserialize=get_split_words)\n\n    data = {\"friends\": \"Clark;Alfred;Robin\"}\n    result = MySchema().load(data)\n    assert result == {\"friends\": [\"Clark\", \"Alfred\", \"Robin\"]}\n"
  },
  {
    "path": "tests/test_validate.py",
    "content": "\"\"\"Tests for marshmallow.validate\"\"\"\n\nimport re\n\nimport pytest\n\nfrom marshmallow import ValidationError, validate\n\n\n@pytest.mark.parametrize(\n    \"valid_url\",\n    [\n        \"http://example.org\",\n        \"https://example.org\",\n        \"ftp://example.org\",\n        \"ftps://example.org\",\n        \"http://example.co.jp\",\n        \"http://www.example.com/a%C2%B1b\",\n        \"http://www.example.com/~username/\",\n        \"http://info.example.com/?fred\",\n        \"http://xn--mgbh0fb.xn--kgbechtv/\",\n        \"http://example.com/blue/red%3Fand+green\",\n        \"http://www.example.com/?array%5Bkey%5D=value\",\n        \"http://xn--rsum-bpad.example.org/\",\n        \"http://123.45.67.8/\",\n        \"http://123.45.67.8:8329/\",\n        \"http://[2001:db8::ff00:42]:8329\",\n        \"http://[2001::1]:8329\",\n        \"http://www.example.com:8000/foo\",\n        \"http://user@example.com\",\n        \"http://user:pass@example.com\",\n        \"http://:pass@example.com\",\n        \"http://@example.com\",\n        \"http://AZaz09-._~%2A!$&'()*+,;=:@example.com\",\n    ],\n)\ndef test_url_absolute_valid(valid_url):\n    validator = validate.URL(relative=False)\n    assert validator(valid_url) == valid_url\n\n\n@pytest.mark.parametrize(\n    \"invalid_url\",\n    [\n        \"http:///example.com/\",\n        \"https:///example.com/\",\n        \"https://example.org\\\\\",\n        \"https://example.org\\n\",\n        \"ftp:///example.com/\",\n        \"ftps:///example.com/\",\n        \"http//example.org\",\n        \"http:///\",\n        \"http:/example.org\",\n        \"foo://example.org\",\n        \"../icons/logo.gif\",\n        \"http://2001:db8::ff00:42:8329\",\n        \"http://[192.168.1.1]:8329\",\n        \"abc\",\n        \"..\",\n        \"/\",\n        \" \",\n        \"\",\n        None,\n        \"http://user@pass@example.com\",\n        \"http://@pass@example.com\",\n        \"http://@@example.com\",\n        \"http://^@example.com\",\n        \"http://%0G@example.com\",\n        \"http://%@example.com\",\n    ],\n)\ndef test_url_absolute_invalid(invalid_url):\n    validator = validate.URL(relative=False)\n    with pytest.raises(ValidationError):\n        validator(invalid_url)\n\n\n@pytest.mark.parametrize(\n    \"valid_url\",\n    [\n        \"http://example.org\",\n        \"http://123.45.67.8/\",\n        \"http://example.com/foo/bar/../baz\",\n        \"https://example.com/../icons/logo.gif\",\n        \"http://example.com/./icons/logo.gif\",\n        \"ftp://example.com/../../../../g\",\n        \"http://example.com/g?y/./x\",\n        \"/foo/bar\",\n        \"/foo?bar\",\n        \"/foo?bar#baz\",\n    ],\n)\ndef test_url_relative_valid(valid_url):\n    validator = validate.URL(relative=True)\n    assert validator(valid_url) == valid_url\n\n\n@pytest.mark.parametrize(\n    \"invalid_url\",\n    [\n        \"http//example.org\",\n        \"http://example.org\\n\",\n        \"suppliers.html\",\n        \"../icons/logo.gif\",\n        \"icons/logo.gif\",\n        \"../.../g\",\n        \"...\",\n        \"\\\\\",\n        \" \",\n        \"\",\n        None,\n    ],\n)\ndef test_url_relative_invalid(invalid_url):\n    validator = validate.URL(relative=True)\n    with pytest.raises(ValidationError):\n        validator(invalid_url)\n\n\n@pytest.mark.parametrize(\n    \"valid_url\",\n    [\n        \"/foo/bar\",\n        \"/foo?bar\",\n        \"?bar\",\n        \"/foo?bar#baz\",\n    ],\n)\ndef test_url_relative_only_valid(valid_url):\n    validator = validate.URL(relative=True, absolute=False)\n    assert validator(valid_url) == valid_url\n\n\n@pytest.mark.parametrize(\n    \"invalid_url\",\n    [\n        \"http//example.org\",\n        \"http://example.org\\n\",\n        \"suppliers.html\",\n        \"../icons/logo.gif\",\n        \"icons/logo.gif\",\n        \"../.../g\",\n        \"...\",\n        \"\\\\\",\n        \" \",\n        \"\",\n        \"http://example.org\",\n        \"http://123.45.67.8/\",\n        \"http://example.com/foo/bar/../baz\",\n        \"https://example.com/../icons/logo.gif\",\n        \"http://example.com/./icons/logo.gif\",\n        \"ftp://example.com/../../../../g\",\n        \"http://example.com/g?y/./x\",\n    ],\n)\ndef test_url_relative_only_invalid(invalid_url):\n    validator = validate.URL(relative=True, absolute=False)\n    with pytest.raises(ValidationError):\n        validator(invalid_url)\n\n\n@pytest.mark.parametrize(\n    \"valid_url\",\n    [\n        \"http://example.org\",\n        \"http://123.45.67.8/\",\n        \"http://example\",\n        \"http://example.\",\n        \"http://example:80\",\n        \"http://user.name:pass.word@example\",\n        \"http://example/foo/bar\",\n    ],\n)\ndef test_url_dont_require_tld_valid(valid_url):\n    validator = validate.URL(require_tld=False)\n    assert validator(valid_url) == valid_url\n\n\n@pytest.mark.parametrize(\n    \"invalid_url\",\n    [\n        \"http//example\",\n        \"http://example\\n\",\n        \"http://.example.org\",\n        \"http:///foo/bar\",\n        \"http:// /foo/bar\",\n        \"\",\n        None,\n    ],\n)\ndef test_url_dont_require_tld_invalid(invalid_url):\n    validator = validate.URL(require_tld=False)\n    with pytest.raises(ValidationError):\n        validator(invalid_url)\n\n\ndef test_url_custom_scheme():\n    validator = validate.URL()\n    # By default, ws not allowed\n    url = \"ws://test.test\"\n    with pytest.raises(ValidationError):\n        validator(url)\n\n    validator = validate.URL(schemes={\"http\", \"https\", \"ws\"})\n    assert validator(url) == url\n\n\ndef test_url_custom_scheme_case_insensitive():\n    validator = validate.URL(schemes={\"HTTP\"})\n    assert validator(\"http://example.com\") == \"http://example.com\"\n\n    validator = validate.URL(schemes={\"HtTp\"})\n    assert validator(\"hTtP://example.com\") == \"hTtP://example.com\"\n\n\n@pytest.mark.parametrize(\n    \"valid_url\",\n    (\n        \"file:///tmp/tmp1234\",\n        \"file://localhost/tmp/tmp1234\",\n        \"file:///C:/Users/test/file.txt\",\n        \"file://localhost/C:/Program%20Files/file.exe\",\n        \"file:///home/user/documents/test.pdf\",\n        \"file:///tmp/test%20file.txt\",\n        \"file:///\",\n        \"file://localhost/\",\n        \"FILE:///tmp/tmp1234\",\n        \"FILE://localhost/tmp/tmp1234\",\n        \"FILE:///C:/Users/test/file.txt\",\n        \"FILE://localhost/C:/Program%20Files/file.exe\",\n        \"FILE:///home/user/documents/test.pdf\",\n        \"FILE:///tmp/test%20file.txt\",\n        \"FILE:///\",\n        \"FILE://localhost/\",\n    ),\n)\ndef test_url_accepts_valid_file_urls(valid_url):\n    validator = validate.URL(schemes={\"file\"})\n    assert validator(valid_url) == valid_url\n\n\n@pytest.mark.parametrize(\n    \"invalid_url\",\n    (\n        \"file://\",\n        \"file:/tmp/file.txt\",\n        \"file:tmp/file.txt\",\n        \"file://hostname/path\",\n        \"file:///tmp/test file.txt\",\n    ),\n)\ndef test_url_rejects_invalid_file_urls(invalid_url):\n    validator = validate.URL(schemes={\"file\"})\n    with pytest.raises(ValidationError, match=\"Not a valid URL.\"):\n        assert validator(invalid_url)\n\n\ndef test_url_relative_and_custom_schemes():\n    validator = validate.URL(relative=True)\n    # By default, ws not allowed\n    url = \"ws://test.test\"\n    with pytest.raises(ValidationError):\n        validator(url)\n\n    validator = validate.URL(relative=True, schemes={\"http\", \"https\", \"ws\"})\n    assert validator(url) == url\n\n\ndef test_url_custom_message():\n    validator = validate.URL(error=\"{input} ain't an URL\")\n    with pytest.raises(ValidationError, match=\"invalid ain't an URL\"):\n        validator(\"invalid\")\n\n\ndef test_url_repr():\n    assert repr(\n        validate.URL(relative=False, error=None)\n    ) == \"<URL(relative=False, absolute=True, error={!r})>\".format(\"Not a valid URL.\")\n    assert repr(\n        validate.URL(relative=True, error=\"foo\")\n    ) == \"<URL(relative=True, absolute=True, error={!r})>\".format(\"foo\")\n    assert repr(\n        validate.URL(relative=True, absolute=False, error=\"foo\")\n    ) == \"<URL(relative=True, absolute=False, error={!r})>\".format(\"foo\")\n\n\ndef test_url_rejects_invalid_relative_usage():\n    with pytest.raises(\n        ValueError,\n        match=\"URL validation cannot set both relative and absolute to False\",\n    ):\n        validate.URL(relative=False, absolute=False)\n\n\n@pytest.mark.parametrize(\n    \"valid_email\",\n    [\n        \"niceandsimple@example.com\",\n        \"NiCeAnDsImPlE@eXaMpLe.CoM\",\n        \"very.common@example.com\",\n        \"a.little.lengthy.but.fine@a.iana-servers.net\",\n        \"disposable.style.email.with+symbol@example.com\",\n        '\"very.unusual.@.unusual.com\"@example.com',\n        \"!#$%&'*+-/=?^_`{}|~@example.org\",\n        \"niceandsimple@[64.233.160.0]\",\n        \"niceandsimple@localhost\",\n        \"josé@blah.com\",\n        \"δοκ.ιμή@παράδειγμα.δοκιμή\",\n    ],\n)\ndef test_email_valid(valid_email):\n    validator = validate.Email()\n    assert validator(valid_email) == valid_email\n\n\n@pytest.mark.parametrize(\n    \"invalid_email\",\n    [\n        \"niceandsimple\\n@example.com\",\n        \"NiCeAnDsImPlE@eXaMpLe.CoM\\n\",\n        'a\"b(c)d,e:f;g<h>i[j\\\\k]l@example.com',\n        'just\"not\"right@example.com',\n        'this is\"not\\allowed@example.com',\n        'this\\\\ still\\\\\"not\\\\\\\\allowed@example.com',\n        '\"much.more unusual\"@example.com',\n        '\"very.(),:;<>[]\".VERY.\"very@\\\\ \"very\".unusual\"@strange.example.com',\n        '\" \"@example.org',\n        \"user@example\",\n        \"@nouser.com\",\n        \"example.com\",\n        \"user\",\n        \"\",\n        None,\n    ],\n)\ndef test_email_invalid(invalid_email):\n    validator = validate.Email()\n    with pytest.raises(ValidationError):\n        validator(invalid_email)\n\n\ndef test_email_custom_message():\n    validator = validate.Email(error=\"{input} is not an email addy.\")\n    with pytest.raises(ValidationError, match=\"invalid is not an email addy.\"):\n        validator(\"invalid\")\n\n\ndef test_email_repr():\n    assert repr(validate.Email(error=None)) == \"<Email(error={!r})>\".format(\n        \"Not a valid email address.\"\n    )\n    assert repr(validate.Email(error=\"foo\")) == \"<Email(error={!r})>\".format(\"foo\")\n\n\ndef test_range_min():\n    assert validate.Range(1, 2)(1) == 1\n    assert validate.Range(0)(1) == 1\n    assert validate.Range()(1) == 1\n    assert validate.Range(min_inclusive=False, max_inclusive=False)(1) == 1\n    assert validate.Range(1, 1)(1) == 1\n\n    with pytest.raises(ValidationError, match=\"Must be greater than or equal to 2\"):\n        validate.Range(2, 3)(1)\n    with pytest.raises(ValidationError, match=\"Must be greater than or equal to 2\"):\n        validate.Range(2)(1)\n    with pytest.raises(ValidationError, match=\"Must be greater than 1\"):\n        validate.Range(1, 2, min_inclusive=False, max_inclusive=True, error=None)(1)\n    with pytest.raises(ValidationError, match=\"less than 1\"):\n        validate.Range(1, 1, min_inclusive=True, max_inclusive=False, error=None)(1)\n\n\ndef test_range_max():\n    assert validate.Range(1, 2)(2) == 2\n    assert validate.Range(None, 2)(2) == 2\n    assert validate.Range()(2) == 2\n    assert validate.Range(min_inclusive=False, max_inclusive=False)(2) == 2\n    assert validate.Range(2, 2)(2) == 2\n\n    with pytest.raises(ValidationError, match=\"less than or equal to 1\"):\n        validate.Range(0, 1)(2)\n    with pytest.raises(ValidationError, match=\"less than or equal to 1\"):\n        validate.Range(None, 1)(2)\n    with pytest.raises(ValidationError, match=\"less than 2\"):\n        validate.Range(1, 2, min_inclusive=True, max_inclusive=False, error=None)(2)\n    with pytest.raises(ValidationError, match=\"greater than 2\"):\n        validate.Range(2, 2, min_inclusive=False, max_inclusive=True, error=None)(2)\n\n\ndef test_range_custom_message():\n    v = validate.Range(2, 3, error=\"{input} is not between {min} and {max}\")\n    with pytest.raises(ValidationError, match=\"1 is not between 2 and 3\"):\n        v(1)\n\n    v = validate.Range(2, None, error=\"{input} is less than {min}\")\n    with pytest.raises(ValidationError, match=\"1 is less than 2\"):\n        v(1)\n\n    v = validate.Range(None, 3, error=\"{input} is greater than {max}\")\n    with pytest.raises(ValidationError, match=\"4 is greater than 3\"):\n        v(4)\n\n\ndef test_range_repr():\n    assert (\n        repr(\n            validate.Range(\n                min=None, max=None, error=None, min_inclusive=True, max_inclusive=True\n            )\n        )\n        == \"<Range(min=None, max=None, min_inclusive=True, max_inclusive=True, error=None)>\"\n    )\n    assert (\n        repr(\n            validate.Range(\n                min=1, max=3, error=\"foo\", min_inclusive=False, max_inclusive=False\n            )\n        )\n        == \"<Range(min=1, max=3, min_inclusive=False, max_inclusive=False, error={!r})>\".format(\n            \"foo\"\n        )\n    )\n\n\ndef test_length_min():\n    assert validate.Length(3, 5)(\"foo\") == \"foo\"\n    assert validate.Length(3, 5)([1, 2, 3]) == [1, 2, 3]\n    assert validate.Length(0)(\"a\") == \"a\"\n    assert validate.Length(0)([1]) == [1]\n    assert validate.Length()(\"\") == \"\"\n    assert validate.Length()([]) == []\n    assert validate.Length(1, 1)(\"a\") == \"a\"\n    assert validate.Length(1, 1)([1]) == [1]\n\n    with pytest.raises(ValidationError):\n        validate.Length(4, 5)(\"foo\")\n    with pytest.raises(ValidationError):\n        validate.Length(4, 5)([1, 2, 3])\n    with pytest.raises(ValidationError):\n        validate.Length(5)(\"foo\")\n    with pytest.raises(ValidationError):\n        validate.Length(5)([1, 2, 3])\n\n\ndef test_length_max():\n    assert validate.Length(1, 3)(\"foo\") == \"foo\"\n    assert validate.Length(1, 3)([1, 2, 3]) == [1, 2, 3]\n    assert validate.Length(None, 1)(\"a\") == \"a\"\n    assert validate.Length(None, 1)([1]) == [1]\n    assert validate.Length()(\"\") == \"\"\n    assert validate.Length()([]) == []\n    assert validate.Length(2, 2)(\"ab\") == \"ab\"\n    assert validate.Length(2, 2)([1, 2]) == [1, 2]\n\n    with pytest.raises(ValidationError):\n        validate.Length(1, 2)(\"foo\")\n    with pytest.raises(ValidationError):\n        validate.Length(1, 2)([1, 2, 3])\n    with pytest.raises(ValidationError):\n        validate.Length(None, 2)(\"foo\")\n    with pytest.raises(ValidationError):\n        validate.Length(None, 2)([1, 2, 3])\n\n\ndef test_length_equal():\n    assert validate.Length(equal=3)(\"foo\") == \"foo\"\n    assert validate.Length(equal=3)([1, 2, 3]) == [1, 2, 3]\n    assert validate.Length(equal=None)(\"\") == \"\"\n    assert validate.Length(equal=None)([]) == []\n\n    with pytest.raises(ValidationError):\n        validate.Length(equal=2)(\"foo\")\n    with pytest.raises(ValidationError):\n        validate.Length(equal=2)([1, 2, 3])\n    error_message = \"The `equal` parameter was provided, maximum or minimum parameter must not be provided\"\n    with pytest.raises(ValueError, match=error_message):\n        validate.Length(1, None, equal=3)(\"foo\")\n    with pytest.raises(ValueError, match=error_message):\n        validate.Length(None, 5, equal=3)(\"foo\")\n    with pytest.raises(ValueError, match=error_message):\n        validate.Length(1, 5, equal=3)(\"foo\")\n\n\ndef test_length_custom_message():\n    v = validate.Length(5, 6, error=\"{input} is not between {min} and {max}\")\n    with pytest.raises(ValidationError, match=\"foo is not between 5 and 6\"):\n        v(\"foo\")\n\n    v = validate.Length(5, None, error=\"{input} is shorter than {min}\")\n    with pytest.raises(ValidationError, match=\"foo is shorter than 5\"):\n        v(\"foo\")\n\n    v = validate.Length(None, 2, error=\"{input} is longer than {max}\")\n    with pytest.raises(ValidationError, match=\"foo is longer than 2\"):\n        v(\"foo\")\n\n    v = validate.Length(None, None, equal=4, error=\"{input} does not have {equal}\")\n    with pytest.raises(ValidationError, match=\"foo does not have 4\"):\n        v(\"foo\")\n\n\ndef test_length_repr():\n    assert (\n        repr(validate.Length(min=None, max=None, error=None, equal=None))\n        == \"<Length(min=None, max=None, equal=None, error=None)>\"\n    )\n    assert repr(\n        validate.Length(min=1, max=3, error=\"foo\", equal=None)\n    ) == \"<Length(min=1, max=3, equal=None, error={!r})>\".format(\"foo\")\n    assert repr(\n        validate.Length(min=None, max=None, error=\"foo\", equal=5)\n    ) == \"<Length(min=None, max=None, equal=5, error={!r})>\".format(\"foo\")\n\n\ndef test_equal():\n    assert validate.Equal(\"a\")(\"a\") == \"a\"\n    assert validate.Equal(1)(1) == 1\n    assert validate.Equal([1])([1]) == [1]\n\n    with pytest.raises(ValidationError):\n        validate.Equal(\"b\")(\"a\")\n    with pytest.raises(ValidationError):\n        validate.Equal(2)(1)\n    with pytest.raises(ValidationError):\n        validate.Equal([2])([1])\n\n\ndef test_equal_custom_message():\n    v = validate.Equal(\"a\", error=\"{input} is not equal to {other}.\")\n    with pytest.raises(ValidationError, match=\"b is not equal to a.\"):\n        v(\"b\")\n\n\ndef test_equal_repr():\n    assert repr(\n        validate.Equal(comparable=123, error=None)\n    ) == \"<Equal(comparable=123, error={!r})>\".format(\"Must be equal to {other}.\")\n    assert repr(\n        validate.Equal(comparable=123, error=\"foo\")\n    ) == \"<Equal(comparable=123, error={!r})>\".format(\"foo\")\n\n\ndef test_regexp_str():\n    assert validate.Regexp(r\"a\")(\"a\") == \"a\"\n    assert validate.Regexp(r\"\\w\")(\"_\") == \"_\"\n    assert validate.Regexp(r\"\\s\")(\" \") == \" \"\n    assert validate.Regexp(r\"1\")(\"1\") == \"1\"\n    assert validate.Regexp(r\"[0-9]+\")(\"1\") == \"1\"\n    assert validate.Regexp(r\"a\", re.IGNORECASE)(\"A\") == \"A\"\n\n    with pytest.raises(ValidationError):\n        validate.Regexp(r\"[0-9]+\")(\"a\")\n    with pytest.raises(ValidationError):\n        validate.Regexp(r\"[a-z]+\")(\"1\")\n    with pytest.raises(ValidationError):\n        validate.Regexp(r\"a\")(\"A\")\n\n\ndef test_regexp_compile():\n    assert validate.Regexp(re.compile(r\"a\"))(\"a\") == \"a\"\n    assert validate.Regexp(re.compile(r\"\\w\"))(\"_\") == \"_\"\n    assert validate.Regexp(re.compile(r\"\\s\"))(\" \") == \" \"\n    assert validate.Regexp(re.compile(r\"1\"))(\"1\") == \"1\"\n    assert validate.Regexp(re.compile(r\"[0-9]+\"))(\"1\") == \"1\"\n    assert validate.Regexp(re.compile(r\"a\", re.IGNORECASE))(\"A\") == \"A\"\n    assert validate.Regexp(re.compile(r\"a\", re.IGNORECASE), re.IGNORECASE)(\"A\") == \"A\"\n\n    with pytest.raises(ValidationError):\n        validate.Regexp(re.compile(r\"[0-9]+\"))(\"a\")\n    with pytest.raises(ValidationError):\n        validate.Regexp(re.compile(r\"[a-z]+\"))(\"1\")\n    with pytest.raises(ValidationError):\n        validate.Regexp(re.compile(r\"a\"))(\"A\")\n    with pytest.raises(ValidationError):\n        validate.Regexp(re.compile(r\"a\"), re.IGNORECASE)(\"A\")\n\n\ndef test_regexp_custom_message():\n    rex = r\"[0-9]+\"\n    v = validate.Regexp(rex, error=\"{input} does not match {regex}\")\n    with pytest.raises(ValidationError, match=\"a does not match\"):\n        v(\"a\")\n\n\ndef test_regexp_repr():\n    assert repr(\n        validate.Regexp(regex=\"abc\", flags=0, error=None)\n    ) == \"<Regexp(regex={!r}, error={!r})>\".format(\n        re.compile(\"abc\"), \"String does not match expected pattern.\"\n    )\n    assert repr(\n        validate.Regexp(regex=\"abc\", flags=re.IGNORECASE, error=\"foo\")\n    ) == \"<Regexp(regex={!r}, error={!r})>\".format(\n        re.compile(\"abc\", re.IGNORECASE), \"foo\"\n    )\n\n\ndef test_predicate():\n    class Dummy:\n        def _true(self):\n            return True\n\n        def _false(self):\n            return False\n\n        def _list(self):\n            return [1, 2, 3]\n\n        def _empty(self):\n            return []\n\n        def _identity(self, arg):\n            return arg\n\n    d = Dummy()\n\n    assert validate.Predicate(\"_true\")(d) == d\n    assert validate.Predicate(\"_list\")(d) == d\n    assert validate.Predicate(\"_identity\", arg=True)(d) == d\n    assert validate.Predicate(\"_identity\", arg=1)(d) == d\n    assert validate.Predicate(\"_identity\", arg=\"abc\")(d) == d\n\n    with pytest.raises(ValidationError, match=\"Invalid input.\"):\n        validate.Predicate(\"_false\")(d)\n    with pytest.raises(ValidationError):\n        validate.Predicate(\"_empty\")(d)\n    with pytest.raises(ValidationError):\n        validate.Predicate(\"_identity\", arg=False)(d)\n    with pytest.raises(ValidationError):\n        validate.Predicate(\"_identity\", arg=0)(d)\n    with pytest.raises(ValidationError):\n        validate.Predicate(\"_identity\", arg=\"\")(d)\n\n\ndef test_predicate_custom_message():\n    class Dummy:\n        def _false(self):\n            return False\n\n        def __str__(self):\n            return \"Dummy\"\n\n    d = Dummy()\n    with pytest.raises(ValidationError, match=\"Dummy._false is invalid!\"):\n        validate.Predicate(\"_false\", error=\"{input}.{method} is invalid!\")(d)\n\n\ndef test_predicate_repr():\n    assert repr(\n        validate.Predicate(method=\"foo\", error=None)\n    ) == \"<Predicate(method={!r}, kwargs={!r}, error={!r})>\".format(\n        \"foo\", {}, \"Invalid input.\"\n    )\n    assert repr(\n        validate.Predicate(method=\"foo\", error=\"bar\", zoo=1)\n    ) == \"<Predicate(method={!r}, kwargs={!r}, error={!r})>\".format(\n        \"foo\", {\"zoo\": 1}, \"bar\"\n    )\n\n\ndef test_noneof():\n    assert validate.NoneOf([1, 2, 3])(4) == 4\n    assert validate.NoneOf(\"abc\")(\"d\") == \"d\"\n    assert validate.NoneOf(\"\")([]) == []\n    assert validate.NoneOf([])(\"\") == \"\"\n    assert validate.NoneOf([])([]) == []\n    assert validate.NoneOf([1, 2, 3])(None) is None\n\n    with pytest.raises(ValidationError, match=\"Invalid input.\"):\n        validate.NoneOf([1, 2, 3])(3)\n    with pytest.raises(ValidationError):\n        validate.NoneOf(\"abc\")(\"c\")\n    with pytest.raises(ValidationError):\n        validate.NoneOf([1, 2, None])(None)\n    with pytest.raises(ValidationError):\n        validate.NoneOf(\"\")(\"\")\n\n\ndef test_noneof_custom_message():\n    with pytest.raises(ValidationError, match=\"<not valid>\"):\n        validate.NoneOf([1, 2], error=\"<not valid>\")(1)\n\n    none_of = validate.NoneOf([1, 2], error=\"{input} cannot be one of {values}\")\n    with pytest.raises(ValidationError, match=\"1 cannot be one of 1, 2\"):\n        none_of(1)\n\n\ndef test_noneof_repr():\n    assert repr(\n        validate.NoneOf(iterable=[1, 2, 3], error=None)\n    ) == \"<NoneOf(iterable=[1, 2, 3], error={!r})>\".format(\"Invalid input.\")\n    assert repr(\n        validate.NoneOf(iterable=[1, 2, 3], error=\"foo\")\n    ) == \"<NoneOf(iterable=[1, 2, 3], error={!r})>\".format(\"foo\")\n\n\ndef test_oneof():\n    assert validate.OneOf([1, 2, 3])(2) == 2\n    assert validate.OneOf(\"abc\")(\"b\") == \"b\"\n    assert validate.OneOf(\"\")(\"\") == \"\"\n    assert validate.OneOf(dict(a=0, b=1))(\"a\") == \"a\"\n    assert validate.OneOf((1, 2, None))(None) is None\n\n    with pytest.raises(ValidationError, match=\"Must be one of: 1, 2, 3.\"):\n        validate.OneOf([1, 2, 3])(4)\n    with pytest.raises(ValidationError):\n        validate.OneOf(\"abc\")(\"d\")\n    with pytest.raises(ValidationError):\n        validate.OneOf((1, 2, 3))(None)\n    with pytest.raises(ValidationError):\n        validate.OneOf([])([])\n    with pytest.raises(ValidationError):\n        validate.OneOf(())(())\n    with pytest.raises(ValidationError):\n        validate.OneOf(dict(a=0, b=1))(0)\n    with pytest.raises(ValidationError):\n        validate.OneOf(\"123\")(1)\n\n\ndef test_oneof_options():\n    oneof = validate.OneOf([1, 2, 3], [\"one\", \"two\", \"three\"])\n    expected = [(\"1\", \"one\"), (\"2\", \"two\"), (\"3\", \"three\")]\n    assert list(oneof.options()) == expected\n\n    oneof = validate.OneOf([1, 2, 3], [\"one\", \"two\"])\n    expected = [(\"1\", \"one\"), (\"2\", \"two\"), (\"3\", \"\")]\n    assert list(oneof.options()) == expected\n\n    oneof = validate.OneOf([1, 2], [\"one\", \"two\", \"three\"])\n    expected = [(\"1\", \"one\"), (\"2\", \"two\"), (\"\", \"three\")]\n    assert list(oneof.options()) == expected\n\n    oneof = validate.OneOf([1, 2])\n    expected = [(\"1\", \"\"), (\"2\", \"\")]\n    assert list(oneof.options()) == expected\n\n\ndef test_oneof_text():\n    oneof = validate.OneOf([1, 2, 3], [\"one\", \"two\", \"three\"])\n    assert oneof.choices_text == \"1, 2, 3\"\n    assert oneof.labels_text == \"one, two, three\"\n\n    oneof = validate.OneOf([1], [\"one\"])\n    assert oneof.choices_text == \"1\"\n    assert oneof.labels_text == \"one\"\n\n    oneof = validate.OneOf(dict(a=0, b=1))\n    assert \", \".join(sorted(oneof.choices_text.split(\", \"))) == \"a, b\"\n    assert oneof.labels_text == \"\"\n\n\ndef test_oneof_custom_message():\n    oneof = validate.OneOf([1, 2, 3], error=\"{input} is not one of {choices}\")\n    expected = \"4 is not one of 1, 2, 3\"\n    with pytest.raises(ValidationError):\n        oneof(4)\n    assert expected in str(expected)\n\n    oneof = validate.OneOf(\n        [1, 2, 3], [\"one\", \"two\", \"three\"], error=\"{input} is not one of {labels}\"\n    )\n    expected = \"4 is not one of one, two, three\"\n    with pytest.raises(ValidationError):\n        oneof(4)\n    assert expected in str(expected)\n\n\ndef test_oneof_repr():\n    assert repr(\n        validate.OneOf(choices=[1, 2, 3], labels=None, error=None)\n    ) == \"<OneOf(choices=[1, 2, 3], labels=[], error={!r})>\".format(\n        \"Must be one of: {choices}.\"\n    )\n    assert repr(\n        validate.OneOf(choices=[1, 2, 3], labels=[\"a\", \"b\", \"c\"], error=\"foo\")\n    ) == \"<OneOf(choices=[1, 2, 3], labels={!r}, error={!r})>\".format(\n        [\"a\", \"b\", \"c\"], \"foo\"\n    )\n\n\ndef test_containsonly_in_list():\n    assert validate.ContainsOnly([])([]) == []\n    assert validate.ContainsOnly([1, 2, 3])([1]) == [1]\n    assert validate.ContainsOnly([1, 1, 2])([1, 1]) == [1, 1]\n    assert validate.ContainsOnly([1, 2, 3])([1, 2]) == [1, 2]\n    assert validate.ContainsOnly([1, 2, 3])([2, 1]) == [2, 1]\n    assert validate.ContainsOnly([1, 2, 3])([1, 2, 3]) == [1, 2, 3]\n    assert validate.ContainsOnly([1, 2, 3])([3, 1, 2]) == [3, 1, 2]\n    assert validate.ContainsOnly([1, 2, 3])([2, 3, 1]) == [2, 3, 1]\n    assert validate.ContainsOnly([1, 2, 3])([1, 2, 3, 1]) == [1, 2, 3, 1]\n    assert validate.ContainsOnly([1, 2, 3])([]) == []\n\n    with pytest.raises(\n        ValidationError,\n        match=\"One or more of the choices you made was not in: 1, 2, 3.\",\n    ):\n        validate.ContainsOnly([1, 2, 3])([4])\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly([])([1])\n\n\ndef test_contains_only_unhashable_types():\n    assert validate.ContainsOnly([[1], [2], [3]])([[1]]) == [[1]]\n    assert validate.ContainsOnly([[1], [1], [2]])([[1], [1]]) == [[1], [1]]\n    assert validate.ContainsOnly([[1], [2], [3]])([[1], [2]]) == [[1], [2]]\n    assert validate.ContainsOnly([[1], [2], [3]])([[2], [1]]) == [[2], [1]]\n    assert validate.ContainsOnly([[1], [2], [3]])([[1], [2], [3]]) == [[1], [2], [3]]\n    assert validate.ContainsOnly([[1], [2], [3]])([[3], [1], [2]]) == [[3], [1], [2]]\n    assert validate.ContainsOnly([[1], [2], [3]])([[2], [3], [1]]) == [[2], [3], [1]]\n    assert validate.ContainsOnly([[1], [2], [3]])([]) == []\n\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly([[1], [2], [3]])([[4]])\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly([])([1])\n\n\ndef test_containsonly_in_tuple():\n    assert validate.ContainsOnly(())(()) == ()\n    assert validate.ContainsOnly((1, 2, 3))((1,)) == (1,)\n    assert validate.ContainsOnly((1, 1, 2))((1, 1)) == (1, 1)\n    assert validate.ContainsOnly((1, 2, 3))((1, 2)) == (1, 2)\n    assert validate.ContainsOnly((1, 2, 3))((2, 1)) == (2, 1)\n    assert validate.ContainsOnly((1, 2, 3))((1, 2, 3)) == (1, 2, 3)\n    assert validate.ContainsOnly((1, 2, 3))((3, 1, 2)) == (3, 1, 2)\n    assert validate.ContainsOnly((1, 2, 3))((2, 3, 1)) == (2, 3, 1)\n    assert validate.ContainsOnly((1, 2, 3))(()) == tuple()\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly((1, 2, 3))((4,))\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly(())((1,))\n\n\ndef test_contains_only_in_string():\n    assert validate.ContainsOnly(\"\")(\"\") == \"\"\n    assert validate.ContainsOnly(\"abc\")(\"a\") == \"a\"\n    assert validate.ContainsOnly(\"aab\")(\"aa\") == \"aa\"\n    assert validate.ContainsOnly(\"abc\")(\"ab\") == \"ab\"\n    assert validate.ContainsOnly(\"abc\")(\"ba\") == \"ba\"\n    assert validate.ContainsOnly(\"abc\")(\"abc\") == \"abc\"\n    assert validate.ContainsOnly(\"abc\")(\"cab\") == \"cab\"\n    assert validate.ContainsOnly(\"abc\")(\"bca\") == \"bca\"\n    assert validate.ContainsOnly(\"abc\")(\"\") == \"\"\n\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly(\"abc\")(\"d\")\n    with pytest.raises(ValidationError):\n        validate.ContainsOnly(\"\")(\"a\")\n\n\ndef test_containsonly_custom_message():\n    containsonly = validate.ContainsOnly(\n        [1, 2, 3], error=\"{input} is not one of {choices}\"\n    )\n    expected = \"4, 5 is not one of 1, 2, 3\"\n    with pytest.raises(ValidationError):\n        containsonly([4, 5])\n    assert expected in str(expected)\n\n    containsonly = validate.ContainsOnly(\n        [1, 2, 3], [\"one\", \"two\", \"three\"], error=\"{input} is not one of {labels}\"\n    )\n    expected = \"4, 5 is not one of one, two, three\"\n    with pytest.raises(ValidationError):\n        containsonly([4, 5])\n    assert expected in str(expected)\n\n\ndef test_containsonly_repr():\n    assert repr(\n        validate.ContainsOnly(choices=[1, 2, 3], labels=None, error=None)\n    ) == \"<ContainsOnly(choices=[1, 2, 3], labels=[], error={!r})>\".format(\n        \"One or more of the choices you made was not in: {choices}.\"\n    )\n    assert repr(\n        validate.ContainsOnly(choices=[1, 2, 3], labels=[\"a\", \"b\", \"c\"], error=\"foo\")\n    ) == \"<ContainsOnly(choices=[1, 2, 3], labels={!r}, error={!r})>\".format(\n        [\"a\", \"b\", \"c\"], \"foo\"\n    )\n\n\ndef test_containsnoneof_error_message():\n    with pytest.raises(\n        ValidationError, match=\"One or more of the choices you made was in: 1\"\n    ):\n        validate.ContainsNoneOf([1])([1])\n\n    with pytest.raises(\n        ValidationError, match=\"One or more of the choices you made was in: 1, 2, 3\"\n    ):\n        validate.ContainsNoneOf([1, 2, 3])([1])\n\n    with pytest.raises(\n        ValidationError, match=\"One or more of the choices you made was in: one, two\"\n    ):\n        validate.ContainsNoneOf([\"one\", \"two\"])([\"one\"])\n\n    with pytest.raises(\n        ValidationError, match=\"One or more of the choices you made was in: @, !, &, ?\"\n    ):\n        validate.ContainsNoneOf(\"@!&?\")(\"@\")\n\n\ndef test_containsnoneof_in_list():\n    assert validate.ContainsNoneOf([])([]) == []\n    assert validate.ContainsNoneOf([])([1, 2, 3]) == [1, 2, 3]\n    assert validate.ContainsNoneOf([4])([1, 2, 3]) == [1, 2, 3]\n    assert validate.ContainsNoneOf([2])([1, 3, 4]) == [1, 3, 4]\n    assert validate.ContainsNoneOf([1, 2, 3])([4]) == [4]\n    assert validate.ContainsNoneOf([4])([1, 1, 1, 1]) == [1, 1, 1, 1]\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([1])([1, 2, 3])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([1, 1, 1])([1, 2, 3])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([1, 2])([1, 2])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([1])([1, 1, 1, 1])\n\n\ndef test_containsnoneof_unhashable_types():\n    assert validate.ContainsNoneOf([[1], [2], [3]])([]) == []\n    assert validate.ContainsNoneOf([[1], [2], [3]])([[4]]) == [[4]]\n    assert validate.ContainsNoneOf([[1], [2], [3]])([[4], [4]]) == [[4], [4]]\n    assert validate.ContainsNoneOf([[1], [2], [3]])([[4], [5]]) == [[4], [5]]\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([[1], [2], [3]])([[1]])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([[1], [2], [3]])([[1], [2]])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([[1], [2], [3]])([[2], [1]])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([[1], [2], [3]])([[1], [2], [3]])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([[1], [2], [3]])([[3], [2], [1]])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([[1], [2], [3]])([[2], [3], [1]])\n\n\ndef test_containsnoneof_in_tuple():\n    assert validate.ContainsNoneOf(())(()) == ()\n    assert validate.ContainsNoneOf(())((1, 2, 3)) == (1, 2, 3)\n    assert validate.ContainsNoneOf((4,))((1, 2, 3)) == (1, 2, 3)\n    assert validate.ContainsNoneOf((2,))((1, 3, 4)) == (1, 3, 4)\n    assert validate.ContainsNoneOf((1, 2, 3))((4,)) == (4,)\n    assert validate.ContainsNoneOf((4,))((1, 1, 1, 1)) == (1, 1, 1, 1)\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf((1,))((1, 2, 3))\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf((1, 1, 1))((1, 2, 3))\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf((1, 2))((1, 2))\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf((1,))((1, 1, 1, 1))\n\n\ndef test_containsnoneof_in_string():\n    assert validate.ContainsNoneOf(\"\")(\"\") == \"\"\n    assert validate.ContainsNoneOf(\"\")(\"abc\") == \"abc\"\n    assert validate.ContainsNoneOf(\"d\")(\"abc\") == \"abc\"\n    assert validate.ContainsNoneOf(\"b\")(\"acd\") == \"acd\"\n    assert validate.ContainsNoneOf(\"abc\")(\"d\") == \"d\"\n    assert validate.ContainsNoneOf(\"d\")(\"aaaa\") == \"aaaa\"\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf(\"a\")(\"abc\")\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf(\"aaa\")(\"abc\")\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf(\"ab\")(\"ab\")\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf(\"a\")(\"aaaa\")\n\n\ndef test_containsnoneof_custom_message():\n    validator = validate.ContainsNoneOf(\n        [1, 2, 3], error=\"{input} was in the banned list: {values}\"\n    )\n    expected = \"1 was in the banned list: 1, 2, 3\"\n    with pytest.raises(ValidationError, match=expected):\n        validator([1])\n\n\ndef test_containsnoneof_mixing_types():\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf(\"abc\")([\"a\"])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([\"a\", \"b\", \"c\"])(\"a\")\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf((1, 2, 3))([1])\n\n    with pytest.raises(ValidationError):\n        validate.ContainsNoneOf([1, 2, 3])((1,))\n\n\ndef is_even(value):\n    if value % 2 != 0:\n        raise ValidationError(\"Not an even value.\")\n\n\ndef test_and():\n    validator = validate.And(validate.Range(min=0), is_even)\n    assert validator(2)\n    with pytest.raises(ValidationError) as excinfo:\n        validator(-1)\n    errors = excinfo.value.messages\n    assert errors == [\"Must be greater than or equal to 0.\", \"Not an even value.\"]\n\n    validator_with_composition = validate.And(validator, validate.Range(max=6))\n    assert validator_with_composition(4)\n    with pytest.raises(ValidationError) as excinfo:\n        validator_with_composition(7)\n\n    errors = excinfo.value.messages\n    assert errors == [\"Not an even value.\", \"Must be less than or equal to 6.\"]\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist = lint,mypy,py{310,311,312,313,314},docs\n\n[testenv]\nextras = tests\ncommands = pytest {posargs}\n\n[testenv:lint]\ndeps = pre-commit>=3.5,<5.0\nskip_install = true\ncommands = pre-commit run --all-files\n\n[testenv:mypy]\ndeps = \n  mypy>=1.14.1\n  types-simplejson\ncommands = mypy --show-error-codes\n\n[testenv:docs]\nextras = docs\ncommands = sphinx-build --fresh-env docs/ docs/_build {posargs}\n\n; Below tasks are for development only (not run in CI)\n\n[testenv:docs-serve]\ndeps = sphinx-autobuild\nextras = docs\ncommands = sphinx-autobuild --port=0 --open-browser --delay=2 docs/ docs/_build {posargs} --watch src --watch CONTRIBUTING.rst --watch README.rst\n\n[testenv:readme-serve]\ndeps = restview\nskip_install = true\ncommands = restview README.rst\n\n[testenv:benchmark]\nusedevelop = true\ncommands = python performance/benchmark.py --iterations=100 --repeat=3\n"
  }
]