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 2022-11-01 13:42:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-marshmallow (Old)
 and      /work/SRC/openSUSE:Factory/.python-marshmallow.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-marshmallow"

Tue Nov  1 13:42:18 2022 rev:18 rq:1032503 version:3.18.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-marshmallow/python-marshmallow.changes    
2022-09-30 17:58:05.401286521 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-marshmallow.new.2275/python-marshmallow.changes
  2022-11-01 13:42:29.399871111 +0100
@@ -2 +2 @@
-Thu Sep 29 15:53:34 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
+Fri Oct 28 18:21:19 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
@@ -8,0 +9,3 @@
+
+-------------------------------------------------------------------
+Thu Sep 29 15:53:34 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>

Old:
----
  marshmallow-3.17.1.tar.gz

New:
----
  marshmallow-3.18.0.tar.gz

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

Other differences:
------------------
++++++ python-marshmallow.spec ++++++
--- /var/tmp/diff_new_pack.GQCtsu/_old  2022-11-01 13:42:29.799873240 +0100
+++ /var/tmp/diff_new_pack.GQCtsu/_new  2022-11-01 13:42:29.807873282 +0100
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-marshmallow
-Version:        3.17.1
+Version:        3.18.0
 Release:        0
 Summary:        ORM/ODM/framework-agnostic library to convert datatypes 
from/to Python types
 License:        BSD-3-Clause AND MIT

++++++ marshmallow-3.17.1.tar.gz -> marshmallow-3.18.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/CHANGELOG.rst 
new/marshmallow-3.18.0/CHANGELOG.rst
--- old/marshmallow-3.17.1/CHANGELOG.rst        2022-08-22 21:36:43.000000000 
+0200
+++ new/marshmallow-3.18.0/CHANGELOG.rst        2022-09-15 22:26:57.000000000 
+0200
@@ -1,12 +1,23 @@
 Changelog
 ---------
 
+3.18.0 (2022-09-15)
+*******************
+
+Features:
+
+- Add ``Enum`` field (:pr:`2017`) and (:pr:`2044`).
+
+Bug fixes:
+
+- Fix typing in ``Field._serialize`` signature (:pr:`2046`).
+
 3.17.1 (2022-08-22)
 *******************
 
 Bug fixes:
 
-- Add return type to `fields.Email.__init__` (:pr:`2018`).
+- Add return type to ``fields.Email.__init__`` (:pr:`2018`).
   Thanks :user:`kkirsche` for the PR.
 - Add missing type hint to IPInterface __init__ (:pr:`2036`).
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/PKG-INFO 
new/marshmallow-3.18.0/PKG-INFO
--- old/marshmallow-3.17.1/PKG-INFO     2022-08-22 21:36:55.306264200 +0200
+++ new/marshmallow-3.18.0/PKG-INFO     2022-09-15 22:27:10.895295400 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: marshmallow
-Version: 3.17.1
+Version: 3.18.0
 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
@@ -173,12 +173,6 @@
     :target: 
https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=pypi-marshmallow&utm_medium=readme
     :alt: Get supported marshmallow with Tidelift
 
-Security Contact Information
-============================
-
-To report a security vulnerability, please use the
-`Tidelift security contact <https://tidelift.com/security>`_.
-Tidelift will coordinate the fix and disclosure.
 
 Project Links
 =============
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/README.rst 
new/marshmallow-3.18.0/README.rst
--- old/marshmallow-3.17.1/README.rst   2022-08-22 21:36:43.000000000 +0200
+++ new/marshmallow-3.18.0/README.rst   2022-09-15 22:26:57.000000000 +0200
@@ -145,12 +145,6 @@
     :target: 
https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=pypi-marshmallow&utm_medium=readme
     :alt: Get supported marshmallow with Tidelift
 
