Files
TeraHz/backend/venv/lib/python3.6/site-packages/serial/test.py
2019-01-21 17:36:00 +01:00

305 lines
9.1 KiB
Python

from __future__ import nested_scopes, generators, division, absolute_import, with_statement, \
print_function, unicode_literals
from .utilities.compatibility import backport
backport() # noqa
from future.utils import native_str
from serial.utilities import qualified_name, calling_function_qualified_name
from serial.abc.model import Model
from warnings import warn
import collections
import json as _json
from itertools import chain
import yaml as _yaml
import serial
try:
import typing
except ImportError as e:
typing = None
def _object_discrepancies(a, b):
# type: (serial.model.Object, serial.model.Object) -> dict
discrepancies = {}
a_properties = set(serial.meta.read(a).properties.keys())
b_properties = set(serial.meta.read(b).properties.keys())
for property_ in a_properties | b_properties:
try:
a_value = getattr(a, property_)
except AttributeError:
a_value = None
try:
b_value = getattr(b, property_)
except AttributeError:
b_value = None
if a_value != b_value:
discrepancies[property_] = (a_value, b_value)
return discrepancies
def json(
model_instance, # type: serial.model.Model
raise_validation_errors=True, # type: bool
):
# type: (...) -> None
model(
model_instance=model_instance,
format_='json',
raise_validation_errors=raise_validation_errors
)
def yaml(
model_instance, # type: serial.model.Model
raise_validation_errors=True, # type: bool
):
# type: (...) -> None
model(
model_instance=model_instance,
format_='yaml',
raise_validation_errors=raise_validation_errors
)
def xml(
model_instance, # type: serial.model.Model
raise_validation_errors=True, # type: bool
):
# type: (...) -> None
raise NotImplementedError()
# model(
# model_instance=model_instance,
# format_='xml',
# raise_validation_errors=raise_validation_errors
# )
def model(
model_instance, # type: serial.model.Model
format_, # type: str
raise_validation_errors=True, # type: bool
):
# type: (...) -> None
"""
Tests an instance of a `serial.model.Model` sub-class.
Parameters:
- model_instance (serial.model.Model):
An instance of a `serial.model.Model` sub-class.
- format_ (str):
The serialization format being tested: 'json', 'yaml' or 'xml'.
- raise_validation_errors (bool):
The function `serial.model.validate` verifies that all required attributes are present, as well as any
additional validations implemented using the model's validation hooks `after_validate` and/or
`before_validate`.
- If `True`, errors resulting from `serial.model.validate` are raised.
- If `False`, errors resulting from `serial.model.validate` are expressed only as warnings.
"""
if not isinstance(model_instance, Model):
value_representation = repr(model_instance)
raise TypeError(
'`%s` requires an instance of `%s` for the parameter `model_instance`, not%s' % (
calling_function_qualified_name(),
qualified_name(Model),
(
(':\n%s' if '\n' in value_representation else ' `%s`') %
value_representation
)
)
)
serial.meta.format_(model_instance, format_)
if isinstance(model_instance, serial.model.Object):
errors = serial.marshal.validate(model_instance, raise_errors=raise_validation_errors)
if errors:
warn('\n' + '\n'.join(errors))
model_type = type(model_instance)
string = str(model_instance)
assert string != ''
reloaded_model_instance = model_type(string)
qualified_model_name = qualified_name(type(model_instance))
try:
assert model_instance == reloaded_model_instance
except AssertionError as e:
sa = serial.marshal.serialize(model_instance)
sb = serial.marshal.serialize(reloaded_model_instance)
ra = ''.join(l.strip() for l in repr(model_instance).split('\n'))
rb = ''.join(l.strip() for l in repr(reloaded_model_instance).split('\n'))
message = [
'Discrepancies were found between the instance of `%s` provided and ' % qualified_model_name +
'a serialized/deserialized clone:'
]
if sa != sb:
message.append(
'\n :\n\n %s\n !=\n %s' % (
sa,
sb
)
)
if ra != rb:
message.append(
'\n %s\n !=\n %s\n' % (
ra,
rb
)
)
for k, a_b in _object_discrepancies(model_instance, reloaded_model_instance).items():
a, b = a_b
assert a != b
sa = serial.marshal.serialize(a)
sb = serial.marshal.serialize(b)
if sa != sb:
message.append(
'\n %s().%s:\n\n %s\n %s\n %s' % (
qualified_model_name,
k,
sa,
'==' if sa == sb else '!=',
sb
)
)
ra = ''.join(l.strip() for l in repr(a).split('\n'))
rb = ''.join(l.strip() for l in repr(b).split('\n'))
if ra != rb:
message.append(
'\n %s\n %s\n %s' % (
ra,
'==' if ra == rb else '!=',
rb
)
)
e.args = tuple(
chain(
(e.args[0] + '\n' + '\n'.join(message) if e.args else '\n'.join(message),),
e.args[1:] if e.args else tuple()
)
)
raise e
reloaded_string = str(reloaded_model_instance)
try:
assert string == reloaded_string
except AssertionError as e:
m = '\n%s\n!=\n%s' % (string, reloaded_string)
if e.args:
e.args = tuple(chain(
(e.args[0] + '\n' + m,),
e.args[1:]
))
else:
e.args = (m,)
raise e
if format_ == 'json':
reloaded_marshalled_data = _json.loads(
string,
object_hook=collections.OrderedDict,
object_pairs_hook=collections.OrderedDict
)
elif format_ == 'yaml':
reloaded_marshalled_data = _yaml.load(string)
elif format_ == 'xml':
raise NotImplementedError()
else:
format_representation = repr(format_)
raise ValueError(
'Valid serialization types for parameter `format_` are "json", "yaml", or "xml'", not" + (
(
':\n%s' if '\n' in format_representation else ' %s.'
) % format_representation
)
)
keys = set()
for property_name, property in serial.meta.read(model_instance).properties.items():
keys.add(property.name or property_name)
property_value = getattr(model_instance, property_name)
if isinstance(property_value, Model) or (
hasattr(property_value, '__iter__') and
(not isinstance(property_value, (str, native_str, bytes)))
):
model(property_value, format_=format_, raise_validation_errors=raise_validation_errors)
for k in reloaded_marshalled_data.keys():
if k not in keys:
raise KeyError(
'"%s" not found in serialized/re-deserialized data: %s' % (
k,
string
)
)
elif isinstance(model_instance, serial.model.Array):
serial.marshal.validate(model_instance)
for item in model_instance:
if isinstance(item, Model) or (
hasattr(item, '__iter__') and
(not isinstance(item, (str, native_str, bytes)))
):
model(item, format_=format_, raise_validation_errors=raise_validation_errors)
elif isinstance(model_instance, serial.model.Dictionary):
serial.marshal.validate(model_instance)
for key, value in model_instance.items():
if isinstance(value, Model) or (
hasattr(value, '__iter__') and
(not isinstance(value, (str, native_str, bytes)))
):
model(value, format_=format_, raise_validation_errors=raise_validation_errors)