[registry] introduce objid/objname method on registries instead of using function/inlined code. Partially closes #98742

So they become customizable per registry.

authorSylvain Thénault <sylvain.thenault@logilab.fr>
changeset99757eea1647
branchdefault
phasepublic
hiddenno
parent revision#2a3b4eb9402f backport stable
child revision#2e1a3c06ad32 [registry] deprecate usage of leading underscore to mark class as abstract / not to register
files modified by this revision
ChangeLog
registry.py
# HG changeset patch
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1357904695 -3600
# Fri Jan 11 12:44:55 2013 +0100
# Node ID 99757eea164702955f97c456253370d8e7941562
# Parent 2a3b4eb9402f978b06edb3d5df9bf8d1ffb47912
[registry] introduce objid/objname method on registries instead of using function/inlined code. Partially closes #98742

So they become customizable per registry.

diff --git a/ChangeLog b/ChangeLog
@@ -1,9 +1,13 @@
1  ChangeLog for logilab.common
2  ============================
3 
4  --
5 +    * registry:
6 +      - introduce objid and objname methods on Registry instead of classid
7 +        function and inlined code (closes #98742)
8 +
9      * loggin_ext: on windows, use colorama to display colored logs, if available (closes #107436)
10 
11  2012-11-14  --  0.58.3
12      * date: fix ustrftime() impl. for python3 (closes #82161, patch by Arfrever
13        Frehtes Taifersar Arahesis) and encoding detection for python2 (closes
diff --git a/registry.py b/registry.py
@@ -143,14 +143,10 @@
14              _toload[0][modname] = fileordir
15              _toload[1].append((fileordir, modname))
16      return _toload
17 
18 
19 -def classid(cls):
20 -    """returns a unique identifier for an object class"""
21 -    return '%s.%s' % (cls.__module__, cls.__name__)
22 -
23  def class_registries(cls, registryname):
24      """return a tuple of registry names (see __registries__)"""
25      if registryname:
26          return (registryname,)
27      return cls.__registries__
@@ -200,10 +196,20 @@
28          try:
29              return super(Registry, self).__getitem__(name)
30          except KeyError:
31              raise ObjectNotFound(name), None, sys.exc_info()[-1]
32 
33 +    @classmethod
34 +    def objid(cls, obj):
35 +        """returns a unique identifier for an object stored in the registry"""
36 +        return '%s.%s' % (obj.__module__, cls.objname(obj))
37 +
38 +    @classmethod
39 +    def objname(cls, obj):
40 +        """returns a readable name for an object stored in the registry"""
41 +        return getattr(obj, '__name__', id(obj))
42 +
43      def initialization_completed(self):
44          """call method __registered__() on registered objects when the callback
45          is defined"""
46          for objects in self.itervalues():
47              for objectcls in objects:
@@ -232,36 +238,36 @@
48          """remove <replaced> and register <obj>"""
49          # XXXFIXME this is a duplication of unregister()
50          # remove register_and_replace in favor of unregister + register
51          # or simplify by calling unregister then register here
52          if not isinstance(replaced, basestring):
53 -            replaced = classid(replaced)
54 +            replaced = self.objid(replaced)
55          # prevent from misspelling
56          assert obj is not replaced, 'replacing an object by itself: %s' % obj
57          registered_objs = self.get(obj.__regid__, ())
58          for index, registered in enumerate(registered_objs):
59 -            if classid(registered) == replaced:
60 +            if self.objid(registered) == replaced:
61                  del registered_objs[index]
62                  break
63          else:
64              self.warning('trying to replace %s that is not registered with %s',
65                           replaced, obj)
66          self.register(obj)
67 
68      def unregister(self, obj):
69          """remove object <obj> from this registry"""
70 -        clsid = classid(obj)
71 +        objid = self.objid(obj)
72          oid = obj.__regid__
73          for registered in self.get(oid, ()):
74 -            # use classid() to compare classes because vreg will probably
75 -            # have its own version of the class, loaded through execfile
76 -            if classid(registered) == clsid:
77 +            # use self.objid() to compare objects because vreg will probably
78 +            # have its own version of the object, loaded through execfile
79 +            if self.objid(registered) == objid:
80                  self[oid].remove(registered)
81                  break
82          else:
83              self.warning('can\'t remove %s, no id %s in the registry',
84 -                         clsid, oid)
85 +                         objid, oid)
86 
87      def all_objects(self):
88          """return a list containing all objects in this registry.
89          """
90          result = []
@@ -548,12 +554,12 @@
91              vname = obj.__class__.__name__
92          for registryname in class_registries(obj, registryname):
93              registry = self.setdefault(registryname)
94              registry.register(obj, oid=oid, clear=clear)
95              self.debug('register %s in %s[\'%s\']',
96 -                       vname, registryname, oid or obj.__regid__)
97 -        self._loadedmods.setdefault(obj.__module__, {})[classid(obj)] = obj
98 +                       registry.objname(obj), registryname, oid or obj.__regid__)
99 +            self._loadedmods.setdefault(obj.__module__, {})[registry.objid(obj)] = obj
100 
101      def unregister(self, obj, registryname=None):
102          """unregister `obj` implementation object from the registry
103          `registryname` or `obj.__registry__` if not specified.
104          """
@@ -654,13 +660,11 @@
105          """
106          self.info('loading %s from %s', module.__name__, module.__file__)
107          if hasattr(module, 'registration_callback'):
108              module.registration_callback(self)
109          else:
110 -            for objname, obj in vars(module).items():
111 -                if objname.startswith('_'):
112 -                    continue
113 +            for obj in vars(module).values():
114                  self._load_ancestors_then_object(module.__name__, obj)
115 
116      def _load_ancestors_then_object(self, modname, objectcls):
117          """handle automatic object class registration:
118 
@@ -683,11 +687,12 @@
119              if not (getattr(objectcls, '__regid__', None)
120                      and getattr(objectcls, '__select__', None)):
121                  return
122          except TypeError:
123              return
124 -        clsid = classid(objectcls)
125 +        reg = self.setdefault(class_registries(obj)[0])
126 +        clsid = reg.objid(obj)
127          if clsid in self._loadedmods[modname]:
128              return
129          self._loadedmods[modname][clsid] = objectcls
130          for parent in objectcls.__bases__:
131              self._load_ancestors_then_object(modname, parent)
@@ -972,5 +977,16 @@
132      def __init__(self, score=0.5):
133          self.score = score
134 
135      def __call__(self, *args, **kwargs):
136          return self.score
137 +
138 +
139 +# deprecated stuff #############################################################
140 +
141 +from logilab.common.deprecation import deprecated
142 +
143 +@deprecated('[lgc 0.59] use Registry.objid class method instead')
144 +def classid(cls):
145 +    """returns a unique identifier for an object class"""
146 +    return '%s.%s' % (cls.__module__, cls.__name__)
147 +