def _fixture(self, some=20):
     data = self._some_data()
     wim = util.WeakIdentityMapping()
     for idx, obj in enumerate(data):
         wim[obj] = idx
     return data, wim
Example #2
0
class InstrumentationRegistry(object):
    """Private instrumentation registration singleton.

    All classes are routed through this registry
    when first instrumented, however the InstrumentationRegistry
    is not actually needed unless custom ClassManagers are in use.

    """

    _manager_finders = weakref.WeakKeyDictionary()
    _state_finders = util.WeakIdentityMapping()
    _dict_finders = util.WeakIdentityMapping()
    _extended = False

    dispatch = event.dispatcher(events.InstrumentationEvents)

    def create_manager_for_cls(self, class_, **kw):
        assert class_ is not None
        assert manager_of_class(class_) is None

        for finder in instrumentation_finders:
            factory = finder(class_)
            if factory is not None:
                break
        else:
            factory = ClassManager

        existing_factories = self._collect_management_factories_for(class_).\
                                difference([factory])
        if existing_factories:
            raise TypeError(
                "multiple instrumentation implementations specified "
                "in %s inheritance hierarchy: %r" %
                (class_.__name__, list(existing_factories)))

        manager = factory(class_)
        if not isinstance(manager, ClassManager):
            manager = _ClassInstrumentationAdapter(class_, manager)

        if factory != ClassManager and not self._extended:
            # somebody invoked a custom ClassManager.
            # reinstall global "getter" functions with the more
            # expensive ones.
            self._extended = True
            _install_lookup_strategy(self)

        manager.factory = factory
        self._manager_finders[class_] = manager.manager_getter()
        self._state_finders[class_] = manager.state_getter()
        self._dict_finders[class_] = manager.dict_getter()

        self.dispatch.class_instrument(class_)

        return manager

    def _collect_management_factories_for(self, cls):
        """Return a collection of factories in play or specified for a
        hierarchy.

        Traverses the entire inheritance graph of a cls and returns a
        collection of instrumentation factories for those classes. Factories
        are extracted from active ClassManagers, if available, otherwise
        instrumentation_finders is consulted.

        """
        hierarchy = util.class_hierarchy(cls)
        factories = set()
        for member in hierarchy:
            manager = manager_of_class(member)
            if manager is not None:
                factories.add(manager.factory)
            else:
                for finder in instrumentation_finders:
                    factory = finder(member)
                    if factory is not None:
                        break
                else:
                    factory = None
                factories.add(factory)
        factories.discard(None)
        return factories

    def manager_of_class(self, cls):
        # this is only called when alternate instrumentation
        # has been established
        if cls is None:
            return None
        try:
            finder = self._manager_finders[cls]
        except KeyError:
            return None
        else:
            return finder(cls)

    def state_of(self, instance):
        # this is only called when alternate instrumentation
        # has been established
        if instance is None:
            raise AttributeError("None has no persistent state.")
        try:
            return self._state_finders[instance.__class__](instance)
        except KeyError:
            raise AttributeError("%r is not instrumented" % instance.__class__)

    def dict_of(self, instance):
        # this is only called when alternate instrumentation
        # has been established
        if instance is None:
            raise AttributeError("None has no persistent state.")
        try:
            return self._dict_finders[instance.__class__](instance)
        except KeyError:
            raise AttributeError("%r is not instrumented" % instance.__class__)

    def unregister(self, class_):
        if class_ in self._manager_finders:
            manager = self.manager_of_class(class_)
            self.dispatch.class_uninstrument(class_)
            manager.unregister()
            manager.dispose()
            del self._manager_finders[class_]
            del self._state_finders[class_]
            del self._dict_finders[class_]
        if ClassManager.MANAGER_ATTR in class_.__dict__:
            delattr(class_, ClassManager.MANAGER_ATTR)