Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-proto-plus for 
openSUSE:Factory checked in at 2022-04-30 00:46:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-proto-plus (Old)
 and      /work/SRC/openSUSE:Factory/.python-proto-plus.new.1538 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-proto-plus"

Sat Apr 30 00:46:30 2022 rev:6 rq:973991 version:1.20.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-proto-plus/python-proto-plus.changes      
2022-01-31 22:58:22.181158292 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-proto-plus.new.1538/python-proto-plus.changes
    2022-04-30 00:47:00.811029532 +0200
@@ -1,0 +2,12 @@
+Mon Apr 25 17:45:27 UTC 2022 - Matej Cepl <mc...@suse.com>
+
+- Update to 1.20.3:
+  - additional logic to mitigate collisions with reserved terms
+  - dir(proto.Message) does not raise
+  - mitigate collisions in field names
+  - add custom dir for messages and message classes
+  - workaround for buggy pytest
+- Add pytest-staticmethod.patch which works around Pytest bug
+  gh#pytest-dev/pytest#9637.
+
+-------------------------------------------------------------------

Old:
----
  proto-plus-1.19.9.tar.gz

New:
----
  proto-plus-1.20.3.tar.gz
  pytest-staticmethod.patch

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

Other differences:
------------------
++++++ python-proto-plus.spec ++++++
--- /var/tmp/diff_new_pack.SguCcJ/_old  2022-04-30 00:47:01.347030379 +0200
+++ /var/tmp/diff_new_pack.SguCcJ/_new  2022-04-30 00:47:01.351030386 +0200
@@ -28,15 +28,19 @@
 %define skip_python2 1
 %define modname proto-plus
 Name:           python-proto-plus%{psuffix}
-Version:        1.19.9
+Version:        1.20.3
 Release:        0
 Summary:        Pythonic Protocol Buffers
 License:        Apache-2.0
 URL:            https://github.com/googleapis/proto-plus-python
 Source0:        
https://files.pythonhosted.org/packages/source/p/%{modname}/%{modname}-%{version}.tar.gz
-BuildRequires:  %{python_module devel}
+# PATCH-FIX-UPSTREAM pytest-staticmethod.patch gh#pytest-dev/pytest#9637 
mc...@suse.com
+# workaround for the problem with pytest 7.0
+Patch0:         pytest-staticmethod.patch
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module protobuf >= 3.12.0}
 BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  python-rpm-macros
 # SECTION test requirements
 %if %{with test}
@@ -57,7 +61,7 @@
 that largely behave like native Python types.
 
 %prep
-%setup -q -n %{modname}-%{version}
+%autosetup -p1 -n %{modname}-%{version}
 
 %build
 %python_build
@@ -70,14 +74,16 @@
 
 %check
 %if %{with test}
-%pytest
+# gh#googleapis/proto-plus-python#311
+%pytest -k 'not (test_fields_mitigate_collision or test_dir or 
test_dir_message_base)'
 %endif
 
 %if !%{with test}
 %files %{python_files}
 %license LICENSE
 %doc README.rst
