Package logilab :: Package common :: Module registry :: Class RegistryStore
[frames] | no frames]

Class RegistryStore

source code

object --+    
         |    
      dict --+
             |
            RegistryStore

This class is responsible for loading objects and storing them
in their registry which is created on the fly as needed.

It handles dynamic registration of objects and provides a
convenient api to access them. To be recognized as an object that
should be stored into one of the store's registry
(:class:`Registry`), an object must provide the following
attributes, used control how they interact with the registry:

:attr:`__registries__`
  list of registry names (string like 'views', 'templates'...) into which
  the object should be registered

:attr:`__regid__`
  object identifier in the registry (string like 'main',
  'primary', 'folder_box')

:attr:`__select__`
  the object predicate selectors

Moreover, the :attr:`__abstract__` attribute may be set to `True`
to indicate that an object is abstract and should not be registered
(such inherited attributes not considered).

.. Note::

  When using the store to load objects dynamically, you *always* have
  to use **super()** to get the methods and attributes of the
  superclasses, and not use the class identifier. If not, you'll get into
  trouble at reload time.

  For example, instead of writing::

      class Thing(Parent):
          __regid__ = 'athing'
          __select__ = yes()

          def f(self, arg1):
              Parent.f(self, arg1)

  You must write::

      class Thing(Parent):
          __regid__ = 'athing'
          __select__ = yes()

          def f(self, arg1):
              super(Thing, self).f(arg1)

Controlling object registration
-------------------------------

Dynamic loading is triggered by calling the
:meth:`register_objects` method, given a list of directories to
inspect for python modules.

.. automethod:: register_objects

For each module, by default, all compatible objects are registered
automatically. However if some objects come as replacement of
other objects, or have to be included only if some condition is
met, you'll have to define a `registration_callback(vreg)`
function in the module and explicitly register **all objects** in
this module, using the api defined below.


.. automethod:: RegistryStore.register_all
.. automethod:: RegistryStore.register_and_replace
.. automethod:: RegistryStore.register
.. automethod:: RegistryStore.unregister

.. Note::
    Once the function `registration_callback(vreg)` is implemented in a
    module, all the objects from this module have to be explicitly
    registered as it disables the automatic object registration.


Examples:

.. sourcecode:: python

   def registration_callback(store):
      # register everything in the module except BabarClass
      store.register_all(globals().values(), __name__, (BabarClass,))

      # conditionally register BabarClass
      if 'babar_relation' in store.schema:
          store.register(BabarClass)

In this example, we register all application object classes defined in the module
except `BabarClass`. This class is then registered only if the 'babar_relation'
relation type is defined in the instance schema.

.. sourcecode:: python

   def registration_callback(store):
      store.register(Elephant)
      # replace Babar by Celeste
      store.register_and_replace(Celeste, Babar)

In this example, we explicitly register classes one by one:

* the `Elephant` class
* the `Celeste` to replace `Babar`

If at some point we register a new appobject class in this module, it won't be
registered at all without modification to the `registration_callback`
implementation. The first example will register it though, thanks to the call
to the `register_all` method.

Controlling registry instantiation
----------------------------------

The `REGISTRY_FACTORY` class dictionary allows to specify which class should
be instantiated for a given registry name. The class associated to `None`
key will be the class used when there is no specific class for a name.

Instance Methods
new empty dictionary

__init__(self, debugmode=False)
x.__init__(...) initializes x; see help(type(x)) for signature
source code
 
reset(self)
clear all registries managed by this store
source code
 
__getitem__(self, name)
return the registry (dictionary of class objects) associated to...
source code
 
registry_class(self, regid)
return existing registry named regid or use factory to create one and...
source code
D.get(k,d), also set D[k]=d if k not in D
setdefault(self, regid) source code
 
register_all(self, objects, modname, butclasses=())
register registrable objects into `objects`.
source code
 
register(self, obj, registryname=None, oid=None, clear=False)
register `obj` implementation into `registryname` or `obj.__registries__` if not specified, with identifier `oid` or `obj.__regid__` if not specified.
source code
 
unregister(self, obj, registryname=None)
unregister `obj` object from the registry `registryname` or `obj.__registries__` if not specified.
source code
 