-Security Contact Information
-============================
-
-To report a security vulnerability, please use the
-`Tidelift security contact <https://tidelift.com/security>`_.
-Tidelift will coordinate the fix and disclosure.
 
 Project Links
 =============
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/setup.py 
new/marshmallow-3.18.0/setup.py
--- old/marshmallow-3.17.1/setup.py     2022-08-22 21:36:43.000000000 +0200
+++ new/marshmallow-3.18.0/setup.py     2022-09-15 22:26:57.000000000 +0200
@@ -6,7 +6,7 @@
     "lint": [
         "mypy==0.971",
         "flake8==5.0.4",
-        "flake8-bugbear==22.8.22",
+        "flake8-bugbear==22.9.11",
         "pre-commit~=2.4",
     ],
     "docs": [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/src/marshmallow/__init__.py 
new/marshmallow-3.18.0/src/marshmallow/__init__.py
--- old/marshmallow-3.17.1/src/marshmallow/__init__.py  2022-08-22 
21:36:43.000000000 +0200
+++ new/marshmallow-3.18.0/src/marshmallow/__init__.py  2022-09-15 
22:26:57.000000000 +0200
@@ -16,7 +16,7 @@
 
 from . import fields
 
-__version__ = "3.17.1"
+__version__ = "3.18.0"
 __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.17.1/src/marshmallow/fields.py 
new/marshmallow-3.18.0/src/marshmallow/fields.py
--- old/marshmallow-3.17.1/src/marshmallow/fields.py    2022-08-22 
21:36:43.000000000 +0200
+++ new/marshmallow-3.18.0/src/marshmallow/fields.py    2022-09-15 
22:26:57.000000000 +0200
@@ -11,6 +11,7 @@
 import math
 import typing
 import warnings
+from enum import Enum as EnumType
 from collections.abc import Mapping as _Mapping
 
 from marshmallow import validate, utils, class_registry, types
@@ -59,6 +60,7 @@
     "IPInterface",
     "IPv4Interface",
     "IPv6Interface",
+    "Enum",
     "Method",
     "Function",
     "Str",
@@ -384,7 +386,9 @@
             self.parent.root if isinstance(self.parent, FieldABC) else 
self.parent
         )
 
-    def _serialize(self, value: typing.Any, attr: str, obj: typing.Any, 
**kwargs):
+    def _serialize(
+        self, value: typing.Any, attr: str | None, obj: typing.Any, **kwargs
+    ):
         """Serializes ``value`` to a basic Python datatype. Noop by default.
         Concrete :class:`Field` classes should implement this method.
 
@@ -995,11 +999,7 @@
 
     # override Number
     def _validated(self, value):
-        if self.strict:
-            if isinstance(value, numbers.Number) and isinstance(
-                value, numbers.Integral
-            ):
-                return super()._validated(value)
+        if self.strict and not isinstance(value, numbers.Integral):
             raise self.make_error("invalid", input=value)
         return super()._validated(value)
 
@@ -1855,6 +1855,79 @@
     DESERIALIZATION_CLASS = ipaddress.IPv6Interface
 
 
+class Enum(Field):
+    """An Enum field (de)serializing enum members by symbol (name) or by value.
+
+    :param enum Enum: Enum class
+    :param boolean|Schema|Field by_value: Whether to (de)serialize by value or 
by name,
+        or Field class or instance to use to (de)serialize by value. Defaults 
to False.
+
+    If `by_value` is `False` (default), enum members are (de)serialized by 
symbol (name).
+    If it is `True`, they are (de)serialized by value using :class:`Field`.
+    If it is a field instance or class, they are (de)serialized by value using 
this field.
+
+    .. versionadded:: 3.18.0
+    """
+
+    default_error_messages = {
+        "unknown": "Must be one of: {choices}.",
+    }
+
+    def __init__(
+        self,
+        enum: type[EnumType],
+        *,
+        by_value: bool | Field | type = False,
+        **kwargs,
+    ):
+        super().__init__(**kwargs)
+        self.enum = enum
+        self.by_value = by_value
+
+        # Serialization by name
+        if by_value is False:
+            self.field: Field = String()
+            self.choices_text = ", ".join(
+                str(self.field._serialize(m, None, None)) for m in 
enum.__members__
+            )
+        # Serialization by value
+        else:
+            if by_value is True:
+                self.field = Field()
+            else:
+                try:
+                    self.field = resolve_field_instance(by_value)
+                except FieldInstanceResolutionError as error:
+                    raise ValueError(
+                        '"by_value" must be either a bool or a subclass or 
instance of '
+                        "marshmallow.base.FieldABC."
+                    ) from error
+            self.choices_text = ", ".join(
+                str(self.field._serialize(m.value, None, None)) for m in enum
+            )
+
+    def _serialize(self, value, attr, obj, **kwargs):
+        if value is None:
+            return None
+        if self.by_value:
+            val = value.value
+        else:
+            val = value.name
+        return self.field._serialize(val, attr, obj, **kwargs)
+
+    def _deserialize(self, value, attr, data, **kwargs):
+        val = self.field._deserialize(value, attr, data, **kwargs)
+        if self.by_value:
+            try:
+                return self.enum(val)
+            except ValueError as error:
+                raise self.make_error("unknown", choices=self.choices_text) 
from error
+        try:
+            return getattr(self.enum, val)
+        except AttributeError as error:
+            raise self.make_error("unknown", choices=self.choices_text) from 
error
+
+
 class Method(Field):
     """A field that takes the value returned by a `Schema` method.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/src/marshmallow.egg-info/PKG-INFO 
