Source code for anyblok.declarations

# This file is a part of the AnyBlok project
#
#    Copyright (C) 2014 Jean-Sebastien SUZANNE <jssuzanne@anybox.fr>
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file,You can
# obtain one at http://mozilla.org/MPL/2.0/.
from .common import add_autodocs
from .mapper import MapperAdapter


[docs]class DeclarationsException(AttributeError): """Simple Exception for Declarations"""
[docs]class Declarations: """Represents all the declarations done by the bloks .. warning:: This is a global information, during the execution you must use the registry. The registry is the real assembler of the python classes based on the installed bloks :: from anyblok import Declarations """ declaration_types = {}
[docs] @classmethod def register(cls, parent, cls_=None, **kwargs): """Method to add the blok in the registry under a type of declaration :param parent: An existing blok class in the Declaration :param ``cls_``: The ``class`` object to add in the Declaration :rtype: ``cls_`` :exception: DeclarationsException """ def wrapper(self): name = kwargs.get("name_", self.__name__) if parent.__declaration_type__ not in cls.declaration_types: raise DeclarationsException( "No parents %r for %s" % (parent, name) ) # pragma: no cover declaration = cls.declaration_types[parent.__declaration_type__] declaration.register(parent, name, self, **kwargs) node = getattr(parent, name) setattr(node, "__declaration_type__", parent.__declaration_type__) setattr( node, "__registry_name__", parent.__registry_name__ + "." + name ) # Only for auto doc with autoanyblok-declaration directive setattr(self, "__declaration__", declaration) setattr( self, "__registry_name__", parent.__registry_name__ + "." + name ) return self if cls_: return wrapper(cls_) else: return wrapper
[docs] @classmethod def unregister(cls, entry, cls_): """Method to remove the blok from a type of declaration :param entry: declaration entry of the model where the ``cls_`` must be removed :param ``cls_``: The ``class`` object to remove from the Declaration :rtype: ``cls_`` """ declaration = cls.declaration_types[entry.__declaration_type__] declaration.unregister(entry, cls_) return cls_
[docs] @classmethod def add_declaration_type( cls, cls_=None, isAnEntry=False, pre_assemble=None, assemble=None, initialize=None, unload=None, ): """Add a declaration type :param cls_: The ``class`` object to add as a world of the MetaData :param isAnEntry: if true the type will be assembled by the registry :param pre_assemble: name of the method callback to call (classmethod) :param assemble: name of the method callback to call (classmethod) :param initialize: name of the method callback to call (classmethod) :param unload: name of the method callback to call (classmethod) :exception: DeclarationsException """ def wrapper(self): from anyblok.registry import RegistryManager name = self.__name__ if name in cls.declaration_types: raise DeclarationsException( "The declaration type %r is already defined" % name ) cls.declaration_types[name] = self setattr(self, "__registry_name__", name) setattr(self, "__declaration_type__", name) setattr(cls, name, self) if isAnEntry: pre_assemble_callback = assemble_callback = None initialize_callback = None if pre_assemble and hasattr(self, pre_assemble): pre_assemble_callback = getattr(self, pre_assemble) if assemble and hasattr(self, assemble): assemble_callback = getattr(self, assemble) if initialize and hasattr(self, initialize): initialize_callback = getattr(self, initialize) RegistryManager.declare_entry( name, pre_assemble_callback=pre_assemble_callback, assemble_callback=assemble_callback, initialize_callback=initialize_callback, ) # All declaration type can need to be unload declarated values if unload and hasattr(self, unload): RegistryManager.declare_unload_callback( name, getattr(self, unload) ) # pragma: no cover return self if cls_: return wrapper(cls_) else: return wrapper
def cache(size=128): autodoc = """ **Cached method** with size=%(size)s """ % dict( size=size ) def wrapper(method): add_autodocs(method, autodoc) method.is_cache_method = True method.is_cache_classmethod = False method.size = size return method return wrapper def classmethod_cache(size=128): autodoc = """ **Cached classmethod** with size=%(size)s """ % dict( size=size ) def wrapper(method): add_autodocs(method, autodoc) method.is_cache_method = True method.is_cache_classmethod = True method.size = size return method return wrapper def hybrid_method(method=None): autodoc = """ **Hybrid method** """ if method: add_autodocs(method, autodoc) method.is_an_hybrid_method = True return method else: def wrapper(method): add_autodocs(method, autodoc) method.is_an_hybrid_method = True return method return wrapper def listen(*args, **kwargs): autodoc = """ **listen** event call with the arguments %(args)r and the positionnal argument %(kwargs)r """ % dict( args=args, kwargs=kwargs ) mapper = MapperAdapter(*args, **kwargs) def wrapper(method): add_autodocs(method, autodoc) mapper.listen(method) return classmethod(method) return wrapper