Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-avro for openSUSE:Factory 
checked in at 2022-08-06 22:07:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-avro (Old)
 and      /work/SRC/openSUSE:Factory/.python-avro.new.1521 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-avro"

Sat Aug  6 22:07:54 2022 rev:12 rq:993435 version:1.11.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-avro/python-avro.changes  2021-11-17 
01:15:31.630191456 +0100
+++ /work/SRC/openSUSE:Factory/.python-avro.new.1521/python-avro.changes        
2022-08-06 22:08:02.526636320 +0200
@@ -1,0 +2,21 @@
+Thu Aug  4 09:32:11 UTC 2022 - Otto Hollmann <otto.hollm...@suse.com>
+
+- Update to 1.11.1 (from GitHub release notes):
+  - Avro specification
+    - Clarify which names are allowed to be qualified with
+      namespaces
+    - Inconsistent behaviour on types as invalid names
+    - Clarify how fullnames are created, with example
+    - IDL: add syntax to create optional fields
+    - Improve docs for logical type annotation
+  - Python
+    - Scale assignment optimization
+    - "Scale" property from decimal object
+    - Byte reading in avro.io does not assert bytes read
+    - validate the default value of an enum field
+    - Pass LogicalType to BytesDecimalSchema
+  - Website
+    - Website refactor
+    - Document IDL support in IDEs
+
+-------------------------------------------------------------------

Old:
----
  avro-1.11.0.tar.gz

New:
----
  avro-1.11.1.tar.gz

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

Other differences:
------------------
++++++ python-avro.spec ++++++
--- /var/tmp/diff_new_pack.5Tfjf4/_old  2022-08-06 22:08:04.970643425 +0200
+++ /var/tmp/diff_new_pack.5Tfjf4/_new  2022-08-06 22:08:04.978643448 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-avro
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-avro
-Version:        1.11.0
+Version:        1.11.1
 Release:        0
 Summary:        A serialization and RPC framework for Python
 License:        Apache-2.0

++++++ avro-1.11.0.tar.gz -> avro-1.11.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/PKG-INFO new/avro-1.11.1/PKG-INFO
--- old/avro-1.11.0/PKG-INFO    2021-10-27 17:12:45.792555300 +0200
+++ new/avro-1.11.1/PKG-INFO    2022-07-31 17:26:28.704221500 +0200
@@ -1,18 +1,18 @@
 Metadata-Version: 2.1
 Name: avro
-Version: 1.11.0
+Version: 1.11.1
 Summary: Avro is a serialization and RPC framework.
 Home-page: https://avro.apache.org/
 Author: Apache Avro
 Author-email: d...@avro.apache.org
 License: Apache License 2.0
 Keywords: avro,serialization,rpc
-Platform: UNKNOWN
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Programming Language :: Python :: 3.6
 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: Development Status :: 5 - Production/Stable
 Requires-Python: >=3.6
 Description-Content-Type: text/markdown
@@ -38,5 +38,3 @@
 ### License, Credits and Acknowledgements
 
 License, credits and acknowledgements are maintained in the 
