[Checkins] SVN: zope.browsermenu/trunk/ Fix dependency versions.

Dan Korostelev nadako at gmail.com
Thu Aug 27 09:56:03 EDT 2009


Log message for revision 103270:
  Fix dependency versions.
  Add svn:keywords=Id to *.py files.
  Rename menu.txt doctest to README.txt.
  Use simplier namespace declratation command.

Changed:
  UU  zope.browsermenu/trunk/bootstrap.py
  UU  zope.browsermenu/trunk/setup.py
  UU  zope.browsermenu/trunk/src/zope/__init__.py
  A   zope.browsermenu/trunk/src/zope/browsermenu/README.txt
  _U  zope.browsermenu/trunk/src/zope/browsermenu/__init__.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/field.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/interfaces.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/menu.py
  D   zope.browsermenu/trunk/src/zope/browsermenu/menu.txt
  UU  zope.browsermenu/trunk/src/zope/browsermenu/metaconfigure.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/metadirectives.py
  _U  zope.browsermenu/trunk/src/zope/browsermenu/tests/__init__.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/tests/test_addMenuItem.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/tests/test_directives.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/tests/test_fields.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menu.py
  UU  zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menudirectives.py

-=-
Modified: zope.browsermenu/trunk/bootstrap.py
===================================================================
--- zope.browsermenu/trunk/bootstrap.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/bootstrap.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -17,7 +17,7 @@
 The script accepts buildout command-line options, so you can
 use the -c option to specify an alternate configuration file.
 
