Ejemplo n.º 1
0
def _compute_annotation(t, bookkeeper=None):
    from pypy.rpython.lltypesystem import lltype
    from pypy.rpython import extregistry
    if isinstance(t, SomeObject):
        return t
    elif isinstance(t, lltype.LowLevelType):
        return lltype_to_annotation(t)
    elif isinstance(t, list):
        assert len(t) == 1, "We do not support type joining in list"
        listdef = ListDef(bookkeeper,
                          annotation(t[0]),
                          mutated=True,
                          resized=True)
        return SomeList(listdef)
    elif isinstance(t, tuple):
        return SomeTuple(tuple([annotation(i) for i in t]))
    elif isinstance(t, dict):
        assert len(t) == 1, "We do not support type joining in dict"
        result = SomeDict(
            DictDef(bookkeeper, annotation(t.keys()[0]),
                    annotation(t.values()[0])))
        return result
    elif type(t) is types.NoneType:
        return s_None
    elif extregistry.is_registered(t):
        entry = extregistry.lookup(t)
        entry.bookkeeper = bookkeeper
        return entry.compute_result_annotation()
    else:
        return annotationoftype(t, bookkeeper)
Ejemplo n.º 2
0
def _compute_annotation(t, bookkeeper=None):
    from pypy.rpython.lltypesystem import lltype
    from pypy.annotation.bookkeeper import getbookkeeper
    from pypy.rpython import extregistry
    if isinstance(t, SomeObject):
        return t
    elif isinstance(t, lltype.LowLevelType):
        return lltype_to_annotation(t)
    elif isinstance(t, list):
        assert len(t) == 1, "We do not support type joining in list"
        listdef = ListDef(bookkeeper, annotation(t[0]), mutated=True, resized=True)
        return SomeList(listdef)
    elif isinstance(t, tuple):
        return SomeTuple(tuple([annotation(i) for i in t]))
    elif isinstance(t, dict):
        assert len(t) == 1, "We do not support type joining in dict"
        result = SomeDict(DictDef(bookkeeper, annotation(t.keys()[0]),
                                annotation(t.values()[0])))
        return result
    elif type(t) is types.NoneType:
        return s_None
    elif extregistry.is_registered(t):
        entry = extregistry.lookup(t)
        entry.bookkeeper = bookkeeper
        return entry.compute_result_annotation()
    else:
        return annotationoftype(t, bookkeeper)
Ejemplo n.º 3
0
 def initialize_const(self, p, value):
     if isinstance(value, self.ctype):
         value = value.value
     if extregistry.is_registered(value):
         entry = extregistry.lookup(value)
         if hasattr(entry, 'get_ll_pyobjectptr'):
             p.c_data[0] = entry.get_ll_pyobjectptr(self.rtyper)
             return
     p.c_data[0] = lltype.pyobjectptr(value)
Ejemplo n.º 4
0
def _annotation_key(t):
    from pypy.rpython import extregistry
    if type(t) is list:
        assert len(t) == 1
        return ('list', _annotation_key(t[0]))
    elif type(t) is dict:
        assert len(t.keys()) == 1
        return ('dict', _annotation_key(t.items()[0]))
    elif isinstance(t, tuple):
        return tuple([_annotation_key(i) for i in t])
    elif extregistry.is_registered(t):
        # XXX should it really be always different?
        return t
    return t
Ejemplo n.º 5
0
def _annotation_key(t):
    from pypy.rpython import extregistry
    if type(t) is list:
        assert len(t) == 1
        return ('list', _annotation_key(t[0]))
    elif type(t) is dict:
        assert len(t.keys()) == 1
        return ('dict', _annotation_key(t.items()[0]))
    elif isinstance(t, tuple):
        return tuple([_annotation_key(i) for i in t])
    elif extregistry.is_registered(t):
        # XXX should it really be always different?
        return t
    return t
