Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-marshmallow for 
openSUSE:Factory checked in at 2023-12-11 21:49:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-marshmallow (Old)
 and      /work/SRC/openSUSE:Factory/.python-marshmallow.new.25432 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-marshmallow"

Mon Dec 11 21:49:40 2023 rev:23 rq:1132365 version:3.20.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-marshmallow/python-marshmallow.changes    
2023-05-26 20:15:35.840306959 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-marshmallow.new.25432/python-marshmallow.changes
 2023-12-11 21:49:41.593621335 +0100
@@ -1,0 +2,16 @@
+Sun Dec 10 21:27:36 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 3.20.1:
+  * Fix call to ``get_declared_fields``: pass ``dict_cls`` again
+  * Add ``absolute`` parameter to ``URL`` validator and ``Url``
+  * Use Abstract Base Classes to define ``FieldABC`` and
+    ``SchemaABC``
+  * Use `OrderedSet` as default `set_class`. Schemas are now
+    ordered by default.
+  * Handle ``OSError`` and ``OverflowError`` in
+    ``utils.from_timestamp`` (:pr:`2102`).
+  * Fix the default inheritance of nested partial schemas
+  * Officially support Python 3.11 (:pr:`2067`).
+  * Drop support for Python 3.7 (:pr:`2135`).
+
+-------------------------------------------------------------------

Old:
----
  marshmallow-3.19.0.tar.gz

New:
----
  marshmallow-3.20.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-marshmallow.spec ++++++
--- /var/tmp/diff_new_pack.yftqPI/_old  2023-12-11 21:49:43.297684441 +0100
+++ /var/tmp/diff_new_pack.yftqPI/_new  2023-12-11 21:49:43.297684441 +0100
@@ -16,10 +16,9 @@
 #
 
 
-%{?!python_module:%define python_module() python3-%{**}}
 %{?sle15_python_module_pythons}
 Name:           python-marshmallow
-Version:        3.19.0
+Version:        3.20.1
 Release:        0
 Summary:        ORM/ODM/framework-agnostic library to convert datatypes 
from/to Python types
 License:        BSD-3-Clause AND MIT
@@ -29,7 +28,7 @@
 # https://github.com/humitos/sphinx-version-warning/issues/22
 Patch0:         python-marshmallow-no-version-warning.patch
 BuildRequires:  %{python_module autodocsumm}
-BuildRequires:  %{python_module base >= 3.7}
+BuildRequires:  %{python_module base >= 3.8}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros

++++++ marshmallow-3.19.0.tar.gz -> marshmallow-3.20.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/AUTHORS.rst 
new/marshmallow-3.20.1/AUTHORS.rst
--- old/marshmallow-3.19.0/AUTHORS.rst  2022-11-11 17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/AUTHORS.rst  2023-07-21 00:08:04.000000000 +0200
@@ -171,3 +171,5 @@
 - Karthikeyan Singaravelan `@tirkarthi  <https://github.com/tirkarthi>`_
 - Marco Satti `@marcosatti  <https://github.com/marcosatti>`_
 - Ivo Reumkens `@vanHoi <https://github.com/vanHoi>`_
+- Aditya Tewary `@aditkumar72 <https://github.com/aditkumar72>`_
+- Sebastien Lovergne `@TheBigRoomXXL <https://github.com/TheBigRoomXXL>`_
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/CHANGELOG.rst 
new/marshmallow-3.20.1/CHANGELOG.rst
--- old/marshmallow-3.19.0/CHANGELOG.rst        2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/CHANGELOG.rst        2023-07-21 00:08:04.000000000 
+0200
@@ -1,12 +1,44 @@
 Changelog
 ---------
 
+3.20.1 (2023-07-20)
+*******************
+
+Bug fixes:
+
+- Fix call to ``get_declared_fields``: pass ``dict_cls`` again (:issue:`2152`).
+  Thanks :user:`Cheaterman` for reporting.
+
+3.20.0 (2023-07-20)
+*******************
+
+Features:
+
+- Add ``absolute`` parameter to ``URL`` validator and ``Url`` field 
(:pr:`2123`).
+  Thanks :user:`sirosen` for the PR.
+- Use Abstract Base Classes to define ``FieldABC`` and ``SchemaABC``
+  (:issue:`1449`). Thanks :user:`aditkumar72` for the PR.
+- Use `OrderedSet` as default `set_class`. Schemas are now ordered by default.
+  (:issue:`1744`)
+
+Bug fixes:
+
+- Handle ``OSError`` and ``OverflowError`` in ``utils.from_timestamp`` 
(:pr:`2102`).
+  Thanks :user:`TheBigRoomXXL` for the PR.
+- Fix the default inheritance of nested partial schemas (:issue:`2149`).
+  Thanks :user:`matejsp` for reporting.
+
+Other changes:
+
+- Officially support Python 3.11 (:pr:`2067`).
+- Drop support for Python 3.7 (:pr:`2135`).
+
 3.19.0 (2022-11-11)
 *******************
 
 Features:
 
-- Add ``timestamp`` and ``timestamp_ms`` formats to `fields.DateTime`
+- Add ``timestamp`` and ``timestamp_ms`` formats to ``fields.DateTime``
   (:issue:`612`).
   Thanks :user:`vgavro` for the suggestion and thanks :user:`vanHoi` for
   the PR.
@@ -93,7 +125,7 @@
 
 Other changes:
 
-- Fix type-hints for ```data``` arg in ```Schema.validate``` to accept
+- Fix type-hints for ``data`` arg in ``Schema.validate`` to accept
   list of dictionaries (:issue:`1790`, :pr:`1868`).
   Thanks  :user:`yourun-proger` for PR.
 - Improve warning when passing metadata as keyword arguments (:pr:`1882`).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/PKG-INFO 
new/marshmallow-3.20.1/PKG-INFO
--- old/marshmallow-3.19.0/PKG-INFO     2022-11-11 17:10:43.928643500 +0100
+++ new/marshmallow-3.20.1/PKG-INFO     2023-07-21 00:08:15.534859200 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: marshmallow
-Version: 3.19.0
+Version: 3.20.1
 Summary: A lightweight library for converting complex datatypes to and from 
native Python datatypes.
 Home-page: https://github.com/marshmallow-code/marshmallow
 Author: Steven Loria
@@ -15,11 +15,11 @@
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
-Requires-Python: >=3.7
+Classifier: Programming Language :: Python :: 3.11
+Requires-Python: >=3.8
 Provides-Extra: tests
 Provides-Extra: lint
 Provides-Extra: docs
@@ -34,10 +34,14 @@
     :target: https://pypi.org/project/marshmallow/
     :alt: Latest version
 
-.. image:: 
https://dev.azure.com/sloria/sloria/_apis/build/status/marshmallow-code.marshmallow?branchName=dev
-    :target: 
https://dev.azure.com/sloria/sloria/_build/latest?definitionId=5&branchName=dev
+.. image:: 
https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml/badge.svg
+    :target: 
https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml
     :alt: Build status
 
