Source code for umongo.instance

import abc

from .document import DocumentTemplate
from .embedded_document import EmbeddedDocumentTemplate
from .exceptions import (
    AlreadyRegisteredDocumentError,
    NoDBDefinedError,
    NotRegisteredDocumentError,
)
from .template import get_template


[docs] class Instance(abc.ABC): """Abstract instance class Instances aims at collecting and implementing :class:`umongo.template.Template`:: # Doc is a template, cannot use it for the moment class Doc(DocumentTemplate): pass instance = MyFrameworkInstance() # doc_cls is the instance's implementation of Doc doc_cls = instance.register(Doc) # Implementations are registered as attribute into the instance instance.Doc is doc_cls # Now we can work with the implementations doc_cls.find() .. note:: Instance registration is divided between :class:`umongo.Document` and :class:`umongo.EmbeddedDocument`. """ BUILDER_CLS = None def __init__(self, db=None): self.builder = self.BUILDER_CLS(self) self._doc_lookup = {} self._embedded_lookup = {} self._mixin_lookup = {} self._db = db if db is not None: self.set_db(db) @classmethod def from_db(cls, db): from .frameworks import find_instance_from_db # noqa: PLC0415 instance_cls = find_instance_from_db(db) instance = instance_cls() instance.set_db(db) return instance
[docs] def retrieve_document(self, name_or_template): """Retrieve a :class:`umongo.document.DocumentImplementation` registered into this instance from its name or its template class (i.e. :class:`umongo.Document`). """ if not isinstance(name_or_template, str): name_or_template = name_or_template.__name__ if name_or_template not in self._doc_lookup: raise NotRegisteredDocumentError( f'Unknown document class "{name_or_template}"' ) return self._doc_lookup[name_or_template]
[docs] def retrieve_embedded_document(self, name_or_template): """Retrieve a :class:`umongo.embedded_document.EmbeddedDocumentImplementation` registered into this instance from it name or it template class (i.e. :class:`umongo.EmbeddedDocument`). """ if not isinstance(name_or_template, str): name_or_template = name_or_template.__name__ if name_or_template not in self._embedded_lookup: raise NotRegisteredDocumentError( f'Unknown embedded document class "{name_or_template}"', ) return self._embedded_lookup[name_or_template]
[docs] def register(self, template): """Generate an :class:`umongo.template.Implementation` from the given :class:`umongo.template.Template` for this instance. :param template: :class:`umongo.template.Template` to implement :return: The :class:`umongo.template.Implementation` generated .. note:: This method can be used as a decorator. This is useful when you only have a single instance to work with to directly use the class you defined:: @instance.register class MyEmbedded(EmbeddedDocument): pass @instance.register class MyDoc(Document): emb = fields.EmbeddedField(MyEmbedded) MyDoc.find() """ # Retrieve the template if another implementation has been provided instead template = get_template(template) if issubclass(template, DocumentTemplate): implementation = self._register_doc(template) elif issubclass(template, EmbeddedDocumentTemplate): implementation = self._register_embedded_doc(template) else: # MixinDocument implementation = self._register_mixin_doc(template) return implementation
def _register_doc(self, template): implementation = self.builder.build_from_template(template) if implementation.__name__ in self._doc_lookup: raise AlreadyRegisteredDocumentError( f'Document "{implementation.__name__}" already registered' ) self._doc_lookup[implementation.__name__] = implementation return implementation def _register_embedded_doc(self, template): implementation = self.builder.build_from_template(template) if implementation.__name__ in self._embedded_lookup: raise AlreadyRegisteredDocumentError( f'EmbeddedDocument "{implementation.__name__}" already registered' ) self._embedded_lookup[implementation.__name__] = implementation return implementation def _register_mixin_doc(self, template): implementation = self.builder.build_from_template(template) if implementation.__name__ in self._mixin_lookup: raise AlreadyRegisteredDocumentError( f'MixinDocument "{implementation.__name__}" already registered' ) self._mixin_lookup[implementation.__name__] = implementation return implementation @property def db(self): if self._db is None: raise NoDBDefinedError("db not set, please call set_db") return self._db @abc.abstractmethod def is_compatible_with(self, db): return NotImplemented
[docs] def set_db(self, db): """Set the database to use whithin this instance. .. note:: The documents registered in the instance cannot be used before this function is called. """ assert self.is_compatible_with(db) self._db = db