new/marshmallow-3.18.0/src/marshmallow.egg-info/PKG-INFO
--- old/marshmallow-3.17.1/src/marshmallow.egg-info/PKG-INFO    2022-08-22 
21:36:55.000000000 +0200
+++ new/marshmallow-3.18.0/src/marshmallow.egg-info/PKG-INFO    2022-09-15 
22:27:10.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: marshmallow
-Version: 3.17.1
+Version: 3.18.0
 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
@@ -173,12 +173,6 @@
     :target: 
https://tidelift.com/subscription/pkg/pypi-marshmallow?utm_source=pypi-marshmallow&utm_medium=readme
     :alt: Get supported marshmallow with Tidelift
 
-Security Contact Information
-============================
-
-To report a security vulnerability, please use the
-`Tidelift security contact <https://tidelift.com/security>`_.
-Tidelift will coordinate the fix and disclosure.
 
 Project Links
 =============
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/marshmallow-3.17.1/src/marshmallow.egg-info/requires.txt 
new/marshmallow-3.18.0/src/marshmallow.egg-info/requires.txt
--- old/marshmallow-3.17.1/src/marshmallow.egg-info/requires.txt        
2022-08-22 21:36:55.000000000 +0200
+++ new/marshmallow-3.18.0/src/marshmallow.egg-info/requires.txt        
2022-09-15 22:27:10.000000000 +0200
@@ -6,7 +6,7 @@
 simplejson
 mypy==0.971
 flake8==5.0.4
-flake8-bugbear==22.8.22
+flake8-bugbear==22.9.11
 pre-commit~=2.4
 tox
 
@@ -20,7 +20,7 @@
 [lint]
 mypy==0.971
 flake8==5.0.4
-flake8-bugbear==22.8.22
+flake8-bugbear==22.9.11
 pre-commit~=2.4
 
 [tests]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/tests/base.py 
new/marshmallow-3.18.0/tests/base.py
--- old/marshmallow-3.17.1/tests/base.py        2022-08-22 21:36:43.000000000 
+0200
+++ new/marshmallow-3.18.0/tests/base.py        2022-09-15 22:26:57.000000000 
+0200
@@ -1,6 +1,8 @@
 """Test utilities and fixtures."""
+import functools
 import datetime as dt
 import uuid
+from enum import Enum, IntEnum
 
 import simplejson
 
@@ -12,6 +14,25 @@
 central = pytz.timezone("US/Central")
 
 
+class GenderEnum(IntEnum):
+    male = 1
+    female = 2
+    non_binary = 3
+
+
+class HairColorEnum(Enum):
+    black = "black hair"
+    brown = "brown hair"
+    blond = "blond hair"
+    red = "red hair"
+
+
+class DateEnum(Enum):
+    date_1 = dt.date(2004, 2, 29)
+    date_2 = dt.date(2008, 2, 29)
+    date_3 = dt.date(2012, 2, 29)
+
+
 ALL_FIELDS = [
     fields.String,
     fields.Integer,
@@ -33,8 +54,12 @@
     fields.IPInterface,
     fields.IPv4Interface,
     fields.IPv6Interface,
+    functools.partial(fields.Enum, GenderEnum),
+    functools.partial(fields.Enum, HairColorEnum, by_value=fields.String),
+    functools.partial(fields.Enum, GenderEnum, by_value=fields.Integer),
 ]
 
+
 ##### Custom asserts #####
 
 