Ejemplo n.º 6
0
 def findbltintyper(self, rtyper):
     "Find the function to use to specialize calls to this built-in func."
     try:
         return BUILTIN_TYPER[self.builtinfunc]
     except (KeyError, TypeError):
         pass
     try:
         return rtyper.type_system.rbuiltin.BUILTIN_TYPER[self.builtinfunc]
     except (KeyError, TypeError):
         pass
     if extregistry.is_registered(self.builtinfunc):
         entry = extregistry.lookup(self.builtinfunc)
         return entry.specialize_call
     raise TyperError("don't know about built-in function %r" % (self.builtinfunc,))
Ejemplo n.º 7
0
 def findbltintyper(self, rtyper):
     "Find the function to use to specialize calls to this built-in func."
     try:
         return BUILTIN_TYPER[self.builtinfunc]
     except (KeyError, TypeError):
         pass
     try:
         return rtyper.type_system.rbuiltin.BUILTIN_TYPER[self.builtinfunc]
     except (KeyError, TypeError):
         pass
     if extregistry.is_registered(self.builtinfunc):
         entry = extregistry.lookup(self.builtinfunc)
         return entry.specialize_call
     raise TyperError("don't know about built-in function %r" % (
         self.builtinfunc,))
Ejemplo n.º 8
0
    def rtyper_makekey(self):
        if self.s_self is None:
            # built-in function case

            const = getattr(self, 'const', None)

            if extregistry.is_registered(const):
                const = extregistry.lookup(const)

            return self.__class__, const
        else:
            # built-in method case
            # NOTE: we hash by id of self.s_self here.  This appears to be
            # necessary because it ends up in hop.args_s[0] in the method call,
            # and there is no telling what information the called
            # rtype_method_xxx() will read from that hop.args_s[0].
            # See test_method_join in test_rbuiltin.
            # There is no problem with self.s_self being garbage-collected and
            # its id reused, because the BuiltinMethodRepr keeps a reference
            # to it.
            return (self.__class__, self.methodname, id(self.s_self))
Ejemplo n.º 9
0
    def rtyper_makekey(self):
        if self.s_self is None:
            # built-in function case

            const = getattr(self, 'const', None)

            if extregistry.is_registered(const):
                const = extregistry.lookup(const)

            return self.__class__, const
        else:
            # built-in method case
            # NOTE: we hash by id of self.s_self here.  This appears to be
            # necessary because it ends up in hop.args_s[0] in the method call,
            # and there is no telling what information the called
            # rtype_method_xxx() will read from that hop.args_s[0].
            # See test_method_join in test_rbuiltin.
            # There is no problem with self.s_self being garbage-collected and
            # its id reused, because the BuiltinMethodRepr keeps a reference
            # to it.
            return (self.__class__, self.methodname, id(self.s_self))
Ejemplo n.º 10
0
 def nameof_instance(self, instance):
     if extregistry.is_registered(instance):
         return extregistry.lookup(instance).genc_pyobj(self)
     if instance in self.import_hints:
         return self.import_instance(instance)
     klass = instance.__class__
     if issubclass(klass, LowLevelType):
         raise Exception, 'nameof_LowLevelType(%r)' % (instance,)
     name = self.uniquename('ginst_' + klass.__name__)
     cls = self.nameof(klass)
     if hasattr(klass, '__base__'):
         base_class = builtin_base(instance)
         base = self.nameof(base_class)
     else:
         base_class = None
         base = cls
     def initinstance():
         content = instance.__dict__.items()
         content.sort()
         for key, value in content:
             if self.should_translate_attr(instance, key):
                 line = '%s.%s = %s' % (name, key, self.nameof(value))
                 yield line
     if hasattr(instance,'__reduce_ex__'):
         import copy_reg
         reduced = instance.__reduce_ex__()
         assert reduced[0] is copy_reg._reconstructor,"not clever enough"
         assert reduced[1][1] is base_class, "not clever enough for %r vs. %r" % (base_class, reduced)
         state = reduced[1][2]
     else:
         state = None
     self.initcode.append('if isinstance(%s, type):' % cls)
     if state is not None:
         self.initcode.append('    %s = %s.__new__(%s, %r)' % (name, base, cls, state))
     else:
         self.initcode.append('    %s = %s.__new__(%s)' % (name, base, cls))
     self.initcode.append('else:')
     self.initcode.append('    %s = new.instance(%s)' % (name, cls))
     self.later(initinstance())
     return name
