[Checkins] SVN: zope.app.publisher/trunk/ Merge the zope.app.publisher refactoring results from my sandbox.
Dan Korostelev
nadako at gmail.com
Thu Aug 27 11:12:52 EDT 2009
Log message for revision 103291:
Merge the zope.app.publisher refactoring results from my sandbox.
Changed:
U zope.app.publisher/trunk/CHANGES.txt
U zope.app.publisher/trunk/README.txt
U zope.app.publisher/trunk/buildout.cfg
U zope.app.publisher/trunk/setup.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml
U zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py
D zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt
U zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml
U zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py
U zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py
D zope.app.publisher/trunk/src/zope/app/publisher/browser/tests/
U zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py
U zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml
U zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py
U zope.app.publisher/trunk/src/zope/app/publisher/http.zcml
U zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py
U zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py
U zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py
U zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py
U zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py
U zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py
U zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py
U zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml
-=-
Modified: zope.app.publisher/trunk/CHANGES.txt
===================================================================
--- zope.app.publisher/trunk/CHANGES.txt 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/CHANGES.txt 2009-08-27 15:12:51 UTC (rev 103291)
@@ -2,11 +2,37 @@
CHANGES
=======
-3.8.5 (unreleased)
+3.9.0 (unreleased)
==================
-- ...
+Refactor package, spliting it to several new packages:
+ * ``zope.browserresource`` - the resources mechanism was moved here, see its
+ CHANGES.txt for more information about changes during move.
+
+ * ``zope.ptresource`` - the page template resource was moved into another
+ package so zope.browserresource doesn't depend on any templating system.
+ See zope.ptresource's CHANGES.txt for more information.
+
+ * ``zope.browsermenu`` - the menu mechanism was moved here completely.
+
+ * ``zope.browserpage`` - the browser:page directive and friends were
+ moved here. Also, these directives don't depend hardly on menu system
+ anymore, so they simply ignore the "menu" argument when zope.browsermenu
+ is not available.
+
+Backward-compatibility imports are provided, so there should not be much impact
+for those who uses old imports.
+
+The CacheableBrowserLanguages and ModifiableBrowserLanguages adapters were
+moved into ``zope.publisher`` package, as well as browser:defaultSkin and
+browser:defaultView ZCML directives and ZCML class configuration for
+zope.publisher classes.
+
+ZCML registrations of IXMLRPCPublisher adapters for zope.container were moved
+into zope.container for now.
+
+
3.8.4 (2009-07-23)
==================
Modified: zope.app.publisher/trunk/README.txt
===================================================================
--- zope.app.publisher/trunk/README.txt 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/README.txt 2009-08-27 15:12:51 UTC (rev 103291)
@@ -6,97 +6,20 @@
chunk of the Zope Toolkit and its assumptions. It is maintained by the*
`Zope Toolkit project <http://docs.zope.org/zopetoolkit/>`_.
-``zope.publisher`` is a general purpose object publishing framework
-which delegates to a publication object for determining the
-to-be-published object. With Zope 3's default publication from
-``zope.app.publication``, this is usually a view or a resource.
+This package used to provide browser page, resource and menu classes
+for use with zope.publisher object publishing framework, as well as some
+other useful utilities and adapters, but most of things was factored out
+to separate packages, leaving here only backward-compatibility imports.
-This package, ``zope.app.publisher``, provides base implementations
-for those. It also provides ZCML directives for configuring views and
-resources. More specifically, ``zope.app.publisher`` defines the
-following ZCML directives:
+However, some potentially useful things are still contained in this package:
-* browser:page
+ * "date" field converter for zope.publisher's BrowserRequest field converter
+ mechanism.
+
+ * "Browser Skins" vocabulary (a vocabulary for IBrowserSkinType utilities)
+
+ * ManagementViewSelector (a browser view that redirects to a first available
+ management view)
-* browser:pages
-
-* browser:view
-
-* browser:menu
-
-* browser:menuItem
-
-* browser:menuItems
-
-* browser:addMenuitem
-
-* browser:resource
-
-* browser:resourceDirectory
-
-* browser:defaultSkin
-
-* browser:icon
-
-* xmlrpc:view
-
-
-Views and Browser pages
-=======================
-
-XXX writeme
-
-
-Resources
-=========
-
-Resources are static files and directories that are served to the browser
-directly from the filesystem. The most common example are images, CSS style
-sheets, or JavaScript files.
-
-Resources are be registered under a symbolic name and can later be referred to
-by that name, so their usage is independent from their physical location.
-
-You can register a single file with the `<browser:resource>` directive, and a
-whole directory with the `<browser:resourceDirectory>` directive, for example
-
- <browser:resource
- directory="/path/to/static.file"
- name="myfile"
- />
-
- <browser:resourceDirectory
- directory="/path/to/images"
- name="main-images"
- />
-
-This causes a named adapter to be registered that adapts the request to
-zope.interface.Interface (XXX why do we not use an explicit interface?),
-so to later retrieve a resource, use
-`zope.component.getAdapter(request, name='myfile')`.
-
-There are two ways to traverse to a resource,
-
-1. with the 'empty' view on a site, e. g. `http://localhost/@@/myfile`
- (This is declared by zope.app.publisher.browser)
-
-2. with the `++resource++` namespace, e. g. `http://localhost/++resource++myfile`
- (This is declared by zope.traversing.namespace)
-
-In case of resource-directories traversal simply continues through its contents,
-e. g. `http://localhost/@@/main-images/subdir/sample.jpg`
-
-Rather than putting together the URL to a resource manually, you should use
-zope.traversing.browser.interfaces.IAbsoluteURL to get the URL, or for a
-shorthand, call the resource object. This has an additional benefit:
-
-If you want to serve resources from a different URL, for example
-because you want to use a web server specialized in serving static files instead
-of the appserver, you can register an IAbsoluteURL adapter for the site under
-the name 'resource' that will be used to compute the base URLs for resources.
-
-For example, if you register 'http://static.example.com/' as the base 'resource'
-URL, the resources from the above example would yield the following absolute
-URLs: http://static.example.com/myfile and
-http://static.example.com/main-images
-(XXX what about http://static.example.com/main-images/subdir/sample.jpg?)
+ * XML-RPC view and method publishing mechanism along with xmlrpc:view ZCML
+ directive.
Modified: zope.app.publisher/trunk/buildout.cfg
===================================================================
--- zope.app.publisher/trunk/buildout.cfg 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/buildout.cfg 2009-08-27 15:12:51 UTC (rev 103291)
@@ -1,6 +1,6 @@
[buildout]
develop = .
-parts = test coverage-test coverage-report
+parts = test coverage-test coverage-report pydev
[test]
recipe = zc.recipe.testrunner
@@ -16,3 +16,7 @@
eggs = z3c.coverage
scripts = coverage=coverage-report
arguments = ('coverage', 'coverage/report')
+
+[pydev]
+recipe = pb.recipes.pydev
+eggs = zope.app.publisher
Modified: zope.app.publisher/trunk/setup.py
===================================================================
--- zope.app.publisher/trunk/setup.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/setup.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -19,7 +19,7 @@
open('CHANGES.txt').read())
setup(name='zope.app.publisher',
- version = '3.8.5dev',
+ version = '3.9.0dev',
url='http://pypi.python.org/pypi/zope.app.publisher/',
author='Zope Corporation and Contributors',
author_email='zope-dev at zope.org',
@@ -41,29 +41,26 @@
namespace_packages=['zope', 'zope.app'],
include_package_data=True,
install_requires=['setuptools',
- 'zope.component>=3.7.0',
+ 'zope.browsermenu',
+ 'zope.browserpage',
+ 'zope.browserresource',
+ 'zope.component',
'zope.configuration',
- 'zope.container',
- 'zope.contenttype',
'zope.datetime',
- 'zope.i18n',
'zope.interface',
'zope.location',
- 'zope.pagetemplate>=3.5.0',
- 'zope.publisher>=3.8.0',
+ 'zope.ptresource',
+ 'zope.publisher>=3.9',
'zope.schema',
- 'zope.site',
'zope.security',
- 'zope.traversing>3.7.0',
'zope.componentvocabulary',
- 'zope.browser',
- 'zope.app.pagetemplate',
],
extras_require={
'test': ['zope.testing',
'zope.app.testing',
'zope.app.securitypolicy',
'zope.app.zcmlfiles',
+ 'zope.container>=3.8.3',
'zope.site'],
},
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/__init__.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,56 +15,11 @@
$Id$
"""
-
-from zope.interface import implements
+# BBB imports
from zope.publisher.browser import BrowserLanguages
-from zope.i18n.interfaces import IUserPreferredLanguages
-from zope.i18n.interfaces import IModifiableUserPreferredLanguages
-
-from zope.publisher.defaultview import IDefaultViewNameAPI #BBB import
-from zope.publisher.defaultview import getDefaultViewName #BBB import
-from zope.publisher.defaultview import queryDefaultViewName #BBB import
-
-
-class NotCompatibleAdapterError(Exception):
- """Adapter not compatible with
- zope.i18n.interfaces.IModifiableBrowserLanguages has been used.
- """
-
-key = "zope.app.publisher.browser.IUserPreferredLanguages"
-
-class CacheableBrowserLanguages(BrowserLanguages):
-
- implements(IUserPreferredLanguages)
-
- def getPreferredLanguages(self):
- languages_data = self._getLanguagesData()
- if "overridden" in languages_data:
- return languages_data["overridden"]
- elif "cached" not in languages_data:
- languages_data["cached"] = super(
- CacheableBrowserLanguages, self).getPreferredLanguages()
- return languages_data["cached"]
-
- def _getLanguagesData(self):
- annotations = self.request.annotations
- languages_data = annotations.get(key)
- if languages_data is None:
- annotations[key] = languages_data = {}
- return languages_data
-
-class ModifiableBrowserLanguages(CacheableBrowserLanguages):
-
- implements(IModifiableUserPreferredLanguages)
-
- def setPreferredLanguages(self, languages):
- languages_data = self.request.annotations.get(key)
- if languages_data is None:
- # Better way to create a compatible with
- # IModifiableUserPreferredLanguages adapter is to use
- # CacheableBrowserLanguages as base class or as example.
- raise NotCompatibleAdapterError("Adapter not compatible with "
- "zope.i18n.interfaces.IModifiableBrowserLanguages "
- "has been used.")
- languages_data["overridden"] = languages
- self.request.setupLocale()
+from zope.publisher.browser import CacheableBrowserLanguages
+from zope.publisher.browser import ModifiableBrowserLanguages
+from zope.publisher.browser import NotCompatibleAdapterError
+from zope.publisher.defaultview import IDefaultViewNameAPI
+from zope.publisher.defaultview import getDefaultViewName
+from zope.publisher.defaultview import queryDefaultViewName
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/configure.zcml 2009-08-27 15:12:51 UTC (rev 103291)
@@ -3,72 +3,15 @@
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:zcml="http://namespaces.zope.org/zcml">
-<adapter
- factory=".ModifiableBrowserLanguages"
- for="zope.publisher.interfaces.http.IHTTPRequest"
- provides="zope.i18n.interfaces.IModifiableUserPreferredLanguages"
- />
+ <include package="zope.browserresource" />
+ <include package="zope.ptresource" />
+ <include package="zope.browsermenu" />
-<interface
- interface="zope.app.publisher.interfaces.browser.IMenuItemType" />
-
<utility
name="Browser Skins"
component=".vocabulary.BrowserSkinsVocabulary"
/>
-<class class="zope.publisher.browser.BrowserRequest">
- <allow
- interface="zope.publisher.interfaces.browser.IBrowserApplicationRequest"
- attributes="response locale __str__"
- />
-</class>
-
-<class class="zope.publisher.browser.TestRequest">
- <allow
- interface="zope.publisher.interfaces.browser.IBrowserApplicationRequest"
- attributes="response"
- />
-</class>
-
-<class class="zope.publisher.browser.BrowserResponse">
- <allow
- interface="zope.publisher.interfaces.http.IHTTPResponse"
- />
-</class>
-
-<class class="zope.app.publisher.browser.fileresource.FileResource">
- <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
- <allow attributes="GET HEAD __call__" />
-</class>
-
-<class class="zope.app.publisher.browser.i18nfileresource.I18nFileResource">
- <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
- <allow attributes="GET HEAD __call__" />
-</class>
-
-<class class=".pagetemplateresource.PageTemplateResource">
- <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
- <allow attributes="__call__" />
-</class>
-
-<class class=".directoryresource.DirectoryResource">
- <allow interface="zope.publisher.interfaces.browser.IBrowserPublisher" />
- <allow attributes="get __getitem__" />
-</class>
-
-<adapter
- factory=".resource.AbsoluteURL"
- />
-
-<browser:page
- name=""
- for="zope.location.interfaces.ISite"
- class="zope.app.publisher.browser.resources.Resources"
- permission="zope.Public"
- allowed_interface="zope.publisher.interfaces.browser.IBrowserPublisher"
- />
-
<!-- Management view selector -->
<!-- Get first accessible item from zmi_views menu -->
<browser:page
@@ -88,13 +31,4 @@
allowed_interface="zope.publisher.interfaces.browser.IBrowserPublisher"
/>
-<!-- Menu access -->
-<browser:page
- for="*"
- name="view_get_menu"
- permission="zope.Public"
- class=".menu.MenuAccessView"
- allowed_interface="zope.app.publisher.interfaces.browser.IMenuAccessView"
- />
-
</configure>
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/directoryresource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -23,97 +23,6 @@
$Id$
"""
-import os
-import posixpath
-
-from zope.interface import implements
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import BrowserView
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from zope.app.publisher.browser.resource import Resource
-
-from fileresource import FileResourceFactory, ImageResourceFactory
-from pagetemplateresource import PageTemplateResourceFactory
-from resources import empty
-
-_marker = object()
-
-# we only need this class as a context for DirectoryResource
-class Directory(object):
-
- def __init__(self, path, checker, name):
- self.path = path
- self.checker = checker
- self.__name__ = name
-
-class DirectoryResource(BrowserView, Resource):
-
- implements(IBrowserPublisher)
-
- resource_factories = {
- '.gif': ImageResourceFactory,
- '.png': ImageResourceFactory,
- '.jpg': ImageResourceFactory,
- '.pt': PageTemplateResourceFactory,
- '.zpt': PageTemplateResourceFactory,
- '.html': PageTemplateResourceFactory,
- }
-
- default_factory = FileResourceFactory
- directory_factory = None
-
- def publishTraverse(self, request, name):
- '''See interface IBrowserPublisher'''
- return self.get(name)
-
- def browserDefault(self, request):
- '''See interface IBrowserPublisher'''
- return empty, ()
-
- def __getitem__(self, name):
- res = self.get(name, None)
- if res is None:
- raise KeyError(name)
- return res
-
- def get(self, name, default=_marker):
- path = self.context.path
- filename = os.path.join(path, name)
- isfile = os.path.isfile(filename)
- isdir = os.path.isdir(filename)
-
- if not (isfile or isdir):
- if default is _marker:
- raise NotFound(None, name)
- return default
-
- if isfile:
- ext = os.path.splitext(os.path.normcase(name))[1]
- factory = self.resource_factories.get(ext, self.default_factory)
- else:
- factory = self.directory_factory
-
- rname = posixpath.join(self.__name__, name)
- resource = factory(filename, self.context.checker, rname)(self.request)
- resource.__parent__ = self
- return resource
-
-
-class DirectoryResourceFactory(object):
-
- factoryClass = DirectoryResource
-
- def __init__(self, path, checker, name):
- self.__dir = Directory(path, checker, name)
- self.__checker = checker
- self.__name = name
-
- def __call__(self, request):
- resource = self.factoryClass(self.__dir, request)
- resource.__Security_checker__ = self.__checker
- resource.__name__ = self.__name
- return resource
-
-
-DirectoryResource.directory_factory = DirectoryResourceFactory
+# BBB imports
+from zope.browserresource.directory import Directory, DirectoryResource
+from zope.browserresource.directory import DirectoryResourceFactory
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/fields.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,94 +15,4 @@
$Id$
"""
-__docformat__ = 'restructuredtext'
-
-import zope.component
-import zope.schema
-from zope.component.interfaces import ComponentLookupError
-from zope.configuration.exceptions import ConfigurationError
-from zope.configuration.fields import GlobalObject
-from zope.app.publisher.interfaces.browser import IMenuItemType
-
-
-class MenuField(GlobalObject):
- r"""This fields represents a menu (item type).
-
- Besides being able to look up the menu by importing it, we also try
- to look up the name in the site manager.
-
- >>> from zope.interface import directlyProvides
- >>> from zope.interface.interface import InterfaceClass
-
- >>> menu1 = InterfaceClass('menu1', (),
- ... __doc__='Menu Item Type: menu1',
- ... __module__='zope.app.menus')
- >>> directlyProvides(menu1, IMenuItemType)
-
- >>> menus = None
- >>> class Resolver(object):
- ... def resolve(self, path):
- ... if path.startswith('zope.app.menus') and \
- ... hasattr(menus, 'menu1') or \
- ... path == 'zope.app.publisher.menus.menu1':
- ... return menu1
- ... raise ConfigurationError('menu1')
-
- >>> field = MenuField()
- >>> field = field.bind(Resolver())
-
- Test 1: Import the menu
- -----------------------
-
- >>> field.fromUnicode('zope.app.publisher.menus.menu1') is menu1
- True
-
- Test 2: We have a shortcut name. Import the menu from `zope.app.menus1`.
- ------------------------------------------------------------------------
-
- >>> from types import ModuleType as module
- >>> import sys
- >>> menus = module('menus')
- >>> old = sys.modules.get('zope.app.menus', None)
- >>> sys.modules['zope.app.menus'] = menus
- >>> setattr(menus, 'menu1', menu1)
-
- >>> field.fromUnicode('menu1') is menu1
- True
-
- >>> if old is not None:
- ... sys.modules['zope.app.menus'] = old
-
- Test 3: Get the menu from the Site Manager
- ------------------------------------------
-
- >>> from zope.app.testing import ztapi
- >>> ztapi.provideUtility(IMenuItemType, menu1, 'menu1')
-
- >>> field.fromUnicode('menu1') is menu1
- True
- """
-
- def fromUnicode(self, u):
- name = str(u.strip())
-
- try:
- value = zope.component.queryUtility(IMenuItemType, name)
- except ComponentLookupError:
- # The component architecture is not up and running.
- pass
- else:
- if value is not None:
- self.validate(value)
- return value
-
- try:
- value = self.context.resolve('zope.app.menus.'+name)
- except ConfigurationError, v:
- try:
- value = self.context.resolve(name)
- except ConfigurationError, v:
- raise zope.schema.ValidationError(v)
-
- self.validate(value)
- return value
+from zope.browsermenu.field import MenuField # BBB import
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/fileresource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,133 +15,7 @@
$Id$
"""
-
-import time
-from zope.interface import implements
-from zope.datetime import time as timeFromDateTimeString
-from zope.publisher.interfaces import NotFound
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.browser import BrowserView
-
-from zope.app.publisher.fileresource import File, Image
-from zope.app.publisher.browser.resource import Resource
-
-class FileResource(BrowserView, Resource):
-
- implements(IBrowserPublisher)
-
- cacheTimeout = 86400
-
- def publishTraverse(self, request, name):
- '''See interface IBrowserPublisher'''
- raise NotFound(None, name)
-
- def browserDefault(self, request):
- '''See interface IBrowserPublisher'''
- return getattr(self, request.method), ()
-
- #
- ############################################################
-
- # for unit tests
- def _testData(self):
- f = open(self.context.path, 'rb')
- data = f.read()
- f.close()
- return data
-
-
- def chooseContext(self):
- """Choose the appropriate context"""
- return self.context
-
-
- def GET(self):
- """Default document"""
-
- file = self.chooseContext()
- request = self.request
- response = request.response
-
- setCacheControl(response, self.cacheTimeout)
-
- # HTTP If-Modified-Since header handling. This is duplicated
- # from OFS.Image.Image - it really should be consolidated
- # somewhere...
- header = request.getHeader('If-Modified-Since', None)
- if header is not None:
- header = header.split(';')[0]
- # Some proxies seem to send invalid date strings for this
- # header. If the date string is not valid, we ignore it
- # rather than raise an error to be generally consistent
- # with common servers such as Apache (which can usually
- # understand the screwy date string as a lucky side effect
- # of the way they parse it).
- try: mod_since=long(timeFromDateTimeString(header))
- except: mod_since=None
- if mod_since is not None:
- if getattr(file, 'lmt', None):
- last_mod = long(file.lmt)
- else:
- last_mod = long(0)
- if last_mod > 0 and last_mod <= mod_since:
- response.setStatus(304)
- return ''
-
- response.setHeader('Content-Type', file.content_type)
- response.setHeader('Last-Modified', file.lmh)
-
- f = open(file.path,'rb')
- data = f.read()
- f.close()
-
- return data
-
- def HEAD(self):
- file = self.chooseContext()
- response = self.request.response
- response.setHeader('Content-Type', file.content_type)
- response.setHeader('Last-Modified', file.lmh)
- setCacheControl(response, self.cacheTimeout)
- return ''
-
-
-def setCacheControl(response, secs=86400):
- # Cache for one day by default
- response.setHeader('Cache-Control', 'public,max-age=%s' % secs)
- t = time.time() + secs
- response.setHeader('Expires',
- time.strftime("%a, %d %b %Y %H:%M:%S GMT",
- time.gmtime(t)))
-
-
-class FileResourceFactory(object):
-
- resourceClass = FileResource
-
- def __init__(self, path, checker, name):
- self.__file = File(path, name)
- self.__checker = checker
- self.__name = name
-
- def __call__(self, request):
- resource = self.resourceClass(self.__file, request)
- resource.__Security_checker__ = self.__checker
- resource.__name__ = self.__name
- return resource
-
-
-class ImageResourceFactory(object):
-
- resourceClass = FileResource
-
- def __init__(self, path, checker, name):
- self.__file = Image(path, name)
- self.__checker = checker
- self.__name = name
-
- def __call__(self, request):
- resource = self.resourceClass(self.__file, request)
- resource.__Security_checker__ = self.__checker
- resource.__name__ = self.__name
- return resource
+# BBB imports
+from zope.browserresource.file import FileResource, setCacheControl
+from zope.browserresource.file import FileResourceFactory
+ImageResourceFactory = FileResourceFactory
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nfileresource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,75 +15,6 @@
$Id$
"""
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from zope.app.publisher.browser.fileresource import FileResource
-
-from zope.i18n.negotiator import negotiator
-from zope.i18n.interfaces import II18nAware
-from zope.interface import implements
-
-
-class I18nFileResource(FileResource):
-
- implements(IBrowserPublisher, II18nAware)
-
- def __init__(self, data, request, defaultLanguage='en'):
- """Creates an internationalized file resource. data should be
- a mapping from languages to File or Image objects.
- """
- self._data = data
- self.request = request
- self.defaultLanguage = defaultLanguage
-
-
- def chooseContext(self):
- """Choose the appropriate context according to language"""
- langs = self.getAvailableLanguages()
- language = negotiator.getLanguage(langs, self.request)
- try:
- return self._data[language]
- except KeyError:
- return self._data[self.defaultLanguage]
-
-
- # for unit tests
- def _testData(self, language):
- file = self._data[language]
- f=open(file.path,'rb')
- data=f.read()
- f.close()
- return data
-
-
- ############################################################
- # Implementation methods for interface
- # II18nAware.py
-
- def getDefaultLanguage(self):
- 'See II18nAware'
- return self.defaultLanguage
-
- def setDefaultLanguage(self, language):
- 'See II18nAware'
- if not self._data.has_key(language):
- raise ValueError(
- 'cannot set nonexistent language (%s) as default' % language)
- self.defaultLanguage = language
-
- def getAvailableLanguages(self):
- 'See II18nAware'
- return self._data.keys()
-
- #
- ############################################################
-
-
-class I18nFileResourceFactory(object):
-
- def __init__(self, data, defaultLanguage):
- self.__data = data
- self.__defaultLanguage = defaultLanguage
-
- def __call__(self, request):
- return I18nFileResource(self.__data, request, self.__defaultLanguage)
+# BBB imports
+from zope.browserresource.i18nfile import I18nFileResource
+from zope.browserresource.i18nfile import I18nFileResourceFactory
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/i18nresourcemeta.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,108 +15,4 @@
$Id$
"""
-from zope.configuration.exceptions import ConfigurationError
-from zope.interface import Interface
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.security.proxy import Proxy
-from zope.security.checker import CheckerPublic, Checker
-from zope.component.zcml import handler
-
-from zope.app.publisher.fileresource import File, Image
-from zope.app.publisher.browser.i18nfileresource import I18nFileResourceFactory
-
-
-class I18nResource(object):
-
- type = IBrowserRequest
- default_allowed_attributes = '__call__'
-
- def __init__(self, _context, name=None, defaultLanguage='en',
- layer=IDefaultBrowserLayer, permission=None):
- self._context = _context
- self.name = name
- self.defaultLanguage = defaultLanguage
- self.layer = layer
- self.permission = permission
- self.__data = {}
- self.__format = None
-
- def translation(self, _context, language, file=None, image=None):
-
- if file is not None and image is not None:
- raise ConfigurationError(
- "Can't use more than one of file, and image "
- "attributes for resource directives"
- )
- elif file is not None:
- if self.__format is not None and self.__format != File:
- raise ConfigurationError(
- "Can't use both files and images in the same "
- "i18n-resource directive"
- )
- self.__data[language] = File(_context.path(file), self.name)
- self.__format = File
- elif image is not None:
- if self.__format is not None and self.__format != Image:
- raise ConfigurationError(
- "Can't use both files and images in the same "
- "i18n-resource directive"
- )
- self.__data[language] = Image(_context.path(image), self.name)
- self.__format = Image
- else:
- raise ConfigurationError(
- "At least one of the file, and image "
- "attributes for resource directives must be specified"
- )
-
- return ()
-
-
- def __call__(self, require = None):
- if self.name is None:
- return ()
-
- if not self.__data.has_key(self.defaultLanguage):
- raise ConfigurationError(
- "A translation for the default language (%s) "
- "must be specified" % self.defaultLanguage
- )
-
- permission = self.permission
- factory = I18nFileResourceFactory(self.__data, self.defaultLanguage)
-
- if permission:
- if require is None:
- require = {}
-
- if permission == 'zope.Public':
- permission = CheckerPublic
-
- if require:
- checker = Checker(require)
-
- factory = self._proxyFactory(factory, checker)
-
- self._context.action(
- discriminator = ('i18n-resource', self.name, self.type, self.layer),
- callable = handler,
- args = ('registerAdapter',
- factory, (self.layer,), Interface, self.name,
- self._context.info)
- )
-
-
- def _proxyFactory(self, factory, checker):
- def proxyView(request,
- factory=factory, checker=checker):
- resource = factory(request)
-
- # We need this in case the resource gets unwrapped and
- # needs to be rewrapped
- resource.__Security_checker__ = checker
-
- return Proxy(resource, checker)
-
- return proxyView
+from zope.browserresource.metaconfigure import I18nResource # BBB import
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/icon.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,100 +15,6 @@
$Id$
"""
-import os
-import re
-
-from zope.interface import Interface
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.configuration.exceptions import ConfigurationError
-from zope.traversing.namespace import getResource
-from zope.component.interface import provideInterface
-from zope.component.zcml import handler
-
-from zope.app.publisher.browser import metaconfigure
-
-IName = re.compile('I[A-Z][a-z]')
-
-class IconView(object):
-
- def __init__(self, context, request, rname, alt, width, height):
- self.context = context
- self.request = request
- self.rname = rname
- self.alt = alt
- self.width = width
- self.height = height
-
- def __call__(self):
- # The context is important here, since it becomes the parent of the
- # icon, which is needed to generate the absolute URL.
- resource = getResource(self.context, self.rname, self.request)
- src = resource()
-
- return ('<img src="%s" alt="%s" width="%s" height="%s" border="0" />'
- % (src, self.alt, self.width, self.height))
-
- def url(self):
- resource = getResource(self.context, self.rname, self.request)
- src = resource()
- return src
-
-class IconViewFactory(object):
-
- def __init__(self, rname, alt, width, height):
- self.rname = rname
- self.alt = alt
- self.width = width
- self.height = height
-
- def __call__(self, context, request):
- return IconView(context, request, self.rname, self.alt,
- self.width, self.height)
-
-def IconDirective(_context, name, for_, file=None, resource=None,
- layer=IDefaultBrowserLayer, title=None,
- width=16, height=16):
-
- iname = for_.getName()
-
- if title is None:
- title = iname
- if IName.match(title):
- title = title[1:] # Remove leading 'I'
-
- if file is not None and resource is not None:
- raise ConfigurationError(
- "Can't use more than one of file, and resource "
- "attributes for icon directives"
- )
- elif file is not None:
- resource = '-'.join(for_.__module__.split('.'))
- resource = "%s-%s-%s" % (resource, iname, name)
- ext = os.path.splitext(file)[1]
- if ext:
- resource += ext
- metaconfigure.resource(_context, image=file,
- name=resource, layer=layer)
- elif resource is None:
- raise ConfigurationError(
- "At least one of the file, and resource "
- "attributes for resource directives must be specified"
- )
-
- vfactory = IconViewFactory(resource, title, width, height)
-
- _context.action(
- discriminator = ('view', name, vfactory, layer),
- callable = handler,
- args = ('registerAdapter',
- vfactory, (for_, layer), Interface, name, _context.info)
- )
-
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = (for_.__module__+'.'+for_.getName(),
- for_)
- )
-
-
+# BBB imports
+from zope.browserresource.icon import IconView, IconViewFactory
+from zope.browserresource.metaconfigure import icon as IconDirective
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/managementviewselector.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -18,7 +18,7 @@
from zope.interface import implements
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.publisher.browser import BrowserView
-from zope.app.publisher.browser.menu import getFirstMenuItem
+from zope.browsermenu.menu import getFirstMenuItem
class ManagementViewSelector(BrowserView):
"""View that selects the first available management view.
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,197 +15,12 @@
$Id$
"""
-__docformat__ = "reStructuredText"
-import sys
-
-from zope.component import getAdapters
-from zope.component import getUtility
-from zope.interface import Interface
-from zope.interface import implements
-from zope.interface import providedBy
-from zope.interface.interfaces import IInterface
-from zope.pagetemplate.engine import Engine
-from zope.publisher.browser import BrowserView
-from zope.security import canAccess
-from zope.security import checkPermission
-from zope.security.interfaces import Forbidden
-from zope.security.interfaces import Unauthorized
-from zope.security.proxy import removeSecurityProxy
-from zope.traversing.publicationtraverse import PublicationTraverser
-
-from zope.app.publisher.interfaces.browser import IMenuAccessView
-from zope.app.publisher.interfaces.browser import IBrowserMenu
-from zope.app.publisher.interfaces.browser import IBrowserMenuItem
-from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
-from zope.app.publisher.interfaces.browser import IMenuItemType
-
-class BrowserMenu(object):
- """Browser Menu"""
- implements(IBrowserMenu)
-
- def __init__(self, id, title=u'', description=u''):
- self.id = id
- self.title = title
- self.description = description
-
- def getMenuItemType(self):
- return getUtility(IMenuItemType, self.id)
-
- def getMenuItems(self, object, request):
- """Return menu item entries in a TAL-friendly form."""
-
- result = []
- for name, item in getAdapters((object, request),
- self.getMenuItemType()):
- if item.available():
- result.append(item)
-
- # Now order the result. This is not as easy as it seems.
- #
- # (1) Look at the interfaces and put the more specific menu entries
- # to the front.
- # (2) Sort unambigious entries by order and then by title.
- ifaces = list(providedBy(removeSecurityProxy(object)).__iro__)
- max_key = len(ifaces)
- def iface_index(item):
- iface = item._for
- if not iface:
- iface = Interface
- if IInterface.providedBy(iface):
- return ifaces.index(iface)
- if isinstance(removeSecurityProxy(object), item._for):
- # directly specified for class, this goes first.
- return -1
- # no idea. This goes last.
- return max_key
- result = [(iface_index(item), item.order, item.title, item)
- for item in result]
- result.sort()
-
- result = [
- {'title': title,
- 'description': item.description,
- 'action': item.action,
- 'selected': (item.selected() and u'selected') or u'',
- 'icon': item.icon,
- 'extra': item.extra,
- 'submenu': (IBrowserSubMenuItem.providedBy(item) and
- getMenu(item.submenuId, object, request)) or None}
- for index, order, title, item in result]
-
- return result
-
-
-class BrowserMenuItem(BrowserView):
- """Browser Menu Item Class"""
- implements(IBrowserMenuItem)
-
- # See zope.app.publisher.interfaces.browser.IBrowserMenuItem
- title = u''
- description = u''
- action = u''
- extra = None
- order = 0
- permission = None
- filter = None
- icon = None
- _for = Interface
-
- def available(self):
- """See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
- # Make sure we have the permission needed to access the menu's action
- if self.permission is not None:
- # If we have an explicit permission, check that we
- # can access it.
- if not checkPermission(self.permission, self.context):
- return False
-
- elif self.action != u'':
- # Otherwise, test access by attempting access
- path = self.action
- l = self.action.find('?')
- if l >= 0:
- path = self.action[:l]
-
- traverser = PublicationTraverser()
- try:
- view = traverser.traverseRelativeURL(
- self.request, self.context, path)
- except (Unauthorized, Forbidden, LookupError):
- return False
- else:
- # we're assuming that view pages are callable
- # this is a pretty sound assumption
- if not canAccess(view, '__call__'):
- return False
-
- # Make sure that we really want to see this menu item
- if self.filter is not None:
-
- try:
- include = self.filter(Engine.getContext(
- context = self.context,
- nothing = None,
- request = self.request,
- modules = sys.modules,
- ))
- except Unauthorized:
- return False
- else:
- if not include:
- return False
-
- return True
-
- def selected(self):
- """See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
- request_url = self.request.getURL()
-
- normalized_action = self.action
- if self.action.startswith('@@'):
- normalized_action = self.action[2:]
-
- if request_url.endswith('/'+normalized_action):
- return True
- if request_url.endswith('/++view++'+normalized_action):
- return True
- if request_url.endswith('/@@'+normalized_action):
- return True
-
- return False
-
-
-class BrowserSubMenuItem(BrowserMenuItem):
- """Browser Menu Item Base Class"""
- implements(IBrowserSubMenuItem)
-
- # See zope.app.publisher.interfaces.browser.IBrowserSubMenuItem
- submenuId = None
-
- def selected(self):
- """See zope.app.publisher.interfaces.browser.IBrowserMenuItem"""
- if self.action is u'':
- return False
- return super(BrowserSubMenuItem, self).selected()
-
-
-def getMenu(id, object, request):
- """Return menu item entries in a TAL-friendly form."""
- menu = getUtility(IBrowserMenu, id)
- return menu.getMenuItems(object, request)
-
-
-def getFirstMenuItem(id, object, request):
- """Get the first item of a menu."""
- items = getMenu(id, object, request)
- if items:
- return items[0]
- return None
-
-
-class MenuAccessView(BrowserView):
- """A view allowing easy access to menus."""
- implements(IMenuAccessView)
-
- def __getitem__(self, menuId):
- return getMenu(menuId, self.context, self.request)
+# BBB imports
+from zope.browsermenu.menu import (
+ BrowserMenu,
+ BrowserMenuItem,
+ BrowserSubMenuItem,
+ getMenu,
+ getFirstMenuItem,
+ MenuAccessView,
+)
Deleted: zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menu.txt 2009-08-27 15:12:51 UTC (rev 103291)
@@ -1,697 +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.app.publisher.browser import menu, menumeta
-
-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.app.publisher.interfaces.browser import IMenuItemType
- >>> zope.interface.directlyProvides(EditMenu, IMenuItemType)
-
- >>> from zope.app.testing import ztapi
- >>> ztapi.provideUtility(IMenuItemType, EditMenu, 'edit')
-
-Now we have to create and register the menu itself:
-
- >>> from zope.app.publisher.interfaces.browser import IBrowserMenu
- >>> ztapi.provideUtility(
- ... IBrowserMenu, menu.BrowserMenu('edit', u'Edit', u'Edit Menu'), '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
- >>> from zope.app.testing import ztapi
- >>> perm = Permission('perm', 'Permission')
- >>> ztapi.provideUtility(IPermission, perm, '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)
-
- >>> ztapi.provideUtility(IMenuItemType, SaveOptions, 'save')
- >>> ztapi.provideUtility(IBrowserMenu,
- ... menu.BrowserMenu('save', u'Save', u'Save Menu'),
- ... '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.app.testing import ztapi
- >>> from zope.publisher.interfaces.browser import IBrowserRequest
-
- >>> undo = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Undo",
- ... action="undo.html")
- >>> ztapi.provideAdapter((IContent, IBrowserRequest), EditMenu, undo, 'undo')
-
- >>> redo = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Redo",
- ... action="redo.html", icon="/@@/redo.png")
- >>> ztapi.provideAdapter((IContent, IBrowserRequest), EditMenu, redo, 'redo')
-
- >>> save = menumeta.MenuItemFactory(menu.BrowserSubMenuItem, title="Save",
- ... submenuId='save', order=2)
- >>> ztapi.provideAdapter((IContent, IBrowserRequest), EditMenu, save, 'save')
-
-And now the save options:
-
- >>> saveas = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Save as",
- ... action="saveas.html")
- >>> ztapi.provideAdapter((IContent, IBrowserRequest),
- ... SaveOptions, saveas, 'saveas')
-
- >>> saveall = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Save all",
- ... action="saveall.html")
- >>> ztapi.provideAdapter((IContent, IBrowserRequest),
- ... SaveOptions, saveall, 'saveall')
-
-Note that we can also register menu items for classes:
-
-
- >>> new = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="New",
- ... action="new.html", _for=Content)
- >>> ztapi.provideAdapter((Content, IBrowserRequest), EditMenu, new, '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.app.publisher.interfaces.browser 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:
-
- >>> ztapi.provideUtility(IBrowserMenu,
- ... Items('items', u'Items', u'Items Menu'),
- ... '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 = menumeta.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 = menumeta.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()
- >>> menumeta.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()
- >>> menumeta.menuDirective(context, interface=menu1)
- >>> context.actions[0]['args'][1] is menu1
- True
-
-Possibility 3: Specify an interface and an id
-+++++++++++++++++++++++++++++++++++++++++++++
-
- >>> context = Context()
- >>> menumeta.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.app.publisher.interfaces.browser.IBrowserMenu>,
- 'menu1'),
- None]
-
-Here are some disallowed configurations.
-
- >>> context = Context()
- >>> menumeta.menuDirective(context)
- Traceback (most recent call last):
- ...
- ConfigurationError: You must specify the 'id' or 'interface' attribute.
-
- >>> menumeta.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 = menumeta.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 = menumeta.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
-
-``ManagementViewSelector``
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Test the action (redirect url) of the first menu item and ensure that we don't
-redirect to the parent before we reach the item if we use actions like: '../'
-'javascript:popup()' or '++namespace++'.
-
-First setup the 'zmi_views' menu.
-
- >>> class ZMIViews(zope.interface.Interface):
- ... """This is the zmi_views menu."""
- >>> zope.interface.directlyProvides(ZMIViews, IMenuItemType)
- >>> ztapi.provideUtility(IMenuItemType, ZMIViews, 'zmi_views')
- >>> from zope.app.publisher.interfaces.browser import IBrowserMenu
- >>> ztapi.provideUtility(
- ... IBrowserMenu, menu.BrowserMenu('zmi_views', u'ZMIViews',
- ... u'ZMI Views'), 'zmi_views')
-
-Register some 'zmi_views' menu items.
-
- >>> first = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="First",
- ... action="../")
- >>> ztapi.provideAdapter((IContent, IBrowserRequest), ZMIViews, first,
- ... 'first')
-
- >>> second = menumeta.MenuItemFactory(menu.BrowserMenuItem, title="Second",
- ... action="second.html")
- >>> ztapi.provideAdapter((IContent, IBrowserRequest), ZMIViews, second,
- ... 'second')
-
-Now create a new content object.
-
- >>> content = Content()
- >>> request = TestRequest(SERVER_URL='http://127.0.0.1/',
- ... PATH_INFO='/')
-
-Test the actions. Remember that this action get redirected before we traverse
-to the content. This means actions like ``../`` will make it impossible to
-access the view because the ``../`` will redirect us before we traverse.
-
- >>> menus = menu.getMenu('zmi_views', content, request)
- >>> [menu['action'] for menu in menus]
- ['../', 'second.html']
-
-Now call the ManagementViewSelector view and we get a empty string as result.
-
- >>> from zope.app.publisher.browser.managementviewselector import \
- ... ManagementViewSelector
- >>> view = ManagementViewSelector(content, request)
- >>> view()
- u''
-
-Now check the more interesting redirect in the request. The redirect location
-is not like excpected '../'. We get '.' as the redirect location. This is
-important otherwise we get redirected to the parent if we call the
-first menu item with actions like '../parentview.html' instead of traverse
-to the item.
-
- >>> request.response.getHeader('Location')
- '.'
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/menumeta.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,294 +15,13 @@
$Id$
"""
-from zope.browser.interfaces import IAdding
-from zope.component import getGlobalSiteManager
-from zope.component import getUtility
-from zope.component.interface import provideInterface
-from zope.component.zcml import adapter
-from zope.component.zcml import proxify
-from zope.component.zcml import utility
-from zope.configuration.exceptions import ConfigurationError
-from zope.interface.interface import InterfaceClass
-from zope.interface import Interface
-from zope.pagetemplate.engine import Engine
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.security.checker import InterfaceChecker, CheckerPublic
-from zope.security.metaconfigure import ClassDirective
-
-from zope.app.publisher.browser.menu import BrowserMenu
-from zope.app.publisher.browser.menu import BrowserMenuItem, BrowserSubMenuItem
-from zope.app.publisher.interfaces.browser import IBrowserMenu
-from zope.app.publisher.interfaces.browser import IBrowserMenuItem
-from zope.app.publisher.interfaces.browser import IBrowserSubMenuItem
-from zope.app.publisher.interfaces.browser import IMenuItemType
-from zope.app.publisher.interfaces.browser import AddMenu
-
-# Create special modules that contain all menu item types
-from types import ModuleType as module
-import sys
-menus = module('menus')
-sys.modules['zope.app.menus'] = menus
-
-
-_order_counter = {}
-
-
-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 menuItemDirective(_context, menu, for_,
- action, title, description=u'', icon=None, filter=None,
- permission=None, layer=IDefaultBrowserLayer, extra=None,
- order=0, item_class=None):
- """Register a single menu item."""
- return menuItemsDirective(_context, menu, for_, layer).menuItem(
- _context, action, title, description, icon, filter,
- permission, extra, order, item_class)
-
-
-def subMenuItemDirective(_context, menu, for_, title, submenu,
- action=u'', description=u'', icon=None, filter=None,
- permission=None, layer=IDefaultBrowserLayer,
- extra=None, order=0, item_class=None):
- """Register a single sub-menu menu item."""
- return menuItemsDirective(_context, menu, for_, layer).subMenuItem(
- _context, submenu, title, description, action, icon, filter,
- permission, extra, order, item_class)
-
-
-class MenuItemFactory(object):
- """generic factory for menu items."""
-
- def __init__(self, factory, **kwargs):
- self.factory = factory
- if 'permission' in kwargs and kwargs['permission'] == 'zope.Public':
- kwargs['permission'] = CheckerPublic
- self.kwargs = kwargs
-
- def __call__(self, context, request):
- item = self.factory(context, request)
-
- for key, value in self.kwargs.items():
- setattr(item, key, value)
-
- if item.permission is not None:
- checker = InterfaceChecker(IBrowserMenuItem, item.permission)
- item = proxify(item, checker)
-
- return item
-
-
-class menuItemsDirective(object):
- """Register several menu items for a particular menu."""
-
- menuItemClass = BrowserMenuItem
- subMenuItemClass = BrowserSubMenuItem
-
- def __init__(self, _context, menu, for_, layer=IDefaultBrowserLayer,
- permission=None):
- self.for_ = for_
- self.menuItemType = menu
- self.layer = layer
- self.permission = permission
-
- def menuItem(self, _context, action, title, description=u'',
- icon=None, filter=None, permission=None, extra=None,
- order=0, item_class=None):
-
- if filter is not None:
- filter = Engine.compile(filter)
-
- if permission is None:
- permission = self.permission
-
- if order == 0:
- order = _order_counter.get(self.for_, 1)
- _order_counter[self.for_] = order + 1
-
- if item_class is None:
- item_class = self.menuItemClass
-
- if not IBrowserMenuItem.implementedBy(item_class):
- raise ValueError("Item class (%s) must implement IBrowserMenuItem" % item_class)
-
- factory = MenuItemFactory(
- item_class,
- title=title, description=description, icon=icon, action=action,
- filter=filter, permission=permission, extra=extra, order=order,
- _for=self.for_)
- adapter(_context, (factory,), self.menuItemType,
- (self.for_, self.layer), name=title)
-
- def subMenuItem(self, _context, submenu, title, description=u'',
- action=u'', icon=None, filter=None, permission=None,
- extra=None, order=0, item_class=None):
-
- if filter is not None:
- filter = Engine.compile(filter)
-
- if permission is None:
- permission = self.permission
-
- if order == 0:
- order = _order_counter.get(self.for_, 1)
- _order_counter[self.for_] = order + 1
-
- if item_class is None:
- item_class = self.subMenuItemClass
-
- if not IBrowserSubMenuItem.implementedBy(item_class):
- raise ValueError("Item class (%s) must implement IBrowserSubMenuItem" % item_class)
-
- factory = MenuItemFactory(
- item_class,
- title=title, description=description, icon=icon, action=action,
- filter=filter, permission=permission, extra=extra, order=order,
- _for=self.for_, submenuId=submenu)
- adapter(_context, (factory,), self.menuItemType,
- (self.for_, self.layer), name=title)
-
- def __call__(self, _context):
- # Nothing to do.
- pass
-
-def _checkViewFor(for_=None, layer=None, view_name=None):
- """Check if there is a view of that name registered for IAdding
- and IBrowserRequest. If not raise a ConfigurationError
-
- It will raise a ConfigurationError if :
- o view=""
- o if view_name is not registred
- """
-
- if view_name is None:
- raise ConfigurationError(
- "Within a addMenuItem directive the view attribut"
- " is optional but can\'t be empty"
- )
-
- gsm = getGlobalSiteManager()
- if gsm.adapters.lookup((for_, layer),
- Interface, view_name) is None:
- raise ConfigurationError(
- "view name %s not found " %view_name
- )
-
-def addMenuItem(_context, title, description='', menu=None, for_=None,
- class_=None, factory=None, view=None, icon=None, filter=None,
- permission=None, layer=IDefaultBrowserLayer, extra=None,
- order=0, item_class=None):
- """Create an add menu item for a given class or factory
-
- As a convenience, a class can be provided, in which case, a
- factory is automatically defined based on the class. In this
- case, the factory id is based on the class name.
-
- """
-
- if for_ is not None:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = ('', for_)
- )
- forname = 'For' + for_.getName()
- else:
- for_ = IAdding
- forname = ''
-
- if menu is not None:
- if isinstance(menu, (str, unicode)):
- menu = getUtility(IMenuItemType, menu)
- if menu is None:
- raise ValueError("Missing menu id '%s'" % menu)
-
- if class_ is None:
- if factory is None:
- raise ValueError("Must specify either class or factory")
- else:
- if factory is not None:
- raise ValueError("Can't specify both class and factory")
- if permission is None:
- raise ValueError(
- "A permission must be specified when a class is used")
- factory = "BrowserAdd%s__%s.%s" % (
- forname, class_.__module__, class_.__name__)
- ClassDirective(_context, class_).factory(_context, id=factory)
-
- extra = {'factory': factory}
-
- if view:
- action = view
- # This action will check if the view exists
- _context.action(
- discriminator = None,
- callable = _checkViewFor,
- args = (for_, layer, view),
- order=999999
- )
- else:
- action = factory
-
- if menu == None:
- menu = AddMenu
-
- return menuItemsDirective(_context, menu, for_, layer=layer).menuItem(
- _context, action, title, description, icon, filter,
- permission, extra, order, item_class)
+# BBB imports
+from zope.browsermenu.metaconfigure import (
+ menuDirective,
+ menuItemDirective,
+ subMenuItemDirective,
+ MenuItemFactory,
+ menuItemsDirective,
+ _checkViewFor,
+ addMenuItem,
+)
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/meta.zcml 2009-08-27 15:12:51 UTC (rev 103291)
@@ -1,146 +1,8 @@
-<configure
- xmlns="http://namespaces.zope.org/zope"
- xmlns:meta="http://namespaces.zope.org/meta"
- xmlns:zcml="http://namespaces.zope.org/zcml">
+<configure xmlns="http://namespaces.zope.org/zope">
- <meta:directives namespace="http://namespaces.zope.org/browser">
+ <include package="zope.publisher" file="meta.zcml" />
+ <include package="zope.browserresource" file="meta.zcml" />
+ <include package="zope.browsermenu" file="meta.zcml" />
+ <include package="zope.browserpage" file="meta.zcml" />
- <!-- browser menus -->
-
- <meta:directive
- name="menu"
- schema=".metadirectives.IMenuDirective"
- handler=".menumeta.menuDirective"
- />
-
- <meta:complexDirective
- name="menuItems"
- schema=".metadirectives.IMenuItemsDirective"
- handler=".menumeta.menuItemsDirective"
- >
-
- <meta:subdirective
- name="menuItem"
- schema=".metadirectives.IMenuItemSubdirective"
- />
-
- <meta:subdirective
- name="subMenuItem"
- schema=".metadirectives.ISubMenuItemSubdirective"
- />
-
- </meta:complexDirective>
-
- <meta:directive
- name="menuItem"
- schema=".metadirectives.IMenuItemDirective"
- handler=".menumeta.menuItemDirective"
- />
-
- <meta:directive
- name="subMenuItem"
- schema=".metadirectives.ISubMenuItemDirective"
- handler=".menumeta.subMenuItemDirective"
- />
-
- <meta:directive
- name="addMenuItem"
- schema=".metadirectives.IAddMenuItemDirective"
- handler=".menumeta.addMenuItem"
- />
-
-
- <!-- browser views -->
-
- <meta:complexDirective
- name="view"
- schema=".metadirectives.IViewDirective"
- handler=".viewmeta.view"
- >
-
- <meta:subdirective
- name="page"
- schema=".metadirectives.IViewPageSubdirective"
- />
-
- <meta:subdirective
- name="defaultPage"
- schema=".metadirectives.IViewDefaultPageSubdirective"
- />
-
- </meta:complexDirective>
-
- <meta:directive
- name="defaultView"
- schema=".metadirectives.IDefaultViewDirective"
- handler=".metaconfigure.defaultView"
- />
-
-
- <!-- browser pages -->
-
- <meta:directive
- name="page"
- schema=".metadirectives.IPageDirective"
- handler=".viewmeta.page"
- />
-
- <meta:complexDirective
- name="pages"
- schema=".metadirectives.IPagesDirective"
- handler=".viewmeta.pages"
- >
-
- <meta:subdirective
- name="page"
- schema=".metadirectives.IPagesPageSubdirective"
- />
-
- </meta:complexDirective>
-
-
- <!-- browser resources -->
-
- <meta:directive
- name="resource"
- schema=".metadirectives.IResourceDirective"
- handler=".metaconfigure.resource"
- />
-
- <meta:directive
- name="resourceDirectory"
- schema=".metadirectives.IResourceDirectoryDirective"
- handler=".metaconfigure.resourceDirectory"
- />
-
- <meta:complexDirective
- name="i18n-resource"
- schema=".metadirectives.II18nResourceDirective"
- handler=".metaconfigure.I18nResource"
- >
-
- <meta:subdirective
- name="translation"
- schema=".metadirectives.II18nResourceTranslationSubdirective"
- />
-
- </meta:complexDirective>
-
-
- <!-- misc. directives -->
-
- <meta:directive
- name="defaultSkin"
- schema=".metadirectives.IDefaultSkinDirective"
- handler=".metaconfigure.defaultSkin"
- />
-
- <meta:directive
- name="icon"
- schema=".metadirectives.IIconDirective"
- handler=".icon.IconDirective"
- />
-
- </meta:directives>
-
</configure>
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/metaconfigure.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,66 +15,9 @@
$Id$
"""
-__docformat__ = 'restructuredtext'
-
-import warnings
-from zope import component
-from zope.component.interface import provideInterface
-from zope.component.zcml import handler
-from zope.publisher.interfaces import IDefaultViewName
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IBrowserSkinType
-from zope.publisher.interfaces.browser import IDefaultSkin
-
-# referred to through ZCML
-from zope.app.publisher.browser.resourcemeta import resource
-from zope.app.publisher.browser.resourcemeta import resourceDirectory
-from zope.app.publisher.browser.i18nresourcemeta import I18nResource
-from zope.app.publisher.browser.viewmeta import view
-
-
-def setDefaultSkin(name, info=''):
- """Set the default skin.
-
- >>> from zope.interface import directlyProvides
- >>> from zope.app.testing import ztapi
-
- >>> class Skin1: pass
- >>> directlyProvides(Skin1, IBrowserSkinType)
-
- >>> ztapi.provideUtility(IBrowserSkinType, Skin1, 'Skin1')
- >>> setDefaultSkin('Skin1')
- >>> adapters = component.getSiteManager().adapters
-
- Lookup the default skin for a request that has the
-
- >>> adapters.lookup((IBrowserRequest,), IDefaultSkin, '') is Skin1
- True
- """
- skin = component.getUtility(IBrowserSkinType, name)
- handler('registerAdapter',
- skin, (IBrowserRequest,), IDefaultSkin, '', info),
-
-def defaultSkin(_context, name):
-
- _context.action(
- discriminator = 'defaultSkin',
- callable = setDefaultSkin,
- args = (name, _context.info)
- )
-
-def defaultView(_context, name, for_=None, layer=IBrowserRequest):
-
- _context.action(
- discriminator = ('defaultViewName', for_, layer, name),
- callable = handler,
- args = ('registerAdapter',
- name, (for_, layer), IDefaultViewName, '', _context.info)
- )
-
- if for_ is not None:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = ('', for_)
- )
+# BBB imports
+from zope.browserresource.metaconfigure import resource
+from zope.browserresource.metaconfigure import resourceDirectory
+from zope.browserresource.metaconfigure import I18nResource
+from zope.browserpage.metaconfigure import view
+from zope.publisher.zcml import setDefaultSkin, defaultSkin, defaultView
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/metadirectives.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -17,643 +17,31 @@
$Id$
"""
-from zope.interface import Interface
-from zope.configuration.fields import GlobalObject, GlobalInterface
-from zope.configuration.fields import Tokens, Path, PythonIdentifier, MessageID
-from zope.schema import TextLine, Id, Int, Bool
-from zope.security.zcml import Permission
-
-from zope.component.zcml import IBasicViewInformation
-from zope.app.publisher.browser.fields import MenuField
-
-#
-# browser views
-#
-
-class IPagesDirective(IBasicViewInformation):
- """
- Define multiple pages without repeating all of the parameters.
-
- The pages directive allows multiple page views to be defined
- without repeating the 'for', 'permission', 'class', 'layer',
- 'allowed_attributes', and 'allowed_interface' attributes.
- """
-
- for_ = GlobalObject(
- title=u"The interface or class this view is for.",
- required=False
- )
-
- permission = Permission(
- title=u"Permission",
- description=u"The permission needed to use the view.",
- required=True
- )
-
-class IViewDirective(IPagesDirective):
- """
- The view directive defines a view that has subpages.
-
- The pages provided by the defined view are accessed by first
- traversing to the view name and then traversing to the page name.
- """
-
- for_ = GlobalInterface(
- title=u"The interface this view is for.",
- required=False
- )
-
- name = TextLine(
- title=u"The name of the view.",
- description=u"The name shows up in URLs/paths. For example 'foo'.",
- required=False,
- default=u'',
- )
-
- menu = MenuField(
- title=u"The browser menu to include the page (view) in.",
- description=u"""
- Many views are included in menus. It's convenient to name
- the menu in the page directive, rather than having to give a
- separate menuItem directive. 'zmi_views' is the menu most often
- used in the Zope management interface.
- </description>
- """,
- required=False
- )
-
- title = MessageID(
- title=u"The browser menu label for the page (view)",
- description=u"""
- This attribute must be supplied if a menu attribute is
- supplied.
- """,
- required=False
- )
-
- provides = GlobalInterface(
- title=u"The interface this view provides.",
- description=u"""
- A view can provide an interface. This would be used for
- views that support other views.""",
- required=False,
- default=Interface,
- )
-
-class IViewPageSubdirective(Interface):
- """
- Subdirective to IViewDirective.
- """
-
- name = TextLine(
- title=u"The name of the page (view)",
- description=u"""
- The name shows up in URLs/paths. For example 'foo' or
- 'foo.html'. This attribute is required unless you use the
- subdirective 'page' to create sub views. If you do not have
- sub pages, it is common to use an extension for the view name
- such as '.html'. If you do have sub pages and you want to
- provide a view name, you shouldn't use extensions.""",
- required=True
- )
-
- attribute = PythonIdentifier(
- title=u"The name of the view attribute implementing the page.",
- description=u"""
- This refers to the attribute (method) on the view that is
- implementing a specific sub page.""",
- required=False
- )
-
- template = Path(
- title=u"The name of a template that implements the page.",
- description=u"""
- Refers to a file containing a page template (should end in
- extension '.pt' or '.html').""",
- required=False
- )
-
-class IViewDefaultPageSubdirective(Interface):
- """
- Subdirective to IViewDirective.
- """
-
- name = TextLine(
- title=u"The name of the page that is the default.",
- description=u"""
- The named page will be used as the default if no name is
- specified explicitly in the path. If no defaultPage directive
- is supplied, the default page will be the first page
- listed.""",
- required=True
- )
-
-class IDefaultViewDirective(Interface):
- """
- The name of the view that should be the default.
-
- This name refers to view that should be the
- view used by default (if no view name is supplied
- explicitly).
- """
-
- name = TextLine(
- title=u"The name of the view that should be the default.",
- description=u"""
- This name refers to view that should be the view used by
- default (if no view name is supplied explicitly).""",
- required=True
- )
-
- for_ = GlobalObject(
- title=u"The interface this view is the default for.",
- description=u"""Specifies the interface for which the view is
- registered. All objects implementing this interface can make use of
- this view. If this attribute is not specified, the view is available
- for all objects.""",
- required=False
- )
-
- layer = GlobalInterface(
- title=u"The layer the default view is declared for",
- description=u"The default layer for which the default view is "
- u"applicable. By default it is applied to all layers.",
- required=False
- )
-
-#
-# browser pages
-#
-
-class IPagesPageSubdirective(IViewPageSubdirective):
- """
- Subdirective to IPagesDirective
- """
-
- menu = MenuField(
- title=u"The browser menu to include the page (view) in.",
- description=u"""
- Many views are included in menus. It's convenient to name the
- menu in the page directive, rather than having to give a
- separate menuItem directive.""",
- required=False
- )
-
- title = MessageID(
- title=u"The browser menu label for the page (view)",
- description=u"""
- This attribute must be supplied if a menu attribute is
- supplied.""",
- required=False
- )
-
-class IPageDirective(IPagesDirective, IPagesPageSubdirective):
- """
- The page directive is used to create views that provide a single
- url or page.
-
- The page directive creates a new view class from a given template
- and/or class and registers it.
- """
-
-
-#
-# browser resources
-#
-
-class IBasicResourceInformation(Interface):
- """
- This is the basic information for all browser resources.
- """
-
- layer = GlobalInterface(
- title=u"The layer the resource should be found in",
- description=u"""
- For information on layers, see the documentation for the skin
- directive. Defaults to "default".""",
- required=False
- )
-
- permission = Permission(
- title=u"The permission needed to access the resource.",
- description=u"""
- If a permission isn't specified, the resource will always be
- accessible.""",
- required=False
- )
-
-class IResourceDirective(IBasicResourceInformation):
- """
- Defines a browser resource
- """
-
- name = TextLine(
- title=u"The name of the resource",
- description=u"""
- This is the name used in resource urls. Resource urls are of
- the form site/@@/resourcename, where site is the url of
- "site", a folder with a site manager.
-
- We make resource urls site-relative (as opposed to
- content-relative) so as not to defeat caches.""",
- required=True
- )
-
- factory = GlobalObject(
- title=u"Resource Factory",
- description=u"The factory used to create the resource. The factory "
- u"should only expect to get the request passed when "
- u"called.",
- required=False
- )
-
- file = Path(
- title=u"File",
- description=u"The file containing the resource data.",
- required=False
- )
-
- image = Path(
- title=u"Image",
- description=u"""
- If the image attribute is used, then an image resource, rather
- than a file resource will be created.""",
- required=False
- )
-
- template = Path(
- title=u"Template",
- description=u"""
- If the template attribute is used, then a page template resource,
- rather than a file resource will be created.""",
- required=False
- )
-
-class II18nResourceDirective(IBasicResourceInformation):
- """
- Defines an i18n'd resource.
- """
-
- name = TextLine(
- title=u"The name of the resource",
- description=u"""
- This is the name used in resource urls. Resource urls are of
- the form site/@@/resourcename, where site is the url of
- "site", a folder with a site manager.
-
- We make resource urls site-relative (as opposed to
- content-relative) so as not to defeat caches.""",
- required=True
- )
-
- defaultLanguage = TextLine(
- title=u"Default language",
- description=u"Defines the default language",
- required=False
- )
-
-class II18nResourceTranslationSubdirective(IBasicResourceInformation):
- """
- Subdirective to II18nResourceDirective.
- """
-
- language = TextLine(
- title=u"Language",
- description=u"Language of this translation of the resource",
- required=True
- )
-
- file = Path(
- title=u"File",
- description=u"The file containing the resource data.",
- required=False
- )
-
- image = Path(
- title=u"Image",
- description=u"""
- If the image attribute is used, then an image resource, rather
- than a file resource will be created.""",
- required=False
- )
-
-class IResourceDirectoryDirective(IBasicResourceInformation):
- """
- Defines a directory containing browser resource
- """
-
- name = TextLine(
- title=u"The name of the resource",
- description=u"""
- This is the name used in resource urls. Resource urls are of
- the form site/@@/resourcename, where site is the url of
- "site", a folder with a site manager.
-
- We make resource urls site-relative (as opposed to
- content-relative) so as not to defeat caches.""",
- required=True
- )
-
- directory = Path(
- title=u"Directory",
- description=u"The directory containing the resource data.",
- required=True
- )
-
-#
-# browser menus
-#
-
-class IMenuDirective(Interface):
- """Define a browser menu"""
-
- id = TextLine(
- title=u"The name of the menu.",
- description=u"This is, effectively, an id.",
- required=False
- )
-
- title = MessageID(
- title=u"Title",
- description=u"A descriptive title for documentation purposes",
- required=False
- )
-
- description = MessageID(
- title=u"Description",
- description=u"A description title of the menu.",
- required=False
- )
-
- class_ = GlobalObject(
- title=u"Menu Class",
- description=u"The menu class used to generate the menu.",
- required=False
- )
-
- interface = GlobalInterface(
- title=u"The menu's interface.",
- required=False
- )
-
-
-class IMenuItemsDirective(Interface):
- """
- Define a group of browser menu items
-
- This directive is useful when many menu items are defined for the
- same interface and menu.
- """
-
- menu = MenuField(
- title=u"Menu name",
- description=u"The (name of the) menu the items are defined for",
- required=True,
- )
-
- for_ = GlobalObject(
- title=u"Interface",
- description=u"The interface the menu items are defined for",
- required=True
- )
-
- layer = GlobalInterface(
- title=u"Layer",
- description=u"The Layer for which the item is declared.",
- required=False
- )
-
- permission = Permission(
- title=u"The permission needed access the item",
- description=u"""
- This can usually be inferred by the system, however, doing so
- may be expensive. When displaying a menu, the system tries to
- traverse to the URLs given in each action to determine whether
- the url is accessible to the current user. This can be
- avoided if the permission is given explicitly.""",
- required=False
- )
-
-
-class IMenuItem(Interface):
- """Common menu item configuration
- """
-
- title = MessageID(
- title=u"Title",
- description=u"The text to be displayed for the menu item",
- required=True
- )
-
- description = MessageID(
- title=u"A longer explanation of the menu item",
- description=u"""
- A UI may display this with the item or display it when the
- user requests more assistance.""",
- required=False
- )
-
- icon = TextLine(
- title=u"Icon Path",
- description=u"Path to the icon resource representing this menu item.",
- required=False
- )
-
- permission = Permission(
- title=u"The permission needed access the item",
- description=u"""
- This can usually be inferred by the system, however, doing so
- may be expensive. When displaying a menu, the system tries to
- traverse to the URLs given in each action to determine whether
- the url is accessible to the current user. This can be
- avoided if the permission is given explicitly.""",
- required=False
- )
-
- filter = TextLine(
- title=u"A condition for displaying the menu item",
- description=u"""
- The condition is given as a TALES expression. The expression
- has access to the variables:
-
- context -- The object the menu is being displayed for
-
- request -- The browser request
-
- nothing -- None
-
- The menu item will not be displayed if there is a filter and
- the filter evaluates to a false value.""",
- required=False
- )
-
- order = Int(
- title=u"Order",
- description=u"A relative position of the menu item in the menu.",
- required=False,
- default=0
- )
-
- item_class = GlobalObject(
- title=u"Menu item class",
- description=u"""
- A class to be used as a factory for creating menu item""",
- required=False
- )
-
-class IMenuItemSubdirective(IMenuItem):
- """Define a menu item within a group of menu items"""
-
- action = TextLine(
- title=u"The relative url to use if the item is selected",
- description=u"""
- The url is relative to the object the menu is being displayed
- for.""",
- required=True
- )
-
-class IMenuItemDirective(IMenuItemsDirective, IMenuItemSubdirective):
- """Define one menu item"""
-
-class ISubMenuItemSubdirective(IMenuItem):
- """Define a menu item that represents a a sub menu.
-
- For a sub-menu menu item, the action is optional, this the item itself
- might not represent a destination, but just an entry point to the sub menu.
- """
-
- action = TextLine(
- title=u"The relative url to use if the item is selected",
- description=u"""
- The url is relative to the object the menu is being displayed
- for.""",
- required=False
- )
-
- submenu = TextLine(
- title=u"Sub-Menu Id",
- description=u"The menu that will be used to provide the sub-entries.",
- required=True,
- )
-
-class ISubMenuItemDirective(IMenuItemsDirective, ISubMenuItemSubdirective):
- """Define one menu item"""
-
-class IAddMenuItemDirective(IMenuItem):
- """Define an add-menu item"""
-
- for_ = GlobalInterface(
- title=u"Interface",
- description=u"The interface the menu items are defined for",
- required=False
- )
-
- class_ = GlobalObject(
- title=u"Class",
- description=u"""
- A class to be used as a factory for creating new objects""",
- required=False
- )
-
- factory = Id(
- title=u"Factory",
- description=u"A factory id for creating new objects",
- required = False,
- )
-
- view = TextLine(
- title=u"Custom view name",
- description=u"The name of a custom add view",
- required = False,
- )
-
- menu = MenuField(
- title=u"Menu name",
- description=u"The (name of the) menu the items are defined for",
- required=False,
- )
-
- layer = GlobalInterface(
- title=u"The layer the custom view is declared for",
- description=u"The default layer for which the custom view is "
- u"applicable. By default it is applied to all layers.",
- required=False
- )
-
-#
-# misc. directives
-#
-
-class IDefaultSkinDirective(Interface):
- """Sets the default browser skin
- """
-
- name = TextLine(
- title=u"Default skin name",
- description=u"Default skin name",
- required=True
- )
-
-
-class IIconDirective(Interface):
- """
- Define an icon for an interface
- """
-
- name = TextLine(
- title=u"The name of the icon.",
- description=u"The name shows up in URLs/paths. For example 'foo'.",
- required=True
- )
-
- for_ = GlobalInterface(
- title=u"The interface this icon is for.",
- description=u"""
- The icon will be for all objects that implement this
- interface.""",
- required=True
- )
-
- file = Path(
- title=u"File",
- description=u"The file containing the icon.",
- required=False
- )
-
- resource = TextLine(
- title=u"Resource",
- description=u"A resource containing the icon.",
- required=False
- )
-
- title = MessageID(
- title=u"Title",
- description=u"Descriptive title",
- required=False
- )
-
- layer = GlobalInterface(
- title=u"The layer the icon should be found in",
- description=u"""
- For information on layers, see the documentation for the skin
- directive. Defaults to "default".""",
- required=False
- )
-
- width = Int(
- title=u"The width of the icon.",
- description=u"""
- The width will be used for the <img width="..." />
- attribute. Defaults to 16.""",
- required=False,
- default=16
- )
-
- height = Int(
- title=u"The height of the icon.",
- description=u"""
- The height will be used for the <img height="..." />
- attribute. Defaults to 16.""",
- required=False,
- default=16
- )
+# BBB imports
+from zope.browserresource.metadirectives import (
+ IBasicResourceInformation,
+ IResourceDirective,
+ II18nResourceDirective,
+ II18nResourceTranslationSubdirective,
+ IResourceDirectoryDirective,
+ IIconDirective
+)
+from zope.browsermenu.metadirectives import (
+ IMenuDirective,
+ IMenuItemsDirective,
+ IMenuItem,
+ IMenuItemSubdirective,
+ IMenuItemDirective,
+ ISubMenuItemSubdirective,
+ ISubMenuItemDirective,
+ IAddMenuItemDirective,
+)
+from zope.browserpage.metadirectives import (
+ IPagesDirective,
+ IViewDirective,
+ IViewPageSubdirective,
+ IViewDefaultPageSubdirective,
+ IPagesPageSubdirective,
+ IPageDirective,
+)
+from zope.publisher.zcml import IDefaultSkinDirective, IDefaultViewDirective
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/pagetemplateresource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,43 +15,6 @@
$Id$
"""
-
-from zope.interface import implements
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import BrowserView
-from zope.publisher.interfaces.browser import IBrowserPublisher
-
-from zope.app.publisher.pagetemplateresource import PageTemplate
-from zope.app.publisher.browser.resource import Resource
-
-class PageTemplateResource(BrowserView, Resource):
-
- implements(IBrowserPublisher)
-
- def publishTraverse(self, request, name):
- '''See interface IBrowserPublisher'''
- raise NotFound(None, name)
-
- def browserDefault(self, request):
- '''See interface IBrowserPublisher'''
- return self, ()
-
- def __call__(self):
- pt = self.context
- response = self.request.response
- if not response.getHeader("Content-Type"):
- response.setHeader("Content-Type", pt.content_type)
- return pt(self.request)
-
-class PageTemplateResourceFactory(object):
-
- def __init__(self, path, checker, name):
- self.__pt = PageTemplate(path)
- self.__checker = checker
- self.__name = name
-
- def __call__(self, request):
- resource = PageTemplateResource(self.__pt, request)
- resource.__Security_checker__ = self.__checker
- resource.__name__ = self.__name
- return resource
+# BBB imports
+from zope.ptresource.ptresource import PageTemplateResource
+from zope.ptresource.ptresource import PageTemplateResourceFactory
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/resource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,48 +15,4 @@
$Id$
"""
-from zope.app.publisher.interfaces import IResource
-from zope.component import adapts
-from zope.component import getMultiAdapter
-from zope.component import queryMultiAdapter
-from zope.interface import implements, implementsOnly
-from zope.location import Location
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.site.hooks import getSite
-from zope.traversing.browser.interfaces import IAbsoluteURL
-import zope.traversing.browser.absoluteurl
-
-class Resource(Location):
-
- implements(IResource)
-
- def __init__(self, request):
- self.request = request
-
- def __call__(self):
- return str(getMultiAdapter((self, self.request), IAbsoluteURL))
-
-
-class AbsoluteURL(zope.traversing.browser.absoluteurl.AbsoluteURL):
-
- implementsOnly(IAbsoluteURL)
- adapts(IResource, IBrowserRequest)
-
- def __init__(self, context, request):
- self.context = context
- self.request = request
-
- def __str__(self):
- name = self.context.__name__
- if name.startswith('++resource++'):
- name = name[12:]
-
- site = getSite()
- base = queryMultiAdapter((site, self.request), IAbsoluteURL,
- name="resource")
- if base is None:
- url = str(getMultiAdapter((site, self.request), IAbsoluteURL))
- else:
- url = str(base)
-
- return "%s/@@/%s" % (url, name)
+from zope.browserresource.resource import Resource, AbsoluteURL # BBB imports
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/resourcemeta.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,87 +15,10 @@
$Id$
"""
-import os
-
-from zope.configuration.exceptions import ConfigurationError
-from zope.interface import Interface
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.security.checker import CheckerPublic, NamesChecker
-from zope.component.zcml import handler
-
-from fileresource import FileResourceFactory, ImageResourceFactory
-from pagetemplateresource import PageTemplateResourceFactory
-from directoryresource import DirectoryResourceFactory
-
-allowed_names = ('GET', 'HEAD', 'publishTraverse', 'browserDefault',
- 'request', '__call__')
-
-class ResourceFactoryWrapper(object):
-
- def __init__(self, factory, checker, name):
- self.__factory = factory
- self.__checker = checker
- self.__name = name
-
- def __call__(self, request):
- resource = self.__factory(request)
- resource.__Security_checker__ = self.__checker
- resource.__name__ = self.__name
- return resource
-
-
-def resource(_context, name, layer=IDefaultBrowserLayer,
- permission='zope.Public', factory=None,
- file=None, image=None, template=None):
-
- if permission == 'zope.Public':
- permission = CheckerPublic
-
- checker = NamesChecker(allowed_names, permission)
-
- if (factory and (file or image or template)) or \
- (file and (factory or image or template)) or \
- (image and (factory or file or template)) or \
- (template and (factory or file or image)):
- raise ConfigurationError(
- "Must use exactly one of factory or file or image or template"
- " attributes for resource directives"
- )
-
- if factory is not None:
- factory = ResourceFactoryWrapper(factory, checker, name)
- elif file:
- factory = FileResourceFactory(file, checker, name)
- elif image:
- factory = ImageResourceFactory(image, checker, name)
- else:
- factory = PageTemplateResourceFactory(template, checker, name)
-
- _context.action(
- discriminator = ('resource', name, IBrowserRequest, layer),
- callable = handler,
- args = ('registerAdapter',
- factory, (layer,), Interface, name, _context.info),
- )
-
-def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer,
- permission='zope.Public'):
- if permission == 'zope.Public':
- permission = CheckerPublic
-
- checker = NamesChecker(allowed_names + ('__getitem__', 'get'),
- permission)
-
- if not os.path.isdir(directory):
- raise ConfigurationError(
- "Directory %s does not exist" % directory
- )
-
- factory = DirectoryResourceFactory(directory, checker, name)
- _context.action(
- discriminator = ('resource', name, IBrowserRequest, layer),
- callable = handler,
- args = ('registerAdapter',
- factory, (layer,), Interface, name, _context.info),
- )
+# BBB imports
+from zope.browserresource.metaconfigure import (
+ allowed_names,
+ ResourceFactoryWrapper,
+ resource,
+ resourceDirectory
+)
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/resources.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,37 +15,5 @@
$Id$
"""
-import zope.component
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import BrowserView
-from zope.interface import implements
-from zope.location import locate
-class Resources(BrowserView):
- """Provide a URL-accessible resource namespace
- """
-
- implements(IBrowserPublisher)
-
- def publishTraverse(self, request, name):
- '''See interface IBrowserPublisher'''
-
- resource = zope.component.queryAdapter(request, name=name)
- if resource is None:
- raise NotFound(self, name)
-
- sm = zope.component.getSiteManager()
- locate(resource, sm, name)
- return resource
-
- def browserDefault(self, request):
- '''See IBrowserPublisher'''
- return empty, ()
-
- def __getitem__(self, name):
- return self.publishTraverse(self.request, name)
-
-
-def empty():
- return ''
+from zope.browserresource.resources import Resources, empty # BBB imports
Modified: zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/browser/viewmeta.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,404 +15,16 @@
$Id$
"""
-import os
-
-from zope.component import queryMultiAdapter
-from zope.component.interface import provideInterface
-from zope.component.zcml import handler
-from zope.interface import implements, classImplements, Interface
-from zope.publisher.interfaces import NotFound
-from zope.security.checker import CheckerPublic, Checker, defineChecker
-from zope.configuration.exceptions import ConfigurationError
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.publisher.interfaces.browser import IDefaultBrowserLayer
-from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.publisher.browser import BrowserView
-
-from zope.app.pagetemplate.simpleviewclass import SimpleViewClass
-from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
-from zope.app.publisher.browser.menumeta import menuItemDirective
-
-# There are three cases we want to suport:
-#
-# Named view without pages (single-page view)
-#
-# <browser:page
-# for=".IContact.IContactInfo."
-# name="info.html"
-# template="info.pt"
-# class=".ContactInfoView."
-# permission="zope.View"
-# />
-#
-# Unnamed view with pages (multi-page view)
-#
-# <browser:pages
-# for=".IContact."
-# class=".ContactEditView."
-# permission="ZopeProducts.Contact.ManageContacts"
-# >
-#
-# <browser:page name="edit.html" template="edit.pt" />
-# <browser:page name="editAction.html" attribute="action" />
-# </browser:pages>
-#
-# Named view with pages (add view is a special case of this)
-#
-# <browser:view
-# name="ZopeProducts.Contact"
-# for="Zope.App.OFS.Container.IAdding."
-# class=".ContactAddView."
-# permission="ZopeProducts.Contact.ManageContacts"
-# >
-#
-# <browser:page name="add.html" template="add.pt" />
-# <browser:page name="action.html" attribute="action" />
-# </browser:view>
-
-# We'll also provide a convenience directive for add views:
-#
-# <browser:add
-# name="ZopeProducts.Contact"
-# class=".ContactAddView."
-# permission="ZopeProducts.Contact.ManageContacts"
-# >
-#
-# <browser:page name="add.html" template="add.pt" />
-# <browser:page name="action.html" attribute="action" />
-# </browser:view>
-
-# page
-
-def page(_context, name, permission, for_,
- layer=IDefaultBrowserLayer, template=None, class_=None,
- allowed_interface=None, allowed_attributes=None,
- attribute='__call__', menu=None, title=None,
- ):
- _handle_menu(_context, menu, title, [for_], name, permission, layer)
- required = {}
-
- permission = _handle_permission(_context, permission)
-
- if not (class_ or template):
- raise ConfigurationError("Must specify a class or template")
-
- if attribute != '__call__':
- if template:
- raise ConfigurationError(
- "Attribute and template cannot be used together.")
-
- if not class_:
- raise ConfigurationError(
- "A class must be provided if attribute is used")
-
- if template:
- template = os.path.abspath(str(_context.path(template)))
- if not os.path.isfile(template):
- raise ConfigurationError("No such file", template)
- required['__getitem__'] = permission
-
- # TODO: new __name__ attribute must be tested
- if class_:
- if attribute != '__call__':
- if not hasattr(class_, attribute):
- raise ConfigurationError(
- "The provided class doesn't have the specified attribute "
- )
- if template:
- # class and template
- new_class = SimpleViewClass(template, bases=(class_, ), name=name)
- else:
- if not hasattr(class_, 'browserDefault'):
- cdict = {
- 'browserDefault':
- lambda self, request: (getattr(self, attribute), ())
- }
- else:
- cdict = {}
-
- cdict['__name__'] = name
- cdict['__page_attribute__'] = attribute
- new_class = type(class_.__name__, (class_, simple,), cdict)
-
- if hasattr(class_, '__implements__'):
- classImplements(new_class, IBrowserPublisher)
-
- else:
- # template
- new_class = SimpleViewClass(template, name=name)
-
- for n in (attribute, 'browserDefault', '__call__', 'publishTraverse'):
- required[n] = permission
-
- _handle_allowed_interface(_context, allowed_interface, permission,
- required)
- _handle_allowed_attributes(_context, allowed_attributes, permission,
- required)
-
- _handle_for(_context, for_)
-
- defineChecker(new_class, Checker(required))
-
- _context.action(
- discriminator = ('view', for_, name, IBrowserRequest, layer),
- callable = handler,
- args = ('registerAdapter',
- new_class, (for_, layer), Interface, name, _context.info),
- )
-
-
-# pages, which are just a short-hand for multiple page directives.
-
-# Note that a class might want to access one of the defined
-# templates. If it does though, it should use getMultiAdapter.
-
-class pages(object):
-
- def __init__(self, _context, for_, permission,
- layer=IDefaultBrowserLayer, class_=None,
- allowed_interface=None, allowed_attributes=None,
- ):
- self.opts = dict(for_=for_, permission=permission,
- layer=layer, class_=class_,
- allowed_interface=allowed_interface,
- allowed_attributes=allowed_attributes,
- )
-
- def page(self, _context, name, attribute='__call__', template=None,
- menu=None, title=None):
- return page(_context,
- name=name,
- attribute=attribute,
- template=template,
- menu=menu, title=title,
- **(self.opts))
-
- def __call__(self):
- return ()
-
-# view (named view with pages)
-
-# This is a different case. We actually build a class with attributes
-# for all of the given pages.
-
-class view(object):
-
- default = None
-
- def __init__(self, _context, for_, permission,
- name='', layer=IDefaultBrowserLayer, class_=None,
- allowed_interface=None, allowed_attributes=None,
- menu=None, title=None, provides=Interface,
- ):
-
- _handle_menu(_context, menu, title, [for_], name, permission, layer)
-
- permission = _handle_permission(_context, permission)
-
- self.args = (_context, name, for_, permission, layer, class_,
- allowed_interface, allowed_attributes)
-
- self.pages = []
- self.menu = menu
- self.provides = provides
-
- def page(self, _context, name, attribute=None, template=None):
- if template:
- template = os.path.abspath(_context.path(template))
- if not os.path.isfile(template):
- raise ConfigurationError("No such file", template)
- else:
- if not attribute:
- raise ConfigurationError(
- "Must specify either a template or an attribute name")
-
- self.pages.append((name, attribute, template))
- return ()
-
- def defaultPage(self, _context, name):
- self.default = name
- return ()
-
- def __call__(self):
- (_context, name, for_, permission, layer, class_,
- allowed_interface, allowed_attributes) = self.args
-
- required = {}
-
- cdict = {}
- pages = {}
-
- for pname, attribute, template in self.pages:
-
- if template:
- cdict[pname] = ViewPageTemplateFile(template)
- if attribute and attribute != name:
- cdict[attribute] = cdict[pname]
- else:
- if not hasattr(class_, attribute):
- raise ConfigurationError("Undefined attribute",
- attribute)
-
- attribute = attribute or pname
- required[pname] = permission
-
- pages[pname] = attribute
-
- # This should go away, but noone seems to remember what to do. :-(
- if hasattr(class_, 'publishTraverse'):
-
- def publishTraverse(self, request, name,
- pages=pages, getattr=getattr):
-
- if name in pages:
- return getattr(self, pages[name])
- view = queryMultiAdapter((self, request), name=name)
- if view is not None:
- return view
-
- m = class_.publishTraverse.__get__(self)
- return m(request, name)
-
- else:
- def publishTraverse(self, request, name,
- pages=pages, getattr=getattr):
-
- if name in pages:
- return getattr(self, pages[name])
- view = queryMultiAdapter((self, request), name=name)
- if view is not None:
- return view
-
- raise NotFound(self, name, request)
-
- cdict['publishTraverse'] = publishTraverse
-
- if not hasattr(class_, 'browserDefault'):
- if self.default or self.pages:
- default = self.default or self.pages[0][0]
- cdict['browserDefault'] = (
- lambda self, request, default=default:
- (self, (default, ))
- )
- elif providesCallable(class_):
- cdict['browserDefault'] = (
- lambda self, request: (self, ())
- )
-
- if class_ is not None:
- bases = (class_, simple)
- else:
- bases = (simple,)
-
- try:
- cname = str(name)
- except:
- cname = "GeneratedClass"
-
- cdict['__name__'] = name
- newclass = type(cname, bases, cdict)
-
- for n in ('publishTraverse', 'browserDefault', '__call__'):
- required[n] = permission
-
- _handle_allowed_interface(_context, allowed_interface, permission,
- required)
- _handle_allowed_attributes(_context, allowed_attributes, permission,
- required)
- _handle_for(_context, for_)
-
- defineChecker(newclass, Checker(required))
-
- if self.provides is not None:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = ('', self.provides)
- )
-
- _context.action(
- discriminator = ('view', (for_, layer), name, self.provides),
- callable = handler,
- args = ('registerAdapter',
- newclass, (for_, layer), self.provides, name,
- _context.info),
- )
-
-def _handle_menu(_context, menu, title, for_, name, permission,
- layer=IDefaultBrowserLayer):
-
- if menu or title:
- if not (menu and title):
- raise ConfigurationError(
- "If either menu or title are specified, they must "
- "both be specified.")
- if len(for_) != 1:
- raise ConfigurationError(
- "Menus can be specified only for single-view, not for "
- "multi-views.")
-
- return menuItemDirective(
- _context, menu, for_[0], '@@' + name, title,
- permission=permission, layer=layer)
-
- return []
-
-def _handle_permission(_context, permission):
- if permission == 'zope.Public':
- permission = CheckerPublic
-
- return permission
-
-def _handle_allowed_interface(_context, allowed_interface, permission,
- required):
- # Allow access for all names defined by named interfaces
- if allowed_interface:
- for i in allowed_interface:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = (None, i)
- )
-
- for name in i:
- required[name] = permission
-
-def _handle_allowed_attributes(_context, allowed_attributes, permission,
- required):
- # Allow access for all named attributes
- if allowed_attributes:
- for name in allowed_attributes:
- required[name] = permission
-
-def _handle_for(_context, for_):
- if for_ is not None:
- _context.action(
- discriminator = None,
- callable = provideInterface,
- args = ('', for_)
- )
-
-class simple(BrowserView):
- implements(IBrowserPublisher)
-
- def publishTraverse(self, request, name):
- raise NotFound(self, name, request)
-
- def __call__(self, *a, **k):
- # If a class doesn't provide it's own call, then get the attribute
- # given by the browser default.
-
- attr = self.__page_attribute__
- if attr == '__call__':
- raise AttributeError("__call__")
-
- meth = getattr(self, attr)
- return meth(*a, **k)
-
-def providesCallable(class_):
- if hasattr(class_, '__call__'):
- for c in class_.__mro__:
- if '__call__' in c.__dict__:
- return True
- return False
+# BBB imports
+from zope.browserpage.metaconfigure import (
+ page,
+ pages,
+ view,
+ _handle_menu,
+ _handle_permission,
+ _handle_allowed_interface,
+ _handle_allowed_attributes,
+ _handle_for,
+ simple,
+ providesCallable,
+)
Modified: zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/configure.zcml 2009-08-27 15:12:51 UTC (rev 103291)
@@ -3,9 +3,9 @@
xmlns:apidoc="http://namespaces.zope.org/apidoc"
>
+ <include package="zope.publisher" />
<include package=".browser" />
<include package=".xmlrpc" />
- <include file="http.zcml" />
</configure>
Modified: zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/fileresource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,33 +15,7 @@
$Id$
"""
-import os
-from time import time
-from zope.contenttype import guess_content_type
-from zope.datetime import rfc1123_date
-
-
-class File(object):
-
- def __init__(self, path, name):
- self.path = path
-
- f = open(path, 'rb')
- data = f.read()
- f.close()
- self.content_type, enc = guess_content_type(path, data)
- self.__name__ = name
- self.lmt = float(os.path.getmtime(path)) or time()
- self.lmh = rfc1123_date(self.lmt)
-
-
-class Image(File):
- """Image objects stored in external files."""
-
- def __init__(self, path, name):
- super(Image, self).__init__(path, name)
- if self.content_type in (None, 'application/octet-stream'):
- ext = os.path.splitext(self.path)[1]
- if ext:
- self.content_type = 'image/%s' % ext[1:]
+# BBB imports
+from zope.browserresource.file import File
+Image = File
Modified: zope.app.publisher/trunk/src/zope/app/publisher/http.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/http.zcml 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/http.zcml 2009-08-27 15:12:51 UTC (rev 103291)
@@ -2,19 +2,6 @@
xmlns="http://namespaces.zope.org/zope"
package="zope.publisher.http">
- <class class="zope.publisher.http.HTTPRequest">
- <require
- permission="zope.View"
- interface="zope.publisher.interfaces.http.IHTTPApplicationRequest"/>
- </class>
+ <!-- The contents of this file was moved into zope.publisher's configure.zcml -->
- <class class="zope.publisher.http.URLGetter">
- <allow
- attributes="get __getitem__ __str__" />
- </class>
-
- <class class="zope.publisher.http.DirectResult">
- <allow interface="zope.publisher.http.IResult" />
- </class>
-
</configure>
Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/__init__.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,12 +15,4 @@
$Id$
"""
-from zope.interface import Interface, Attribute
-
-
-class IResource(Interface):
-
- request = Attribute('Request object that is requesting the resource')
-
- def __call__():
- """return the absolute URL of this resource."""
+from zope.browserresource.interfaces import IResource # BBB import
Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/browser.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,147 +15,13 @@
$Id$
"""
-from zope.app.publisher.i18n import ZopeMessageFactory as _
-from zope.interface import Interface, directlyProvides
-from zope.interface.interfaces import IInterface
-from zope.schema import TextLine, Text, URI, Int
-
-class IMenuItemType(IInterface):
- """Menu item type
-
- Menu item types are interfaces that define classes of
- menu items.
- """
-
-class AddMenu(Interface):
- """Special menu for providing a list of addable objects."""
-
-directlyProvides(AddMenu, IMenuItemType)
-
-
-class IBrowserMenu(Interface):
- """Menu
-
- Menus are objects that can return a list of menu items they contain. How
- they generate this list is up to them. Commonly, however, they will look
- up adapters that provide the ``IBrowserMenuItem`` interface.
- """
-
- id = TextLine(
- title=_("Menu Id"),
- description=_("The id uniquely identifies this menu."),
- required=True
- )
-
- title = TextLine(
- title=_("Menu title"),
- description=_("The title provides the basic label for the menu."),
- required=False
- )
-
- description = Text(
- title=_("Menu description"),
- description=_("A description of the menu. This might be shown "
- "on menu pages or in pop-up help for menus."),
- required=False
- )
-
- def getMenuItems(object, request):
- """Return a TAL-friendly list of menu items.
-
- The object (acts like the context) and request can be used to select
- the items that are available.
- """
-
-
-class IBrowserMenuItem(Interface):
- """Menu type
-
- An interface that defines a menu.
- """
-
- title = TextLine(
- title=_("Menu item title"),
- description=_("The title provides the basic label for the menu item."),
- required=True
- )
-
- description = Text(
- title=_("Menu item description"),
- description=_("A description of the menu item. This might be shown "
- "on menu pages or in pop-up help for menu items."),
- required=False
- )
-
- action = TextLine(
- title=_("The URL to display if the item is selected"),
- description=_("When a user selects a browser menu item, the URL"
- "given in the action is displayed. The action is "
- "usually given as a relative URL, relative to the "
- "object the menu item is for."),
- required=True
- )
-
- order = Int(
- title=_("Menu item ordering hint"),
- description=_("This attribute provides a hint for menu item ordering."
- "Menu items will generally be sorted by the `for_`"
- "attribute and then by the order.")
- )
-
- filter_string = TextLine(
- title=_("A condition for displaying the menu item"),
- description=_("The condition is given as a TALES expression. The "
- "expression has access to the variables:\n"
- "\n"
- "context -- The object the menu is being displayed "
- "for\n"
- "\n"
- "request -- The browser request\n"
- "\n"
- "nothing -- None\n"
- "\n"
- "The menu item will not be displayed if there is a \n"
- "filter and the filter evaluates to a false value."),
- required=False)
-
- icon = URI(
- title=_("Icon URI"),
- description=_("URI of the icon representing this menu item"))
-
- def available():
- """Test whether the menu item should be displayed
-
- A menu item might not be available for an object, for example
- due to security limitations or constraints.
- """
-
-class IBrowserSubMenuItem(IBrowserMenuItem):
- """A menu item that points to a sub-menu."""
-
- submenuId = TextLine(
- title=_("Sub-Menu Id"),
- description=_("The menu id of the menu that describes the "
- "sub-menu below this item."),
- required=True)
-
- action = TextLine(
- title=_("The URL to display if the item is selected"),
- description=_("When a user selects a browser menu item, the URL "
- "given in the action is displayed. The action is "
- "usually given as a relative URL, relative to the "
- "object the menu item is for."),
- required=False
- )
-
-
-class IMenuAccessView(Interface):
- """View that provides access to menus"""
-
- def __getitem__(menu_id):
- """Get menu information
-
- Return a sequence of dictionaries with labels and
- actions, where actions are relative URLs.
- """
+# BBB imports
+from zope.browsermenu.interfaces import (
+ IMenuItemType,
+ AddMenu,
+ IBrowserMenu,
+ IBrowserMenuItem,
+ IBrowserSubMenuItem,
+ IMenuAccessView
+)
Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/ftp.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,14 +15,9 @@
$Id$
"""
-from zope.publisher.interfaces import IView
-from zope.publisher.interfaces.ftp import IFTPPublisher
+from zope.publisher.interfaces.ftp import IFTPPublisher, IFTPView
-class IFTPView(IView):
- "FTP View"
-
-
class IFTPDirectoryPublisher(IFTPPublisher, IFTPView):
def type(name):
Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/http.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,13 +15,9 @@
$Id$
"""
-from zope.publisher.interfaces import IView
+from zope.publisher.interfaces.http import IHTTPView
-class IHTTPView(IView):
- "HTTP View"
-
-
class ILogin(IHTTPView):
"""A simple login interface."""
Modified: zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/interfaces/xmlrpc.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,8 +15,4 @@
$Id$
"""
-from zope.publisher.interfaces import IView
-
-
-class IXMLRPCView(IView):
- """XMLRPC View"""
+from zope.publisher.interfaces.xmlrpc import IXMLRPCView # BBB import
Modified: zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/pagetemplateresource.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -15,30 +15,5 @@
$Id$
"""
+from zope.ptresource.ptresource import PageTemplate # BBB import
-from zope.pagetemplate.engine import TrustedAppPT
-from zope.pagetemplate.pagetemplatefile import PageTemplateFile
-
-class PageTemplate(TrustedAppPT, PageTemplateFile):
- """
- Resource that is a page template
- """
-
- def __init__(self, filename, _prefix=None, content_type=None):
- _prefix = self.get_path_from_prefix(_prefix)
- super(PageTemplate, self).__init__(filename, _prefix)
- if content_type is not None:
- self.content_type = content_type
-
- def pt_getContext(self, request, **kw):
- namespace = super(PageTemplate, self).pt_getContext(**kw)
- namespace['context'] = None
- namespace['request'] = request
- return namespace
-
- def __call__(self, request, **keywords):
- namespace = self.pt_getContext(
- request=request,
- options=keywords
- )
- return self.pt_render(namespace)
Modified: zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/__init__.py 2009-08-27 15:12:51 UTC (rev 103291)
@@ -22,13 +22,8 @@
import zope.publisher.interfaces.xmlrpc
import zope.app.publisher.interfaces.xmlrpc
-class XMLRPCView(object):
- """A base XML-RPC view that can be used as mix-in for XML-RPC views."""
- zope.interface.implements(zope.app.publisher.interfaces.xmlrpc.IXMLRPCView)
+from zope.publisher.xmlrpc import XMLRPCView
- def __init__(self, context, request):
- self.context = context
- self.request = request
class IMethodPublisher(zope.interface.Interface):
"""Marker interface for an object that wants to publish methods
Modified: zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml
===================================================================
--- zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml 2009-08-27 15:10:05 UTC (rev 103290)
+++ zope.app.publisher/trunk/src/zope/app/publisher/xmlrpc/configure.zcml 2009-08-27 15:12:51 UTC (rev 103291)
@@ -3,31 +3,7 @@
xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
>
- <class class="xmlrpclib.Fault">
- <allow attributes="faultCode faultString" />
- </class>
-
- <class class="xmlrpclib.DateTime">
- <allow attributes="value" />
- </class>
-
<view
- for="zope.container.interfaces.IItemContainer"
- type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
- provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
- factory="zope.container.traversal.ItemTraverser"
- permission="zope.Public"
- />
-
- <view
- for="zope.container.interfaces.IReadContainer"
- type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
- provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
- factory="zope.container.traversal.ContainerTraverser"
- permission="zope.Public"
- />
-
- <view
for=".IMethodPublisher"
type="zope.publisher.interfaces.xmlrpc.IXMLRPCRequest"
provides="zope.publisher.interfaces.xmlrpc.IXMLRPCPublisher"
More information about the Checkins
mailing list