zope.app.testing.ztapi.remove*

Zope でユーティリティやらアダプタやらファクトリやら ZCML から登録しますが、等価なコードは zope.app.testing.ztapi.provide* を利用することで実現できます。
しかし、zope.component は登録の解除をサポートしていないので ztapi にも remove* とか unprovide* とかありませんが、適当に作って登録してしまえ。

# -*- coding: utf-8 -*-
# all registration codes in zope.interface.adapter
from zope.interface import Interface
from zope.app import zapi
from zope.app.testing import ztapi


def removeAdapter(required, provided, factory, name = u'', with = ()):
    gsm = zapi.getGlobalSiteManager()

    if isinstance(factory, (list, tuple, )):
        raise ValueError("Factory cannot be a list or tuple")

    if with:
        required = (required, ) + tuple(with)
    elif not isinstance(required, (list, tuple, )):
        required = (required, )

    # remove registration
    key = (required, provided, name, )
    if key in gsm._registrations:
        from zope.component.site import AdapterRegistration
        value = gsm._registrations[key]
        if isinstance(value, AdapterRegistration) and value.value is factory:
            del gsm._registrations[key]

    if required:
        with = []
        for iface in required[1:]:
            if iface is None:
                iface = Interface
            with.append(iface)
        with = tuple(with)
        repository = gsm._registrations.get(required[0])
    else:
        with = ()
        repository = gsm._registrations._null

    if repository is None:
        repository = gsm.adapters._default

    key = (False, tuple(with), name, provided, )
    if key in repository.adapters and repository.adapters[key] is factory:
        del repository.adapters[key]
        repository.changed()


def removeMultiView(for_, type, providing, name, factory, layer = None):
    if layer is None:
        layer = type
    ztapi.removeAdapter(for_[0], providing, factory, name, tuple(for_[1:]) + (layer, ))


def removeNamespaceHandler(name, handler):
    from zope.app.traversing.interfaces import ITraversable
    ztapi.removeAdapter(None, ITraversable, handler, name = name)
    ztapi.removeView(None, None, ITraversable, name, handler)


def removeService(name, service, interface = None):
    from zope.component.interfaces import IService, IServiceDefinition
    if interface is not None:
        ztapi.removeUtility(IServiceDefinition, (name, interface, ), name)
    component = service
    ztapi.removeUtility(IService, component, name)


def removeUtility(provided, component, name = u''):
    gsm = zapi.getGlobalSiteManager()

    repository = gsm.utilities._null

    # remove null adapter
    key = (False, (), name, provided, )
    if key in repository.adapters:
        value = repository.adapters[key]
        if value is component:
            del repository.adapters[key]

    # remove subscriptions
    key = (True, (), '', provided, )
    if key in repository.adapters:
        value = tuple(factory for factory in repository.adapters[key] if factory is not component)
        repository.adapters[key] = value

    # refresh cache
    repository.changed()

    # remove registration
    key = (provided, name, )
    if key in gsm._registrations:
        from zope.component.site import UtilityRegistration
        value = gsm._registrations[key]
        if isinstance(value, UtilityRegistration) and value.component is component:
            del gsm._registrations[key]


def removeView(for_, type, providing, name, factory, layer = None):
    if layer is None:
        layer = type
    ztapi.removeAdapter(for_, providing, factory, name, (layer, ))


repository = (
    removeAdapter,
    removeMultiView,
    removeNamespaceHandler,
    removeService,
    removeUtility,
    removeView,
    )

for func in repository:
    if hasattr(ztapi, func.func_name):
        print 'Warning: %s.%s is rewrote.' % (ztapi.__name__, func.func_name, )
    setattr(ztapi, func.func_name, func)