Ejemplo n.º 11
0
 def immutablevalue(self, x, need_const=True):
     """The most precise SomeValue instance that contains the
     immutable value x."""
     # convert unbound methods to the underlying function
     if hasattr(x, 'im_self') and x.im_self is None:
         x = x.im_func
         assert not hasattr(x, 'im_self')
     if x is sys:  # special case constant sys to someobject
         return SomeObject()
     tp = type(x)
     if issubclass(tp, Symbolic):  # symbolic constants support
         result = x.annotation()
         result.const_box = Constant(x)
         return result
     if tp is bool:
         result = SomeBool()
     elif tp is int:
         result = SomeInteger(nonneg=x >= 0)
     elif tp is long:
         if -sys.maxint - 1 <= x <= sys.maxint:
             x = int(x)
             result = SomeInteger(nonneg=x >= 0)
         else:
             raise Exception("seeing a prebuilt long (value %s)" % hex(x))
     elif issubclass(tp, str):  # py.lib uses annotated str subclasses
         if len(x) == 1:
             result = SomeChar()
         else:
             result = SomeString()
     elif tp is unicode:
         if len(x) == 1:
             result = SomeUnicodeCodePoint()
         else:
             result = SomeUnicodeString()
     elif tp is tuple:
         result = SomeTuple(
             items=[self.immutablevalue(e, need_const) for e in x])
     elif tp is float:
         result = SomeFloat()
     elif tp is list:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeList(ListDef(self, s_ImpossibleValue))
                 self.immutable_cache[key] = result
                 for e in x:
                     result.listdef.generalize(self.immutablevalue(e))
                 result.const_box = key
                 return result
         else:
             listdef = ListDef(self, s_ImpossibleValue)
             for e in x:
                 listdef.generalize(self.immutablevalue(e, False))
             result = SomeList(listdef)
     elif tp is dict or tp is r_dict:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeDict(
                     DictDef(self,
                             s_ImpossibleValue,
                             s_ImpossibleValue,
                             is_r_dict=tp is r_dict))
                 self.immutable_cache[key] = result
                 if tp is r_dict:
                     s_eqfn = self.immutablevalue(x.key_eq)
                     s_hashfn = self.immutablevalue(x.key_hash)
                     result.dictdef.dictkey.update_rdict_annotations(
                         s_eqfn, s_hashfn)
                 seen_elements = 0
                 while seen_elements != len(x):
                     items = x.items()
                     for ek, ev in items:
                         result.dictdef.generalize_key(
                             self.immutablevalue(ek))
                         result.dictdef.generalize_value(
                             self.immutablevalue(ev))
                         result.dictdef.seen_prebuilt_key(ek)
                     seen_elements = len(items)
                     # if the dictionary grew during the iteration,
                     # start over again
                 result.const_box = key
                 return result
         else:
             dictdef = DictDef(self,
                               s_ImpossibleValue,
                               s_ImpossibleValue,
                               is_r_dict=tp is r_dict)
             if tp is r_dict:
                 s_eqfn = self.immutablevalue(x.key_eq)
                 s_hashfn = self.immutablevalue(x.key_hash)
                 dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn)
             for ek, ev in x.iteritems():
                 dictdef.generalize_key(self.immutablevalue(ek, False))
                 dictdef.generalize_value(self.immutablevalue(ev, False))
                 dictdef.seen_prebuilt_key(ek)
             result = SomeDict(dictdef)
     elif tp is weakref.ReferenceType:
         x1 = x()
         if x1 is None:
             result = SomeWeakRef(None)  # dead weakref
         else:
             s1 = self.immutablevalue(x1)
             assert isinstance(s1, SomeInstance)
             result = SomeWeakRef(s1.classdef)
     elif ishashable(x) and x in BUILTIN_ANALYZERS:
         _module = getattr(x, "__module__", "unknown")
         result = SomeBuiltin(BUILTIN_ANALYZERS[x],
                              methodname="%s.%s" % (_module, x.__name__))
     elif extregistry.is_registered(x, self.policy):
         entry = extregistry.lookup(x, self.policy)
         result = entry.compute_annotation_bk(self)
     elif isinstance(x, lltype._ptr):
         result = SomePtr(lltype.typeOf(x))
     elif isinstance(x, llmemory.fakeaddress):
         result = SomeAddress()
     elif isinstance(x, ootype._static_meth):
         result = SomeOOStaticMeth(ootype.typeOf(x))
     elif isinstance(x, ootype._class):
         result = SomeOOClass(x._INSTANCE)  # NB. can be None
     elif isinstance(x, ootype.instance_impl):  # XXX
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._record, ootype._string)):
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._object)):
         result = SomeOOObject()
     elif callable(x):
         if hasattr(x, 'im_self') and hasattr(x, 'im_func'):
             # on top of PyPy, for cases like 'l.append' where 'l' is a
             # global constant list, the find_method() returns non-None
             s_self = self.immutablevalue(x.im_self, need_const)
             result = s_self.find_method(x.im_func.__name__)
         elif hasattr(x, '__self__') and x.__self__ is not None:
             # for cases like 'l.append' where 'l' is a global constant list
             s_self = self.immutablevalue(x.__self__, need_const)
             result = s_self.find_method(x.__name__)
             if result is None:
                 result = SomeObject()
         else:
             result = None
         if result is None:
             if (self.annotator.policy.allow_someobjects
                     and getattr(x, '__module__', None) == '__builtin__'
                     # XXX note that the print support functions are __builtin__
                     and tp not in (types.FunctionType, types.MethodType)):
                 result = SomeObject()
                 result.knowntype = tp  # at least for types this needs to be correct
             else:
                 result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '_freeze_') and x._freeze_():
         # user-defined classes can define a method _freeze_(), which
         # is called when a prebuilt instance is found.  If the method
         # returns True, the instance is considered immutable and becomes
         # a SomePBC().  Otherwise it's just SomeInstance().
         result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '__class__') \
              and x.__class__.__module__ != '__builtin__':
         self.see_mutable(x)
         result = SomeInstance(self.getuniqueclassdef(x.__class__))
     elif x is None:
         return s_None
     else:
         result = SomeObject()
     if need_const:
         result.const = x
     return result