register_and_replace(self, obj, replaced, registryname=None)
register `obj` object into `registryname` or `obj.__registries__` if not specified.
source code
 
init_registration(self, path, extrapath=None)
reset registry and walk down path to return list of (path, name)...
source code
 
register_objects(self, path, extrapath=None)
register all objects found walking down <path>
source code
 
initialization_completed(self)
call initialization_completed() on all known registries
source code
 
is_reload_needed(self, path)
return True if something module changed and the registry should be...
source code
 
load_file(self, filepath, modname)
load registrable objects (if any) from a python file
source code
 
load_module(self, module)
Automatically handle module objects registration.
source code

Inherited from dict: __cmp__, __contains__, __delitem__, __eq__, __ge__, __getattribute__, __gt__, __iter__, __le__, __len__, __lt__, __ne__, __new__, __repr__, __setitem__, __sizeof__, clear, copy, fromkeys, get, has_key, items, iteritems, iterkeys, itervalues, keys, pop, popitem, update, values, viewitems, viewkeys, viewvalues

Inherited from object: __delattr__, __format__, __reduce__, __reduce_ex__, __setattr__, __str__, __subclasshook__

Class Methods
 
is_registrable(cls, obj)
ensure `obj` should be registered
source code
Class Variables
  REGISTRY_FACTORY = {None: Registry}
  debug = lambda msg,* a,** kw:
  exception = lambda msg,* a,** kw:
  critical = lambda msg,* a,** kw:
  error = lambda msg,* a,** kw:
  warning = lambda msg,* a,** kw:
  info = lambda msg,* a,** kw:

Inherited from dict: __hash__

Properties

Inherited from object: __class__

Method Details

__init__(self, debugmode=False)
(Constructor)

source code 

x.__init__(...) initializes x; see help(type(x)) for signature

Returns:
new empty dictionary

Overrides: object.__init__
(inherited documentation)

__getitem__(self, name)
(Indexing operator)

source code 
return the registry (dictionary of class objects) associated to
this name

Overrides: dict.__getitem__

registry_class(self, regid)

source code 
return existing registry named regid or use factory to create one and
return it

setdefault(self, regid)

source code 
Returns: D.get(k,d), also set D[k]=d if k not in D
Overrides: dict.setdefault
(inherited documentation)

register_all(self, objects, modname, butclasses=())

source code 
register registrable objects into `objects`.

Registrable objects are properly configured subclasses of
:class:`RegistrableObject`.  Objects which are not defined in the module
`modname` or which are in `butclasses` won't be registered.

Typical usage is:

.. sourcecode:: python

    store.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))

So you get partially automatic registration, keeping manual registration
for some object (to use
:meth:`~logilab.common.registry.RegistryStore.register_and_replace` for
instance).

register(self, obj, registryname=None, oid=None, clear=False)

source code 
register `obj` implementation into `registryname` or
`obj.__registries__` if not specified, with identifier `oid` or
`obj.__regid__` if not specified.

If `clear` is true, all objects with the same identifier will be
previously unregistered.

register_and_replace(self, obj, replaced, registryname=None)

source code 
register `obj` object into `registryname` or
`obj.__registries__` if not specified. If found, the `replaced` object
will be unregistered first (else a warning will be issued as it is
generally unexpected).

init_registration(self, path, extrapath=None)

source code 
reset registry and walk down path to return list of (path, name)
file modules to be loaded

is_reload_needed(self, path)

source code 
return True if something module changed and the registry should be
reloaded

load_module(self, module)

source code 
Automatically handle module objects registration.

Instances are registered as soon as they are hashable and have the
following attributes:

* __regid__ (a string)
* __select__ (a callable)
* __registries__ (a tuple/list of string)

For classes this is a bit more complicated :

- first ensure parent classes are already registered

- class with __abstract__ == True in their local dictionary are skipped

- object class needs to have registries and identifier properly set to a
  non empty string to be registered.

is_registrable(cls, obj)
Class Method

source code 
ensure `obj` should be registered

as arbitrary stuff may be registered, do a lot of check and warn about
weird cases (think to dumb proxy objects)