fix return_record_name for named types
MODIFY
fastavro/_read.pyx
fastavro/_read.pyx
@@ -398,27 +398,33 @@ cdef read_union(fo, writer_schema, reader_schema=None, return_record_name=False)
"""
# schema resolution
index = read_long(fo)
+ idx_schema = writer_schema[index]
if reader_schema:
# Handle case where the reader schema is just a single type (not union)
if not isinstance(reader_schema, list):
- if match_types(writer_schema[index], reader_schema):
- return _read_data(fo, writer_schema[index], reader_schema,
- return_record_name)
+ if match_types(idx_schema, reader_schema):
+ return _read_data(fo, idx_schema, reader_schema, return_record_name)
else:
for schema in reader_schema:
- if match_types(writer_schema[index], schema):
- return _read_data(fo, writer_schema[index], schema,
- return_record_name)
+ if match_types(idx_schema, schema):
+ return _read_data(fo, idx_schema, schema, return_record_name)
msg = 'schema mismatch: %s not found in %s' % (writer_schema, reader_schema)
raise SchemaResolutionError(msg)
else:
- if return_record_name and extract_record_type(writer_schema[index]) == 'record':
- result = (writer_schema[index]['name'],
- _read_data(fo, writer_schema[index], None, return_record_name))
- else:
- result = _read_data(fo, writer_schema[index], None, return_record_name)
+ if return_record_name and extract_record_type(idx_schema) == 'record':
+ return (
+ idx_schema['name'],
+ _read_data(fo, idx_schema, None, return_record_name)
+ )
+ elif return_record_name and extract_record_type(idx_schema) not in AVRO_TYPES:
+ # idx_schema is a named type
+ return (
+ SCHEMA_DEFS[idx_schema]['name'],
+ _read_data(fo, idx_schema, None, return_record_name)
+ )
- return result
+ else:
+ return _read_data(fo, idx_schema, None, return_record_name)
cdef read_record(fo, writer_schema, reader_schema=None, return_record_name=False):

MODIFY
fastavro/_read_py.py
fastavro/_read_py.py
@@ -262,32 +262,42 @@ def read_union(decoder, writer_schema, reader_schema=None,
return_record_name=False):
# schema resolution
index = decoder.read_index()
+ idx_schema = writer_schema[index]
if reader_schema:
# Handle case where the reader schema is just a single type (not union)
if not isinstance(reader_schema, list):
- if match_types(writer_schema[index], reader_schema):
- return read_data(decoder, writer_schema[index], reader_schema,
- return_record_name)
+ if match_types(idx_schema, reader_schema):
+ return read_data(
+ decoder, idx_schema, reader_schema, return_record_name
+ )
else:
for schema in reader_schema:
- if match_types(writer_schema[index], schema):
- return read_data(decoder, writer_schema[index], schema,
- return_record_name)
+ if match_types(idx_schema, schema):
+ return read_data(
+ decoder, idx_schema, schema, return_record_name
+ )
msg = 'schema mismatch: %s not found in %s' % \
(writer_schema, reader_schema)
raise SchemaResolutionError(msg)
else:
if (
+ return_record_name and extract_record_type(idx_schema) == 'record'
+ ):
+ return (
+ idx_schema['name'],
+ read_data(decoder, idx_schema, None, return_record_name)
+ )
+ elif (
return_record_name
- and extract_record_type(writer_schema[index]) == 'record'
+ and extract_record_type(idx_schema) not in AVRO_TYPES
):
- result = (writer_schema[index]['name'],
- read_data(decoder, writer_schema[index], None,
- return_record_name))
+ # idx_schema is a named type
+ return (
+ SCHEMA_DEFS[idx_schema]['name'],
+ read_data(decoder, idx_schema, None, return_record_name)
+ )
else:
- result = read_data(decoder, writer_schema[index])
-
- return result
+ return read_data(decoder, idx_schema)
def read_record(decoder, writer_schema, reader_schema=None,

MODIFY
tests/test_fastavro.py
tests/test_fastavro.py
@@ -32,15 +32,12 @@ NO_DATA = {
}
-def roundtrip(schema, records, pass_schema_to_reader=False):
+def roundtrip(schema, records, **reader_kwargs):
new_file = MemoryIO()
fastavro.writer(new_file, schema, records)
new_file.seek(0)
- if pass_schema_to_reader:
- reader = fastavro.reader(new_file, schema)
- else:
- reader = fastavro.reader(new_file)
+ reader = fastavro.reader(new_file, **reader_kwargs)
new_records = list(reader)
return new_records
@@ -1473,7 +1470,7 @@ def test_passing_same_schema_to_reader():
}
}]
- assert records == roundtrip(schema, records, pass_schema_to_reader=True)
+ assert records == roundtrip(schema, records, reader_schema=schema)
def test_helpful_error_when_a_single_record_is_passed_to_writer():
@@ -1969,3 +1966,40 @@ def test_named_schema_with_logical_type_in_union():
]
assert expected == roundtrip(schema, records)
+
+
+def test_return_record_name_with_named_type_in_union():
+ schema = {
+ "type": "record",
+ "name": "my_record",
+ "fields": [
+ {
+ "name": "my_1st_union",
+ "type": [
+ {
+ "name": "foo",
+ "type": "record",
+ "fields": [{"name": "some_field", "type": "int"}],
+ },
+ {
+ "name": "bar",
+ "type": "record",
+ "fields": [{"name": "some_field", "type": "int"}],
+ },
+ ],
+ },
+ {"name": "my_2nd_union", "type": ["foo", "bar"]},
+ ],
+ }
+
+ records = [
+ {
+ "my_1st_union": ("foo", {"some_field": 1}),
+ "my_2nd_union": ("bar", {"some_field": 2}),
+ }
+ ]
+
+ rt_records = roundtrip(
+ fastavro.parse_schema(schema), records, return_record_name=True
+ )
+ assert records == rt_records

fix return_record_name for named types