Entity store and decorators¶
The entity store class provides functions to register entity instances in an entity store.
It also allow entity classes to be registered at class-level in a “base store”. These entity classes will be instantiated when the entity store gets instantiated, and the resulting instances will be registered.
It also allows “register mappings” to be defined, they allow objects passed to register functions to be transformed based on a mapping. When looking for a mapping, register functions will compare their argument to the mapping key (using issubclass, or isinstance), and use the corresponding mapping value to get the object that will be registered.
Additionally, register mapping keys can be iterables (list or tuples), in which case the register functions will compare their argument to any of the elements in the mapping key, and match even if only a single item in the mapping key matches the argument.
The base store is copied on each class definition, using a metaclass, so that using register functions that class-level won’t alter the base store of other class definitions.
This module also contains a provides() decorator, that decorates a entity store class, adding an object to its base store.
Doctests that use functionality in EntityStore can be seen in other classes (in particular django_crucrudile.routers.Router). They may help to get a good idea of what the entity, entity store and entity graph concepts mean.
Decorators¶
- django_crucrudile.entities.store.provides(provided, **kwargs)[source]¶
Return a decorator that uses EntityStore.register_class() to register the given object in the base store.
Parameters: provided (object) – Class (or object) to register in the base store. This can be an object since it may be transformed by :func:`EntityStore.register_apply_map`d
Entity store¶
- class django_crucrudile.entities.store.EntityStoreMetaclass(name, bases, attrs)[source]¶
Bases: abc.ABCMeta
EntityStoreMetaclass allows EntityStore to use a different _base_store store (list instance) for each class definitions (cls instantiation)
Note
Subclasses abc.ABCMeta because it will be used as the metaclass for an entity, and entity are abstract classes, which needs the âbc.ABCMeta base class.
>>> class Store(metaclass=EntityStoreMetaclass): ... pass >>> >>> class FailStore: ... _fail_store = [] >>> >>> class NewStore(Store): ... pass >>> >>> class FailNewStore(FailStore): ... pass
>>> (NewStore._base_store is ... Store._base_store) False >>> (NewStore._base_register_map is ... Store._base_register_map) False >>> (NewStore._base_register_class_map is ... Store._base_register_class_map) False
>>> (FailNewStore._fail_store is ... FailStore._fail_store) True
- class django_crucrudile.entities.store.EntityStore[source]¶
Bases: builtins.object
Provides an entity store, and a register() method that registers entities in the entity store.
The subclass implementation of patterns() should iterate over the entity store.
- static register_apply_map(entity, mapping, transform_kwargs=None, silent=True)[source]¶
Apply mapping of value in mapping if entity is subclass (issubclass()) or instance (isinstance()) of key
Parameters: - entity (object or class) – Object to pass to found mappings
- mapping (dict) – Register mapping, used to get callable to pass entity to
- transform_kwargs (dict) – Extra keyword arguments to pass to the found transform functions (mapping keys)
- silent – If set to False, will fail if not matching mapping was found.
Raises LookupError: If silent is False, and no matching mapping was found
>>> from mock import Mock >>> >>> class Class: ... pass >>> class SubClass(Class): ... pass >>> class OtherClass: ... pass >>> >>> instance = SubClass()
With instance :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... instance, ... {Class: class_mock} ... ) >>> class_mock.assert_called_once_with(instance)
With instance, and default mapping :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... instance, ... {None: class_mock} ... ) >>> class_mock.assert_called_once_with(instance)
With instance and iterable bases :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... instance, ... {(OtherClass, Class): class_mock} ... ) >>> class_mock.assert_called_once_with(instance)
With instance and iterable bases (no matching base) :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... instance, ... {(OtherClass, ): class_mock} ... ) >>> applied is instance True >>> class_mock.called False
With instance and iterable bases (no matching base, not silent) :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... instance, ... {(OtherClass, ): class_mock}, ... silent=False ... ) ... Traceback (most recent call last): ... LookupError: Could not find matching key in register mapping. Used test 'isinstance', register mapping bases are 'OtherClass', tested against 'SubClass'
With subclass :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... SubClass, ... {Class: class_mock} ... ) >>> class_mock.assert_called_once_with(SubClass)
With subclass and iterable bases (no matching base) :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... SubClass, ... {(OtherClass, ): class_mock} ... ) >>> applied is SubClass True >>> class_mock.called False
With subclass and single bases (no matching base, not silent) :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... SubClass, ... {OtherClass: class_mock}, ... silent=False ... ) ... Traceback (most recent call last): ... LookupError: Could not find matching key in register mapping. Used test 'issubclass', register mapping bases are 'OtherClass', tested against 'SubClass'
With subclass and no mappings (not silent) :
>>> class_mock = Mock() >>> applied = EntityStore.register_apply_map( ... SubClass, ... {}, ... silent=False ... ) ... Traceback (most recent call last): ... LookupError: Could not find matching key in register mapping. Used test 'issubclass', register mapping bases are '', tested against 'SubClass'
- classmethod get_register_class_map()[source]¶
Mapping of type to function that will be evaluated (with entity) when calling register. See register_class() and register_apply_map().
Overriding implementations must call the base implementation (using super(), usually), so that the base mappings set by set_register_class_mapping() can be returned.
The base implementation returns a copy of the stored mapping, so overriding implementations may append to the return value.
See also
For doctests that use this member, see django_crucrudile.entities.store.EntityStore.register_class()
- classmethod get_register_class_map_kwargs()[source]¶
Arguments passed when applying register map, in register_class()
See also
For doctests that use this member, see django_crucrudile.entities.store.EntityStore.register_class()
- get_register_map()[source]¶
Mapping of type to function that will be evaluated (with entity) when calling register. See register() and register_apply_map()
Overriding implementations MUST call the base implementation (using super(), usually), so that the base mappings set by set_register_mapping() can be returned.
The base implementation returns a copy of the stored mapping, so overriding implementations may append to the return value.
See also
For doctests that use this member, see django_crucrudile.entities.store.EntityStore.register()
- get_register_map_kwargs()[source]¶
Arguments passed when applying register map, in register()
See also
For doctests that use this member, see django_crucrudile.entities.store.EntityStore.register()
- classmethod set_register_class_mapping(key, value)[source]¶
Set a base register class mapping, that will be returned (possibly with other mappings) by get_register_class_map().
Parameters: - key (class or tuple of classes) – Register class mapping bases
- value (callable) – Register class mapping value
>>> from mock import Mock >>> mock_mapping_func = Mock() >>> >>> class Class: ... pass >>> class Store(EntityStore): ... pass >>> >>> >>> Store.set_register_class_mapping( ... Class, mock_mapping_func ... ) >>> Store.get_register_class_map() == ( ... {Class: mock_mapping_func} ... ) True
- classmethod set_register_mapping(key, value)[source]¶
Set a base register mapping, that will be returned (possibly with other mappings) by get_register_map().
Parameters: - key (class or tuple of classes) – Register mapping bases
- value (callable) – Register mapping value
>>> from mock import Mock >>> mock_mapping_func = Mock() >>> >>> class Class: ... pass >>> >>> class Store(EntityStore): ... pass >>> >>> Store.set_register_mapping( ... Class, mock_mapping_func ... ) >>> Store().get_register_map() == ( ... {Class: mock_mapping_func} ... ) True
- classmethod register_class(register_cls, map_kwargs=None)[source]¶
Add a route class to _base_store, appling mapping from get_register_class_map() where required. This route class will be instantiated (with kwargs from get_base_store_kwargs()) when the Router is itself instiated, using register_base_store().
Parameters: - register_cls – Object to register (usually Route or Router classes, but could be anything because of possible mapping in get_register_class_map_kwargs())
- map_kwargs (dict) – Argument to pass to mapping value if entity gets transformed.
Returns: The registered class, transformed by class register mappings if there was a matching mapping
Return type: class
>>> from mock import Mock >>> mock_entity_instance = Mock() >>> mock_entity = Mock() >>> mock_entity.side_effect = [mock_entity_instance] >>> mock_mapping_func = Mock() >>> mock_mapping_func.side_effect = [mock_entity] >>> >>> class Class: ... pass >>> >>> class Store(EntityStore): ... @classmethod ... def get_register_class_map(self): ... return {Class: mock_mapping_func} >>> >>> Store.register_class(Class) is mock_entity True >>> >>> Store._base_store == [mock_entity] True >>> >>> store = Store() >>> store._store == [mock_entity_instance] True
- register(entity, map_kwargs=None)[source]¶
Register routed entity, applying mapping from get_register_map() where required
Parameters: - entity (django_crucrudile.entities.Entity) – Entity to register
- map_kwargs (dict) – Argument to pass to mapping value if entity gets transformed.
Returns: The registered entity, transformed by register mappings if there was a matching mapping
Return type: >>> from mock import Mock >>> mock_entity_instance = Mock() >>> mock_mapping_func = Mock() >>> mock_mapping_func.side_effect = [mock_entity_instance] >>> >>> class Class: ... pass >>> instance = Class() >>> >>> class Store(EntityStore): ... @classmethod ... def get_register_map(self): ... return {Class: mock_mapping_func} >>> >>> store = Store() >>> store.register(instance) == mock_entity_instance True >>> store._store == [mock_entity_instance] True
- get_base_store_kwargs()[source]¶
Arguments passed when instantiating entity classes in _base_store
Returns: Keyword arguments Return type: dict >>> from mock import Mock >>> mock_entity = Mock() >>> >>> class Store(EntityStore): ... def get_base_store_kwargs(self): ... return {'x': mock_entity} >>> >>> Store.register_class(lambda x: x) is not None True >>> >>> store = Store() >>> store._store == [mock_entity] True
- register_base_store()[source]¶
Instantiate entity classes in _base_store, using arguments from get_base_store_kwargs()
>>> class Store(EntityStore): ... pass >>> >>> Store.register_class(lambda: None) is not None True >>> >>> store = Store() >>> store._store [None]