Ejemplo n.º 12
0
        return val
    except (SystemExit, MemoryError, KeyboardInterrupt), e:
        raise
    except:
        if 0:
            import traceback
            print >> sys.stderr, 'WARNING: cannot register', func_or_list, ':'
            traceback.print_exc()
            import pdb; pdb.set_trace()
        exc, exc_inst, tb = sys.exc_info()
        for func in funcs:
            # if the function has already been registered and we got
            # an exception afterwards, the ExtRaisingEntry would create
            # a double-registration and crash in an AssertionError that
            # masks the original problem.  In this case, just re-raise now.
            if extregistry.is_registered(func):
                raise exc, exc_inst, tb
            class ExtRaisingEntry(ExtRegistryEntry):
                _about_ = func
                def __getattr__(self, attr):
                    if attr == '_about_' or attr == '__dict__':
                        return super(ExtRegistryEntry, self).__getattr__(attr)
                    raise exc, exc_inst, tb

def registering(func):
    def decorator(method):
        method._registering_func = func
        return method
    return decorator

def registering_if(ns, name):
Ejemplo n.º 13
0
 def immutablevalue(self, x, need_const=True):
     """The most precise SomeValue instance that contains the
     immutable value x."""
     # convert unbound methods to the underlying function
     if hasattr(x, 'im_self') and x.im_self is None:
         x = x.im_func
         assert not hasattr(x, 'im_self')
     if x is sys: # special case constant sys to someobject
         return SomeObject()
     tp = type(x)
     if issubclass(tp, Symbolic): # symbolic constants support
         result = x.annotation()
         result.const_box = Constant(x)
         return result
     if tp is bool:
         result = SomeBool()
     elif tp is int:
         result = SomeInteger(nonneg = x>=0)
     elif tp is long:
         if -sys.maxint-1 <= x <= sys.maxint:
             x = int(x)
             result = SomeInteger(nonneg = x>=0)
         else:
             raise Exception("seeing a prebuilt long (value %s)" % hex(x))
     elif issubclass(tp, str): # py.lib uses annotated str subclasses
         no_nul = not '\x00' in x
         if len(x) == 1:
             result = SomeChar(no_nul=no_nul)
         else:
             result = SomeString(no_nul=no_nul)
     elif tp is unicode:
         if len(x) == 1:
             result = SomeUnicodeCodePoint()
         else:
             result = SomeUnicodeString()
     elif tp is tuple:
         result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x])
     elif tp is float:
         result = SomeFloat()
     elif tp is list:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeList(ListDef(self, s_ImpossibleValue))
                 self.immutable_cache[key] = result
                 for e in x:
                     result.listdef.generalize(self.immutablevalue(e))
                 result.const_box = key
                 return result
         else:
             listdef = ListDef(self, s_ImpossibleValue)
             for e in x:
                 listdef.generalize(self.immutablevalue(e, False))
             result = SomeList(listdef)    
     elif tp is dict or tp is r_dict:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeDict(DictDef(self, 
                                           s_ImpossibleValue,
                                           s_ImpossibleValue,
                                           is_r_dict = tp is r_dict))
                 self.immutable_cache[key] = result
                 if tp is r_dict:
                     s_eqfn = self.immutablevalue(x.key_eq)
                     s_hashfn = self.immutablevalue(x.key_hash)
                     result.dictdef.dictkey.update_rdict_annotations(s_eqfn,
                                                                     s_hashfn)
                 seen_elements = 0
                 while seen_elements != len(x):
                     items = x.items()
                     for ek, ev in items:
                         result.dictdef.generalize_key(self.immutablevalue(ek))
                         result.dictdef.generalize_value(self.immutablevalue(ev))
                         result.dictdef.seen_prebuilt_key(ek)
                     seen_elements = len(items)
                     # if the dictionary grew during the iteration,
                     # start over again
                 result.const_box = key
                 return result
         else:
             dictdef = DictDef(self, 
             s_ImpossibleValue,
             s_ImpossibleValue,
             is_r_dict = tp is r_dict)
             if tp is r_dict:
                 s_eqfn = self.immutablevalue(x.key_eq)
                 s_hashfn = self.immutablevalue(x.key_hash)
                 dictdef.dictkey.update_rdict_annotations(s_eqfn,
                     s_hashfn)
             for ek, ev in x.iteritems():
                 dictdef.generalize_key(self.immutablevalue(ek, False))
                 dictdef.generalize_value(self.immutablevalue(ev, False))
                 dictdef.seen_prebuilt_key(ek)
             result = SomeDict(dictdef)
     elif tp is weakref.ReferenceType:
         x1 = x()
         if x1 is None:
             result = SomeWeakRef(None)    # dead weakref
         else:
             s1 = self.immutablevalue(x1)
             assert isinstance(s1, SomeInstance)
             result = SomeWeakRef(s1.classdef)
     elif ishashable(x) and x in BUILTIN_ANALYZERS:
         _module = getattr(x,"__module__","unknown")
         result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__))
     elif extregistry.is_registered(x, self.policy):
         entry = extregistry.lookup(x, self.policy)
         result = entry.compute_annotation_bk(self)
     elif isinstance(x, lltype._ptr):
         result = SomePtr(lltype.typeOf(x))
     elif isinstance(x, llmemory.fakeaddress):
         result = SomeAddress()
     elif isinstance(x, ootype._static_meth):
         result = SomeOOStaticMeth(ootype.typeOf(x))
     elif isinstance(x, ootype._class):
         result = SomeOOClass(x._INSTANCE)   # NB. can be None
     elif isinstance(x, ootype.instance_impl): # XXX
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._record, ootype._string)):
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._object)):
         result = SomeOOObject()
     elif callable(x):
         if hasattr(x, 'im_self') and hasattr(x, 'im_func'):
             # on top of PyPy, for cases like 'l.append' where 'l' is a
             # global constant list, the find_method() returns non-None
             s_self = self.immutablevalue(x.im_self, need_const)
             result = s_self.find_method(x.im_func.__name__)
         elif hasattr(x, '__self__') and x.__self__ is not None:
             # for cases like 'l.append' where 'l' is a global constant list
             s_self = self.immutablevalue(x.__self__, need_const)
             result = s_self.find_method(x.__name__)
             if result is None:
                 result = SomeObject()
         else:
             result = None
         if result is None:
             if (self.annotator.policy.allow_someobjects
                 and getattr(x, '__module__', None) == '__builtin__'
                 # XXX note that the print support functions are __builtin__
                 and tp not in (types.FunctionType, types.MethodType)):
                 result = SomeObject()
                 result.knowntype = tp # at least for types this needs to be correct
             else:
                 result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '_freeze_') and x._freeze_():
         # user-defined classes can define a method _freeze_(), which
         # is called when a prebuilt instance is found.  If the method
         # returns True, the instance is considered immutable and becomes
         # a SomePBC().  Otherwise it's just SomeInstance().
         result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '__class__') \
              and x.__class__.__module__ != '__builtin__':
         self.see_mutable(x)
         result = SomeInstance(self.getuniqueclassdef(x.__class__))
     elif x is None:
         return s_None
     else:
         result = SomeObject()
     if need_const:
         result.const = x
     return result
