Source code for pydent.marshaller.registry

"""Model and schema registry meta-classes."""
from collections import defaultdict
from pprint import pformat

from pydent.marshaller.exceptions import ModelRegistryError
from pydent.marshaller.exceptions import SchemaRegistryError
from pydent.utils.loggable import condense_long_lists
from pydent.utils.logging_helpers import did_you_mean


[docs]class SchemaRegistry(type): """Stores a list of models that can be accessed by name.""" schemas = {} # the registry of Schemas instantiated _fields = None # list of fields instantiated _model_class = None # reference to model class the schema is attached to BASE = "DynamicSchema"
[docs] def __init__(cls, name, bases, selfdict): """Saves model to the registry.""" super().__init__(name, bases, selfdict) if bases != () and name != SchemaRegistry.BASE: if name in SchemaRegistry.schemas: raise SchemaRegistryError( "Cannot register '{}' since it already exists.".format(name) ) SchemaRegistry.schemas[name] = cls
@property def model_class(cls): """The registered model class.""" return cls._model_class @property def fields(cls): """The shcmea fields.""" return cls._fields @property def grouped_fields(cls): """Fields grouped by their base classes. Returns empty list of base class not in fields. """ grouped = defaultdict(dict) for fname, field in cls.fields.items(): mro = field.__class__.__mro__ for b in mro[:-2]: grouped[b.__name__][fname] = field return grouped
[docs] @staticmethod def make_schema_name(name): """Makes a Schema class name from a model name (appending 'Schema' to name)""" return name + "Schema"
[docs] @staticmethod def get_schema(name): """Gets model by model_name.""" if name not in SchemaRegistry.schemas: raise SchemaRegistryError( 'Schema "{}" not found in SchemaRegistry. Available schemas:\n{}'.format( name, ",".join(SchemaRegistry.schemas.keys()) ) ) else: return SchemaRegistry.schemas[name]
[docs] @staticmethod def get_model_schema(model_name): """Gets a model schema from a model name.""" return SchemaRegistry.get_schema(SchemaRegistry.make_schema_name(model_name))
[docs]class ModelRegistry(type): """Stores list of all models instantiated from the SchemaModel base.""" models = {} # the dictionary of model classes instantiated _model_schema = None # the class attribute to store the model_classes Schema class _fields_key = "fields" # the class level attribute key to instantiate model fields _data_key = "__serialized_data" # the attribute key used to store serialized data _deserialized_key = ( "__deserialized_data" # the attribute key used to store serialized data ) BASE = "SchemaModel"
[docs] def __init__(cls, name, bases, selfdict): """Saves model to the registry.""" super().__init__(name, bases, selfdict) if bases != () and bases[0].__name__ != ModelRegistry.BASE: ModelRegistry.models[name] = cls
@property def model_schema(cls): """Returns the class's schema.""" return cls._model_schema @classmethod def did_you_mean_model(cls, model_name, fallback=True): model_names = list(cls.models.keys()) available_models = ", ".join(model_names) msg = did_you_mean(model_name, model_names) if not msg and fallback: return "Available models: {}".format(pformat(available_models)) return msg
[docs] @classmethod def get_model(cls, name): """Gets a model class by name.""" if name not in ModelRegistry.models: raise ModelRegistryError( "Model '{}' not found in registry.\n{}".format( name, cls.did_you_mean_model(name) ) ) return cls.models[name]