def menuDirective(_context, id=None, class_=BrowserMenu, interface=None, title=u'', description=u''): """Registers a new browser menu.""" if id is None and interface is None: raise ConfigurationError( "You must specify the 'id' or 'interface' attribute.") if interface is None: if id in dir(menus): # reuse existing interfaces for the id, without this we are not # able to override menus. interface = getattr(menus, id) else: interface = InterfaceClass(id, (), __doc__='Menu Item Type: %s' %id, __module__='zope.app.menus') # Add the menu item type to the `menus` module. # Note: We have to do this immediately, so that directives using the # MenuField can find the menu item type. setattr(menus, id, interface) path = 'zope.app.menus.' + id else: path = interface.__module__ + '.' + interface.getName() # If an id was specified, make this menu available under this id. # Note that the menu will be still available under its path, since it # is an adapter, and the `MenuField` can resolve paths as well. if id is None: id = path else: # Make the interface available in the `zope.app.menus` module, so # that other directives can find the interface under the name # before the CA is setup. _context.action( discriminator=('browser', 'MenuItemType', path), callable=provideInterface, args=(path, interface, IMenuItemType, _context.info) ) setattr(menus, id, interface) # Register the layer interface as an interface _context.action( discriminator=('interface', path), callable=provideInterface, args=(path, interface), kw={'info': _context.info} ) # Register the menu item type interface as an IMenuItemType _context.action( discriminator=('browser', 'MenuItemType', id), callable=provideInterface, args=(id, interface, IMenuItemType, _context.info) ) # Register the menu as a utility utility(_context, IBrowserMenu, class_(id, title, description), name=id)
def menuDirective(_context, id=None, class_=BrowserMenu, interface=None, title=u'', description=u''): """Registers a new browser menu.""" if id is None and interface is None: raise ConfigurationError( "You must specify the 'id' or 'interface' attribute.") if interface is None: if id in dir(menus): # reuse existing interfaces for the id, without this we are not # able to override menus. interface = getattr(menus, id) else: interface = InterfaceClass(id, (), __doc__='Menu Item Type: %s' %id, __module__='zope.app.menus') # Add the menu item type to the `menus` module. # Note: We have to do this immediately, so that directives using the # MenuField can find the menu item type. setattr(menus, id, interface) path = 'zope.app.menus.' + id else: path = interface.__module__ + '.' + interface.getName() # If an id was specified, make this menu available under this id. # Note that the menu will be still available under its path, since it # is an adapter, and the `MenuField` can resolve paths as well. if id is None: id = path else: # Make the interface available in the `zope.app.menus` module, so # that other directives can find the interface under the name # before the CA is setup. _context.action( discriminator = ('browser', 'MenuItemType', path), callable = provideInterface, args = (path, interface, IMenuItemType, _context.info) ) setattr(menus, id, interface) # Register the layer interface as an interface _context.action( discriminator = ('interface', path), callable = provideInterface, args = (path, interface), kw = {'info': _context.info} ) # Register the menu item type interface as an IMenuItemType _context.action( discriminator = ('browser', 'MenuItemType', id), callable = provideInterface, args = (id, interface, IMenuItemType, _context.info) ) # Register the menu as a utility utility(_context, IBrowserMenu, class_(id, title, description), name=id)
def layer(_context, name=None, interface=None, base=IBrowserRequest): """Provides a new layer. >>> class Context(object): ... info = u'doc' ... def __init__(self): self.actions = [] ... def action(self, **kw): self.actions.append(kw) Possibility 1: The Old Way -------------------------- >>> context = Context() >>> layer(context, u'layer1') >>> iface = context.actions[0]['args'][1] >>> iface.getName() 'layer1' >>> ILayer.providedBy(iface) True >>> hasattr(sys.modules['zope.app.layers'], 'layer1') True >>> del sys.modules['zope.app.layers'].layer1 Possibility 2: Providing a custom base interface ------------------------------------------------ >>> class BaseLayer(IBrowserRequest): ... pass >>> context = Context() >>> layer(context, u'layer1', base=BaseLayer) >>> iface = context.actions[0]['args'][1] >>> iface.getName() 'layer1' >>> iface.__bases__ (<InterfaceClass zope.app.publisher.browser.metaconfigure.BaseLayer>,) >>> hasattr(sys.modules['zope.app.layers'], 'layer1') True >>> del sys.modules['zope.app.layers'].layer1 Possibility 3: Define a Layer just through an Interface ------------------------------------------------------- >>> class layer1(IBrowserRequest): ... pass >>> context = Context() >>> layer(context, interface=layer1) >>> context.actions[0]['args'][1] is layer1 True >>> hasattr(sys.modules['zope.app.layers'], 'layer1') False Possibility 4: Use an Interface and a Name ------------------------------------------ >>> context = Context() >>> layer(context, name='layer1', interface=layer1) >>> context.actions[0]['args'][1] is layer1 True >>> hasattr(sys.modules['zope.app.layers'], 'layer1') True >>> import pprint >>> pprint.pprint([action['discriminator'] for action in context.actions]) [('interface', 'zope.app.publisher.browser.metaconfigure.layer1'), ('layer', 'layer1')] Here are some disallowed configurations. >>> context = Context() >>> layer(context, 'foo,bar') Traceback (most recent call last): ... TypeError: Commas are not allowed in layer names. >>> layer(context) Traceback (most recent call last): ... ConfigurationError: You must specify the 'name' or 'interface' attribute. >>> layer(context, base=BaseLayer) Traceback (most recent call last): ... ConfigurationError: You must specify the 'name' or 'interface' attribute. >>> layer(context, interface=layer1, base=BaseLayer) Traceback (most recent call last): ... ConfigurationError: You cannot specify the 'interface' and 'base' together. """ if name is not None and "," in name: raise TypeError("Commas are not allowed in layer names.") if name is None and interface is None: raise ConfigurationError("You must specify the 'name' or 'interface' attribute.") if interface and not interface.extends(IBrowserRequest): raise ConfigurationError("The layer interface must extend `IBrowserRequest`.") if base is not IBrowserRequest and not base.extends(IBrowserRequest): raise ConfigurationError("The base interface must extend `IBrowserRequest`.") if interface is not None and base is not IBrowserRequest: raise ConfigurationError("You cannot specify the 'interface' and 'base' together.") if interface is None: interface = InterfaceClass(str(name), (base,), __doc__="Layer: %s" % str(name), __module__="zope.app.layers") # Add the layer to the layers module. # Note: We have to do this immediately, so that directives using the # InterfaceField can find the layer. setattr(zope.app.layers, name, interface) path = "zope.app.layers." + name else: path = interface.__module__ + "." + interface.getName() # If a name was specified, make this layer available under this name. # Note that the layer will be still available under its path, since it # is an adapter, and the `LayerField` can resolve paths as well. if name is None: name = path else: # Make the interface available in the `zope.app.layers` module, so # that other directives can find the interface under the name # before the CA is setup. setattr(zope.app.layers, name, interface) # Register the layer interface as an interface _context.action( discriminator=("interface", path), callable=provideInterface, args=(path, interface), kw={"info": _context.info} ) directlyProvides(interface, ILayer) # Register the layer interface as a layer _context.action( discriminator=("layer", name), callable=provideInterface, args=(name, interface, ILayer, _context.info) )
def skin(_context, name=None, interface=None, layers=None): """Provides a new skin. >>> import pprint >>> class Context(object): ... info = u'doc' ... def __init__(self): self.actions = [] ... def action(self, **kw): self.actions.append(kw) >>> class Layer1(ILayer): pass >>> class Layer2(ILayer): pass Possibility 1: The Old Way -------------------------- >>> context = Context() >>> skin(context, u'skin1', layers=[Layer1, Layer2]) >>> iface = context.actions[3]['args'][1] >>> iface.getName() 'skin1' >>> pprint.pprint(iface.__bases__) (<InterfaceClass zope.app.publisher.browser.metaconfigure.Layer1>, <InterfaceClass zope.app.publisher.browser.metaconfigure.Layer2>) >>> hasattr(sys.modules['zope.app.skins'], 'skin1') True >>> del sys.modules['zope.app.skins'].skin1 Possibility 2: Just specify an interface ---------------------------------------- >>> class skin1(Layer1, Layer2): ... pass >>> context = Context() >>> skin(context, interface=skin1) >>> context.actions[0]['args'][1] is skin1 True Possibility 3: Specify an interface and a Name ---------------------------------------------- >>> context = Context() >>> skin(context, name='skin1', interface=skin1) >>> context.actions[0]['args'][1] is skin1 True >>> import pprint >>> pprint.pprint([action['discriminator'] for action in context.actions]) [('skin', 'skin1'), ('interface', 'zope.app.publisher.browser.metaconfigure.skin1'), ('skin', 'zope.app.publisher.browser.metaconfigure.skin1')] Here are some disallowed configurations. >>> context = Context() >>> skin(context) Traceback (most recent call last): ... ConfigurationError: You must specify the 'name' or 'interface' attribute. >>> skin(context, layers=[Layer1]) Traceback (most recent call last): ... ConfigurationError: You must specify the 'name' or 'interface' attribute. """ if name is None and interface is None: raise ConfigurationError("You must specify the 'name' or 'interface' attribute.") if name is not None and layers is not None: interface = InterfaceClass(str(name), layers, __doc__="Skin: %s" % str(name), __module__="zope.app.skins") # Add the layer to the skins module. # Note: We have to do this immediately, so that directives using the # InterfaceField can find the layer. setattr(zope.app.skins, name, interface) path = "zope.app.skins" + name # Register the layers for layer in layers: _context.action( discriminator=None, callable=provideInterface, args=(layer.getName(), layer, ILayer, _context.info) ) else: path = interface.__module__ + "." + interface.getName() # Register the skin interface as a skin using the passed name. if name is not None: _context.action( discriminator=("skin", name), callable=provideInterface, args=(name, interface, ISkin, _context.info) ) name = path # Register the skin interface as an interface _context.action( discriminator=("interface", path), callable=provideInterface, args=(path, interface), kw={"info": _context.info} ) # Register the skin interface as a skin _context.action( discriminator=("skin", name), callable=provideInterface, args=(name, interface, ISkin, _context.info) )