Skip to content

Commit

Permalink
Change: Improve error message if model can't be created
Browse files Browse the repository at this point in the history
Sometimes the models are incomplete or the schema description at the
GitHub REST API docs are wrong, in this case we need error information
about which property can't be set from which value. This allows for
easier fixing of the model.
  • Loading branch information
bjoernricks committed Feb 3, 2023
1 parent 4a0ae82 commit 2e6d234
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
26 changes: 20 additions & 6 deletions pontos/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

from dateutil import parser as dateparser

from pontos.errors import PontosError

try:
from typing import get_args, get_origin
except ImportError:
Expand All @@ -30,6 +32,12 @@
__all__ = ("Model",)


class ModelError(PontosError):
"""
Errors raised for Models
"""


def dotted_attributes(obj: Any, data: Dict[str, Any]) -> Any:
"""
Set dotted attributes on an object
Expand Down Expand Up @@ -147,12 +155,18 @@ def from_dict(cls, data: Dict[str, Any]):
additional_attrs = {}
type_hints = get_type_hints(cls)
for name, value in data.items():
if isinstance(value, list):
model_field_cls = type_hints.get(name)
value = [cls._get_value(model_field_cls, v) for v in value]
elif value is not None:
model_field_cls = type_hints.get(name)
value = cls._get_value(model_field_cls, value)
try:
if isinstance(value, list):
model_field_cls = type_hints.get(name)
value = [cls._get_value(model_field_cls, v) for v in value]
elif value is not None:
model_field_cls = type_hints.get(name)
value = cls._get_value(model_field_cls, value)
except TypeError as e:
raise ModelError(
f"Error while creating {cls.__name__}. Could not set value "
f"for '{name}' from '{value}'."
) from e

if name in type_hints:
kwargs[name] = value
Expand Down
14 changes: 13 additions & 1 deletion tests/models/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from datetime import date, datetime, timedelta, timezone
from typing import Dict, List, Optional, Union

from pontos.models import Model, ModelAttribute, dotted_attributes
from pontos.models import Model, ModelAttribute, ModelError, dotted_attributes


class ModelTestCase(unittest.TestCase):
Expand Down Expand Up @@ -197,3 +197,15 @@ class ExampleModel(Model):

model = ExampleModel.from_dict({"foo": [{"a": 1}, {"b": 2}, {"c": 3}]})
self.assertEqual(model.foo, [{"a": 1}, {"b": 2}, {"c": 3}])

def test_model_error(self):
@dataclass
class ExampleModel(Model):
foo: Optional[str] = None

with self.assertRaisesRegex(
ModelError,
"Error while creating ExampleModel. Could not set value for 'foo' "
"from '{'bar': 'baz'}'.",
):
ExampleModel.from_dict({"foo": {"bar": "baz"}})

0 comments on commit 2e6d234

Please sign in to comment.