Ejemplo n.º 14
0
         s_ImpossibleValue,
         s_ImpossibleValue,
         is_r_dict = tp is r_dict)
         if tp is r_dict:
             s_eqfn = self.immutablevalue(x.key_eq)
             s_hashfn = self.immutablevalue(x.key_hash)
             dictdef.dictkey.update_rdict_annotations(s_eqfn,
                 s_hashfn)
         for ek, ev in x.iteritems():
             dictdef.generalize_key(self.immutablevalue(ek, False))
             dictdef.generalize_value(self.immutablevalue(ev, False))
         result = SomeDict(dictdef)
 elif ishashable(x) and x in BUILTIN_ANALYZERS:
     _module = getattr(x,"__module__","unknown")
     result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__))
 elif extregistry.is_registered(x, self.policy):
     entry = extregistry.lookup(x, self.policy)
     result = entry.compute_annotation_bk(self)
 elif tp in EXTERNAL_TYPE_ANALYZERS:
     result = SomeExternalObject(tp)
 elif isinstance(x, lltype._ptr):
     result = SomePtr(lltype.typeOf(x))
 elif isinstance(x, llmemory.fakeaddress):
     result = SomeAddress(is_null=not x)
 elif isinstance(x, llmemory.fakeweakaddress):
     result = SomeWeakGcAddress()
 elif isinstance(x, ootype._static_meth):
     result = SomeOOStaticMeth(ootype.typeOf(x))
 elif isinstance(x, ootype._class):
     result = SomeOOClass(x._INSTANCE)   # NB. can be None
 elif isinstance(x, ootype.instance_impl): # XXX
Ejemplo n.º 15
0
        return val
    except (SystemExit, MemoryError, KeyboardInterrupt), e:
        raise
    except:
        if 0:
            import traceback
            print >> sys.stderr, 'WARNING: cannot register', func_or_list, ':'
            traceback.print_exc()
            import pdb; pdb.set_trace()
        exc, exc_inst, tb = sys.exc_info()
        for func in funcs:
            # if the function has already been registered and we got
            # an exception afterwards, the ExtRaisingEntry would create
            # a double-registration and crash in an AssertionError that
            # masks the original problem.  In this case, just re-raise now.
            if extregistry.is_registered(func):
                raise exc, exc_inst, tb
            class ExtRaisingEntry(ExtRegistryEntry):
                _about_ = func
                def __getattr__(self, attr):
                    if attr == '_about_' or attr == '__dict__':
                        return super(ExtRegistryEntry, self).__getattr__(attr)
                    raise exc, exc_inst, tb

def registering(func, condition=True):
    if not condition:
        return lambda method: None

    def decorator(method):
        method._registering_func = func
        return method