schematics
schematics copied to clipboard
UnionType with ModelType fails during Model.to_primitive() with AttributeError: 'Context' object has no attribute 'convert'
Attempting to use ModelType as a type within a UnionType seems to work except when trying to convert the model back into a dict via to_primitive():
The test:
import pytest
from schematics import models, types, undefined
class SimpleModel(models.Model):
simple_field = types.StringType()
class MyModel(models.Model):
my_field = types.UnionType((types.StringType, types.ModelType), model_spec=SimpleModel)
def test_union_type():
my_inst = MyModel(dict(my_field={'simple_field': 'simple_value'}))
my_inst.to_primitive()
The error:
============================================================== FAILURES ===============================================================
___________________________________________________________ test_union_type ___________________________________________________________
def test_union_type():
my_inst = MyModel(dict(my_field={'simple_field': 'simple_value'}))
> my_inst.to_primitive()
repro.py:12:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/models.py:309: in to_primitive
return to_primitive(self._schema, self, role=role, app_data=app_data, **kwargs)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/transforms.py:436: in to_primitive
return export_loop(cls, instance_or_dict, to_primitive_converter, **kwargs)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/transforms.py:277: in export_loop
value = _field_converter(field, value, context)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/transforms.py:355: in __call__
return self.func(*args)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/transforms.py:370: in to_primitive_converter
return field.export(value, PRIMITIVE, context)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/types/base.py:286: in export
return self.export_mapping[format](value, context)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/types/union.py:96: in to_primitive
field, _ = self._resolve(value, context)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/types/union.py:67: in _resolve
response = self.resolve(value, context)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/types/union.py:59: in resolve
value = field.convert(value, context)
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/types/compound.py:48: in convert
return self._convert(value, context)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <ModelType(SimpleModel) instance>, value = <SimpleModel instance>
context = Context({'initialized': True, 'field_converter': <schematics.transforms.BasicConverter object at 0x7f483c5c5128>, 'role': None, 'raise_error_on_role': True, 'export_level': None, 'app_data': {}})
def _convert(self, value, context):
field_model_class = self.model_class
if isinstance(value, field_model_class):
model_class = type(value)
elif isinstance(value, dict):
model_class = field_model_class
else:
raise ConversionError(
_("Input must be a mapping or '%s' instance") % field_model_class.__name__)
> if context.convert and context.oo:
E AttributeError: 'Context' object has no attribute 'convert'
../../../../.venv_terrasphere/lib/python3.6/site-packages/schematics/types/compound.py:156: AttributeError
I was able to work around this issue by creating my own uniontype and overriding export() with the following:
if isinstance(value, GetAttrModel):
return self._types[GetAttrType].export(value, format, context)
return super().export(value, format, context)