+.. image:: 
https://results.pre-commit.ci/badge/github/marshmallow-code/marshmallow/dev.svg
+   :target: 
https://results.pre-commit.ci/latest/github/marshmallow-code/marshmallow/dev
+   :alt: pre-commit.ci status
+
 .. image:: https://readthedocs.org/projects/marshmallow/badge/
    :target: https://marshmallow.readthedocs.io/
    :alt: Documentation
@@ -100,7 +104,7 @@
 Requirements
 ============
 
-- Python >= 3.7
+- Python >= 3.8
 
 Ecosystem
 =========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/README.rst 
new/marshmallow-3.20.1/README.rst
--- old/marshmallow-3.19.0/README.rst   2022-11-11 17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/README.rst   2023-07-21 00:08:04.000000000 +0200
@@ -6,10 +6,14 @@
     :target: https://pypi.org/project/marshmallow/
     :alt: Latest version
 
-.. image:: 
https://dev.azure.com/sloria/sloria/_apis/build/status/marshmallow-code.marshmallow?branchName=dev
-    :target: 
https://dev.azure.com/sloria/sloria/_build/latest?definitionId=5&branchName=dev
+.. image:: 
https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml/badge.svg
+    :target: 
https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml
     :alt: Build status
 
+.. image:: 
https://results.pre-commit.ci/badge/github/marshmallow-code/marshmallow/dev.svg
+   :target: 
https://results.pre-commit.ci/latest/github/marshmallow-code/marshmallow/dev
+   :alt: pre-commit.ci status
+
 .. image:: https://readthedocs.org/projects/marshmallow/badge/
    :target: https://marshmallow.readthedocs.io/
    :alt: Documentation
@@ -72,7 +76,7 @@
 Requirements
 ============
 
-- Python >= 3.7
+- Python >= 3.8
 
 Ecosystem
 =========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/docs/conf.py 
new/marshmallow-3.20.1/docs/conf.py
--- old/marshmallow-3.19.0/docs/conf.py 2022-11-11 17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/docs/conf.py 2023-07-21 00:08:04.000000000 +0200
@@ -81,14 +81,14 @@
 }
 
 html_sidebars = {
-    "index": ["about.html", "donate.html", "useful-links.html", 
"searchbox.html"],
+    "index": ["about.html", "searchbox.html", "donate.html", 
"useful-links.html"],
     "**": [
         "about.html",
+        "searchbox.html",
         "donate.html",
         "useful-links.html",
         "localtoc.html",
         "relations.html",
-        "searchbox.html",
     ],
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/docs/install.rst 
new/marshmallow-3.20.1/docs/install.rst
--- old/marshmallow-3.19.0/docs/install.rst     2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/docs/install.rst     2023-07-21 00:08:04.000000000 
+0200
@@ -3,7 +3,7 @@
 Installation
 ============
 
-**marshmallow** requires Python >= 3.7. It has no external dependencies other 
than the `packaging` library.
+**marshmallow** requires Python >= 3.8. It has no external dependencies other 
than the `packaging` library.
 
 Installing/Upgrading from the PyPI
 ----------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/docs/quickstart.rst 
new/marshmallow-3.20.1/docs/quickstart.rst
--- old/marshmallow-3.19.0/docs/quickstart.rst  2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/docs/quickstart.rst  2023-07-21 00:08:04.000000000 
+0200
@@ -524,37 +524,6 @@
                 # No need to include 'uppername'
                 additional = ("name", "email", "created_at")
 
-Ordering Output
----------------
-
-To maintain field ordering, set the ``ordered`` option to `True`. This will 
instruct marshmallow to serialize data to a `collections.OrderedDict`.
-
-.. code-block:: python
-
-    from collections import OrderedDict
-    from pprint import pprint
-
-    from marshmallow import Schema, fields
-
-
-    class UserSchema(Schema):
-        first_name = fields.String()
-        last_name = fields.String()
-        email = fields.Email()
-
-        class Meta:
-            ordered = True
-
-
-    u = User("Charlie", "Stones", "char...@stones.com")
-    schema = UserSchema()
-    result = schema.dump(u)
-    assert isinstance(result, OrderedDict)
-    pprint(result, indent=2)
-    #  OrderedDict([('first_name', 'Charlie'),
-    #              ('last_name', 'Stones'),
-    #              ('email', 'char...@stones.com')])
-
 Next Steps
 ----------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/pyproject.toml 
new/marshmallow-3.20.1/pyproject.toml
--- old/marshmallow-3.19.0/pyproject.toml       2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/pyproject.toml       2023-07-21 00:08:04.000000000 
+0200
@@ -1,3 +1,3 @@
 [tool.black]
 line-length = 88
-target-version = ['py37', 'py38', 'py39', 'py310']
+target-version = ['py38', 'py39', 'py310', 'py311']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/setup.cfg 
new/marshmallow-3.20.1/setup.cfg
--- old/marshmallow-3.19.0/setup.cfg    2022-11-11 17:10:43.932643400 +0100
+++ new/marshmallow-3.20.1/setup.cfg    2023-07-21 00:08:15.534859200 +0200
@@ -2,10 +2,9 @@
 license_files = LICENSE
 
 [flake8]
-extend-ignore = E203, E266, E501, E731, B903
 max-line-length = 90
 max-complexity = 18
-select = B,C,E,F,W,T4,B9
+extend-ignore = E203, E266, E501, E731, B903
 
 [tool:pytest]
 norecursedirs = .git .ropeproject .tox docs env venv tests/mypy_test_cases
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/setup.py 
new/marshmallow-3.20.1/setup.py
--- old/marshmallow-3.19.0/setup.py     2022-11-11 17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/setup.py     2023-07-21 00:08:04.000000000 +0200
@@ -4,17 +4,17 @@
 EXTRAS_REQUIRE = {
     "tests": ["pytest", "pytz", "simplejson"],
     "lint": [
-        "mypy==0.990",
-        "flake8==5.0.4",
-        "flake8-bugbear==22.10.25",
-        "pre-commit~=2.4",
+        "mypy==1.4.1",
+        "flake8==6.0.0",
+        "flake8-bugbear==23.7.10",
+        "pre-commit>=2.4,<4.0",
     ],
     "docs": [
-        "sphinx==5.3.0",
+        "sphinx==7.0.1",
         "sphinx-issues==3.0.1",
-        "alabaster==0.7.12",
+        "alabaster==0.7.13",
         "sphinx-version-warning==1.1.2",
-        "autodocsumm==0.2.9",
+        "autodocsumm==0.2.11",
     ],
 }
 EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + EXTRAS_REQUIRE["lint"] + 
["tox"]
@@ -73,16 +73,16 @@
         "validation",
         "schema",
     ],