[LICENSE.txt](https://github.com/apache/avro/blob/master/LICENSE.txt) and 
[NOTICE.txt](https://github.com/apache/avro/blob/master/NOTICE.txt) in the 
source code repository. Those files are also included with the installed 
package.
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/VERSION.txt 
new/avro-1.11.1/avro/VERSION.txt
--- old/avro-1.11.0/avro/VERSION.txt    2021-10-20 16:06:29.000000000 +0200
+++ new/avro-1.11.1/avro/VERSION.txt    2022-07-26 21:29:56.000000000 +0200
@@ -1 +1 @@
-1.11.0
\ No newline at end of file
+1.11.1
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/__main__.py 
new/avro-1.11.1/avro/__main__.py
--- old/avro-1.11.0/avro/__main__.py    2021-10-13 11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/__main__.py    2022-02-23 17:45:22.000000000 +0100
@@ -171,7 +171,10 @@
 
 def iter_csv(info: IO[AnyStr], schema: avro.schema.RecordSchema) -> 
Generator[Dict[str, object], None, None]:
     header = [field.name for field in schema.fields]
-    for row in csv.reader(getattr(i, "decode", lambda: i)() for i in info):
+    # If i is bytes, decode into a string.
+    # If i is a string, no need to decode.
+    csv_data = (cast(str, getattr(i, "decode", lambda: i)()) for i in info)
+    for row in csv.reader(csv_data):
         values = [convert(v, f) for v, f in zip(row, schema.fields)]
         yield dict(zip(header, values))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/datafile.py 
new/avro-1.11.1/avro/datafile.py
--- old/avro-1.11.0/avro/datafile.py    2021-10-13 11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/datafile.py    2022-02-23 17:45:22.000000000 +0100
@@ -160,7 +160,7 @@
     _datum_writer: avro.io.DatumWriter
     _encoder: avro.io.BinaryEncoder
     _header_written: bool
-    _writer: BinaryIO
+    _writer: IO[bytes]
     block_count: int
     sync_marker: bytes
 
@@ -170,7 +170,7 @@
         """If the schema is not present, presume we're appending."""
         if hasattr(writer, "mode") and "b" not in writer.mode:
             warnings.warn(avro.errors.AvroWarning(f"Writing binary data to a 
writer {writer!r} that's opened for text"))
-        bytes_writer = getattr(writer, "buffer", writer)
+        bytes_writer = cast(IO[bytes], getattr(writer, "buffer", writer))
         self._writer = bytes_writer
         self._encoder = avro.io.BinaryEncoder(bytes_writer)
         self._datum_writer = datum_writer
@@ -202,7 +202,7 @@
         self.datum_writer.writers_schema = writers_schema
 
     @property
-    def writer(self) -> BinaryIO:
+    def writer(self) -> IO[bytes]:
         return self._writer
 
     @property
@@ -307,7 +307,7 @@
     _datum_reader: avro.io.DatumReader
     _file_length: int
     _raw_decoder: avro.io.BinaryDecoder
-    _reader: BinaryIO
+    _reader: IO[bytes]
     block_count: int
     sync_marker: bytes
 
@@ -315,9 +315,9 @@
     # TODO(hammer): allow user to specify the encoder
 
     def __init__(self, reader: IO[AnyStr], datum_reader: avro.io.DatumReader) 
-> None:
-        if "b" not in reader.mode:
+        if hasattr(reader, "mode") and "b" not in reader.mode:
             warnings.warn(avro.errors.AvroWarning(f"Reader binary data from a 
reader {reader!r} that's opened for text"))
-        bytes_reader = getattr(reader, "buffer", reader)
+        bytes_reader = cast(IO[bytes], getattr(reader, "buffer", reader))
         self._reader = bytes_reader
         self._raw_decoder = avro.io.BinaryDecoder(bytes_reader)
         self._datum_decoder = None  # Maybe reset at every block.
@@ -337,7 +337,7 @@
         return self
 
     @property
-    def reader(self) -> BinaryIO:
+    def reader(self) -> IO[bytes]:
         return self._reader
 
     @property
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/errors.py 
new/avro-1.11.1/avro/errors.py
--- old/avro-1.11.0/avro/errors.py      2021-10-13 11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/errors.py      2022-02-23 17:45:22.000000000 +0100
@@ -32,6 +32,10 @@
     """The base class for exceptions in avro."""
 
 
+class InvalidAvroBinaryEncoding(AvroException):
+    """For invalid numbers of bytes read."""
+
+
 class SchemaParseException(AvroException):
     """Raised when a schema failed to parse."""
 
@@ -40,6 +44,10 @@
     """User attempted to parse a schema with an invalid name."""
 
 
+class InvalidDefault(SchemaParseException):
+    """User attempted to parse a schema with an invalid default."""
+
+
 class AvroWarning(UserWarning):
     """Base class for warnings."""
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/io.py new/avro-1.11.1/avro/io.py
--- old/avro-1.11.0/avro/io.py  2021-10-13 11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/io.py  2022-06-24 20:02:21.000000000 +0200
@@ -90,7 +90,7 @@
 import struct
 import warnings
 from typing import (
-    BinaryIO,
+    IO,
     Deque,
     Generator,
     Iterable,
@@ -206,23 +206,28 @@
 class BinaryDecoder:
     """Read leaf values."""
 
-    _reader: BinaryIO
+    _reader: IO[bytes]
 
-    def __init__(self, reader: BinaryIO) -> None:
+    def __init__(self, reader: IO[bytes]) -> None:
         """
         reader is a Python object on which we can call read, seek, and tell.
         """
         self._reader = reader
 
     @property
-    def reader(self) -> BinaryIO:
+    def reader(self) -> IO[bytes]:
         return self._reader
 
     def read(self, n: int) -> bytes:
         """
         Read n bytes.
         """
-        return self.reader.read(n)
+        if n < 0:
+            raise avro.errors.InvalidAvroBinaryEncoding(f"Requested {n} bytes 
to read, expected positive integer.")
+        read_bytes = self.reader.read(n)
+        if len(read_bytes) != n:
+            raise avro.errors.InvalidAvroBinaryEncoding(f"Read 
{len(read_bytes)} bytes, expected {n} bytes")
+        return read_bytes
 
     def read_null(self) -> None:
         """
@@ -410,16 +415,16 @@
 class BinaryEncoder:
     """Write leaf values."""
 
-    _writer: BinaryIO
+    _writer: IO[bytes]
 
-    def __init__(self, writer: BinaryIO) -> None:
+    def __init__(self, writer: IO[bytes]) -> None:
         """
         writer is a Python object on which we can call write.
         """
         self._writer = writer
 
     @property
-    def writer(self) -> BinaryIO:
+    def writer(self) -> IO[bytes]:
         return self._writer
 
     def write(self, datum: bytes) -> None:
@@ -514,7 +519,7 @@
         size_in_bits = size * 8
         offset_bits = size_in_bits - bits_req
 
-        mask = 2 ** size_in_bits - 1
+        mask = 2**size_in_bits - 1
         bit = 1
         for i in range(bits_req):
             mask ^= bit
@@ -579,7 +584,7 @@
         self.write_long(microseconds)
 
     def _timedelta_total_microseconds(self, timedelta_: datetime.timedelta) -> 
int:
-        return timedelta_.microseconds + (timedelta_.seconds + timedelta_.days 
* 24 * 3600) * 10 ** 6
+        return timedelta_.microseconds + (timedelta_.seconds + timedelta_.days 
* 24 * 3600) * 10**6
 
     def write_timestamp_millis_long(self, datum: datetime.datetime) -> None:
         """
@@ -694,8 +699,8 @@
                     warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal precision {precision}. Must be a positive integer."))
                     return decoder.read_bytes()
                 scale = writers_schema.get_prop("scale")
-                if not (isinstance(scale, int) and scale > 0):
-                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a positive integer."))
+                if not (isinstance(scale, int) and scale >= 0):
+                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a non-negative integer."))
                     return decoder.read_bytes()
                 return decoder.read_decimal_from_bytes(precision, scale)
             return decoder.read_bytes()
@@ -706,8 +711,8 @@
                     warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal precision {precision}. Must be a positive integer."))
                     return self.read_fixed(writers_schema, readers_schema, 
decoder)
                 scale = writers_schema.get_prop("scale")
-                if not (isinstance(scale, int) and scale > 0):
-                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a positive integer."))
+                if not (isinstance(scale, int) and scale >= 0):
+                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a non-negative integer."))
                     return self.read_fixed(writers_schema, readers_schema, 
decoder)
                 return decoder.read_decimal_from_fixed(precision, scale, 
writers_schema.size)
             return self.read_fixed(writers_schema, readers_schema, decoder)
@@ -1062,8 +1067,8 @@
         if writers_schema.type == "bytes":
             if logical_type == "decimal":
                 scale = writers_schema.get_prop("scale")
-                if not (isinstance(scale, int) and scale > 0):
-                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a positive integer."))
+                if not (isinstance(scale, int) and scale >= 0):
+                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a non-negative integer."))
                 elif not isinstance(datum, decimal.Decimal):
                     warnings.warn(avro.errors.IgnoredLogicalType(f"{datum} is 
not a decimal type"))
                 else:
@@ -1075,8 +1080,8 @@
             if logical_type == "decimal":
                 scale = writers_schema.get_prop("scale")
                 size = writers_schema.size
-                if not (isinstance(scale, int) and scale > 0):
-                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a positive integer."))
+                if not (isinstance(scale, int) and scale >= 0):
+                    warnings.warn(avro.errors.IgnoredLogicalType(f"Invalid 
decimal scale {scale}. Must be a non-negative integer."))
                 elif not isinstance(datum, decimal.Decimal):
                     warnings.warn(avro.errors.IgnoredLogicalType(f"{datum} is 
not a decimal type"))
                 else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/name.py new/avro-1.11.1/avro/name.py
--- old/avro-1.11.0/avro/name.py        2021-10-13 11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/name.py        2022-06-24 20:02:21.000000000 +0200
@@ -20,7 +20,7 @@
 """Contains the Name classes."""
 from typing import TYPE_CHECKING, Dict, Optional
 
-from avro.constants import VALID_TYPES
+from avro.constants import PRIMITIVE_TYPES
 
 if TYPE_CHECKING:
     from avro.schema import NamedSchema
@@ -154,7 +154,7 @@
         """
         to_add = Name(name_attr, space_attr, self.default_namespace)
 
-        if to_add.fullname in VALID_TYPES:
+        if to_add.fullname in PRIMITIVE_TYPES:
             raise avro.errors.SchemaParseException(f"{to_add.fullname} is a 
reserved type name.")
         if to_add.fullname in self.names:
             raise avro.errors.SchemaParseException(f'The name 
"{to_add.fullname}" is already in use.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/schema.py 
new/avro-1.11.1/avro/schema.py
--- old/avro-1.11.0/avro/schema.py      2021-10-13 11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/schema.py      2022-06-24 20:02:21.000000000 +0200
@@ -303,7 +303,7 @@
             raise avro.errors.IgnoredLogicalType(f"Invalid decimal precision 
{precision}. Max is {max_precision}.")
 
         if not isinstance(scale, int) or scale < 0:
-            raise avro.errors.IgnoredLogicalType(f"Invalid decimal scale 
{scale}. Must be a positive integer.")
+            raise avro.errors.IgnoredLogicalType(f"Invalid decimal scale 
{scale}. Must be a non-negative integer.")
 
         if scale > precision:
             raise avro.errors.IgnoredLogicalType(f"Invalid decimal scale 
{scale}. Cannot be greater than precision {precision}.")
@@ -414,18 +414,15 @@
         @arg writer: the schema to match against
         @return bool
         """
-        return (
-            self.type == writer.type
-            or {
-                "float": self.type == "double",
-                "int": self.type in {"double", "float", "long"},
-                "long": self.type
-                in {
-                    "double",
-                    "float",
-                },
-            }.get(writer.type, False)
-        )
+        return self.type == writer.type or {
+            "float": self.type == "double",
+            "int": self.type in {"double", "float", "long"},
+            "long": self.type
+            in {
+                "double",
+                "float",
+            },
+        }.get(writer.type, False)
 
     def to_json(self, names=None):
         if len(self.props) == 1:
@@ -583,6 +580,11 @@
         if doc is not None:
             self.set_prop("doc", doc)
 
+        if other_props and "default" in other_props:
+            default = other_props["default"]
+            if default not in symbols:
+                raise avro.errors.InvalidDefault(f"Enum default '{default}' is 
not a valid member of symbols '{symbols}'")
+
     @property
     def symbols(self) -> Sequence[str]:
         symbols = self.get_prop("symbols")
@@ -1067,7 +1069,7 @@
 
 def make_bytes_decimal_schema(other_props):
     """Make a BytesDecimalSchema from just other_props."""
-    return BytesDecimalSchema(other_props.get("precision"), 
other_props.get("scale", 0))
+    return BytesDecimalSchema(other_props.get("precision"), 
other_props.get("scale", 0), other_props)
 
 
 def make_logical_schema(logical_type, type_, other_props):
@@ -1130,7 +1132,7 @@
                 size = json_data.get("size")
                 if logical_type == "decimal":
                     precision = json_data.get("precision")
-                    scale = 0 if json_data.get("scale") is None else 
json_data.get("scale")
+                    scale = json_data.get("scale", 0)
                     try:
                         return FixedDecimalSchema(size, name, precision, 
scale, namespace, names, other_props)
                     except avro.errors.IgnoredLogicalType as warning:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/test/gen_interop_data.py 
new/avro-1.11.1/avro/test/gen_interop_data.py
--- old/avro-1.11.0/avro/test/gen_interop_data.py       2021-10-13 
11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/test/gen_interop_data.py       2022-02-23 
17:45:22.000000000 +0100
@@ -54,6 +54,7 @@
 
 def gen_data(codec: str, datum_writer: avro.io.DatumWriter, interop_schema: 
avro.schema.Schema) -> bytes:
     with io.BytesIO() as file_, avro.datafile.DataFileWriter(file_, 
datum_writer, interop_schema, codec=codec) as dfw:
+        dfw.set_meta("user_metadata", b"someByteArray")
         dfw.append(DATUM)
         dfw.flush()
         return file_.getvalue()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/test/test_datafile_interop.py 
new/avro-1.11.1/avro/test/test_datafile_interop.py
--- old/avro-1.11.0/avro/test/test_datafile_interop.py  2021-10-13 
11:58:28.000000000 +0200
+++ new/avro-1.11.1/avro/test/test_datafile_interop.py  2022-02-23 
17:45:22.000000000 +0100
@@ -37,11 +37,16 @@
         for filename in _INTEROP_DATA_DIR.iterdir():
             self.assertGreater(os.stat(filename).st_size, 0)
             base_ext = filename.stem.split("_", 1)
-            if len(base_ext) < 2 or base_ext[1] not in 
avro.codecs.KNOWN_CODECS:
+            if len(base_ext) > 1 and base_ext[1] not in 
avro.codecs.KNOWN_CODECS:
                 print(f"SKIPPING {filename} due to an unsupported codec\n")
                 continue
             i = None
             with self.subTest(filename=filename), 
avro.datafile.DataFileReader(filename.open("rb"), avro.io.DatumReader()) as dfr:
+
+                user_metadata = dfr.get_meta("user_metadata")
+                if user_metadata is not None:
+                    self.assertEqual(user_metadata, b"someByteArray")
+
                 for i, datum in enumerate(cast(avro.datafile.DataFileReader, 
dfr), 1):
                     self.assertIsNotNone(datum)
                 self.assertIsNotNone(i)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/test/test_io.py 
new/avro-1.11.1/avro/test/test_io.py
--- old/avro-1.11.0/avro/test/test_io.py        2021-10-13 11:58:28.000000000 
+0200
+++ new/avro-1.11.1/avro/test/test_io.py        2022-06-24 20:02:21.000000000 
+0200
@@ -72,6 +72,16 @@
             decimal.Decimal("-3.1415"),
         ),
         (
+            {
+                "type": "fixed",
+                "logicalType": "decimal",
+                "name": "Test",
+                "size": 8,
+                "precision": 1,
+            },
+            decimal.Decimal("3"),
+        ),
+        (
             {"type": "bytes", "logicalType": "decimal", "precision": 5, 
"scale": 4},
             decimal.Decimal("3.1415"),
         ),
@@ -79,6 +89,10 @@
             {"type": "bytes", "logicalType": "decimal", "precision": 5, 
"scale": 4},
             decimal.Decimal("-3.1415"),
         ),
+        (
+            {"type": "bytes", "logicalType": "decimal", "precision": 1},
+            decimal.Decimal("3"),
+        ),
         ({"type": "enum", "name": "Test", "symbols": ["A", "B"]}, "B"),
         ({"type": "array", "items": "long"}, [1, 3, 2]),
         ({"type": "map", "values": "long"}, {"a": 1, "b": 3, "c": 2}),
@@ -163,6 +177,14 @@
             },
             {"value": {"car": {"value": "head"}, "cdr": {"value": None}}},
         ),
+        (
+            {"type": "record", "name": "record", "fields": [{"name": "value", 
"type": "int"}, {"name": "next", "type": ["null", "record"]}]},
+            {"value": 0, "next": {"value": 1, "next": None}},
+        ),
+        (
+            {"type": "record", "name": "ns.long", "fields": [{"name": "value", 
"type": "int"}, {"name": "next", "type": ["null", "ns.long"]}]},
+            {"value": 0, "next": {"value": 1, "next": None}},
+        ),
     )
 )
 
@@ -426,6 +448,58 @@
             self.assertEqual(datum_to_read, datum_read)
 
 
+class TestIncompatibleSchemaReading(unittest.TestCase):
+    def test_deserialization_fails(self) -> None:
+
+        reader_schema = avro.schema.parse(
+            json.dumps(
+                {
+                    "namespace": "example.avro",
+                    "type": "record",
+                    "name": "User",
+                    "fields": [
+                        {"name": "name", "type": "string"},
+                        {"name": "age", "type": "int"},
+                        {"name": "location", "type": "string"},
+                    ],
+                }
+            )
+        )
+        writer_schema = avro.schema.parse(
+            json.dumps(
+                {
+                    "namespace": "example.avro",
+                    "type": "record",
+                    "name": "IncompatibleUser",
+                    "fields": [
+                        {"name": "name", "type": "int"},
+                        {"name": "age", "type": "int"},
+                        {"name": "location", "type": "string"},
+                    ],
+                }
+            )
+        )
+
+        incompatibleUserRecord = {"name": 100, "age": 21, "location": 
"Woodford"}
+        writer = avro.io.DatumWriter(writer_schema)
+        with io.BytesIO() as writer_bio:
+            enc = avro.io.BinaryEncoder(writer_bio)
+            writer.write(incompatibleUserRecord, enc)
+            enc_bytes = writer_bio.getvalue()
+        reader = avro.io.DatumReader(reader_schema)
+        with io.BytesIO(enc_bytes) as reader_bio:
+            self.assertRaises(avro.errors.InvalidAvroBinaryEncoding, 
reader.read, avro.io.BinaryDecoder(reader_bio))
+
+        incompatibleUserRecord = {"name": -10, "age": 21, "location": 
"Woodford"}
+        with io.BytesIO() as writer_bio:
+            enc = avro.io.BinaryEncoder(writer_bio)
+            writer.write(incompatibleUserRecord, enc)
+            enc_bytes = writer_bio.getvalue()
+        reader = avro.io.DatumReader(reader_schema)
+        with io.BytesIO(enc_bytes) as reader_bio:
+            self.assertRaises(avro.errors.InvalidAvroBinaryEncoding, 
reader.read, avro.io.BinaryDecoder(reader_bio))
+
+
 class TestMisc(unittest.TestCase):
     def test_decimal_bytes_small_scale(self) -> None:
         """Avro should raise an AvroTypeException when attempting to write a 
decimal with a larger exponent than the schema's scale."""
@@ -585,6 +659,7 @@
         SchemaPromotionTestCase(write_type, read_type) for write_type, 
read_type in itertools.combinations(("int", "long", "float", "double"), 2)
     )
     suite.addTests(DefaultValueTestCase(field_type, default) for field_type, 
default in DEFAULT_VALUE_EXAMPLES)
+    suite.addTests(loader.loadTestsFromTestCase(TestIncompatibleSchemaReading))
     return suite
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro/test/test_schema.py 
new/avro-1.11.1/avro/test/test_schema.py
--- old/avro-1.11.0/avro/test/test_schema.py    2021-10-13 11:58:28.000000000 
+0200
+++ new/avro-1.11.1/avro/test/test_schema.py    2022-06-24 20:02:21.000000000 
+0200
@@ -85,6 +85,7 @@
 ENUM_EXAMPLES = [
     ValidTestSchema({"type": "enum", "name": "Test", "symbols": ["A", "B"]}),
     ValidTestSchema({"type": "enum", "name": "AVRO2174", "symbols": 
["nowhitespace"]}),
+    InvalidTestSchema({"type": "enum", "name": "bad_default", "symbols": 
["A"], "default": "B"}, comment="AVRO-3229"),
     InvalidTestSchema({"type": "enum", "name": "Status", "symbols": "Normal 
Caution Critical"}),
     InvalidTestSchema({"type": "enum", "name": [0, 1, 1, 2, 3, 5, 8], 
"symbols": ["Golden", "Mean"]}),
     InvalidTestSchema({"type": "enum", "symbols": ["I", "will", "fail", "no", 
"name"]}),
@@ -119,6 +120,19 @@
     InvalidTestSchema([{"type": "array", "items": "long"}, {"type": "array", 
"items": "string"}]),
 ]
 
+NAME_EXAMPLES = [
+    ValidTestSchema({"type": "enum", "name": "record", "symbols": ["A", "B"]}),
+    ValidTestSchema({"type": "record", "name": "record", "fields": [{"name": 
"f", "type": "long"}]}),
+    InvalidTestSchema({"type": "enum", "name": "int", "symbols": ["A", "B"]}),
+    ValidTestSchema({"type": "enum", "name": "ns.int", "symbols": ["A", "B"]}),
+    ValidTestSchema({"type": "enum", "namespace": "ns", "name": "int", 
"symbols": ["A", "B"]}),
+    ValidTestSchema(
+        {"type": "record", "name": "LinkedList", "fields": [{"name": "value", 
"type": "int"}, {"name": "next", "type": ["null", "LinkedList"]}]}
+    ),
+    ValidTestSchema({"type": "record", "name": "record", "fields": [{"name": 
"value", "type": "int"}, {"name": "next", "type": ["null", "record"]}]}),
+    ValidTestSchema({"type": "record", "name": "ns.int", "fields": [{"name": 
"value", "type": "int"}, {"name": "next", "type": ["null", "ns.int"]}]}),
+]
+
 NAMED_IN_UNION_EXAMPLES = [
     ValidTestSchema(
         {
@@ -407,7 +421,7 @@
     ),
     ValidTestSchema(
         {"type": "bytes", "logicalType": "decimal", "precision": 2, "scale": 
-2},
-        warnings=[avro.errors.IgnoredLogicalType("Invalid decimal scale -2. 
Must be a positive integer.")],
+        warnings=[avro.errors.IgnoredLogicalType("Invalid decimal scale -2. 
Must be a non-negative integer.")],
     ),
     ValidTestSchema(
         {"type": "bytes", "logicalType": "decimal", "precision": -2, "scale": 
2},
@@ -511,6 +525,7 @@
 EXAMPLES += ARRAY_EXAMPLES
 EXAMPLES += MAP_EXAMPLES
 EXAMPLES += UNION_EXAMPLES
+EXAMPLES += NAME_EXAMPLES
 EXAMPLES += NAMED_IN_UNION_EXAMPLES
 EXAMPLES += RECORD_EXAMPLES
 EXAMPLES += DOC_EXAMPLES
@@ -642,16 +657,16 @@
             }
         )
 
-        bytes_decimal_schema = ValidTestSchema({"type": "bytes", 
"logicalType": "decimal", "precision": 4})
-
         fixed_decimal = fixed_decimal_schema.parse()
         self.assertEqual(4, fixed_decimal.get_prop("precision"))
         self.assertEqual(2, fixed_decimal.get_prop("scale"))
         self.assertEqual(2, fixed_decimal.get_prop("size"))
 
+        bytes_decimal_schema = ValidTestSchema({"type": "bytes", 
"logicalType": "decimal", "precision": 4})
         bytes_decimal = bytes_decimal_schema.parse()
         self.assertEqual(4, bytes_decimal.get_prop("precision"))
         self.assertEqual(0, bytes_decimal.get_prop("scale"))
+        self.assertEqual("decimal", bytes_decimal.get_prop("logicalType"))
 
     def test_fixed_decimal_valid_max_precision(self):
         # An 8 byte number can represent any 18 digit number.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro.egg-info/PKG-INFO 
new/avro-1.11.1/avro.egg-info/PKG-INFO
--- old/avro-1.11.0/avro.egg-info/PKG-INFO      2021-10-27 17:12:45.000000000 
+0200
+++ new/avro-1.11.1/avro.egg-info/PKG-INFO      2022-07-31 17:26:28.000000000 
+0200
@@ -1,18 +1,18 @@
 Metadata-Version: 2.1
 Name: avro
-Version: 1.11.0
+Version: 1.11.1
 Summary: Avro is a serialization and RPC framework.
 Home-page: https://avro.apache.org/
 Author: Apache Avro
 Author-email: d...@avro.apache.org
 License: Apache License 2.0
 Keywords: avro,serialization,rpc
-Platform: UNKNOWN
 Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Programming Language :: Python :: 3.6
 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: Development Status :: 5 - Production/Stable
 Requires-Python: >=3.6
 Description-Content-Type: text/markdown
@@ -38,5 +38,3 @@
 ### License, Credits and Acknowledgements
 
 License, credits and acknowledgements are maintained in the 
[LICENSE.txt](https://github.com/apache/avro/blob/master/LICENSE.txt) and 
[NOTICE.txt](https://github.com/apache/avro/blob/master/NOTICE.txt) in the 
source code repository. Those files are also included with the installed 
package.
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/avro.egg-info/entry_points.txt 
new/avro-1.11.1/avro.egg-info/entry_points.txt
--- old/avro-1.11.0/avro.egg-info/entry_points.txt      2021-10-27 
17:12:45.000000000 +0200
+++ new/avro-1.11.1/avro.egg-info/entry_points.txt      2022-07-31 
17:26:28.000000000 +0200
@@ -1,3 +1,2 @@
 [console_scripts]
 avro = avro.__main__:main
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/avro-1.11.0/setup.cfg new/avro-1.11.1/setup.cfg
--- old/avro-1.11.0/setup.cfg   2021-10-27 17:12:45.793555300 +0200
+++ new/avro-1.11.1/setup.cfg   2022-07-31 17:26:28.704221500 +0200
@@ -19,6 +19,7 @@
        Programming Language :: Python :: 3.7
        Programming Language :: Python :: 3.8
        Programming Language :: Python :: 3.9
+       Programming Language :: Python :: 3.10
        Development Status :: 5 - Production/Stable
 
 [bdist_wheel]

Reply via email to