fix field name when validating arrays
MODIFY
fastavro/_validation.pyx
fastavro/_validation.pyx
@@ -81,13 +81,9 @@ cdef inline bint validate_array(datum, dict schema,
if not isinstance(datum, Iterable) or is_str(datum):
return False
- if raise_errors:
- namespace, name = schema_name(schema, parent_ns)
- else:
- name = parent_ns
for d in datum:
if not validate(datum=d, schema=schema['items'],
- field=name,
+ field=parent_ns,
raise_errors=raise_errors):
return False
return True
@@ -102,13 +98,9 @@ cdef inline bint validate_map(object datum, dict schema, str parent_ns='',
if not is_str(k):
return False
- if raise_errors:
- namespace, name = schema_name(schema, parent_ns)
- else:
- name = parent_ns
for v in itervalues(datum):
if not validate(datum=v, schema=schema['values'],
- field=name,
+ field=parent_ns,
raise_errors=raise_errors):
return False
return True
@@ -118,14 +110,11 @@ cdef inline bint validate_record(object datum, dict schema, str parent_ns='',
bint raise_errors=True) except -1:
if not isinstance(datum, Mapping):
return False
- if raise_errors:
- namespace, name = schema_name(schema, parent_ns)
- else:
- name = parent_ns
+ _, namespace = schema_name(schema, parent_ns)
for f in schema['fields']:
if not validate(datum=datum.get(f['name'], f.get('default')),
schema=f['type'],
- field=schema_name(f, name)[1] if raise_errors else name,
+ field='{}.{}'.format(namespace, f['name']),
raise_errors=raise_errors):
return False
return True
@@ -164,63 +153,57 @@ cpdef validate(object datum, object schema, str field='',
bint raise_errors=True):
record_type = extract_record_type(schema)
result = None
- ns_field = ''
-
- if hasattr(schema, 'get') and raise_errors:
- parent_ns, ns_field = schema_name(schema, None)
- elif field:
- ns_field = field
# explicit, so that cython is faster, but only for Base Validators
if record_type == 'null':
- result = validate_null(datum, schema=schema, parent_ns=ns_field,
+ result = validate_null(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'boolean':
- result = validate_boolean(datum, schema=schema, parent_ns=ns_field,
+ result = validate_boolean(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'string':
- result = validate_string(datum, schema=schema, parent_ns=ns_field,
+ result = validate_string(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'int':
- result = validate_int(datum, schema=schema, parent_ns=ns_field,
+ result = validate_int(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'long':
- result = validate_long(datum, schema=schema, parent_ns=ns_field,
+ result = validate_long(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type in ('float', 'double'):
- result = validate_float(datum, schema=schema, parent_ns=ns_field,
+ result = validate_float(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'bytes':
- result = validate_bytes(datum, schema=schema, parent_ns=ns_field,
+ result = validate_bytes(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'fixed':
- result = validate_fixed(datum, schema=schema, parent_ns=ns_field,
+ result = validate_fixed(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'enum':
- result = validate_enum(datum, schema=schema, parent_ns=ns_field,
+ result = validate_enum(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'array':
- result = validate_array(datum, schema=schema, parent_ns=ns_field,
+ result = validate_array(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type == 'map':
- result = validate_map(datum, schema=schema, parent_ns=ns_field,
+ result = validate_map(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type in ('union', 'error_union'):
- result = validate_union(datum, schema=schema, parent_ns=ns_field,
+ result = validate_union(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type in ('record', 'error', 'request'):
- result = validate_record(datum, schema=schema, parent_ns=ns_field,
+ result = validate_record(datum, schema=schema, parent_ns=field,
raise_errors=raise_errors)
elif record_type in SCHEMA_DEFS:
result = validate(datum,
schema=SCHEMA_DEFS[record_type],
- field=ns_field,
+ field=field,
raise_errors=raise_errors)
else:
raise UnknownType(record_type)
if raise_errors and result is False:
- raise ValidationError(ValidationErrorData(datum, schema, ns_field))
+ raise ValidationError(ValidationErrorData(datum, schema, field))
return bool(result)

MODIFY
fastavro/_validation_py.py
fastavro/_validation_py.py
@@ -7,7 +7,8 @@ from fastavro.const import (
INT_MAX_VALUE, INT_MIN_VALUE, LONG_MAX_VALUE, LONG_MIN_VALUE
)
from ._validate_common import ValidationError, ValidationErrorData
-from .schema import extract_record_type, schema_name, UnknownType
+from .schema import extract_record_type, UnknownType
+from .schema import _schema_name as schema_name
from .six import long, is_str, iterkeys, itervalues
from ._schema_common import SCHEMA_DEFS
@@ -194,15 +195,11 @@ def validate_array(datum, schema, parent_ns=None, raise_errors=True):
raise_errors: bool
If true, raises ValidationError on invalid data
"""
- if raise_errors:
- _, name = schema_name(schema, parent_ns)
- else:
- name = parent_ns
return (
isinstance(datum, Iterable) and
not is_str(datum) and
all(validate(datum=d, schema=schema['items'],
- field=name,
+ field=parent_ns,
raise_errors=raise_errors) for d in datum)
)
@@ -223,15 +220,11 @@ def validate_map(datum, schema, parent_ns=None, raise_errors=True):
raise_errors: bool
If true, raises ValidationError on invalid data
"""
- if raise_errors:
- _, name = schema_name(schema, parent_ns)
- else:
- name = parent_ns
return (
isinstance(datum, Mapping) and
all(is_str(k) for k in iterkeys(datum)) and
all(validate(datum=v, schema=schema['values'],
- field=name,
+ field=parent_ns,
raise_errors=raise_errors) for v in itervalues(datum))
)
@@ -252,15 +245,12 @@ def validate_record(datum, schema, parent_ns=None, raise_errors=True):
raise_errors: bool
If true, raises ValidationError on invalid data
"""
- if raise_errors:
- namespace, name = schema_name(schema, parent_ns)
- else:
- name = parent_ns
+ _, namespace = schema_name(schema, parent_ns)
return (
isinstance(datum, Mapping) and
all(validate(datum=datum.get(f['name'], f.get('default')),
schema=f['type'],
- field=schema_name(f, name)[1] if raise_errors else name,
+ field='{}.{}'.format(namespace, f['name']),
raise_errors=raise_errors)
for f in schema['fields']
)
@@ -357,28 +347,22 @@ def validate(datum, schema, field=None, raise_errors=True):
"""
record_type = extract_record_type(schema)
result = None
- ns_field = ''
-
- if hasattr(schema, 'get') and raise_errors:
- parent_ns, ns_field = schema_name(schema, None)
- elif field:
- ns_field = field
validator = VALIDATORS.get(record_type)
if validator:
result = validator(datum, schema=schema,
- parent_ns=ns_field,
+ parent_ns=field,
raise_errors=raise_errors)
elif record_type in SCHEMA_DEFS:
result = validate(datum,
schema=SCHEMA_DEFS[record_type],
- field=ns_field,
+ field=field,
raise_errors=raise_errors)
else:
raise UnknownType(record_type)
if raise_errors and result is False:
- raise ValidationError(ValidationErrorData(datum, schema, ns_field))
+ raise ValidationError(ValidationErrorData(datum, schema, field))
return result

MODIFY
fastavro/schema.py
fastavro/schema.py
@@ -5,7 +5,7 @@ except ImportError:
from ._schema_common import UnknownType
-schema_name = _schema.schema_name
+_schema_name = _schema.schema_name
load_schema = _schema.load_schema
extract_record_type = _schema.extract_record_type
populate_schema_defs = _schema.populate_schema_defs

MODIFY
tests/test_validation.py
tests/test_validation.py
@@ -234,6 +234,54 @@ def test_validator_numeric():
# and plenty more to add I suppose
+def test_validate_array():
+ my_schema = {
+ "fields": [
+ {
+ "name": "array",
+ "type": {
+ "type": "array",
+ "items": "string",
+ },
+ },
+ ],
+ "namespace": "namespace",
+ "name": "test_validate_array",
+ "type": "record"
+ }
+
+ datum = {"array": [1]}
+ with pytest.raises(ValidationError) as exc:
+ validate(datum, my_schema)
+
+ for error in exc.value.errors:
+ assert error.field == 'namespace.test_validate_array.array'
+
+
+def test_validate_map():
+ my_schema = {
+ "fields": [
+ {
+ "name": "map",
+ "type": {
+ "type": "map",
+ "values": "string",
+ },
+ },
+ ],
+ "namespace": "namespace",
+ "name": "test_validate_map",
+ "type": "record"
+ }
+
+ datum = {"map": {"key": 1}}
+ with pytest.raises(ValidationError) as exc:
+ validate(datum, my_schema)
+
+ for error in exc.value.errors:
+ assert error.field == 'namespace.test_validate_map.map'
+
+
def test_validator_numeric_numpy():
np_ints = [
np.int_,

fix field name when validating arrays