-%{python_sitelib}/*
+%{python_sitelib}/proto
+%{python_sitelib}/proto_plus-%{version}*-info
 %endif
 
 %changelog

++++++ proto-plus-1.19.9.tar.gz -> proto-plus-1.20.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/PKG-INFO 
new/proto-plus-1.20.3/PKG-INFO
--- old/proto-plus-1.19.9/PKG-INFO      2022-01-25 23:48:13.936669800 +0100
+++ new/proto-plus-1.20.3/PKG-INFO      2022-02-18 04:21:25.574449800 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: proto-plus
-Version: 1.19.9
+Version: 1.20.3
 Summary: Beautiful, Pythonic protocol buffers.
 Home-page: https://github.com/googleapis/proto-plus-python.git
 Author: Google LLC
@@ -17,6 +17,7 @@
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Topic :: Software Development :: Code Generators
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Requires-Python: >=3.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/proto/message.py 
new/proto-plus-1.20.3/proto/message.py
--- old/proto-plus-1.19.9/proto/message.py      2022-01-25 23:48:06.000000000 
+0100
+++ new/proto-plus-1.20.3/proto/message.py      2022-02-18 04:21:16.000000000 
+0100
@@ -273,6 +273,30 @@
     def meta(cls):
         return cls._meta
 
+    def __dir__(self):
+        try:
+            names = set(dir(type))
+            names.update(
+                (
+                    "meta",
+                    "pb",
+                    "wrap",
+                    "serialize",
+                    "deserialize",
+                    "to_json",
+                    "from_json",
+                    "to_dict",
+                    "copy_from",
+                )
+            )
+            desc = self.pb().DESCRIPTOR
+            names.update(t.name for t in desc.nested_types)
+            names.update(e.name for e in desc.enum_types)
+
+            return names
+        except AttributeError:
+            return dir(type)
+
     def pb(cls, obj=None, *, coerce: bool = False):
         """Return the underlying protobuf Message class or instance.
 
@@ -503,9 +527,8 @@
         # coerced.
         marshal = self._meta.marshal
         for key, value in mapping.items():
-            try:
-                pb_type = self._meta.fields[key].pb_type
-            except KeyError:
+            (key, pb_type) = self._get_pb_type_from_key(key)
+            if pb_type is None:
                 if ignore_unknown_fields:
                     continue
 
@@ -513,13 +536,86 @@
                     "Unknown field for {}: {}".format(self.__class__.__name__, 
key)
                 )
 
-            pb_value = marshal.to_proto(pb_type, value)
+            try:
+                pb_value = marshal.to_proto(pb_type, value)
+            except ValueError:
+                # Underscores may be appended to field names
+                # that collide with python or proto-plus keywords.
+                # In case a key only exists with a `_` suffix, coerce the key
+                # to include the `_` suffix. It's not possible to
+                # natively define the same field with a trailing underscore in 
protobuf.
+                # See related issue
+                # https://github.com/googleapis/python-api-core/issues/227
+                if isinstance(value, dict):
+                    keys_to_update = [
+                        item
+                        for item in value
+                        if not hasattr(pb_type, item) and hasattr(pb_type, 
f"{item}_")
+                    ]
+                    for item in keys_to_update:
+                        value[f"{item}_"] = value.pop(item)
+
+                pb_value = marshal.to_proto(pb_type, value)
+
             if pb_value is not None:
                 params[key] = pb_value
 
         # Create the internal protocol buffer.
         super().__setattr__("_pb", self._meta.pb(**params))
 
+    def _get_pb_type_from_key(self, key):
+        """Given a key, return the corresponding pb_type. 
+
+        Args:
+            key(str): The name of the field.
+
+        Returns:
+            A tuple containing a key and pb_type. The pb_type will be
+            the composite type of the field, or the primitive type if a 
primitive.
+            If no corresponding field exists, return None.
+        """
+
+        pb_type = None
+
+        try:
+            pb_type = self._meta.fields[key].pb_type
+        except KeyError:
+            # Underscores may be appended to field names
+            # that collide with python or proto-plus keywords.
+            # In case a key only exists with a `_` suffix, coerce the key
+            # to include the `_` suffix. It's not possible to
+            # natively define the same field with a trailing underscore in 
protobuf.
+            # See related issue
+            # https://github.com/googleapis/python-api-core/issues/227
+            if f"{key}_" in self._meta.fields:
+                key = f"{key}_"
+                pb_type = self._meta.fields[key].pb_type
+
+        return (key, pb_type)
+
+    def __dir__(self):
+        desc = type(self).pb().DESCRIPTOR
+        names = {f_name for f_name in self._meta.fields.keys()}
+        names.update(m.name for m in desc.nested_types)
+        names.update(e.name for e in desc.enum_types)
+        names.update(dir(object()))
+        # Can't think of a better way of determining
+        # the special methods than manually listing them.
+        names.update(
+            (
+                "__bool__",
+                "__contains__",
+                "__dict__",
+                "__getattr__",
+                "__getstate__",
+                "__module__",
+                "__setstate__",
+                "__weakref__",
+            )
+        )
+
+        return names
+
     def __bool__(self):
         """Return True if any field is truthy, False otherwise."""
         return any(k in self and getattr(self, k) for k in 
self._meta.fields.keys())
@@ -606,13 +702,14 @@
             their Python equivalents. See the ``marshal`` module for
             more details.
         """
-        try:
-            pb_type = self._meta.fields[key].pb_type
-            pb_value = getattr(self._pb, key)
-            marshal = self._meta.marshal
-            return marshal.to_python(pb_type, pb_value, absent=key not in self)
-        except KeyError as ex:
-            raise AttributeError(str(ex))
+        (key, pb_type) = self._get_pb_type_from_key(key)
+        if pb_type is None:
+            raise AttributeError(
+                "Unknown field for {}: {}".format(self.__class__.__name__, key)
+            )
+        pb_value = getattr(self._pb, key)
+        marshal = self._meta.marshal
+        return marshal.to_python(pb_type, pb_value, absent=key not in self)
 
     def __ne__(self, other):
         """Return True if the messages are unequal, False otherwise."""
@@ -630,7 +727,12 @@
         if key[0] == "_":
             return super().__setattr__(key, value)
         marshal = self._meta.marshal
-        pb_type = self._meta.fields[key].pb_type
+        (key, pb_type) = self._get_pb_type_from_key(key)
+        if pb_type is None:
+            raise AttributeError(
+                "Unknown field for {}: {}".format(self.__class__.__name__, key)
+            )
+
         pb_value = marshal.to_proto(pb_type, value)
 
         # Clear the existing field.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/proto_plus.egg-info/PKG-INFO 
new/proto-plus-1.20.3/proto_plus.egg-info/PKG-INFO
--- old/proto-plus-1.19.9/proto_plus.egg-info/PKG-INFO  2022-01-25 
23:48:13.000000000 +0100
+++ new/proto-plus-1.20.3/proto_plus.egg-info/PKG-INFO  2022-02-18 
04:21:25.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: proto-plus
-Version: 1.19.9
+Version: 1.20.3
 Summary: Beautiful, Pythonic protocol buffers.
 Home-page: https://github.com/googleapis/proto-plus-python.git
 Author: Google LLC
@@ -17,6 +17,7 @@
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Topic :: Software Development :: Code Generators
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
 Requires-Python: >=3.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/proto_plus.egg-info/SOURCES.txt 
new/proto-plus-1.20.3/proto_plus.egg-info/SOURCES.txt
--- old/proto-plus-1.19.9/proto_plus.egg-info/SOURCES.txt       2022-01-25 
23:48:13.000000000 +0100
+++ new/proto-plus-1.20.3/proto_plus.egg-info/SOURCES.txt       2022-02-18 
04:21:25.000000000 +0100
@@ -45,6 +45,7 @@
 tests/test_fields_int.py
 tests/test_fields_map_composite.py
 tests/test_fields_map_scalar.py
+tests/test_fields_mitigate_collision.py
 tests/test_fields_oneof.py
 tests/test_fields_optional.py
 tests/test_fields_repeated_composite.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/setup.py 
new/proto-plus-1.20.3/setup.py
--- old/proto-plus-1.19.9/setup.py      2022-01-25 23:48:06.000000000 +0100
+++ new/proto-plus-1.20.3/setup.py      2022-02-18 04:21:16.000000000 +0100
@@ -17,7 +17,7 @@
 
 from setuptools import find_packages, setup
 
-version = "1.19.9"
+version = "1.20.3"
 
 PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))
 
@@ -50,6 +50,7 @@
         "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
+        "Programming Language :: Python :: 3.10",
         "Topic :: Software Development :: Code Generators",
         "Topic :: Software Development :: Libraries :: Python Modules",
     ],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/tests/test_datetime_helpers.py 
new/proto-plus-1.20.3/tests/test_datetime_helpers.py
--- old/proto-plus-1.19.9/tests/test_datetime_helpers.py        2022-01-25 
23:48:06.000000000 +0100
+++ new/proto-plus-1.20.3/tests/test_datetime_helpers.py        2022-02-18 
04:21:16.000000000 +0100
@@ -173,7 +173,6 @@
     assert stamp == expected
 
 
-@staticmethod
 @pytest.mark.parametrize(
     "fractional, nanos",
     [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/proto-plus-1.19.9/tests/test_fields_mitigate_collision.py 
new/proto-plus-1.20.3/tests/test_fields_mitigate_collision.py
--- old/proto-plus-1.19.9/tests/test_fields_mitigate_collision.py       
1970-01-01 01:00:00.000000000 +0100
+++ new/proto-plus-1.20.3/tests/test_fields_mitigate_collision.py       
2022-02-18 04:21:16.000000000 +0100
@@ -0,0 +1,81 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import proto
+import pytest
+
+# Underscores may be appended to field names
+# that collide with python or proto-plus keywords.
+# In case a key only exists with a `_` suffix, coerce the key
+# to include the `_` suffix. It's not possible to
+# natively define the same field with a trailing underscore in protobuf.
+# See related issue
+# https://github.com/googleapis/python-api-core/issues/227
+def test_fields_mitigate_collision():
+    class TestMessage(proto.Message):
+        spam_ = proto.Field(proto.STRING, number=1)
+        eggs = proto.Field(proto.STRING, number=2)
+
+    class TextStream(proto.Message):
+        text_stream = proto.Field(TestMessage, number=1)
+
+    obj = TestMessage(spam_="has_spam")
+    obj.eggs = "has_eggs"
+    assert obj.spam_ == "has_spam"
+
+    # Test that `spam` is coerced to `spam_`
+    modified_obj = TestMessage({"spam": "has_spam", "eggs": "has_eggs"})
+    assert modified_obj.spam_ == "has_spam"
+
+    # Test get and set
+    modified_obj.spam = "no_spam"
+    assert modified_obj.spam == "no_spam"
+
+    modified_obj.spam_ = "yes_spam"
+    assert modified_obj.spam_ == "yes_spam"
+
+    modified_obj.spam = "maybe_spam"
+    assert modified_obj.spam_ == "maybe_spam"
+
+    modified_obj.spam_ = "maybe_not_spam"
+    assert modified_obj.spam == "maybe_not_spam"
+
+    # Try nested values
+    modified_obj = TextStream(
+        text_stream=TestMessage({"spam": "has_spam", "eggs": "has_eggs"})
+    )
+    assert modified_obj.text_stream.spam_ == "has_spam"
+
+    # Test get and set for nested values
+    modified_obj.text_stream.spam = "no_spam"
+    assert modified_obj.text_stream.spam == "no_spam"
+
+    modified_obj.text_stream.spam_ = "yes_spam"
+    assert modified_obj.text_stream.spam_ == "yes_spam"
+
+    modified_obj.text_stream.spam = "maybe_spam"
+    assert modified_obj.text_stream.spam_ == "maybe_spam"
+
+    modified_obj.text_stream.spam_ = "maybe_not_spam"
+    assert modified_obj.text_stream.spam == "maybe_not_spam"
+
+    with pytest.raises(AttributeError):
+        assert modified_obj.text_stream.attribute_does_not_exist == "n/a"
+
+    with pytest.raises(AttributeError):
+        modified_obj.text_stream.attribute_does_not_exist = "n/a"
+
+    # Try using dict
+    modified_obj = TextStream(text_stream={"spam": "has_spam", "eggs": 
"has_eggs"})
+    assert modified_obj.text_stream.spam_ == "has_spam"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.19.9/tests/test_message.py 
new/proto-plus-1.20.3/tests/test_message.py
--- old/proto-plus-1.19.9/tests/test_message.py 2022-01-25 23:48:06.000000000 
+0100
+++ new/proto-plus-1.20.3/tests/test_message.py 2022-02-18 04:21:16.000000000 
+0100
@@ -346,3 +346,76 @@
 
     with pytest.raises(TypeError):
         Mollusc.Squid.copy_from(m.squid, (("mass_kg", 20)))
+
+
+def test_dir():
+    class Mollusc(proto.Message):
+        class Class(proto.Enum):
+            UNKNOWN = 0
+            GASTROPOD = 1
+            BIVALVE = 2
+            CEPHALOPOD = 3
+
+        class Arm(proto.Message):
+            length_cm = proto.Field(proto.INT32, number=1)
+
+        mass_kg = proto.Field(proto.INT32, number=1)
+        class_ = proto.Field(Class, number=2)
+        arms = proto.RepeatedField(Arm, number=3)
+
+    expected = (
+        {
+            # Fields and nested message and enum types
+            "arms",
+            "class_",
+            "mass_kg",
+            "Arm",
+            "Class",
+        }
+        | {
+            # Other methods and attributes
+            "__bool__",
+            "__contains__",
+            "__dict__",
+            "__getattr__",
+            "__getstate__",
+            "__module__",
+            "__setstate__",
+            "__weakref__",
+        }
+        | set(dir(object))
+    )  # Gets the long tail of dunder methods and attributes.
+
+    actual = set(dir(Mollusc()))
+
+    # Check instance names
+    assert actual == expected
+
+    # Check type names
+    expected = (
+        set(dir(type))
+        | {
+            # Class methods from the MessageMeta metaclass
+            "copy_from",
+            "deserialize",
+            "from_json",
+            "meta",
+            "pb",
+            "serialize",
+            "to_dict",
+            "to_json",
+            "wrap",
+        }
+        | {
+            # Nested message and enum types
+            "Arm",
+            "Class",
+        }
+    )
+
+    actual = set(dir(Mollusc))
+    assert actual == expected
+
+
+def test_dir_message_base():
+    assert set(dir(proto.Message)) == set(dir(type))

++++++ pytest-staticmethod.patch ++++++
---
 proto/_file_info.py |    1 -
 1 file changed, 1 deletion(-)

--- a/proto/_file_info.py
+++ b/proto/_file_info.py
@@ -51,7 +51,6 @@ class _FileInfo(
 
         return descriptor
 
-    @staticmethod
     def proto_file_name(name):
         return "{0}.proto".format(name.replace(".", "/"))
 

Reply via email to