@@ -69,7 +94,8 @@
         birthdate=None,
         birthtime=None,
         balance=100,
-        sex="male",
+        sex=GenderEnum.male,
+        hair_color=HairColorEnum.black,
         employer=None,
         various_data=None,
     ):
@@ -86,8 +112,8 @@
         self.email = email
         self.balance = balance
         self.registered = registered
-        self.hair_colors = ["black", "brown", "blond", "redhead"]
-        self.sex_choices = ("male", "female")
+        self.hair_colors = list(HairColorEnum.__members__)
+        self.sex_choices = list(GenderEnum.__members__)
         self.finger_count = 10
         self.uid = uuid.uuid1()
         self.time_registered = time_registered or dt.time(1, 23, 45, 6789)
@@ -95,6 +121,7 @@
         self.birthtime = birthtime or dt.time(0, 1, 2, 3333)
         self.activation_date = dt.date(2013, 12, 11)
         self.sex = sex
+        self.hair_color = hair_color
         self.employer = employer
         self.relatives = []
         self.various_data = various_data or {
@@ -180,7 +207,7 @@
     birthtime = fields.Time()
     activation_date = fields.Date()
     since_created = fields.TimeDelta()
-    sex = fields.Str(validate=validate.OneOf(["male", "female"]))
+    sex = fields.Str(validate=validate.OneOf(list(GenderEnum.__members__)))
     various_data = fields.Dict()
 
     class Meta:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/tests/test_deserialization.py 
new/marshmallow-3.18.0/tests/test_deserialization.py
--- old/marshmallow-3.17.1/tests/test_deserialization.py        2022-08-22 
21:36:43.000000000 +0200
+++ new/marshmallow-3.18.0/tests/test_deserialization.py        2022-09-15 
22:26:57.000000000 +0200
@@ -10,7 +10,15 @@
 from marshmallow.exceptions import ValidationError
 from marshmallow.validate import Equal
 
-from tests.base import assert_date_equal, assert_time_equal, central, 
ALL_FIELDS
+from tests.base import (
+    assert_date_equal,
+    assert_time_equal,
+    central,
+    ALL_FIELDS,
+    GenderEnum,
+    HairColorEnum,
+    DateEnum,
+)
 
 
 class TestDeserializingNone:
@@ -1089,6 +1097,85 @@
 
         assert excinfo.value.args[0] == "Not a valid IPv6 interface."
 
+    def test_enum_field_by_symbol_deserialization(self):
+        field = fields.Enum(GenderEnum)
+        assert field.deserialize("male") == GenderEnum.male
+
+    def test_enum_field_by_symbol_invalid_value(self):
+        field = fields.Enum(GenderEnum)
+        with pytest.raises(
+            ValidationError, match="Must be one of: male, female, non_binary."
+        ):
+            field.deserialize("dummy")
+
+    def test_enum_field_by_symbol_not_string(self):
+        field = fields.Enum(GenderEnum)
+        with pytest.raises(ValidationError, match="Not a valid string."):
+            field.deserialize(12)
+
+    def test_enum_field_by_value_true_deserialization(self):
+        field = fields.Enum(HairColorEnum, by_value=True)
+        assert field.deserialize("black hair") == HairColorEnum.black
+        field = fields.Enum(GenderEnum, by_value=True)
+        assert field.deserialize(1) == GenderEnum.male
+
+    def test_enum_field_by_value_field_deserialization(self):
+        field = fields.Enum(HairColorEnum, by_value=fields.String)
+        assert field.deserialize("black hair") == HairColorEnum.black
+        field = fields.Enum(GenderEnum, by_value=fields.Integer)
+        assert field.deserialize(1) == GenderEnum.male
+        field = fields.Enum(DateEnum, by_value=fields.Date(format="%d/%m/%Y"))
+        assert field.deserialize("29/02/2004") == DateEnum.date_1
+
+    def test_enum_field_by_value_true_invalid_value(self):
+        field = fields.Enum(HairColorEnum, by_value=True)
+        with pytest.raises(
+            ValidationError,
+            match="Must be one of: black hair, brown hair, blond hair, red 
hair.",
+        ):
+            field.deserialize("dummy")
+        field = fields.Enum(GenderEnum, by_value=True)
+        with pytest.raises(ValidationError, match="Must be one of: 1, 2, 3."):
+            field.deserialize(12)
+
+    def test_enum_field_by_value_field_invalid_value(self):
+        field = fields.Enum(HairColorEnum, by_value=fields.String)
+        with pytest.raises(
+            ValidationError,
+            match="Must be one of: black hair, brown hair, blond hair, red 
hair.",
+        ):
+            field.deserialize("dummy")
+        field = fields.Enum(GenderEnum, by_value=fields.Integer)
+        with pytest.raises(ValidationError, match="Must be one of: 1, 2, 3."):
+            field.deserialize(12)
+        field = fields.Enum(DateEnum, by_value=fields.Date(format="%d/%m/%Y"))
+        with pytest.raises(
+            ValidationError, match="Must be one of: 29/02/2004, 29/02/2008, 
29/02/2012."
+        ):
+            field.deserialize("28/02/2004")
+
+    def test_enum_field_by_value_true_wrong_type(self):
+        field = fields.Enum(HairColorEnum, by_value=True)
+        with pytest.raises(
+            ValidationError,
+            match="Must be one of: black hair, brown hair, blond hair, red 
hair.",
+        ):
+            field.deserialize("dummy")
+        field = fields.Enum(GenderEnum, by_value=True)
+        with pytest.raises(ValidationError, match="Must be one of: 1, 2, 3."):
+            field.deserialize(12)
+
+    def test_enum_field_by_value_field_wrong_type(self):
+        field = fields.Enum(HairColorEnum, by_value=fields.String)
+        with pytest.raises(ValidationError, match="Not a valid string."):
+            field.deserialize(12)
+        field = fields.Enum(GenderEnum, by_value=fields.Integer)
+        with pytest.raises(ValidationError, match="Not a valid integer."):
+            field.deserialize("dummy")
+        field = fields.Enum(DateEnum, by_value=fields.Date(format="%d/%m/%Y"))
+        with pytest.raises(ValidationError, match="Not a valid date."):
+            field.deserialize("30/02/2004")
+
     def test_deserialization_function_must_be_callable(self):
         with pytest.raises(TypeError):
             fields.Function(lambda x: None, deserialize="notvalid")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/marshmallow-3.17.1/tests/test_serialization.py 
new/marshmallow-3.18.0/tests/test_serialization.py
--- old/marshmallow-3.17.1/tests/test_serialization.py  2022-08-22 
21:36:43.000000000 +0200
+++ new/marshmallow-3.18.0/tests/test_serialization.py  2022-09-15 
22:26:57.000000000 +0200
@@ -11,7 +11,7 @@
 
 from marshmallow import Schema, fields, missing as missing_
 
-from tests.base import User, ALL_FIELDS, central
+from tests.base import User, ALL_FIELDS, central, GenderEnum, HairColorEnum, 
DateEnum
 
 
 class DateTimeList:
@@ -255,6 +255,31 @@
             == ipv6interface_exploded_string
         )
 