-$Id: bootstrap.py 73800 2007-03-27 16:16:42Z dobe $
+$Id$
 """
 
 import os, shutil, sys, tempfile, urllib2


Property changes on: zope.browsermenu/trunk/bootstrap.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/setup.py
===================================================================
--- zope.browsermenu/trunk/setup.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/setup.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -41,15 +41,15 @@
       include_package_data=True,
       install_requires=['setuptools',
                         'zope.browser',
-                        'zope.component>=3.7.0',
+                        'zope.component>=3.7',
                         'zope.configuration',
                         'zope.i18nmessageid',
                         'zope.interface',
-                        'zope.pagetemplate>=3.5.0',
-                        'zope.publisher>=3.8.0',
+                        'zope.pagetemplate>=3.5',
+                        'zope.publisher',
                         'zope.schema',
                         'zope.security[untrustedpython]',
-                        'zope.traversing>3.7.0',
+                        'zope.traversing>3.7',
                         ],
       extras_require={
           'test': ['zope.testing'],


Property changes on: zope.browsermenu/trunk/setup.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/__init__.py
===================================================================
--- zope.browsermenu/trunk/src/zope/__init__.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/__init__.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -1,7 +1 @@
-# this is a namespace package
-try:
-    import pkg_resources
-    pkg_resources.declare_namespace(__name__)
-except ImportError:
-    import pkgutil
-    __path__ = pkgutil.extend_path(__path__, __name__)
+__import__('pkg_resources').declare_namespace(__name__)


Property changes on: zope.browsermenu/trunk/src/zope/__init__.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Copied: zope.browsermenu/trunk/src/zope/browsermenu/README.txt (from rev 103268, zope.browsermenu/trunk/src/zope/browsermenu/menu.txt)
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/README.txt	                        (rev 0)
+++ zope.browsermenu/trunk/src/zope/browsermenu/README.txt	2009-08-27 13:56:02 UTC (rev 103270)
@@ -0,0 +1,633 @@
+=============
+Browser Menus
+=============
+
+Browser menus are used to categorize browser actions, such as the views of a
+content component or the addable components of a container. In essence they
+provide the same functionality as menu bars in desktop application.
+
+  >>> from zope.browsermenu import menu, metaconfigure
+
+Menus are simple components that have an id, title and description. They also
+must provide a method called ``getMenuItems(object, request)`` that returns a
+TAL-friendly list of information dictionaries. We will see this in detail
+later. The default menu implementation, however, makes the menu be very
+transparent by identifying the menu through an interface. So let's define and
+register a simple edit menu:
+
+  >>> import zope.interface
+  >>> class EditMenu(zope.interface.Interface):
+  ...     """This is an edit menu."""
+
+  >>> from zope.browsermenu.interfaces import IMenuItemType
+  >>> zope.interface.directlyProvides(EditMenu, IMenuItemType)
+
+  >>> from zope.component import provideUtility
+  >>> provideUtility(EditMenu, IMenuItemType, 'edit')
+
+Now we have to create and register the menu itself:
+
+  >>> from zope.browsermenu.interfaces import IBrowserMenu
+  >>> provideUtility(
+  ...     menu.BrowserMenu('edit', u'Edit', u'Edit Menu'), IBrowserMenu, 'edit')
+
+Note that these steps seem like a lot of boilerplate, but all this work is
+commonly done for you via ZCML. An item in a menu is simply an adapter that
+provides. In the following section we will have a closer look at the browser
+menu item:
+
+``BrowserMenuItem`` class
+-------------------------
+
+The browser menu item represents an entry in the menu. Essentially, the menu
+item is a browser view of a content component. Thus we have to create a
+content component first:
+
+  >>> class IContent(zope.interface.Interface):
+  ...     pass
+
+  >>> from zope.publisher.interfaces.browser import IBrowserPublisher
+  >>> from zope.security.interfaces import Unauthorized, Forbidden
+
+  >>> class Content(object):
+  ...     zope.interface.implements(IContent, IBrowserPublisher)
+  ...
+  ...     def foo(self):
+  ...         pass
+  ...
+  ...     def browserDefault(self, r):
+  ...         return self, ()
+  ...
+  ...     def publishTraverse(self, request, name):
+  ...         if name.startswith('fb'):
+  ...             raise Forbidden, name
+  ...         if name.startswith('ua'):
+  ...             raise Unauthorized, name
+  ...         if name.startswith('le'):
+  ...             raise LookupError, name
+  ...         return self.foo
+
+We also implemented the ``IBrowserPublisher`` interface, because we want to
+make the object traversable, so that we can make availability checks later.
+
+Since the ``BrowserMenuItem`` is just a view, we can initiate it with an
+object and a request.
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> item = menu.BrowserMenuItem(Content(), TestRequest())
+
+Note that the menu item knows *nothing* about the menu itself. It purely
+depends on the adapter registration to determine in which menu it will
+appear. The advantage is that a menu item can be reused in several menus.
+
+Now we add a title, description, order and icon and see whether we can then
+access the value. Note that these assignments are always automatically done by
+the framework.
+
+  >>> item.title = u'Item 1'
+  >>> item.title
+  u'Item 1'
+
+  >>> item.description = u'This is Item 1.'
+  >>> item.description
+  u'This is Item 1.'
+
+  >>> item.order
+  0
+  >>> item.order = 1
+  >>> item.order
+  1
+
+  >>> item.icon is None
+  True
+  >>> item.icon = u'/@@/icon.png'
+  >>> item.icon
+  u'/@@/icon.png'
+
+Since there is no permission or view specified yet, the menu item should
+be available and not selected.
+
+  >>> item.available()
+  True
+  >>> item.selected()
+  False
+
+There are two ways to deny availability of a menu item: (1) the current
+user does not have the correct permission to access the action or the menu
+item itself, or (2) the filter returns ``False``, in which case the menu
+item should also not be shown. 
+
+  >>> from zope.security.interfaces import IPermission
+  >>> from zope.security.permission import Permission
+  >>> perm = Permission('perm', 'Permission')
+  >>> provideUtility(perm, IPermission, 'perm')
+
+  >>> class ParticipationStub(object):
+  ...     principal = 'principal'
+  ...     interaction = None
+
+
+In the first case, the permission of the menu item was explicitely
+specified. Make sure that the user needs this permission to make the menu
+item available.
+
+  >>> item.permission = perm
+
+Now, we are not setting any user. This means that the menu item should be
+available.
+
+  >>> from zope.security.management import newInteraction, endInteraction
+  >>> endInteraction()
+  >>> newInteraction()
+  >>> item.available()
+  True
+
+Now we specify a principal that does not have the specified permission.
+
+  >>> endInteraction()
+  >>> newInteraction(ParticipationStub())
+  >>> item.available()
+  False
+
+In the second case, the permission is not explicitely defined and the
+availability is determined by the permission required to access the
+action.
+
+  >>> item.permission = None
+
+  All views starting with 'fb' are forbidden, the ones with 'ua' are
+  unauthorized and all others are allowed.
+
+  >>> item.action = u'fb'
+  >>> item.available()
+  False
+  >>> item.action = u'ua'
+  >>> item.available()
+  False
+  >>> item.action = u'a'
+  >>> item.available()
+  True
+
+Also, sometimes a menu item might be registered for a view that does not
+exist. In those cases the traversal mechanism raises a `TraversalError`, which
+is a special type of `LookupError`. All actions starting with `le` should
+raise this error:
+
+  >>> item.action = u'le'
+  >>> item.available()
+  False
+
+Now let's test filtering. If the filter is specified, it is assumed to be
+a TALES obejct.
+
+  >>> from zope.pagetemplate.engine import Engine
+  >>> item.action = u'a'
+  >>> item.filter = Engine.compile('not:context')
+  >>> item.available()
+  False
+  >>> item.filter = Engine.compile('context')
+  >>> item.available()
+  True
+
+Finally, make sure that the menu item can be selected.
+
+  >>> item.request = TestRequest(SERVER_URL='http://127.0.0.1/@@view.html',
+  ...                            PATH_INFO='/@@view.html')
+
+  >>> item.selected()
+  False
+  >>> item.action = u'view.html'
+  >>> item.selected()
+  True
+  >>> item.action = u'@@view.html'
+  >>> item.selected()
+  True
+  >>> item.request = TestRequest(
+  ...     SERVER_URL='http://127.0.0.1/++view++view.html',
+  ...     PATH_INFO='/++view++view.html')
+  >>> item.selected()
+  True
+  >>> item.action = u'otherview.html'
+  >>> item.selected()
+  False
+
+
+``BrowserSubMenuItem`` class
+----------------------------
+
+The menu framework also allows for submenus. Submenus can be inserted by
+creating a special menu item that simply points to another menu to be
+inserted:
+
+  >>> item = menu.BrowserSubMenuItem(Content(), TestRequest())
+
+The framework will always set the sub-menu automatically (we do it
+manually here):
+
+  >>> class SaveOptions(zope.interface.Interface):
+  ...     "A sub-menu that describes available save options for the content."
+
+  >>> zope.interface.directlyProvides(SaveOptions, IMenuItemType)
+
+  >>> provideUtility(SaveOptions, IMenuItemType, 'save')
+  >>> provideUtility(menu.BrowserMenu('save', u'Save', u'Save Menu'),
+  ...                IBrowserMenu, 'save')
+
+Now we can assign the sub-menu id to the menu item: 
+
+  >>> item.submenuId = 'save'
+
+Also, the ``action`` attribute for the browser sub-menu item is optional,
+because you often do not want the item itself to represent something. The rest
+of the class is identical to the ``BrowserMenuItem`` class.
+
+
+Getting a Menu
+--------------
+
+Now that we know how the single menu item works, let's have a look at how menu
+items get put together to a menu. But let's first create some menu items and
+register them as adapters with the component architecture.
+
+Register the edit menu entries first. We use the menu item factory to create
+the items:
+
+  >>> from zope.component import provideAdapter
+  >>> from zope.publisher.interfaces.browser import IBrowserRequest
+
+  >>> undo = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Undo", 
+  ...                                 action="undo.html")
+  >>> provideAdapter(undo, (IContent, IBrowserRequest), EditMenu, 'undo')
+
+  >>> redo = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Redo",
+  ...                                 action="redo.html", icon="/@@/redo.png")
+  >>> provideAdapter(redo, (IContent, IBrowserRequest), EditMenu, 'redo')
+
+  >>> save = metaconfigure.MenuItemFactory(menu.BrowserSubMenuItem, title="Save", 
+  ...                                 submenuId='save', order=2)
+  >>> provideAdapter(save, (IContent, IBrowserRequest), EditMenu, 'save')
+
+And now the save options:
+
+  >>> saveas = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Save as", 
+  ...                                   action="saveas.html")
+  >>> provideAdapter(saveas, (IContent, IBrowserRequest), 
+  ...                SaveOptions, 'saveas')
+
+  >>> saveall = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Save all",
+  ...                                    action="saveall.html")
+  >>> provideAdapter(saveall, (IContent, IBrowserRequest), 
+  ...                SaveOptions, 'saveall')
+
+Note that we can also register menu items for classes:
+
+
+  >>> new = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="New",
+  ...                                 action="new.html", _for=Content)
+  >>> provideAdapter(new, (Content, IBrowserRequest), EditMenu, 'new')
+
+
+The utility that is used to generate the menu into a TAL-friendly
+data-structure is ``getMenu()``::
+
+  getMenu(menuId, object, request)
+
+where ``menuId`` is the id originally specified for the menu. Let's look up the
+menu now:
+
+  >>> pprint(menu.getMenu('edit', Content(), TestRequest()))
+  [{'action': 'new.html',
+    'description': u'',
+    'extra': None,
+    'icon': None,
+    'selected': u'',
+    'submenu': None,
+    'title': 'New'},
+  {'action': 'redo.html',
+    'description': u'',
+    'extra': None,
+    'icon': '/@@/redo.png',
+    'selected': u'',
+    'submenu': None,
+    'title': 'Redo'},
+   {'action': 'undo.html',
+    'description': u'',
+    'extra': None,
+    'icon': None,
+    'selected': u'',
+    'submenu': None,
+    'title': 'Undo'},
+   {'action': u'',
+    'description': u'',
+    'extra': None,
+    'icon': None,
+    'selected': u'',
+    'submenu': [{'action': 'saveall.html',
+                 'description': u'',
+                 'extra': None,
+                 'icon': None,
+                 'selected': u'',
+                 'submenu': None,
+                 'title': 'Save all'},
+                {'action': 'saveas.html',
+                 'description': u'',
+                 'extra': None,
+                 'icon': None,
+                 'selected': u'',
+                 'submenu': None,
+                 'title': 'Save as'}],
+    'title': 'Save'}]
+
+
+Custom ``IBrowserMenu`` Implementations
+---------------------------------------
+
+Until now we have only seen how to use the default menu implementation. Much
+of the above boilerplate was necessary just to support custom menus. But what
+could custom menus do? Sometimes menu items are dynamically generated based on
+a certain state of the object the menu is for. For example, you might want to
+show all items in a folder-like component. So first let's create this
+folder-like component:
+
+  >>> class Folderish(Content):
+  ...     names = ['README.txt', 'logo.png', 'script.py']
+
+Now we create a menu using the names to create a menu:
+
+  >>> from zope.browsermenu.interfaces import IBrowserMenu
+
+  >>> class Items(object):
+  ...     zope.interface.implements(IBrowserMenu)
+  ...  
+  ...     def __init__(self, id, title=u'', description=u''):
+  ...         self.id = id
+  ...         self.title = title
+  ...         self.description = description
+  ...     
+  ...     def getMenuItems(self, object, request):
+  ...         return [{'title': name,
+  ...                  'description': None,
+  ...                  'action': name + '/manage',
+  ...                  'selected': u'',
+  ...                  'icon': None,
+  ...                  'extra': {},
+  ...                  'submenu': None}
+  ...                 for name in object.names]
+
+and register it:
+
+  >>> provideUtility(Items('items', u'Items', u'Items Menu'),
+  ...                IBrowserMenu, 'items')
+
+We can now get the menu items using the previously introduced API:
+
+  >>> pprint(menu.getMenu('items', Folderish(), TestRequest()))
+  [{'action': 'README.txt/manage',
+    'description': None,
+    'extra': {},
+    'icon': None,
+    'selected': u'',
+    'submenu': None,
+    'title': 'README.txt'},
+   {'action': 'logo.png/manage',
+    'description': None,
+    'extra': {},
+    'icon': None,
+    'selected': u'',
+    'submenu': None,
+    'title': 'logo.png'},
+   {'action': 'script.py/manage',
+    'description': None,
+    'extra': {},
+    'icon': None,
+    'selected': u'',
+    'submenu': None,
+    'title': 'script.py'}]
+
+
+``MenuItemFactory`` class
+-------------------------
+
+As you have seen above already, we have used the menu item factory to generate
+adapter factories for menu items. The factory needs a particular
+``IBrowserMenuItem`` class to instantiate. Here is an example using a dummy
+menu item class:
+  
+  >>> class DummyBrowserMenuItem(object):
+  ...     "a dummy factory for menu items"
+  ...     def __init__(self, context, request):
+  ...         self.context = context
+  ...         self.request = request
+  
+To instantiate this class, pass the factory and the other arguments as keyword
+arguments (every key in the arguments should map to an attribute of the menu
+item class). We use dummy values for this example.
+  
+  >>> factory = metaconfigure.MenuItemFactory(
+  ...     DummyBrowserMenuItem, title='Title', description='Description', 
+  ...     icon='Icon', action='Action', filter='Filter', 
+  ...     permission='zope.Public', extra='Extra', order='Order', _for='For')
+  >>> factory.factory is DummyBrowserMenuItem
+  True
+  
+The "zope.Public" permission needs to be translated to ``CheckerPublic``.
+  
+  >>> from zope.security.checker import CheckerPublic
+  >>> factory.kwargs['permission'] is CheckerPublic
+  True
+  
+Call the factory with context and request to return the instance.  We continue
+to use dummy values.
+  
+  >>> item = factory('Context', 'Request')
+  
+The returned value should be an instance of the ``DummyBrowserMenuItem``, and
+have all of the values we initially set on the factory.
+  
+  >>> isinstance(item, DummyBrowserMenuItem)
+  True
+  >>> item.context
+  'Context'
+  >>> item.request
+  'Request'
+  >>> item.title
+  'Title'
+  >>> item.description
+  'Description'
+  >>> item.icon
+  'Icon'
+  >>> item.action
+  'Action'
+  >>> item.filter
+  'Filter'
+  >>> item.permission is CheckerPublic
+  True
+  >>> item.extra
+  'Extra'
+  >>> item.order
+  'Order'
+  >>> item._for
+  'For'
+  
+If you pass a permission other than ``zope.Public`` to the
+``MenuItemFactory``, it should pass through unmodified.
+  
+  >>> factory = metaconfigure.MenuItemFactory(
+  ...     DummyBrowserMenuItem, title='Title', description='Description', 
+  ...     icon='Icon', action='Action', filter='Filter', 
+  ...     permission='another.Permission', extra='Extra', order='Order', 
+  ...     _for='For_')
+  >>> factory.kwargs['permission']
+  'another.Permission'
+
+
+Directive Handlers
+------------------
+
+``menu`` Directive Handler
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Provides a new menu (item type).
+
+  >>> 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()
+  >>> metaconfigure.menuDirective(context, u'menu1', title=u'Menu 1')
+  >>> iface = context.actions[0]['args'][1]
+  >>> iface.getName()
+  u'menu1'
+
+  >>> import sys
+  >>> hasattr(sys.modules['zope.app.menus'], 'menu1')
+  True
+
+  >>> del sys.modules['zope.app.menus'].menu1
+
+Possibility 2: Just specify an interface
+++++++++++++++++++++++++++++++++++++++++
+
+  >>> class menu1(zope.interface.Interface):
+  ...     pass
+
+  >>> context = Context()
+  >>> metaconfigure.menuDirective(context, interface=menu1)
+  >>> context.actions[0]['args'][1] is menu1
+  True
+
+Possibility 3: Specify an interface and an id
++++++++++++++++++++++++++++++++++++++++++++++
+
+  >>> context = Context()
+  >>> metaconfigure.menuDirective(context, id='menu1', interface=menu1)
+
+  >>> pprint([action['discriminator'] for action in context.actions])
+  [('browser', 'MenuItemType', '__builtin__.menu1'),
+   ('interface', '__builtin__.menu1'),
+   ('browser', 'MenuItemType', 'menu1'),
+   ('utility',
+    <InterfaceClass zope.browsermenu.interfaces.IBrowserMenu>,
+    'menu1'),
+   None]
+   
+Here are some disallowed configurations.
+
+  >>> context = Context()
+  >>> metaconfigure.menuDirective(context)
+  Traceback (most recent call last):
+  ...
+  ConfigurationError: You must specify the 'id' or 'interface' attribute.
+
+  >>> metaconfigure.menuDirective(context, title='Menu 1')
+  Traceback (most recent call last):
+  ...
+  ConfigurationError: You must specify the 'id' or 'interface' attribute.
+
+
+``menuItems`` Directive Handler
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Register several menu items for a particular menu.
+
+  >>> class TestMenuItemType(zope.interface.Interface):
+  ...     pass
+
+  >>> class ITest(zope.interface.Interface): 
+  ...     pass
+
+  >>> context = Context()
+  >>> items = metaconfigure.menuItemsDirective(context, TestMenuItemType, ITest)
+  >>> context.actions
+  []
+  >>> items.menuItem(context, u'view.html', 'View')
+  >>> items.subMenuItem(context, SaveOptions, 'Save')
+
+  >>> disc = [action['discriminator'] for action in context.actions]
+  >>> disc.sort()
+  >>> pprint(disc[-2:])
+  [('adapter',
+    (<InterfaceClass __builtin__.ITest>,
+     <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
+    <InterfaceClass __builtin__.TestMenuItemType>,
+    'Save'),
+   ('adapter',
+    (<InterfaceClass __builtin__.ITest>,
+     <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
+    <InterfaceClass __builtin__.TestMenuItemType>,
+    'View')]
+
+Custom menu item classes
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+We can register menu items and sub menu items with custom classes instead
+of ones used by default. For that, we need to create an implementation
+of IBrowserMenuItem or IBrowserSubMenuItem.
+
+  >>> context = Context()
+  >>> items = metaconfigure.menuItemsDirective(context, TestMenuItemType, ITest)
+  >>> context.actions
+  []
+
+Let's create a custom menu item class that inherits standard BrowserMenuItem:
+
+  >>> class MyMenuItem(menu.BrowserMenuItem):
+  ...    pass
+
+  >>> items.menuItem(context, u'view.html', 'View', item_class=MyMenuItem)
+
+Also create a custom sub menu item class inheriting standard BrowserSubMenuItem:
+
+  >>> class MySubMenuItem(menu.BrowserSubMenuItem):
+  ...    pass
+
+  >>> items.subMenuItem(context, SaveOptions, 'Save', item_class=MySubMenuItem)
+
+  >>> actions = sorted(context.actions, key=lambda a:a['discriminator'])
+  >>> factories = [action['args'][1] for action in actions][-2:]
+
+  >>> factories[0].factory is MySubMenuItem
+  True
+
+  >>> factories[1].factory is MyMenuItem
+  True
+
+These directive will fail if you provide an item_class that does not
+implement IBrowserMenuItem/IBrowserSubMenuItem:
+
+  >>> items.menuItem(context, u'fail', 'Failed', item_class=object)
+  Traceback (most recent call last):
+  ...
+  ValueError: Item class (<type 'object'>) must implement IBrowserMenuItem
+
+  >>> items.subMenuItem(context, SaveOptions, 'Failed', item_class=object)
+  Traceback (most recent call last):
+  ...
+  ValueError: Item class (<type 'object'>) must implement IBrowserSubMenuItem


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/__init__.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/field.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/field.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/field.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Menu field
 
-$Id: fields.py 100240 2009-05-22 16:33:41Z faassen $
+$Id$
 """
 __docformat__ = 'restructuredtext'
 


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/field.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/interfaces.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/interfaces.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/interfaces.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Menu-specific interfaces
 
