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 2021-03-20 21:26:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-proto-plus (Old)
 and      /work/SRC/openSUSE:Factory/.python-proto-plus.new.2401 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-proto-plus"

Sat Mar 20 21:26:22 2021 rev:2 rq:880254 version:1.18.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-proto-plus/python-proto-plus.changes      
2021-01-06 19:57:29.521216993 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-proto-plus.new.2401/python-proto-plus.changes
    2021-03-20 21:26:46.745233097 +0100
@@ -1,0 +2,37 @@
+Sat Mar 20 12:24:03 UTC 2021 - Matthias Fehring <[email protected]>
+
+- update to 1.18.1
+  * Add arm64 support for PY3.6 (gh#googleapis/proto-plus-python#219)
+- from 1.18.0
+  * add copy_from method for field assignment
+    (gh#googleapis/proto-plus-python#512) 
+
+-------------------------------------------------------------------
+Mon Mar 15 17:22:01 UTC 2021 - Matthias Fehring <[email protected]>
+
+- update to 1.17.0
+  * add preserving_proto_field_name to to_json 
(gh#googleapis/proto-plus-python#213)
+- from 1.16.0
+  * add preserving_proto_field_name passthrough in MessageMeta.to_dict
+    (gh#googleapis/proto-plus-python#211)
+- from 1.15.0
+  * allow_alias fro enums (gh#googleapis/proto-plus-python#207)
+- from 1.14.3
+  * adding enums to a repeated field does not raise a TypeError
+    (gh#googleapis/proto-plus-python#202)
+- from 1.14.2
+  * use the correct environment for uploading to pypi
+- from 1.14.1
+  * install the wheel dependency
+- from 1.14.0
+  * Features
+    + Pypi publish ghub actions (gh#googleapis/proto-plus-python#189)
+  * Bug Fixes
+    * proper setitem and insert for RepeatedComposite
+      (gh#googleapis/proto-plus-python#178)
+    * proper native marshal for repeated enumeration fields
+      (gh#googleapis/proto-plus-python#180)
+- from 1.13.1
+  * update docstring to match type hint (gh#googleapis/proto-plus-python#172)
+
+-------------------------------------------------------------------

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

New:
----
  proto-plus-1.18.1.tar.gz

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

Other differences:
------------------
++++++ python-proto-plus.spec ++++++
--- /var/tmp/diff_new_pack.vGEh1N/_old  2021-03-20 21:26:47.237233673 +0100
+++ /var/tmp/diff_new_pack.vGEh1N/_new  2021-03-20 21:26:47.237233673 +0100
@@ -20,7 +20,7 @@
 %define skip_python2 1
 %define modname proto-plus
 Name:           python-proto-plus
-Version:        1.13.0
+Version:        1.18.1
 Release:        0
 Summary:        Pythonic Protocol Buffers
 License:        Apache-2.0

++++++ proto-plus-1.13.0.tar.gz -> proto-plus-1.18.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/PKG-INFO 
new/proto-plus-1.18.1/PKG-INFO
--- old/proto-plus-1.13.0/PKG-INFO      2020-12-07 19:07:38.340301500 +0100
+++ new/proto-plus-1.18.1/PKG-INFO      2021-03-19 23:17:52.886574700 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: proto-plus
-Version: 1.13.0
+Version: 1.18.1
 Summary: Beautiful, Pythonic protocol buffers.
 Home-page: https://github.com/googleapis/proto-plus-python.git
 Author: Google LLC
@@ -9,7 +9,7 @@
 Description: Proto Plus for Python
         =====================
         
-        |pypi| |release level| |ci| |docs| |codecov|
+        |pypi| |release level| |docs| |codecov|
         
             Beautiful, Pythonic protocol buffers.
         
@@ -34,8 +34,6 @@
           :target: https://cloud.google.com/terms/launch-stages
         .. |docs| image:: 
https://readthedocs.org/projects/proto-plus-python/badge/?version=latest
           :target: https://proto-plus-python.readthedocs.io/en/latest/
-        .. |ci| image:: 
https://circleci.com/gh/googleapis/proto-plus-python.svg?style=shield
-          :target: https://circleci.com/gh/googleapis/proto-plus-python
         .. |codecov| image:: 
https://codecov.io/gh/googleapis/proto-plus-python/graph/badge.svg
           :target: https://codecov.io/gh/googleapis/proto-plus-python
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/README.rst 
new/proto-plus-1.18.1/README.rst
--- old/proto-plus-1.13.0/README.rst    2020-12-07 19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/README.rst    2021-03-19 23:17:44.000000000 +0100
@@ -1,7 +1,7 @@
 Proto Plus for Python
 =====================
 
-|pypi| |release level| |ci| |docs| |codecov|
+|pypi| |release level| |docs| |codecov|
 
     Beautiful, Pythonic protocol buffers.
 
@@ -26,7 +26,5 @@
   :target: https://cloud.google.com/terms/launch-stages
 .. |docs| image:: 
https://readthedocs.org/projects/proto-plus-python/badge/?version=latest
   :target: https://proto-plus-python.readthedocs.io/en/latest/
-.. |ci| image:: 
https://circleci.com/gh/googleapis/proto-plus-python.svg?style=shield
-  :target: https://circleci.com/gh/googleapis/proto-plus-python
 .. |codecov| image:: 
https://codecov.io/gh/googleapis/proto-plus-python/graph/badge.svg
   :target: https://codecov.io/gh/googleapis/proto-plus-python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/proto/enums.py 
new/proto-plus-1.18.1/proto/enums.py
--- old/proto-plus-1.13.0/proto/enums.py        2020-12-07 19:07:31.000000000 
+0100
+++ new/proto-plus-1.18.1/proto/enums.py        2021-03-19 23:17:44.000000000 
+0100
@@ -47,6 +47,21 @@
         filename = _file_info._FileInfo.proto_file_name(
             attrs.get("__module__", name.lower())
         )
+
+        # Retrieve any enum options.
+        # We expect something that looks like an EnumOptions message,
+        # either an actual instance or a dict-like representation.
+        pb_options = "_pb_options"
+        opts = attrs.pop(pb_options, {})
+        # This is the only portable way to remove the _pb_options name
+        # from the enum attrs.
+        # In 3.7 onwards, we can define an _ignore_ attribute and do some
+        # mucking around with that.
+        if pb_options in attrs._member_names:
+            idx = attrs._member_names.index(pb_options)
+            attrs._member_names.pop(idx)
+
+        # Make the descriptor.
         enum_desc = descriptor_pb2.EnumDescriptorProto(
             name=name,
             # Note: the superclass ctor removes the variants, so get them now.
@@ -60,6 +75,7 @@
                 ),
                 key=lambda v: v.number,
             ),
+            options=opts,
         )
 
         file_info = _file_info._FileInfo.maybe_add_descriptor(filename, 
package)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/proto-plus-1.13.0/proto/marshal/collections/repeated.py 
new/proto-plus-1.18.1/proto/marshal/collections/repeated.py
--- old/proto-plus-1.13.0/proto/marshal/collections/repeated.py 2020-12-07 
19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/proto/marshal/collections/repeated.py 2021-03-19 
23:17:44.000000000 +0100
@@ -25,7 +25,7 @@
     modify the underlying field container directly.
     """
 
-    def __init__(self, sequence, *, marshal):
+    def __init__(self, sequence, *, marshal, proto_type=None):
         """Initialize a wrapper around a protobuf repeated field.
 
         Args:
@@ -35,6 +35,7 @@
         """
         self._pb = sequence
         self._marshal = marshal
+        self._proto_type = proto_type
 
     def __copy__(self):
         """Copy this object and return the copy."""
@@ -61,7 +62,7 @@
         return not self == other
 
     def __repr__(self):
-        return repr(self.pb)
+        return repr([*self])
 
     def __setitem__(self, key, value):
         self.pb[key] = value
@@ -89,6 +90,11 @@
     @cached_property
     def _pb_type(self):
         """Return the protocol buffer type for this sequence."""
+        # Provide the marshal-given proto_type, if any.
+        # Used for RepeatedComposite of Enum.
+        if self._proto_type is not None:
+            return self._proto_type
+
         # There is no public-interface mechanism to determine the type
         # of what should go in the list (and the C implementation seems to
         # have no exposed mechanism at all).
@@ -113,22 +119,60 @@
         return self._marshal.to_python(self._pb_type, self.pb[key])
 
     def __setitem__(self, key, value):
-        pb_value = self._marshal.to_proto(self._pb_type, value, strict=True)
+        # The underlying protocol buffer does not define __setitem__, so we
+        # have to implement all the operations on our own.
 
-        # Protocol buffers does not define a useful __setitem__, so we
-        # have to pop everything after this point off the list and reload it.
-        after = [pb_value]
-        while self.pb[key:]:
-            after.append(self.pb.pop(key))
-        self.pb.extend(after)
+        # If ``key`` is an integer, as in list[index] = value:
+        if isinstance(key, int):
+            if -len(self) <= key < len(self):
+                self.pop(key)  # Delete the old item.
+                self.insert(key, value)  # Insert the new item in its place.
+            else:
+                raise IndexError("list assignment index out of range")
+
+        # If ``key`` is a slice object, as in list[start:stop:step] = [values]:
+        elif isinstance(key, slice):
+            start, stop, step = key.indices(len(self))
+
+            if not isinstance(value, collections.abc.Iterable):
+                raise TypeError("can only assign an iterable")
+
+            if step == 1:  # Is not an extended slice.
+                # Assign all the new values to the sliced part, replacing the
+                # old values, if any, and unconditionally inserting those
+                # values whose indices already exceed the slice length.
+                for index, item in enumerate(value):
+                    if start + index < stop:
+                        self.pop(start + index)
+                    self.insert(start + index, item)
+
+                # If there are less values than the length of the slice, remove
+                # the remaining elements so that the slice adapts to the
+                # newly provided values.
+                for _ in range(stop - start - len(value)):
+                    self.pop(start + len(value))
+
+            else:  # Is an extended slice.
+                indices = range(start, stop, step)
+
+                if len(value) != len(indices):  # XXX: Use PEP 572 on 3.8+
+                    raise ValueError(
+                        f"attempt to assign sequence of size "
+                        f"{len(value)} to extended slice of size "
+                        f"{len(indices)}"
+                    )
+
+                # Assign each value to its index, calling this function again
+                # with individual integer indexes that get processed above.
+                for index, item in zip(indices, value):
+                    self[index] = item
+
+        else:
+            raise TypeError(
+                f"list indices must be integers or slices, not 
{type(key).__name__}"
+            )
 
     def insert(self, index: int, value):
         """Insert ``value`` in the sequence before ``index``."""
-        pb_value = self._marshal.to_proto(self._pb_type, value, strict=True)
-
-        # Protocol buffers does not define a useful insert, so we have
-        # to pop everything after this point off the list and reload it.
-        after = [pb_value]
-        while self.pb[index:]:
-            after.append(self.pb.pop(index))
-        self.pb.extend(after)
+        pb_value = self._marshal.to_proto(self._pb_type, value)
+        self.pb.insert(index, pb_value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/proto/marshal/marshal.py 
new/proto-plus-1.18.1/proto/marshal/marshal.py
--- old/proto-plus-1.13.0/proto/marshal/marshal.py      2020-12-07 
19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/proto/marshal/marshal.py      2021-03-19 
23:17:44.000000000 +0100
@@ -157,7 +157,10 @@
         if value_type in compat.repeated_composite_types:
             return RepeatedComposite(value, marshal=self)
         if value_type in compat.repeated_scalar_types:
-            return Repeated(value, marshal=self)
+            if isinstance(proto_type, type):
+                return RepeatedComposite(value, marshal=self, 
proto_type=proto_type)
+            else:
+                return Repeated(value, marshal=self)
 
         # Same thing for maps of messages.
         if value_type in compat.map_composite_types:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/proto/message.py 
new/proto-plus-1.18.1/proto/message.py
--- old/proto-plus-1.13.0/proto/message.py      2020-12-07 19:07:31.000000000 
+0100
+++ new/proto-plus-1.18.1/proto/message.py      2021-03-19 23:17:44.000000000 
+0100
@@ -300,7 +300,7 @@
         """
         # Optimized fast path.
         instance = cls.__new__(cls)
-        instance.__dict__["_pb"] = pb
+        super(cls, instance).__setattr__("_pb", pb)
         return instance
 
     def serialize(cls, instance) -> bytes:
@@ -332,7 +332,8 @@
         instance,
         *,
         use_integers_for_enums=True,
-        including_default_value_fields=True
+        including_default_value_fields=True,
+        preserving_proto_field_name=False,
     ) -> str:
         """Given a message instance, serialize it to json
 
@@ -342,6 +343,9 @@
             use_integers_for_enums (Optional(bool)): An option that determines 
whether enum
                 values should be represented by strings (False) or integers 
(True).
                 Default is True.
+            preserving_proto_field_name (Optional(bool)): An option that
+                determines whether field name representations preserve
+                proto case (snake_case) or use lowerCamelCase. Default is 
False.
 
         Returns:
             str: The json string representation of the protocol buffer.
@@ -350,6 +354,7 @@
             cls.pb(instance),
             use_integers_for_enums=use_integers_for_enums,
             including_default_value_fields=including_default_value_fields,
+            preserving_proto_field_name=preserving_proto_field_name,
         )
 
     def from_json(cls, payload, *, ignore_unknown_fields=False) -> "Message":
@@ -369,7 +374,9 @@
         Parse(payload, instance._pb, 
ignore_unknown_fields=ignore_unknown_fields)
         return instance
 
-    def to_dict(cls, instance, *, use_integers_for_enums=True) -> "Message":
+    def to_dict(
+        cls, instance, *, use_integers_for_enums=True, 
preserving_proto_field_name=True
+    ) -> "Message":
         """Given a message instance, return its representation as a python 
dict.
 
         Args:
@@ -378,6 +385,9 @@
             use_integers_for_enums (Optional(bool)): An option that determines 
whether enum
                 values should be represented by strings (False) or integers 
(True).
                 Default is True.
+            preserving_proto_field_name (Optional(bool)): An option that
+                determines whether field name representations preserve
+                proto case (snake_case) or use lowerCamelCase. Default is True.
 
         Returns:
             dict: A representation of the protocol buffer using pythonic data 
structures.
@@ -387,10 +397,40 @@
         return MessageToDict(
             cls.pb(instance),
             including_default_value_fields=True,
-            preserving_proto_field_name=True,
+            preserving_proto_field_name=preserving_proto_field_name,
             use_integers_for_enums=use_integers_for_enums,
         )
 
+    def copy_from(cls, instance, other):
+        """Equivalent for protobuf.Message.CopyFrom
+
+        Args:
+            instance: An instance of this message type
+            other: (Union[dict, ~.Message):
+                A dictionary or message to reinitialize the values for this 
message.
+        """
+        if isinstance(other, cls):
+            # Just want the underlying proto.
+            other = Message.pb(other)
+        elif isinstance(other, cls.pb()):
+            # Don't need to do anything.
+            pass
+        elif isinstance(other, collections.abc.Mapping):
+            # Coerce into a proto
+            other = cls._meta.pb(**other)
+        else:
+            raise TypeError(
+                "invalid argument type to copy to {}: {}".format(
+                    cls.__name__, other.__class__.__name__
+                )
+            )
+
+        # Note: we can't just run self.__init__ because this may be a message 
field
+        # for a higher order proto; the memory layout for protos is NOT LIKE 
the
+        # python memory model. We cannot rely on just setting things by 
reference.
+        # Non-trivial complexity is (partially) hidden by the protobuf runtime.
+        cls.pb(instance).CopyFrom(other)
+
 
 class Message(metaclass=MessageMeta):
     """The abstract base class for a message.
@@ -414,7 +454,7 @@
         if mapping is None:
             if not kwargs:
                 # Special fast path for empty construction.
-                self.__dict__["_pb"] = self._meta.pb()
+                super().__setattr__("_pb", self._meta.pb())
                 return
 
             mapping = kwargs
@@ -426,11 +466,11 @@
             #
             # The `wrap` method on the metaclass is the public API for taking
             # ownership of the passed in protobuf objet.
-            mapping = copy.copy(mapping)
+            mapping = copy.deepcopy(mapping)
             if kwargs:
                 mapping.MergeFrom(self._meta.pb(**kwargs))
 
-            self.__dict__["_pb"] = mapping
+            super().__setattr__("_pb", mapping)
             return
         elif isinstance(mapping, type(self)):
             # Just use the above logic on mapping's underlying pb.
@@ -468,7 +508,7 @@
                 params[key] = pb_value
 
         # Create the internal protocol buffer.
-        self.__dict__["_pb"] = self._meta.pb(**params)
+        super().__setattr__("_pb", self._meta.pb(**params))
 
     def __bool__(self):
         """Return True if any field is truthy, False otherwise."""
@@ -615,7 +655,7 @@
         package: str,
         full_name: str,
         marshal: Marshal,
-        options: descriptor_pb2.MessageOptions
+        options: descriptor_pb2.MessageOptions,
     ) -> None:
         self.package = package
         self.full_name = full_name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/proto/modules.py 
new/proto-plus-1.18.1/proto/modules.py
--- old/proto-plus-1.13.0/proto/modules.py      2020-12-07 19:07:31.000000000 
+0100
+++ new/proto-plus-1.18.1/proto/modules.py      2021-03-19 23:17:44.000000000 
+0100
@@ -33,7 +33,7 @@
         package (str): The proto package name.
         marshal (str): The name of the marshal to use. It is recommended
             to use one marshal per Python library (e.g. package on PyPI).
-        manifest (Tuple[str]): A tuple of classes to be created. Setting
+        manifest (Set[str]): A set of messages and enums to be created. Setting
             this adds a slight efficiency in piecing together proto
             descriptors under the hood.
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/proto_plus.egg-info/PKG-INFO 
new/proto-plus-1.18.1/proto_plus.egg-info/PKG-INFO
--- old/proto-plus-1.13.0/proto_plus.egg-info/PKG-INFO  2020-12-07 
19:07:38.000000000 +0100
+++ new/proto-plus-1.18.1/proto_plus.egg-info/PKG-INFO  2021-03-19 
23:17:52.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: proto-plus
-Version: 1.13.0
+Version: 1.18.1
 Summary: Beautiful, Pythonic protocol buffers.
 Home-page: https://github.com/googleapis/proto-plus-python.git
 Author: Google LLC
@@ -9,7 +9,7 @@
 Description: Proto Plus for Python
         =====================
         
-        |pypi| |release level| |ci| |docs| |codecov|
+        |pypi| |release level| |docs| |codecov|
         
             Beautiful, Pythonic protocol buffers.
         
@@ -34,8 +34,6 @@
           :target: https://cloud.google.com/terms/launch-stages
         .. |docs| image:: 
https://readthedocs.org/projects/proto-plus-python/badge/?version=latest
           :target: https://proto-plus-python.readthedocs.io/en/latest/
-        .. |ci| image:: 
https://circleci.com/gh/googleapis/proto-plus-python.svg?style=shield
-          :target: https://circleci.com/gh/googleapis/proto-plus-python
         .. |codecov| image:: 
https://codecov.io/gh/googleapis/proto-plus-python/graph/badge.svg
           :target: https://codecov.io/gh/googleapis/proto-plus-python
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/proto_plus.egg-info/SOURCES.txt 
new/proto-plus-1.18.1/proto_plus.egg-info/SOURCES.txt
--- old/proto-plus-1.13.0/proto_plus.egg-info/SOURCES.txt       2020-12-07 
19:07:38.000000000 +0100
+++ new/proto-plus-1.18.1/proto_plus.egg-info/SOURCES.txt       2021-03-19 
23:17:52.000000000 +0100
@@ -50,6 +50,7 @@
 tests/test_file_info_salting_with_manifest.py
 tests/test_json.py
 tests/test_marshal_register.py
+tests/test_marshal_strict.py
 tests/test_marshal_types_dates.py
 tests/test_marshal_types_enum.py
 tests/test_marshal_types_message.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/setup.py 
new/proto-plus-1.18.1/setup.py
--- old/proto-plus-1.13.0/setup.py      2020-12-07 19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/setup.py      2021-03-19 23:17:44.000000000 +0100
@@ -17,7 +17,7 @@
 
 from setuptools import find_packages, setup
 
-version = "1.13.0"
+version = "1.18.1"
 
 PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/tests/test_fields_enum.py 
new/proto-plus-1.18.1/tests/test_fields_enum.py
--- old/proto-plus-1.13.0/tests/test_fields_enum.py     2020-12-07 
19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/tests/test_fields_enum.py     2021-03-19 
23:17:44.000000000 +0100
@@ -12,7 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import os
 import proto
+import pytest
 import sys
 
 
@@ -353,3 +355,40 @@
     t = Task(weekday="TUESDAY")
     t2 = Task.deserialize(Task.serialize(t))
     assert t == t2
+
+
+if os.environ.get("PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION", "python") == "cpp":
+    # This test only works, and is only relevant, with the cpp runtime.
+    # Python just doesn't give a care and lets it work anyway.
+    def test_enum_alias_bad():
+        # Certain enums may shadow the different enum monikers with the same 
value.
+        # This is generally discouraged, and protobuf will object by default,
+        # but will explicitly allow this behavior if the enum is defined with
+        # the `allow_alias` option set.
+        with pytest.raises(TypeError):
+
+            # The wrapper message is a hack to avoid manifest wrangling to
+            # define the enum.
+            class BadMessage(proto.Message):
+                class BadEnum(proto.Enum):
+                    UNKNOWN = 0
+                    DEFAULT = 0
+
+                bad_dup_enum = proto.Field(proto.ENUM, number=1, enum=BadEnum)
+
+
+def test_enum_alias_good():
+    # Have to split good and bad enum alias into two tests so that the 
generated
+    # file descriptor is properly created.
+    # For the python runtime, aliases are allowed by default, but we want to
+    # make sure that the options don't cause problems.
+    # For the cpp runtime, we need to verify that we can in fact define 
aliases.
+    class GoodMessage(proto.Message):
+        class GoodEnum(proto.Enum):
+            _pb_options = {"allow_alias": True}
+            UNKNOWN = 0
+            DEFAULT = 0
+
+        good_dup_enum = proto.Field(proto.ENUM, number=1, enum=GoodEnum)
+
+    assert GoodMessage.GoodEnum.UNKNOWN == GoodMessage.GoodEnum.DEFAULT == 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/proto-plus-1.13.0/tests/test_fields_repeated_composite.py 
new/proto-plus-1.18.1/tests/test_fields_repeated_composite.py
--- old/proto-plus-1.13.0/tests/test_fields_repeated_composite.py       
2020-12-07 19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/tests/test_fields_repeated_composite.py       
2021-03-19 23:17:44.000000000 +0100
@@ -14,6 +14,7 @@
 
 from datetime import datetime
 from datetime import timezone
+from enum import Enum
 
 import pytest
 
@@ -95,6 +96,17 @@
     assert foo.timestamps[2].hour == 0
 
 
+def test_repeated_composite_enum():
+    class Foo(proto.Message):
+        class Bar(proto.Enum):
+            BAZ = 0
+
+        bars = proto.RepeatedField(Bar, number=1)
+
+    foo = Foo(bars=[Foo.Bar.BAZ])
+    assert isinstance(foo.bars[0], Enum)
+
+
 def test_repeated_composite_outer_write():
     class Foo(proto.Message):
         bar = proto.Field(proto.INT32, number=1)
@@ -153,7 +165,7 @@
     assert baz.foos[1].bar == 48
 
 
-def test_repeated_composite_set():
+def test_repeated_composite_set_index():
     class Foo(proto.Message):
         bar = proto.Field(proto.INT32, number=1)
 
@@ -164,9 +176,101 @@
     baz.foos[1] = Foo(bar=55)
     assert baz.foos[0].bar == 96
     assert baz.foos[1].bar == 55
+    assert len(baz.foos) == 2
+
+
+def test_repeated_composite_set_index_error():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[])
+    with pytest.raises(IndexError):
+        baz.foos[0] = Foo(bar=55)
+
+
+def test_repeated_composite_set_slice_less():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[{"bar": 96}, {"bar": 48}, {"bar": 24}])
+    baz.foos[:2] = [{"bar": 12}]
+    assert baz.foos[0].bar == 12
+    assert baz.foos[1].bar == 24
+    assert len(baz.foos) == 2
+
+
+def test_repeated_composite_set_slice_more():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[{"bar": 12}])
+    baz.foos[:2] = [{"bar": 96}, {"bar": 48}, {"bar": 24}]
+    assert baz.foos[0].bar == 96
+    assert baz.foos[1].bar == 48
+    assert baz.foos[2].bar == 24
+    assert len(baz.foos) == 3
+
+
+def test_repeated_composite_set_slice_not_iterable():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[])
+    with pytest.raises(TypeError):
+        baz.foos[:1] = None
+
+
+def test_repeated_composite_set_extended_slice():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[{"bar": 96}, {"bar": 48}])
+    baz.foos[::-1] = [{"bar": 96}, {"bar": 48}]
+    assert baz.foos[0].bar == 48
+    assert baz.foos[1].bar == 96
+    assert len(baz.foos) == 2
+
+
+def test_repeated_composite_set_extended_slice_wrong_length():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[{"bar": 96}])
+    with pytest.raises(ValueError):
+        baz.foos[::-1] = []
+
+
+def test_repeated_composite_set_wrong_key_type():
+    class Foo(proto.Message):
+        bar = proto.Field(proto.INT32, number=1)
+
+    class Baz(proto.Message):
+        foos = proto.RepeatedField(proto.MESSAGE, message=Foo, number=1)
+
+    baz = Baz(foos=[])
+    with pytest.raises(TypeError):
+        baz.foos[None] = Foo(bar=55)
 
 
-def test_repeated_composite_set_wrong_type():
+def test_repeated_composite_set_wrong_value_type():
     class Foo(proto.Message):
         bar = proto.Field(proto.INT32, number=1)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/tests/test_json.py 
new/proto-plus-1.18.1/tests/test_json.py
--- old/proto-plus-1.13.0/tests/test_json.py    2020-12-07 19:07:31.000000000 
+0100
+++ new/proto-plus-1.18.1/tests/test_json.py    2021-03-19 23:17:44.000000000 
+0100
@@ -136,3 +136,15 @@
     # Don't permit unknown fields by default
     with pytest.raises(ParseError):
         o = Octopus.from_json(json_str)
+
+
+def test_json_snake_case():
+    class Squid(proto.Message):
+        mass_kg = proto.Field(proto.INT32, number=1)
+
+    json_str = '{\n  "mass_kg": 20\n}'
+    s = Squid.from_json(json_str)
+
+    assert s.mass_kg == 20
+
+    assert Squid.to_json(s, preserving_proto_field_name=True) == json_str
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/tests/test_marshal_strict.py 
new/proto-plus-1.18.1/tests/test_marshal_strict.py
--- old/proto-plus-1.13.0/tests/test_marshal_strict.py  1970-01-01 
01:00:00.000000000 +0100
+++ new/proto-plus-1.18.1/tests/test_marshal_strict.py  2021-03-19 
23:17:44.000000000 +0100
@@ -0,0 +1,24 @@
+# Copyright (C) 2021  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
+#
+#     http://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
+from proto.marshal.marshal import BaseMarshal
+import pytest
+
+
+def test_strict_to_proto():
+    m = BaseMarshal()
+
+    with pytest.raises(TypeError):
+        m.to_proto(dict, None, strict=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/tests/test_marshal_types_enum.py 
new/proto-plus-1.18.1/tests/test_marshal_types_enum.py
--- old/proto-plus-1.13.0/tests/test_marshal_types_enum.py      2020-12-07 
19:07:31.000000000 +0100
+++ new/proto-plus-1.18.1/tests/test_marshal_types_enum.py      2021-03-19 
23:17:44.000000000 +0100
@@ -58,3 +58,35 @@
     with mock.patch.object(warnings, "warn") as warn:
         assert enum_rule.to_python(4) == 4
         warn.assert_called_once_with("Unrecognized Foo enum value: 4")
+
+
+def test_enum_append():
+    class Bivalve(proto.Enum):
+        CLAM = 0
+        OYSTER = 1
+
+    class MolluscContainer(proto.Message):
+        bivalves = proto.RepeatedField(proto.ENUM, number=1, enum=Bivalve,)
+
+    mc = MolluscContainer()
+    clam = Bivalve.CLAM
+    mc.bivalves.append(clam)
+    mc.bivalves.append(1)
+
+    assert mc.bivalves == [clam, Bivalve.OYSTER]
+
+
+def test_enum_map_insert():
+    class Bivalve(proto.Enum):
+        CLAM = 0
+        OYSTER = 1
+
+    class MolluscContainer(proto.Message):
+        bivalves = proto.MapField(proto.STRING, proto.ENUM, number=1, 
enum=Bivalve,)
+
+    mc = MolluscContainer()
+    clam = Bivalve.CLAM
+    mc.bivalves["clam"] = clam
+    mc.bivalves["oyster"] = 1
+
+    assert mc.bivalves == {"clam": clam, "oyster": Bivalve.OYSTER}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/proto-plus-1.13.0/tests/test_message.py 
new/proto-plus-1.18.1/tests/test_message.py
--- old/proto-plus-1.13.0/tests/test_message.py 2020-12-07 19:07:31.000000000 
+0100
+++ new/proto-plus-1.18.1/tests/test_message.py 2021-03-19 23:17:44.000000000 
+0100
@@ -317,3 +317,27 @@
 
     s = Squid({"mass_kg": 20, "length_cm": 100}, ignore_unknown_fields=True)
     assert not hasattr(s, "length_cm")
+
+
+def test_copy_from():
+    class Mollusc(proto.Message):
+        class Squid(proto.Message):
+            mass_kg = proto.Field(proto.INT32, number=1)
+
+        squid = proto.Field(Squid, number=1)
+
+    m = Mollusc()
+    s = Mollusc.Squid(mass_kg=20)
+    Mollusc.Squid.copy_from(m.squid, s)
+    assert m.squid is not s
+    assert m.squid == s
+
+    s.mass_kg = 30
+    Mollusc.Squid.copy_from(m.squid, Mollusc.Squid.pb(s))
+    assert m.squid == s
+
+    Mollusc.Squid.copy_from(m.squid, {"mass_kg": 10})
+    assert m.squid.mass_kg == 10
+
+    with pytest.raises(TypeError):
+        Mollusc.Squid.copy_from(m.squid, (("mass_kg", 20)))

Reply via email to