-    python_requires=">=3.7",
+    python_requires=">=3.8",
     classifiers=[
         "Development Status :: 5 - Production/Stable",
         "Intended Audience :: Developers",
         "License :: OSI Approved :: MIT License",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
+        "Programming Language :: Python :: 3.11",
     ],
     test_suite="tests",
     project_urls={
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/__init__.py 
new/marshmallow-3.20.1/src/marshmallow/__init__.py
--- old/marshmallow-3.19.0/src/marshmallow/__init__.py  2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/__init__.py  2023-07-21 
00:08:04.000000000 +0200
@@ -16,7 +16,7 @@
 
 from . import fields
 
-__version__ = "3.19.0"
+__version__ = "3.20.1"
 __parsed_version__ = Version(__version__)
 __version_info__: tuple[int, int, int] | tuple[
     int, int, int, str, int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/base.py 
new/marshmallow-3.20.1/src/marshmallow/base.py
--- old/marshmallow-3.19.0/src/marshmallow/base.py      2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/base.py      2023-07-21 
00:08:04.000000000 +0200
@@ -1,6 +1,6 @@
 """Abstract base classes.
 
-These are necessary to avoid circular imports between core.py and fields.py.
+These are necessary to avoid circular imports between schema.py and fields.py.
 
 .. warning::
 
@@ -8,40 +8,49 @@
     Users should not need to use this module directly.
 """
 from __future__ import annotations
+from abc import ABC, abstractmethod
 
 
-class FieldABC:
+class FieldABC(ABC):
     """Abstract base class from which all Field classes inherit."""
 
     parent = None
     name = None
     root = None
 
+    @abstractmethod
     def serialize(self, attr, obj, accessor=None):
-        raise NotImplementedError
+        pass
 
+    @abstractmethod
     def deserialize(self, value):
-        raise NotImplementedError
+        pass
 
+    @abstractmethod
     def _serialize(self, value, attr, obj, **kwargs):
-        raise NotImplementedError
+        pass
 
+    @abstractmethod
     def _deserialize(self, value, attr, data, **kwargs):
-        raise NotImplementedError
+        pass
 
 
-class SchemaABC:
+class SchemaABC(ABC):
     """Abstract base class from which all Schemas inherit."""
 
+    @abstractmethod
     def dump(self, obj, *, many: bool | None = None):
-        raise NotImplementedError
+        pass
 
+    @abstractmethod
     def dumps(self, obj, *, many: bool | None = None):
-        raise NotImplementedError
+        pass
 
+    @abstractmethod
     def load(self, data, *, many: bool | None = None, partial=None, 
unknown=None):
-        raise NotImplementedError
+        pass
 
+    @abstractmethod
     def loads(
         self,
         json_data,
@@ -51,4 +60,4 @@
         unknown=None,
         **kwargs,
     ):
-        raise NotImplementedError
+        pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/decorators.py 
new/marshmallow-3.20.1/src/marshmallow/decorators.py
--- old/marshmallow-3.19.0/src/marshmallow/decorators.py        2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/decorators.py        2023-07-21 
00:08:04.000000000 +0200
@@ -61,7 +61,7 @@
 from __future__ import annotations
 
 import functools
-from typing import Any, Callable, Dict, Optional, Tuple, Union, cast
+from typing import Any, Callable, cast
 
 PRE_DUMP = "pre_dump"
 POST_DUMP = "post_dump"
@@ -72,9 +72,7 @@
 
 
 class MarshmallowHook:
-    __marshmallow_hook__ = (
-        None
-    )  # type: Optional[Dict[Union[Tuple[str, bool], str], Any]]
+    __marshmallow_hook__: dict[tuple[str, bool] | str, Any] | None = None
 
 
 def validates(field_name: str) -> Callable[..., Any]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/fields.py 
new/marshmallow-3.20.1/src/marshmallow/fields.py
--- old/marshmallow-3.19.0/src/marshmallow/fields.py    2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/fields.py    2023-07-21 
00:08:04.000000000 +0200
@@ -137,7 +137,6 @@
     #  to exist as attributes on the objects to serialize. Set this to False
     #  for those fields
     _CHECK_ATTRIBUTE = True
-    _creation_index = 0  # Used for sorting
 
     #: Default error messages for various kinds of errors. The keys in this 
dictionary
     #: are passed to `Field.make_error`. The values are error messages passed 
to
@@ -157,9 +156,9 @@
         default: typing.Any = missing_,
         data_key: str | None = None,
         attribute: str | None = None,
-        validate: None
-        | (
-            typing.Callable[[typing.Any], typing.Any]
+        validate: (
+            None
+            | typing.Callable[[typing.Any], typing.Any]
             | typing.Iterable[typing.Callable[[typing.Any], typing.Any]]
         ) = None,
         required: bool = False,
@@ -227,9 +226,6 @@
                 stacklevel=2,
             )
 
-        self._creation_index = Field._creation_index
-        Field._creation_index += 1
-
         # Collect default error message from self and parent classes
         messages = {}  # type: dict[str, str]
         for cls in reversed(self.__class__.__mro__):
@@ -920,8 +916,7 @@
         try:
             if isinstance(value, bytes) and len(value) == 16:
                 return uuid.UUID(bytes=value)
-            else:
-                return uuid.UUID(value)
+            return uuid.UUID(value)
         except (ValueError, AttributeError, TypeError) as error:
             raise self.make_error("invalid_uuid") from error
 
@@ -1281,28 +1276,21 @@
         format_func = self.SERIALIZATION_FUNCS.get(data_format)
         if format_func:
             return format_func(value)
-        else:
-            return value.strftime(data_format)
+        return value.strftime(data_format)
 
     def _deserialize(self, value, attr, data, **kwargs) -> dt.datetime:
         if not value:  # Falsy values, e.g. '', None, [] are not valid
             raise self.make_error("invalid", input=value, 
obj_type=self.OBJ_TYPE)
         data_format = self.format or self.DEFAULT_FORMAT
         func = self.DESERIALIZATION_FUNCS.get(data_format)
-        if func:
-            try:
+        try:
+            if func:
                 return func(value)
-            except (TypeError, AttributeError, ValueError) as error:
-                raise self.make_error(
-                    "invalid", input=value, obj_type=self.OBJ_TYPE
-                ) from error
-        else:
-            try:
-                return self._make_object_from_format(value, data_format)
-            except (TypeError, AttributeError, ValueError) as error:
-                raise self.make_error(
-                    "invalid", input=value, obj_type=self.OBJ_TYPE
-                ) from error
+            return self._make_object_from_format(value, data_format)
+        except (TypeError, AttributeError, ValueError) as error:
+            raise self.make_error(
+                "invalid", input=value, obj_type=self.OBJ_TYPE
+            ) from error
 
     @staticmethod
     def _make_object_from_format(value, data_format) -> dt.datetime:
@@ -1525,9 +1513,8 @@
             delta = utils.timedelta_to_microseconds(value)
             unit = utils.timedelta_to_microseconds(base_unit)
             return delta // unit
-        else:
-            assert self.serialization_type is float
-            return value.total_seconds() / base_unit.total_seconds()
+        assert self.serialization_type is float
+        return value.total_seconds() / base_unit.total_seconds()
 
     def _deserialize(self, value, attr, data, **kwargs):
         try:
@@ -1710,6 +1697,7 @@
         self,
         *,
         relative: bool = False,
+        absolute: bool = True,
         schemes: types.StrSequenceOrSet | None = None,
         require_tld: bool = True,
         **kwargs,
@@ -1717,10 +1705,12 @@
         super().__init__(**kwargs)
 
         self.relative = relative
+        self.absolute = absolute
         self.require_tld = require_tld
         # Insert validation into self.validators so that multiple errors can 
be stored.
         validator = validate.URL(
             relative=self.relative,
+            absolute=self.absolute,
             schemes=schemes,
             require_tld=self.require_tld,
             error=self.error_messages["invalid"],
@@ -2024,14 +2014,14 @@
 
     def __init__(
         self,
-        serialize: None
-        | (
-            typing.Callable[[typing.Any], typing.Any]
+        serialize: (
+            None
+            | typing.Callable[[typing.Any], typing.Any]
             | typing.Callable[[typing.Any, dict], typing.Any]
         ) = None,
-        deserialize: None
-        | (
-            typing.Callable[[typing.Any], typing.Any]
+        deserialize: (
+            None
+            | typing.Callable[[typing.Any], typing.Any]
             | typing.Callable[[typing.Any, dict], typing.Any]
         ) = None,
         **kwargs,
@@ -2057,8 +2047,7 @@
                 msg = f"No context available for Function field {attr!r}"
                 raise ValidationError(msg)
             return func(value, self.parent.context)
-        else:
-            return func(value)
+        return func(value)
 
 
 class Constant(Field):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/schema.py 
new/marshmallow-3.20.1/src/marshmallow/schema.py
--- old/marshmallow-3.19.0/src/marshmallow/schema.py    2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/schema.py    2023-07-21 
00:08:04.000000000 +0200
@@ -1,5 +1,6 @@
 """The :class:`Schema` class, including its metaclass and options (class 
Meta)."""
 from __future__ import annotations
+from abc import ABCMeta
 
 from collections import defaultdict, OrderedDict
 from collections.abc import Mapping
@@ -41,25 +42,21 @@
 _T = typing.TypeVar("_T")
 
 
-def _get_fields(attrs, ordered=False):
-    """Get fields from a class. If ordered=True, fields will sorted by 
creation index.
+def _get_fields(attrs):
+    """Get fields from a class
 
     :param attrs: Mapping of class attributes
-    :param bool ordered: Sort fields by creation index
     """
-    fields = [
+    return [
         (field_name, field_value)
         for field_name, field_value in attrs.items()
         if is_instance_or_subclass(field_value, base.FieldABC)
     ]
-    if ordered:
-        fields.sort(key=lambda pair: pair[1]._creation_index)
-    return fields
 
 
 # This function allows Schemas to inherit from non-Schema classes and ensures
 #   inheritance according to the MRO
-def _get_fields_by_mro(klass, ordered=False):
+def _get_fields_by_mro(klass):
     """Collect fields from a class, following its method resolution order. The
     class itself is excluded from the search; only its parents are checked. Get
     fields from ``_declared_fields`` if available, else use ``__dict__``.
@@ -72,7 +69,6 @@
         (
             _get_fields(
                 getattr(base, "_declared_fields", base.__dict__),
-                ordered=ordered,
             )
             for base in mro[:0:-1]
         ),
@@ -80,7 +76,7 @@
     )
 
 
-class SchemaMeta(type):
+class SchemaMeta(ABCMeta):
     """Metaclass for the Schema class. Binds the declared fields to
     a ``_declared_fields`` attribute, which is a dictionary mapping attribute
     names to field objects. Also sets the ``opts`` class attribute, which is
@@ -101,13 +97,13 @@
                     break
             else:
                 ordered = False
-        cls_fields = _get_fields(attrs, ordered=ordered)
+        cls_fields = _get_fields(attrs)
         # Remove fields from list of class attributes to avoid shadowing
         # Schema attributes/methods in case of name conflict
         for field_name, _ in cls_fields:
             del attrs[field_name]
         klass = super().__new__(mcs, name, bases, attrs)
-        inherited_fields = _get_fields_by_mro(klass, ordered=ordered)
+        inherited_fields = _get_fields_by_mro(klass)
 
         meta = klass.Meta
         # Set klass.opts in __new__ rather than __init__ so that it is 
accessible in
@@ -116,13 +112,12 @@
         # Add fields specified in the `include` class Meta option
         cls_fields += list(klass.opts.include.items())
 
-        dict_cls = OrderedDict if ordered else dict
         # Assign _declared_fields on class
         klass._declared_fields = mcs.get_declared_fields(
             klass=klass,
             cls_fields=cls_fields,
             inherited_fields=inherited_fields,
-            dict_cls=dict_cls,
+            dict_cls=dict,
         )
         return klass
 
@@ -132,7 +127,7 @@
         klass: type,
         cls_fields: list,
         inherited_fields: list,
-        dict_cls: type,
+        dict_cls: type = dict,
     ):
         """Returns a dictionary of field_name => `Field` pairs declared on the 
class.
         This is exposed mainly so that plugins can add additional fields, e.g. 
fields
@@ -142,8 +137,7 @@
         :param cls_fields: The fields declared on the class, including those 
added
             by the ``include`` class Meta option.
         :param inherited_fields: Inherited fields.
-        :param dict_cls: Either `dict` or `OrderedDict`, depending on whether
-            the user specified `ordered=True`.
+        :param dict_cls: dict-like class to use for dict output Default to 
``dict``.
         """
         return dict_cls(inherited_fields + cls_fields)
 
@@ -318,6 +312,8 @@
 
     OPTIONS_CLASS = SchemaOpts  # type: type
 
+    set_class = OrderedSet
+
     # These get set by SchemaMeta
     opts = None  # type: SchemaOpts
     _declared_fields = {}  # type: typing.Dict[str, ma_fields.Field]
@@ -349,9 +345,7 @@
         - ``timeformat``: Default format for `Time <fields.Time>` fields.
         - ``render_module``: Module to use for `loads <Schema.loads>` and 
`dumps <Schema.dumps>`.
             Defaults to `json` from the standard library.
-        - ``ordered``: If `True`, order serialization output according to the
-            order in which fields were declared. Output of `Schema.dump` will 
be a
-            `collections.OrderedDict`.
+        - ``ordered``: If `True`, output of `Schema.dump` will be a 
`collections.OrderedDict`.
         - ``index_errors``: If `True`, errors dictionaries will include the 
index
             of invalid items in a collection.
         - ``load_only``: Tuple or list of fields to exclude from serialized 
results.
@@ -373,7 +367,7 @@
         context: dict | None = None,
         load_only: types.StrSequenceOrSet = (),
         dump_only: types.StrSequenceOrSet = (),
-        partial: bool | types.StrSequenceOrSet = False,
+        partial: bool | types.StrSequenceOrSet | None = None,
         unknown: str | None = None,
     ):
         # Raise error if only or exclude is passed as string, not list of 
strings
@@ -385,7 +379,9 @@
         self.declared_fields = copy.deepcopy(self._declared_fields)
         self.many = many
         self.only = only
-        self.exclude = set(self.opts.exclude) | set(exclude)
+        self.exclude: set[typing.Any] | typing.MutableSet[typing.Any] = set(
+            self.opts.exclude
+        ) | set(exclude)
         self.ordered = self.opts.ordered
         self.load_only = set(load_only) or set(self.opts.load_only)
         self.dump_only = set(dump_only) or set(self.opts.dump_only)
@@ -418,10 +414,6 @@
     def dict_class(self) -> type:
         return OrderedDict if self.ordered else dict
 
-    @property
-    def set_class(self) -> type:
-        return OrderedSet if self.ordered else set
-
     @classmethod
     def from_dict(
         cls,
@@ -589,7 +581,7 @@
         *,
         error_store: ErrorStore,
         many: bool = False,
-        partial=False,
+        partial=None,
         unknown=RAISE,
         index=None,
     ) -> _T | list[_T]:
@@ -656,11 +648,19 @@
                         f[len_prefix:] for f in partial if f.startswith(prefix)
                     ]
                     d_kwargs["partial"] = sub_partial
-                else:
+                elif partial is not None:
                     d_kwargs["partial"] = partial
-                getter = lambda val: field_obj.deserialize(
-                    val, field_name, data, **d_kwargs
-                )
+
+                def getter(
+                    val, field_obj=field_obj, field_name=field_name, 
d_kwargs=d_kwargs
+                ):
+                    return field_obj.deserialize(
+                        val,
+                        field_name,
+                        data,
+                        **d_kwargs,
+                    )
+
                 value = self._call_and_store(
                     getter_func=getter,
                     data=raw_value,
@@ -961,7 +961,7 @@
 
         if self.only is not None:
             # Return only fields specified in only option
-            field_names = self.set_class(self.only)
+            field_names: typing.AbstractSet[typing.Any] = 
self.set_class(self.only)
 
             invalid_fields |= field_names - available_field_names
         else:
@@ -1047,15 +1047,15 @@
             # the type checker's perspective.
             if isinstance(field_obj, type) and issubclass(field_obj, 
base.FieldABC):
                 msg = (
-                    'Field for "{}" must be declared as a '
+                    'Field for "{field_name}" must be declared as a '
                     "Field instance, not a class. "
-                    'Did you mean "fields.{}()"?'.format(field_name, 
field_obj.__name__)
+                    'Did you mean "fields.{field_obj.__name__}()"?'
                 )
                 raise TypeError(msg) from error
             raise error
         self.on_bind_field(field_name, field_obj)
 
-    @lru_cache(maxsize=8)
+    @lru_cache(maxsize=8)  # noqa 
(https://github.com/PyCQA/flake8-bugbear/issues/310)
     def _has_processors(self, tag) -> bool:
         return bool(self._hooks[(tag, True)] or self._hooks[(tag, False)])
 
@@ -1080,7 +1080,7 @@
         *,
         many: bool,
         original_data,
-        partial: bool | types.StrSequenceOrSet,
+        partial: bool | types.StrSequenceOrSet | None,
     ):
         # This has to invert the order of the dump processors, so run the 
pass_many
         # processors first.
@@ -1157,7 +1157,7 @@
         data,
         original_data,
         many: bool,
-        partial: bool | types.StrSequenceOrSet,
+        partial: bool | types.StrSequenceOrSet | None,
         field_errors: bool = False,
     ):
         for attr_name in self._hooks[(VALIDATES_SCHEMA, pass_many)]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/types.py 
new/marshmallow-3.20.1/src/marshmallow/types.py
--- old/marshmallow-3.19.0/src/marshmallow/types.py     2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/types.py     2023-07-21 
00:08:04.000000000 +0200
@@ -6,6 +6,6 @@
 """
 import typing
 
-StrSequenceOrSet = typing.Union[typing.Sequence[str], typing.Set[str]]
+StrSequenceOrSet = typing.Union[typing.Sequence[str], typing.AbstractSet[str]]
 Tag = typing.Union[str, typing.Tuple[str, bool]]
 Validator = typing.Callable[[typing.Any], typing.Any]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/utils.py 
new/marshmallow-3.20.1/src/marshmallow/utils.py
--- old/marshmallow-3.19.0/src/marshmallow/utils.py     2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/utils.py     2023-07-21 
00:08:04.000000000 +0200
@@ -197,7 +197,12 @@
 
     # Load a timestamp with utc as timezone to prevent using system timezone.
     # Then set timezone to None, to let the Field handle adding timezone info.
-    return dt.datetime.fromtimestamp(value, 
tz=dt.timezone.utc).replace(tzinfo=None)
+    try:
+        return dt.datetime.fromtimestamp(value, 
tz=dt.timezone.utc).replace(tzinfo=None)
+    except OverflowError as exc:
+        raise ValueError("Timestamp is too large") from exc
+    except OSError as exc:
+        raise ValueError("Error converting value to datetime") from exc
 
 
 def from_timestamp_ms(value: typing.Any) -> dt.datetime:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow/validate.py 
new/marshmallow-3.20.1/src/marshmallow/validate.py
--- old/marshmallow-3.19.0/src/marshmallow/validate.py  2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow/validate.py  2023-07-21 
00:08:04.000000000 +0200
@@ -94,6 +94,7 @@
     """Validate a URL.
 
     :param relative: Whether to allow relative URLs.
+    :param absolute: Whether to allow absolute URLs.
     :param error: Error message to raise in case of a validation error.
         Can be interpolated with `{input}`.
     :param schemes: Valid schemes. By default, ``http``, ``https``,
@@ -105,38 +106,68 @@
         def __init__(self):
             self._memoized = {}
 
-        def _regex_generator(self, relative: bool, require_tld: bool) -> 
typing.Pattern:
-            return re.compile(
-                r"".join(
-                    (
-                        r"^",
-                        r"(" if relative else r"",
-                        r"(?:[a-z0-9\.\-\+]*)://",  # scheme is validated 
separately
-                        r"(?:[^:@]+?(:[^:@]*?)?@|)",  # basic auth
-                        r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+",
-                        r"(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|",  # domain...
-                        r"localhost|",  # localhost...
-                        (
-                            r"(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.?)|"
-                            if not require_tld
-                            else r""
-                        ),  # allow dotless hostnames
-                        r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|",  # ...or ipv4
-                        r"\[[A-F0-9]*:[A-F0-9:]+\])",  # ...or ipv6
-                        r"(?::\d+)?",  # optional port
-                        r")?"
-                        if relative
-                        else r"",  # host is optional, allow for relative URLs
-                        r"(?:/?|[/?]\S+)\Z",
-                    )
+        def _regex_generator(
+            self, relative: bool, absolute: bool, require_tld: bool
+        ) -> typing.Pattern:
+            hostname_variants = [
+                # a normal domain name, expressed in [A-Z0-9] chars with 
hyphens allowed only in the middle
+                # note that the regex will be compiled with IGNORECASE, so 
these are upper and lowercase chars
+                (
+                    r"(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+"
+                    r"(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)"
                 ),
-                re.IGNORECASE,
+                # or the special string 'localhost'
+                r"localhost",
+                # or IPv4
+                r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",
+                # or IPv6
+                r"\[[A-F0-9]*:[A-F0-9:]+\]",
+            ]
+            if not require_tld:
+                # allow dotless hostnames
+                
hostname_variants.append(r"(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.?)")
+
+            absolute_part = "".join(
+                (
+                    # scheme (e.g. 'https://', 'ftp://', etc)
+                    # this is validated separately against allowed schemes, so 
in the regex
+                    # we simply want to capture its existence
+                    r"(?:[a-z0-9\.\-\+]*)://",
+                    # basic_auth, for URLs encoding a username:password
+                    # e.g. 'ftp://foo:b...@ftp.example.org/'
+                    r"(?:[^:@]+?(:[^:@]*?)?@|)",
+                    # netloc, the hostname/domain part of the URL plus the 
optional port
+                    r"(?:",
+                    "|".join(hostname_variants),
+                    r")",
+                    r"(?::\d+)?",
+                )
             )
+            relative_part = r"(?:/?|[/?]\S+)\Z"
 
-        def __call__(self, relative: bool, require_tld: bool) -> 
typing.Pattern:
-            key = (relative, require_tld)
+            if relative:
+                if absolute:
+                    parts: tuple[str, ...] = (
+                        r"^(",
+                        absolute_part,
+                        r")?",
+                        relative_part,
+                    )
+                else:
+                    parts = (r"^", relative_part)
+            else:
+                parts = (r"^", absolute_part, relative_part)
+
+            return re.compile("".join(parts), re.IGNORECASE)
+
+        def __call__(
+            self, relative: bool, absolute: bool, require_tld: bool
+        ) -> typing.Pattern:
+            key = (relative, absolute, require_tld)
             if key not in self._memoized:
-                self._memoized[key] = self._regex_generator(relative, 
require_tld)
+                self._memoized[key] = self._regex_generator(
+                    relative, absolute, require_tld
+                )
 
             return self._memoized[key]
 
@@ -149,17 +180,23 @@
         self,
         *,
         relative: bool = False,
+        absolute: bool = True,
         schemes: types.StrSequenceOrSet | None = None,
         require_tld: bool = True,
         error: str | None = None,
     ):
+        if not relative and not absolute:
+            raise ValueError(
+                "URL validation cannot set both relative and absolute to 
False."
+            )
         self.relative = relative
+        self.absolute = absolute
         self.error = error or self.default_message  # type: str
         self.schemes = schemes or self.default_schemes
         self.require_tld = require_tld
 
     def _repr_args(self) -> str:
-        return f"relative={self.relative!r}"
+        return f"relative={self.relative!r}, absolute={self.absolute!r}"
 
     def _format_error(self, value) -> str:
         return self.error.format(input=value)
@@ -175,7 +212,7 @@
             if scheme not in self.schemes:
                 raise ValidationError(message)
 
-        regex = self._regex(self.relative, self.require_tld)
+        regex = self._regex(self.relative, self.absolute, self.require_tld)
 
         if not regex.search(value):
             raise ValidationError(message)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/src/marshmallow.egg-info/PKG-INFO 
new/marshmallow-3.20.1/src/marshmallow.egg-info/PKG-INFO
--- old/marshmallow-3.19.0/src/marshmallow.egg-info/PKG-INFO    2022-11-11 
17:10:43.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow.egg-info/PKG-INFO    2023-07-21 
00:08:15.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: marshmallow
-Version: 3.19.0
+Version: 3.20.1
 Summary: A lightweight library for converting complex datatypes to and from 
native Python datatypes.
 Home-page: https://github.com/marshmallow-code/marshmallow
 Author: Steven Loria
@@ -15,11 +15,11 @@
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
-Requires-Python: >=3.7
+Classifier: Programming Language :: Python :: 3.11
+Requires-Python: >=3.8
 Provides-Extra: tests
 Provides-Extra: lint
 Provides-Extra: docs
@@ -34,10 +34,14 @@
     :target: https://pypi.org/project/marshmallow/
     :alt: Latest version
 
-.. image:: 
https://dev.azure.com/sloria/sloria/_apis/build/status/marshmallow-code.marshmallow?branchName=dev
-    :target: 
https://dev.azure.com/sloria/sloria/_build/latest?definitionId=5&branchName=dev
+.. image:: 
https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml/badge.svg
+    :target: 
https://github.com/marshmallow-code/marshmallow/actions/workflows/build-release.yml
     :alt: Build status
 
+.. image:: 
https://results.pre-commit.ci/badge/github/marshmallow-code/marshmallow/dev.svg
+   :target: 
https://results.pre-commit.ci/latest/github/marshmallow-code/marshmallow/dev
+   :alt: pre-commit.ci status
+
 .. image:: https://readthedocs.org/projects/marshmallow/badge/
    :target: https://marshmallow.readthedocs.io/
    :alt: Documentation
@@ -100,7 +104,7 @@
 Requirements
 ============
 
-- Python >= 3.7
+- Python >= 3.8
 
 Ecosystem
 =========
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/marshmallow-3.19.0/src/marshmallow.egg-info/requires.txt 
new/marshmallow-3.20.1/src/marshmallow.egg-info/requires.txt
--- old/marshmallow-3.19.0/src/marshmallow.egg-info/requires.txt        
2022-11-11 17:10:43.000000000 +0100
+++ new/marshmallow-3.20.1/src/marshmallow.egg-info/requires.txt        
2023-07-21 00:08:15.000000000 +0200
@@ -4,24 +4,24 @@
 pytest
 pytz
 simplejson
-mypy==0.990
-flake8==5.0.4
-flake8-bugbear==22.10.25
-pre-commit~=2.4
+mypy==1.4.1
+flake8==6.0.0
+flake8-bugbear==23.7.10
+pre-commit<4.0,>=2.4
 tox
 
 [docs]
-sphinx==5.3.0
+sphinx==7.0.1
 sphinx-issues==3.0.1
-alabaster==0.7.12
+alabaster==0.7.13
 sphinx-version-warning==1.1.2
-autodocsumm==0.2.9
+autodocsumm==0.2.11
 
 [lint]
-mypy==0.990
-flake8==5.0.4
-flake8-bugbear==22.10.25
-pre-commit~=2.4
+mypy==1.4.1
+flake8==6.0.0
+flake8-bugbear==23.7.10
+pre-commit<4.0,>=2.4
 
 [tests]
 pytest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_deserialization.py 
new/marshmallow-3.20.1/tests/test_deserialization.py
--- old/marshmallow-3.19.0/tests/test_deserialization.py        2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/tests/test_deserialization.py        2023-07-21 
00:08:04.000000000 +0200
@@ -4,6 +4,8 @@
 import decimal
 import math
 
+from unittest.mock import patch
+
 import pytest
 
 from marshmallow import EXCLUDE, INCLUDE, RAISE, fields, Schema, validate
@@ -21,6 +23,20 @@
 )
 
 
+class MockDateTimeOverflowError(dt.datetime):
+    """Used to simulate the possible OverflowError of datetime.fromtimestamp"""
+
+    def fromtimestamp(self, *args, **kwargs):
+        raise OverflowError()
+
+
+class MockDateTimeOSError(dt.datetime):
+    """Used to simulate the possible OSError of datetime.fromtimestamp"""
+
+    def fromtimestamp(self, *args, **kwargs):
+        raise OSError()
+
+
 class TestDeserializingNone:
     @pytest.mark.parametrize("FieldClass", ALL_FIELDS)
     def test_fields_allow_none_deserialize_to_none(self, FieldClass):
@@ -258,7 +274,6 @@
     @pytest.mark.parametrize("allow_nan", (None, False, True))
     @pytest.mark.parametrize("value", ("nan", "-nan", "inf", "-inf"))
     def test_float_field_allow_nan(self, value, allow_nan):
-
         if allow_nan is None:
             # Test default case is False
             field = fields.Float()
@@ -566,10 +581,21 @@
         ["", "!@#", 0, -1, dt.datetime(2013, 11, 10, 1, 23, 45)],
     )
     def test_invalid_timestamp_field_deserialization(self, fmt, in_value):
-        field = fields.DateTime(format="timestamp")
+        field = fields.DateTime(format=fmt)
         with pytest.raises(ValidationError, match="Not a valid datetime."):
             field.deserialize(in_value)
 
+    #  Regression test for 
https://github.com/marshmallow-code/marshmallow/pull/2102
+    @pytest.mark.parametrize("fmt", ["timestamp", "timestamp_ms"])
+    @pytest.mark.parametrize(
+        "mock_fromtimestamp", [MockDateTimeOSError, MockDateTimeOverflowError]
+    )
+    def test_oversized_timestamp_field_deserialization(self, fmt, 
mock_fromtimestamp):
+        with patch("datetime.datetime", mock_fromtimestamp):
+            field = fields.DateTime(format=fmt)
+            with pytest.raises(ValidationError, match="Not a valid datetime."):
+                field.deserialize(99999999999999999)
+
     @pytest.mark.parametrize(
         ("fmt", "timezone", "value", "expected"),
         [
@@ -1546,7 +1572,7 @@
             name = fields.Str()
 
         class StoreSchema(Schema):
-            pets = fields.Nested(PetSchema(), allow_none=False, many=True)
+            pets = fields.Nested(PetSchema, allow_none=False, many=True)
 
         sch = StoreSchema()
         errors = sch.validate({"pets": None})
@@ -1570,7 +1596,7 @@
             name = fields.Str()
 
         class StoreSchema(Schema):
-            pets = fields.Nested(PetSchema(), required=True, many=True)
+            pets = fields.Nested(PetSchema, required=True, many=True)
 
         sch = StoreSchema()
         errors = sch.validate({})
@@ -2210,6 +2236,21 @@
         with pytest.raises(ValidationError):
             SchemaB().load(b_dict, partial=("z.y",))
 
+    def test_nested_partial_default(self):
+        class SchemaA(Schema):
+            x = fields.Integer(required=True)
+            y = fields.Integer(required=True)
+
+        class SchemaB(Schema):
+            z = fields.Nested(SchemaA(partial=("x",)))
+
+        b_dict = {"z": {"y": 42}}
+        # Nested partial args should be respected.
+        result = SchemaB().load(b_dict)
+        assert result["z"]["y"] == 42
+        with pytest.raises(ValidationError):
+            SchemaB().load({"z": {"x": 0}})
+
 
 @pytest.mark.parametrize("FieldClass", ALL_FIELDS)
 def test_required_field_failure(FieldClass):  # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_fields.py 
new/marshmallow-3.20.1/tests/test_fields.py
--- old/marshmallow-3.19.0/tests/test_fields.py 2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/tests/test_fields.py 2023-07-21 00:08:04.000000000 
+0200
@@ -9,6 +9,7 @@
     RAISE,
     missing,
 )
+from marshmallow.orderedset import OrderedSet
 from marshmallow.exceptions import StringNotCollectionError
 
 from tests.base import ALL_FIELDS
@@ -380,14 +381,14 @@
     @pytest.mark.parametrize(
         ("param", "fields_list"), [("only", ["foo"]), ("exclude", ["bar"])]
     )
-    def test_ordered_instanced_nested_schema_only_and_exclude(self, param, 
fields_list):
+    def test_nested_schema_only_and_exclude(self, param, fields_list):
         class NestedSchema(Schema):
+            # We mean to test the use of OrderedSet to specify it explicitly
+            # even if it is default
+            set_class = OrderedSet
             foo = fields.String()
             bar = fields.String()
 
-            class Meta:
-                ordered = True
-
         class MySchema(Schema):
             nested = fields.Nested(NestedSchema(), **{param: fields_list})
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_options.py 
new/marshmallow-3.20.1/tests/test_options.py
--- old/marshmallow-3.19.0/tests/test_options.py        2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/tests/test_options.py        2023-07-21 
00:08:04.000000000 +0200
@@ -178,9 +178,6 @@
 
     def test_nested_field_order_with_exclude_arg_is_maintained(self, user):
         class HasNestedExclude(Schema):
-            class Meta:
-                ordered = True
-
             user = fields.Nested(KeepOrder, exclude=("birthdate",))
 
         ser = HasNestedExclude()
@@ -231,7 +228,7 @@
         result = s.load({"name": "Steve", "from": "Oskosh"})
         assert result == in_data
 
-    def test_ordered_included(self):
+    def test_included_fields_ordered_after_declared_fields(self):
         class AddFieldsOrdered(Schema):
             name = fields.Str()
             email = fields.Str()
@@ -242,7 +239,6 @@
                     "in": fields.Str(),
                     "@at": fields.Str(),
                 }
-                ordered = True
 
         s = AddFieldsOrdered()
         in_data = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_registry.py 
new/marshmallow-3.20.1/tests/test_registry.py
--- old/marshmallow-3.19.0/tests/test_registry.py       2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/tests/test_registry.py       2023-07-21 
00:08:04.000000000 +0200
@@ -52,7 +52,6 @@
 
 
 def test_serializer_class_registry_register_same_classname_different_module():
-
     reglen = len(class_registry._registry)
 
     type("MyTestRegSchema", (Schema,), {"__module__": "modA"})
@@ -83,7 +82,6 @@
 
 
 def test_serializer_class_registry_override_if_same_classname_same_module():
-
     reglen = len(class_registry._registry)
 
     type("MyTestReg2Schema", (Schema,), {"__module__": "SameModulePath"})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_schema.py 
new/marshmallow-3.20.1/tests/test_schema.py
--- old/marshmallow-3.19.0/tests/test_schema.py 2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/tests/test_schema.py 2023-07-21 00:08:04.000000000 
+0200
@@ -2933,3 +2933,16 @@
             MySchema(unknown="badval")
         else:
             MySchema().load({"foo": "bar"}, unknown="badval")
+
+
+@pytest.mark.parametrize("dict_cls", (dict, OrderedDict))
+def test_set_dict_class(dict_cls):
+    """Demonstrate how to specify dict_class as class attribute"""
+
+    class MySchema(Schema):
+        dict_class = dict_cls
+        foo = fields.String()
+
+    result = MySchema().dump({"foo": "bar"})
+    assert result == {"foo": "bar"}
+    assert isinstance(result, dict_cls)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_serialization.py 
new/marshmallow-3.20.1/tests/test_serialization.py
--- old/marshmallow-3.19.0/tests/test_serialization.py  2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/tests/test_serialization.py  2023-07-21 
00:08:04.000000000 +0200
@@ -146,7 +146,6 @@
         assert field.serialize("uuid2", user) is None
 
     def test_ip_address_field(self, user):
-
         ipv4_string = "192.168.0.1"
         ipv6_string = "ffff::ffff"
         ipv6_exploded_string = ipaddress.ip_address("ffff::ffff").exploded
@@ -167,7 +166,6 @@
         assert field_exploded.serialize("ipv6", user) == ipv6_exploded_string
 
     def test_ipv4_address_field(self, user):
-
         ipv4_string = "192.168.0.1"
 
         user.ipv4 = ipaddress.ip_address(ipv4_string)
@@ -179,7 +177,6 @@
         assert field.serialize("empty_ip", user) is None
 
     def test_ipv6_address_field(self, user):
-
         ipv6_string = "ffff::ffff"
         ipv6_exploded_string = ipaddress.ip_address("ffff::ffff").exploded
 
@@ -196,7 +193,6 @@
         assert field_exploded.serialize("ipv6", user) == ipv6_exploded_string
 
     def test_ip_interface_field(self, user):
-
         ipv4interface_string = "192.168.0.1/24"
         ipv6interface_string = "ffff::ffff/128"
         ipv6interface_exploded_string = ipaddress.ip_interface(
@@ -222,7 +218,6 @@
         )
 
     def test_ipv4_interface_field(self, user):
-
         ipv4interface_string = "192.168.0.1/24"
 
         user.ipv4interface = ipaddress.ip_interface(ipv4interface_string)
@@ -234,7 +229,6 @@
         assert field.serialize("empty_ipinterface", user) is None
 
     def test_ipv6_interface_field(self, user):
-
         ipv6interface_string = "ffff::ffff/128"
         ipv6interface_exploded_string = ipaddress.ip_interface(
             "ffff::ffff/128"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_utils.py 
new/marshmallow-3.20.1/tests/test_utils.py
--- old/marshmallow-3.19.0/tests/test_utils.py  2022-11-11 17:10:31.000000000 
+0100
+++ new/marshmallow-3.20.1/tests/test_utils.py  2023-07-21 00:08:04.000000000 
+0200
@@ -228,6 +228,31 @@
     assert_date_equal(result, d)
 
 
+@pytest.mark.parametrize(
+    ("value", "expected"),
+    [
+        (1676386740, dt.datetime(2023, 2, 14, 14, 59, 00)),
+        (1676386740.58, dt.datetime(2023, 2, 14, 14, 59, 00, 580000)),
+    ],
+)
+def test_from_timestamp(value, expected):
+    result = utils.from_timestamp(value)
+    assert type(result) == dt.datetime
+    assert result == expected
+
+
+def test_from_timestamp_with_negative_value():
+    value = -10
+    with pytest.raises(ValueError, match=r"Not a valid POSIX timestamp"):
+        utils.from_timestamp(value)
+
+
+def test_from_timestamp_with_overflow_value():
+    value = 9223372036854775
+    with pytest.raises(ValueError):
+        utils.from_timestamp(value)
+
+
 def test_get_func_args():
     def f1(foo, bar):
         pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.19.0/tests/test_validate.py 
new/marshmallow-3.20.1/tests/test_validate.py
--- old/marshmallow-3.19.0/tests/test_validate.py       2022-11-11 
17:10:31.000000000 +0100
+++ new/marshmallow-3.20.1/tests/test_validate.py       2023-07-21 
00:08:04.000000000 +0200
@@ -75,6 +75,9 @@
         "http://example.com/./icons/logo.gif";,
         "ftp://example.com/../../../../g";,
         "http://example.com/g?y/./x";,
+        "/foo/bar",
+        "/foo?bar",
+        "/foo?bar#baz",
     ],
 )
 def test_url_relative_valid(valid_url):
@@ -107,6 +110,48 @@
 @pytest.mark.parametrize(
     "valid_url",
     [
+        "/foo/bar",
+        "/foo?bar",
+        "?bar",
+        "/foo?bar#baz",
+    ],
+)
+def test_url_relative_only_valid(valid_url):
+    validator = validate.URL(relative=True, absolute=False)
+    assert validator(valid_url) == valid_url
+
+
+@pytest.mark.parametrize(
+    "invalid_url",
+    [
+        "http//example.org",
+        "http://example.org\n";,
+        "suppliers.html",
+        "../icons/logo.gif",
+        "icons/logo.gif",
+        "../.../g",
+        "...",
+        "\\",
+        " ",
+        "",
+        "http://example.org";,
+        "http://123.45.67.8/";,
+        "http://example.com/foo/bar/../baz";,
+        "https://example.com/../icons/logo.gif";,
+        "http://example.com/./icons/logo.gif";,
+        "ftp://example.com/../../../../g";,
+        "http://example.com/g?y/./x";,
+    ],
+)
+def test_url_relative_only_invalid(invalid_url):
+    validator = validate.URL(relative=True, absolute=False)
+    with pytest.raises(ValidationError):
+        validator(invalid_url)
+
+
+@pytest.mark.parametrize(
+    "valid_url",
+    [
         "http://example.org";,
         "http://123.45.67.8/";,
         "http://example";,
@@ -170,10 +215,21 @@
 def test_url_repr():
     assert repr(
         validate.URL(relative=False, error=None)
-    ) == "<URL(relative=False, error={!r})>".format("Not a valid URL.")
+    ) == "<URL(relative=False, absolute=True, error={!r})>".format("Not a 
valid URL.")
     assert repr(
         validate.URL(relative=True, error="foo")
-    ) == "<URL(relative=True, error={!r})>".format("foo")
+    ) == "<URL(relative=True, absolute=True, error={!r})>".format("foo")
+    assert repr(
+        validate.URL(relative=True, absolute=False, error="foo")
+    ) == "<URL(relative=True, absolute=False, error={!r})>".format("foo")
+
+
+def test_url_rejects_invalid_relative_usage():
+    with pytest.raises(
+        ValueError,
+        match="URL validation cannot set both relative and absolute to False",
+    ):
+        validate.URL(relative=False, absolute=False)
 
 
 @pytest.mark.parametrize(

Reply via email to