-$Id: browser.py 97455 2009-03-03 19:57:53Z nadako $
+$Id$
 """
 from zope.i18nmessageid import ZopeMessageFactory as _
 from zope.interface import Interface, directlyProvides


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/interfaces.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/menu.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/menu.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/menu.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Menu implementation code
 
-$Id: menu.py 100372 2009-05-25 19:31:23Z tseaver $
+$Id$
 """
 __docformat__ = "reStructuredText"
 import sys


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/menu.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Deleted: zope.browsermenu/trunk/src/zope/browsermenu/menu.txt
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/menu.txt	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/menu.txt	2009-08-27 13:56:02 UTC (rev 103270)
@@ -1,633 +0,0 @@
-=============
-Browser Menus
-=============
-
-Browser menus are used to categorize browser actions, such as the views of a
-content component or the addable components of a container. In essence they
-provide the same functionality as menu bars in desktop application.
-
-  >>> from zope.browsermenu import menu, metaconfigure
-
-Menus are simple components that have an id, title and description. They also
-must provide a method called ``getMenuItems(object, request)`` that returns a
-TAL-friendly list of information dictionaries. We will see this in detail
-later. The default menu implementation, however, makes the menu be very
-transparent by identifying the menu through an interface. So let's define and
-register a simple edit menu:
-
-  >>> import zope.interface
-  >>> class EditMenu(zope.interface.Interface):
-  ...     """This is an edit menu."""
-
-  >>> from zope.browsermenu.interfaces import IMenuItemType
-  >>> zope.interface.directlyProvides(EditMenu, IMenuItemType)
-
-  >>> from zope.component import provideUtility
-  >>> provideUtility(EditMenu, IMenuItemType, 'edit')
-
-Now we have to create and register the menu itself:
-
-  >>> from zope.browsermenu.interfaces import IBrowserMenu
-  >>> provideUtility(
-  ...     menu.BrowserMenu('edit', u'Edit', u'Edit Menu'), IBrowserMenu, 'edit')
-
-Note that these steps seem like a lot of boilerplate, but all this work is
-commonly done for you via ZCML. An item in a menu is simply an adapter that
-provides. In the following section we will have a closer look at the browser
-menu item:
-
-``BrowserMenuItem`` class
--------------------------
-
-The browser menu item represents an entry in the menu. Essentially, the menu
-item is a browser view of a content component. Thus we have to create a
-content component first:
-
-  >>> class IContent(zope.interface.Interface):
-  ...     pass
-
-  >>> from zope.publisher.interfaces.browser import IBrowserPublisher
-  >>> from zope.security.interfaces import Unauthorized, Forbidden
-
-  >>> class Content(object):
-  ...     zope.interface.implements(IContent, IBrowserPublisher)
-  ...
-  ...     def foo(self):
-  ...         pass
-  ...
-  ...     def browserDefault(self, r):
-  ...         return self, ()
-  ...
-  ...     def publishTraverse(self, request, name):
-  ...         if name.startswith('fb'):
-  ...             raise Forbidden, name
-  ...         if name.startswith('ua'):
-  ...             raise Unauthorized, name
-  ...         if name.startswith('le'):
-  ...             raise LookupError, name
-  ...         return self.foo
-
-We also implemented the ``IBrowserPublisher`` interface, because we want to
-make the object traversable, so that we can make availability checks later.
-
-Since the ``BrowserMenuItem`` is just a view, we can initiate it with an
-object and a request.
-
-  >>> from zope.publisher.browser import TestRequest
-  >>> item = menu.BrowserMenuItem(Content(), TestRequest())
-
-Note that the menu item knows *nothing* about the menu itself. It purely
-depends on the adapter registration to determine in which menu it will
-appear. The advantage is that a menu item can be reused in several menus.
-
-Now we add a title, description, order and icon and see whether we can then
-access the value. Note that these assignments are always automatically done by
-the framework.
-
-  >>> item.title = u'Item 1'
-  >>> item.title
-  u'Item 1'
-
-  >>> item.description = u'This is Item 1.'
-  >>> item.description
-  u'This is Item 1.'
-
-  >>> item.order
-  0
-  >>> item.order = 1
-  >>> item.order
-  1
-
-  >>> item.icon is None
-  True
-  >>> item.icon = u'/@@/icon.png'
-  >>> item.icon
-  u'/@@/icon.png'
-
-Since there is no permission or view specified yet, the menu item should
-be available and not selected.
-
-  >>> item.available()
-  True
-  >>> item.selected()
-  False
-
-There are two ways to deny availability of a menu item: (1) the current
-user does not have the correct permission to access the action or the menu
-item itself, or (2) the filter returns ``False``, in which case the menu
-item should also not be shown. 
-
-  >>> from zope.security.interfaces import IPermission
-  >>> from zope.security.permission import Permission
-  >>> perm = Permission('perm', 'Permission')
-  >>> provideUtility(perm, IPermission, 'perm')
-
-  >>> class ParticipationStub(object):
-  ...     principal = 'principal'
-  ...     interaction = None
-
-
-In the first case, the permission of the menu item was explicitely
-specified. Make sure that the user needs this permission to make the menu
-item available.
-
-  >>> item.permission = perm
-
-Now, we are not setting any user. This means that the menu item should be
-available.
-
-  >>> from zope.security.management import newInteraction, endInteraction
-  >>> endInteraction()
-  >>> newInteraction()
-  >>> item.available()
-  True
-
-Now we specify a principal that does not have the specified permission.
-
-  >>> endInteraction()
-  >>> newInteraction(ParticipationStub())
-  >>> item.available()
-  False
-
-In the second case, the permission is not explicitely defined and the
-availability is determined by the permission required to access the
-action.
-
-  >>> item.permission = None
-
-  All views starting with 'fb' are forbidden, the ones with 'ua' are
-  unauthorized and all others are allowed.
-
-  >>> item.action = u'fb'
-  >>> item.available()
-  False
-  >>> item.action = u'ua'
-  >>> item.available()
-  False
-  >>> item.action = u'a'
-  >>> item.available()
-  True
-
-Also, sometimes a menu item might be registered for a view that does not
-exist. In those cases the traversal mechanism raises a `TraversalError`, which
-is a special type of `LookupError`. All actions starting with `le` should
-raise this error:
-
-  >>> item.action = u'le'
-  >>> item.available()
-  False
-
-Now let's test filtering. If the filter is specified, it is assumed to be
-a TALES obejct.
-
-  >>> from zope.pagetemplate.engine import Engine
-  >>> item.action = u'a'
-  >>> item.filter = Engine.compile('not:context')
-  >>> item.available()
-  False
-  >>> item.filter = Engine.compile('context')
-  >>> item.available()
-  True
-
-Finally, make sure that the menu item can be selected.
-
-  >>> item.request = TestRequest(SERVER_URL='http://127.0.0.1/@@view.html',
-  ...                            PATH_INFO='/@@view.html')
-
-  >>> item.selected()
-  False
-  >>> item.action = u'view.html'
-  >>> item.selected()
-  True
-  >>> item.action = u'@@view.html'
-  >>> item.selected()
-  True
-  >>> item.request = TestRequest(
-  ...     SERVER_URL='http://127.0.0.1/++view++view.html',
-  ...     PATH_INFO='/++view++view.html')
-  >>> item.selected()
-  True
-  >>> item.action = u'otherview.html'
-  >>> item.selected()
-  False
-
-
-``BrowserSubMenuItem`` class
-----------------------------
-
-The menu framework also allows for submenus. Submenus can be inserted by
-creating a special menu item that simply points to another menu to be
-inserted:
-
-  >>> item = menu.BrowserSubMenuItem(Content(), TestRequest())
-
-The framework will always set the sub-menu automatically (we do it
-manually here):
-
-  >>> class SaveOptions(zope.interface.Interface):
-  ...     "A sub-menu that describes available save options for the content."
-
-  >>> zope.interface.directlyProvides(SaveOptions, IMenuItemType)
-
-  >>> provideUtility(SaveOptions, IMenuItemType, 'save')
-  >>> provideUtility(menu.BrowserMenu('save', u'Save', u'Save Menu'),
-  ...                IBrowserMenu, 'save')
-
-Now we can assign the sub-menu id to the menu item: 
-
-  >>> item.submenuId = 'save'
-
-Also, the ``action`` attribute for the browser sub-menu item is optional,
-because you often do not want the item itself to represent something. The rest
-of the class is identical to the ``BrowserMenuItem`` class.
-
-
-Getting a Menu
---------------
-
-Now that we know how the single menu item works, let's have a look at how menu
-items get put together to a menu. But let's first create some menu items and
-register them as adapters with the component architecture.
-
-Register the edit menu entries first. We use the menu item factory to create
-the items:
-
-  >>> from zope.component import provideAdapter
-  >>> from zope.publisher.interfaces.browser import IBrowserRequest
-
-  >>> undo = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Undo", 
-  ...                                 action="undo.html")
-  >>> provideAdapter(undo, (IContent, IBrowserRequest), EditMenu, 'undo')
-
-  >>> redo = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Redo",
-  ...                                 action="redo.html", icon="/@@/redo.png")
-  >>> provideAdapter(redo, (IContent, IBrowserRequest), EditMenu, 'redo')
-
-  >>> save = metaconfigure.MenuItemFactory(menu.BrowserSubMenuItem, title="Save", 
-  ...                                 submenuId='save', order=2)
-  >>> provideAdapter(save, (IContent, IBrowserRequest), EditMenu, 'save')
-
-And now the save options:
-
-  >>> saveas = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Save as", 
-  ...                                   action="saveas.html")
-  >>> provideAdapter(saveas, (IContent, IBrowserRequest), 
-  ...                SaveOptions, 'saveas')
-
-  >>> saveall = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="Save all",
-  ...                                    action="saveall.html")
-  >>> provideAdapter(saveall, (IContent, IBrowserRequest), 
-  ...                SaveOptions, 'saveall')
-
-Note that we can also register menu items for classes:
-
-
-  >>> new = metaconfigure.MenuItemFactory(menu.BrowserMenuItem, title="New",
-  ...                                 action="new.html", _for=Content)
-  >>> provideAdapter(new, (Content, IBrowserRequest), EditMenu, 'new')
-
-
-The utility that is used to generate the menu into a TAL-friendly
-data-structure is ``getMenu()``::
-
-  getMenu(menuId, object, request)
-
-where ``menuId`` is the id originally specified for the menu. Let's look up the
-menu now:
-
-  >>> pprint(menu.getMenu('edit', Content(), TestRequest()))
-  [{'action': 'new.html',
-    'description': u'',
-    'extra': None,
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'New'},
-  {'action': 'redo.html',
-    'description': u'',
-    'extra': None,
-    'icon': '/@@/redo.png',
-    'selected': u'',
-    'submenu': None,
-    'title': 'Redo'},
-   {'action': 'undo.html',
-    'description': u'',
-    'extra': None,
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'Undo'},
-   {'action': u'',
-    'description': u'',
-    'extra': None,
-    'icon': None,
-    'selected': u'',
-    'submenu': [{'action': 'saveall.html',
-                 'description': u'',
-                 'extra': None,
-                 'icon': None,
-                 'selected': u'',
-                 'submenu': None,
-                 'title': 'Save all'},
-                {'action': 'saveas.html',
-                 'description': u'',
-                 'extra': None,
-                 'icon': None,
-                 'selected': u'',
-                 'submenu': None,
-                 'title': 'Save as'}],
-    'title': 'Save'}]
-
-
-Custom ``IBrowserMenu`` Implementations
----------------------------------------
-
-Until now we have only seen how to use the default menu implementation. Much
-of the above boilerplate was necessary just to support custom menus. But what
-could custom menus do? Sometimes menu items are dynamically generated based on
-a certain state of the object the menu is for. For example, you might want to
-show all items in a folder-like component. So first let's create this
-folder-like component:
-
-  >>> class Folderish(Content):
-  ...     names = ['README.txt', 'logo.png', 'script.py']
-
-Now we create a menu using the names to create a menu:
-
-  >>> from zope.browsermenu.interfaces import IBrowserMenu
-
-  >>> class Items(object):
-  ...     zope.interface.implements(IBrowserMenu)
-  ...  
-  ...     def __init__(self, id, title=u'', description=u''):
-  ...         self.id = id
-  ...         self.title = title
-  ...         self.description = description
-  ...     
-  ...     def getMenuItems(self, object, request):
-  ...         return [{'title': name,
-  ...                  'description': None,
-  ...                  'action': name + '/manage',
-  ...                  'selected': u'',
-  ...                  'icon': None,
-  ...                  'extra': {},
-  ...                  'submenu': None}
-  ...                 for name in object.names]
-
-and register it:
-
-  >>> provideUtility(Items('items', u'Items', u'Items Menu'),
-  ...                IBrowserMenu, 'items')
-
-We can now get the menu items using the previously introduced API:
-
-  >>> pprint(menu.getMenu('items', Folderish(), TestRequest()))
-  [{'action': 'README.txt/manage',
-    'description': None,
-    'extra': {},
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'README.txt'},
-   {'action': 'logo.png/manage',
-    'description': None,
-    'extra': {},
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'logo.png'},
-   {'action': 'script.py/manage',
-    'description': None,
-    'extra': {},
-    'icon': None,
-    'selected': u'',
-    'submenu': None,
-    'title': 'script.py'}]
-
-
-``MenuItemFactory`` class
--------------------------
-
-As you have seen above already, we have used the menu item factory to generate
-adapter factories for menu items. The factory needs a particular
-``IBrowserMenuItem`` class to instantiate. Here is an example using a dummy
-menu item class:
-  
-  >>> class DummyBrowserMenuItem(object):
-  ...     "a dummy factory for menu items"
-  ...     def __init__(self, context, request):
-  ...         self.context = context
-  ...         self.request = request
-  
-To instantiate this class, pass the factory and the other arguments as keyword
-arguments (every key in the arguments should map to an attribute of the menu
-item class). We use dummy values for this example.
-  
-  >>> factory = metaconfigure.MenuItemFactory(
-  ...     DummyBrowserMenuItem, title='Title', description='Description', 
-  ...     icon='Icon', action='Action', filter='Filter', 
-  ...     permission='zope.Public', extra='Extra', order='Order', _for='For')
-  >>> factory.factory is DummyBrowserMenuItem
-  True
-  
-The "zope.Public" permission needs to be translated to ``CheckerPublic``.
-  
-  >>> from zope.security.checker import CheckerPublic
-  >>> factory.kwargs['permission'] is CheckerPublic
-  True
-  
-Call the factory with context and request to return the instance.  We continue
-to use dummy values.
-  
-  >>> item = factory('Context', 'Request')
-  
-The returned value should be an instance of the ``DummyBrowserMenuItem``, and
-have all of the values we initially set on the factory.
-  
-  >>> isinstance(item, DummyBrowserMenuItem)
-  True
-  >>> item.context
-  'Context'
-  >>> item.request
-  'Request'
-  >>> item.title
-  'Title'
-  >>> item.description
-  'Description'
-  >>> item.icon
-  'Icon'
-  >>> item.action
-  'Action'
-  >>> item.filter
-  'Filter'
-  >>> item.permission is CheckerPublic
-  True
-  >>> item.extra
-  'Extra'
-  >>> item.order
-  'Order'
-  >>> item._for
-  'For'
-  
-If you pass a permission other than ``zope.Public`` to the
-``MenuItemFactory``, it should pass through unmodified.
-  
-  >>> factory = metaconfigure.MenuItemFactory(
-  ...     DummyBrowserMenuItem, title='Title', description='Description', 
-  ...     icon='Icon', action='Action', filter='Filter', 
-  ...     permission='another.Permission', extra='Extra', order='Order', 
-  ...     _for='For_')
-  >>> factory.kwargs['permission']
-  'another.Permission'
-
-
-Directive Handlers
-------------------
-
-``menu`` Directive Handler
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Provides a new menu (item type).
-
-  >>> 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()
-  >>> metaconfigure.menuDirective(context, u'menu1', title=u'Menu 1')
-  >>> iface = context.actions[0]['args'][1]
-  >>> iface.getName()
-  u'menu1'
-
-  >>> import sys
-  >>> hasattr(sys.modules['zope.app.menus'], 'menu1')
-  True
-
-  >>> del sys.modules['zope.app.menus'].menu1
-
-Possibility 2: Just specify an interface
-++++++++++++++++++++++++++++++++++++++++
-
-  >>> class menu1(zope.interface.Interface):
-  ...     pass
-
-  >>> context = Context()
-  >>> metaconfigure.menuDirective(context, interface=menu1)
-  >>> context.actions[0]['args'][1] is menu1
-  True
-
-Possibility 3: Specify an interface and an id
-+++++++++++++++++++++++++++++++++++++++++++++
-
-  >>> context = Context()
-  >>> metaconfigure.menuDirective(context, id='menu1', interface=menu1)
-
-  >>> pprint([action['discriminator'] for action in context.actions])
-  [('browser', 'MenuItemType', '__builtin__.menu1'),
-   ('interface', '__builtin__.menu1'),
-   ('browser', 'MenuItemType', 'menu1'),
-   ('utility',
-    <InterfaceClass zope.browsermenu.interfaces.IBrowserMenu>,
-    'menu1'),
-   None]
-   
-Here are some disallowed configurations.
-
-  >>> context = Context()
-  >>> metaconfigure.menuDirective(context)
-  Traceback (most recent call last):
-  ...
-  ConfigurationError: You must specify the 'id' or 'interface' attribute.
-
-  >>> metaconfigure.menuDirective(context, title='Menu 1')
-  Traceback (most recent call last):
-  ...
-  ConfigurationError: You must specify the 'id' or 'interface' attribute.
-
-
-``menuItems`` Directive Handler
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Register several menu items for a particular menu.
-
-  >>> class TestMenuItemType(zope.interface.Interface):
-  ...     pass
-
-  >>> class ITest(zope.interface.Interface): 
-  ...     pass
-
-  >>> context = Context()
-  >>> items = metaconfigure.menuItemsDirective(context, TestMenuItemType, ITest)
-  >>> context.actions
-  []
-  >>> items.menuItem(context, u'view.html', 'View')
-  >>> items.subMenuItem(context, SaveOptions, 'Save')
-
-  >>> disc = [action['discriminator'] for action in context.actions]
-  >>> disc.sort()
-  >>> pprint(disc[-2:])
-  [('adapter',
-    (<InterfaceClass __builtin__.ITest>,
-     <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
-    <InterfaceClass __builtin__.TestMenuItemType>,
-    'Save'),
-   ('adapter',
-    (<InterfaceClass __builtin__.ITest>,
-     <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
-    <InterfaceClass __builtin__.TestMenuItemType>,
-    'View')]
-
-Custom menu item classes
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-We can register menu items and sub menu items with custom classes instead
-of ones used by default. For that, we need to create an implementation
-of IBrowserMenuItem or IBrowserSubMenuItem.
-
-  >>> context = Context()
-  >>> items = metaconfigure.menuItemsDirective(context, TestMenuItemType, ITest)
-  >>> context.actions
-  []
-
-Let's create a custom menu item class that inherits standard BrowserMenuItem:
-
-  >>> class MyMenuItem(menu.BrowserMenuItem):
-  ...    pass
-
-  >>> items.menuItem(context, u'view.html', 'View', item_class=MyMenuItem)
-
-Also create a custom sub menu item class inheriting standard BrowserSubMenuItem:
-
-  >>> class MySubMenuItem(menu.BrowserSubMenuItem):
-  ...    pass
-
-  >>> items.subMenuItem(context, SaveOptions, 'Save', item_class=MySubMenuItem)
-
-  >>> actions = sorted(context.actions, key=lambda a:a['discriminator'])
-  >>> factories = [action['args'][1] for action in actions][-2:]
-
-  >>> factories[0].factory is MySubMenuItem
-  True
-
-  >>> factories[1].factory is MyMenuItem
-  True
-
-These directive will fail if you provide an item_class that does not
-implement IBrowserMenuItem/IBrowserSubMenuItem:
-
-  >>> items.menuItem(context, u'fail', 'Failed', item_class=object)
-  Traceback (most recent call last):
-  ...
-  ValueError: Item class (<type 'object'>) must implement IBrowserMenuItem
-
-  >>> items.subMenuItem(context, SaveOptions, 'Failed', item_class=object)
-  Traceback (most recent call last):
-  ...
-  ValueError: Item class (<type 'object'>) must implement IBrowserSubMenuItem

Modified: zope.browsermenu/trunk/src/zope/browsermenu/metaconfigure.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/metaconfigure.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/metaconfigure.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Menu Directives Configuration Handlers
 
-$Id: menumeta.py 100372 2009-05-25 19:31:23Z tseaver $
+$Id$
 """
 from zope.browser.interfaces import IAdding
 from zope.component import getGlobalSiteManager, getUtility


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/metaconfigure.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/metadirectives.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/metadirectives.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/metadirectives.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Menu ZCML directives
 
-$Id: metadirectives.py 103143 2009-08-24 12:28:19Z nadako $
+$Id$
 """
 from zope.interface import Interface
 from zope.configuration.fields import GlobalObject, GlobalInterface


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/metadirectives.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/tests/__init__.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_addMenuItem.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/tests/test_addMenuItem.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/tests/test_addMenuItem.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -60,7 +60,7 @@
    <InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
   {}))
 