+    def test_enum_field_by_symbol_serialization(self, user):
+        user.sex = GenderEnum.male
+        field = fields.Enum(GenderEnum)
+        assert field.serialize("sex", user) == "male"
+
+    def test_enum_field_by_value_true_serialization(self, user):
+        user.hair_color = HairColorEnum.black
+        field = fields.Enum(HairColorEnum, by_value=True)
+        assert field.serialize("hair_color", user) == "black hair"
+        user.sex = GenderEnum.male
+        field = fields.Enum(GenderEnum, by_value=True)
+        assert field.serialize("sex", user) == 1
+        user.some_date = DateEnum.date_1
+
+    def test_enum_field_by_value_field_serialization(self, user):
+        user.hair_color = HairColorEnum.black
+        field = fields.Enum(HairColorEnum, by_value=fields.String)
+        assert field.serialize("hair_color", user) == "black hair"
+        user.sex = GenderEnum.male
+        field = fields.Enum(GenderEnum, by_value=fields.Integer)
+        assert field.serialize("sex", user) == 1
+        user.some_date = DateEnum.date_1
+        field = fields.Enum(DateEnum, by_value=fields.Date(format="%d/%m/%Y"))
+        assert field.serialize("some_date", user) == "29/02/2004"
+
     def test_decimal_field(self, user):
         user.m1 = 12
         user.m2 = "12.355"

Reply via email to