An ebook/comic library service and web client
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
1.8 KiB

  1. """Handle Model Serialization."""
  2. from typing import Dict, Callable, Any, List, Optional, Type
  3. from atheneum import errors
  4. from atheneum.db import db
  5. class BaseSerializer: # pylint: disable=too-few-public-methods
  6. """Base Model serializer."""
  7. def __init__(self, model: Type[db.Model]) -> None:
  8. """Initialize the base serializer."""
  9. self._fields: Dict[str, Callable[[db.Model], Any]] = {}
  10. self.model = model
  11. def serialize(self, options: Optional[List[str]]) -> Any:
  12. """Convert Model field and factories to dicts."""
  13. field_factories = self._serializers()
  14. if not options:
  15. options = list(field_factories.keys())
  16. ret = {}
  17. for key in options:
  18. if key not in field_factories:
  19. raise errors.ValidationError(
  20. 'Invalid key: %r. Valid keys: %r.' % (
  21. key, list(sorted(field_factories.keys()))))
  22. factory = field_factories[key]
  23. val = factory()
  24. if val is not None:
  25. ret[key] = val
  26. return ret
  27. def _serializers(self) -> Dict[str, Callable[[], Any]]:
  28. """Field definitions."""
  29. raise NotImplementedError()
  30. _model_serializers: Dict[str, Type[BaseSerializer]] = {}
  31. def register_serializer(
  32. model_name: str, model_serializer: Type[BaseSerializer]) -> None:
  33. """Add a model to the serializer mapping."""
  34. _model_serializers[model_name] = model_serializer
  35. def serialize_model(model_obj: db.Model) -> Any:
  36. """Lookup a Model and hand off to the serializer."""
  37. try:
  38. return _model_serializers[
  39. type(model_obj).__name__](model_obj).serialize(None)
  40. except KeyError:
  41. raise NotImplementedError(
  42. '{} has no registered serializers'.format(model_obj.__name__))