-$Id: test_addMenuItem.py 100126 2009-05-19 12:55:59Z faassen $
+$Id$
 """
 
 import unittest


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_addMenuItem.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_directives.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/tests/test_directives.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/tests/test_directives.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """'browser' namespace directive tests
 
-$Id: test_directives.py 103143 2009-08-24 12:28:19Z nadako $
+$Id$
 """
 
 import sys


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_directives.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_fields.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/tests/test_fields.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/tests/test_fields.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Test fields.
 
-$Id: test_fields.py 29570 2005-03-18 22:53:37Z rogerineichen $
+$Id$
 """
 import unittest
 from zope.testing import cleanup, doctest


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_fields.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menu.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menu.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menu.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,14 +13,14 @@
 ##############################################################################
 """Browser Menu Item Tests
 
-$Id: test_menu.py 29570 2005-03-18 22:53:37Z rogerineichen $
+$Id$
 """
 import unittest
 from zope.testing import doctest, cleanup, doctestunit
 
 def test_suite():
     return unittest.TestSuite((
-        doctest.DocFileSuite('../menu.txt',
+        doctest.DocFileSuite('../README.txt',
                              setUp=lambda test:cleanup.setUp(),
                              tearDown=lambda test:cleanup.tearDown(),
                              globs={'pprint': doctestunit.pprint},


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menu.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id

Modified: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menudirectives.py
===================================================================
--- zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menudirectives.py	2009-08-27 13:49:34 UTC (rev 103269)
+++ zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menudirectives.py	2009-08-27 13:56:02 UTC (rev 103270)
@@ -13,7 +13,7 @@
 ##############################################################################
 """Browser Menu Directives Tests
 
-$Id: test_menudirectives.py 70102 2006-09-11 20:47:15Z ctheune $
+$Id$
 """
 import unittest
 


Property changes on: zope.browsermenu/trunk/src/zope/browsermenu/tests/test_menudirectives.py
___________________________________________________________________
Modified: svn:keywords
   - Id,svn:eol-style=native
   + Id



More information about the Checkins mailing list