[Checkins] SVN: Sandbox/nadako/zope.browserresource/ Add pluggable file resource factories depending on file extension. The implementation is based on the patch attached to this report - https://bugs.launchpad.net/zope3/+bug/98459. This should be a step to moving PageTemplate resources into a separate package.
Dan Korostelev
nadako at gmail.com
Sun Aug 23 12:05:54 EDT 2009
Log message for revision 103110:
Add pluggable file resource factories depending on file extension. The implementation is based on the patch attached to this report - https://bugs.launchpad.net/zope3/+bug/98459. This should be a step to moving PageTemplate resources into a separate package.
Changed:
U Sandbox/nadako/zope.browserresource/CHANGES.txt
U Sandbox/nadako/zope.browserresource/TODO.txt
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/configure.zcml
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/directoryresource.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/fileresource.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/i18nfileresource.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/icon.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/interfaces.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/metaconfigure.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/metadirectives.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/pagetemplateresource.py
A Sandbox/nadako/zope.browserresource/src/zope/browserresource/resourcefactories.zcml
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directives.py
U Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directoryresource.py
-=-
Modified: Sandbox/nadako/zope.browserresource/CHANGES.txt
===================================================================
--- Sandbox/nadako/zope.browserresource/CHANGES.txt 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/CHANGES.txt 2009-08-23 16:05:54 UTC (rev 103110)
@@ -10,6 +10,20 @@
Additional changes that are made during refactoring:
+ * Resource class for file resources are now selected the pluggable way.
+ The resource directory publisher and browser:resource ZCML directive
+ now creating file resources using factory utility lookup based on the
+ file extension, so it's now possible to add new resource types without
+ introducing new ZCML directives and they will work inside resource
+ directories as well.
+
+ NOTE: the "resource_factories" attribute from the DirectoryResource
+ was removed, so if you were using this attribute for changing resource
+ classes for some file extensions, you need to migrate your code to new
+ utility-based mechanism.
+
+ See zope.browserresource.interfaces.IResourceFactoryFactory interface.
+
* Fix stripping the "I" from an interface name for icon title, if no
title is specified.
Modified: Sandbox/nadako/zope.browserresource/TODO.txt
===================================================================
--- Sandbox/nadako/zope.browserresource/TODO.txt 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/TODO.txt 2009-08-23 16:05:54 UTC (rev 103110)
@@ -1,6 +1,4 @@
* Clean up tests, possibly move them to doctests.
* Simplify the overall mechanism, remove extra entities.
- * Implement pluggable resource factories for resource
- directory (see https://bugs.launchpad.net/zope3/+bug/98459).
* Move PageTemplateResource to a separate package, so this
one could be independent on any templating system.
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/configure.zcml
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/configure.zcml 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/configure.zcml 2009-08-23 16:05:54 UTC (rev 103110)
@@ -31,4 +31,6 @@
<allow attributes="get __getitem__" />
</class>
+ <include file="resourcefactories.zcml" />
+
</configure>
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/directoryresource.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/directoryresource.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/directoryresource.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -25,16 +25,17 @@
"""
import os
-from zope.interface import implements
+from zope.component import queryUtility
+from zope.interface import implements, classProvides
from zope.publisher.browser import BrowserView
from zope.publisher.interfaces import NotFound
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.browserresource.fileresource import FileResourceFactory
-from zope.browserresource.fileresource import ImageResourceFactory
-from zope.browserresource.pagetemplateresource import PageTemplateResourceFactory
from zope.browserresource.resource import Resource
from zope.browserresource.resources import empty
+from zope.browserresource.interfaces import IResourceFactory
+from zope.browserresource.interfaces import IResourceFactoryFactory
_marker = object()
@@ -50,15 +51,6 @@
implements(IBrowserPublisher)
- resource_factories = {
- '.gif': ImageResourceFactory,
- '.png': ImageResourceFactory,
- '.jpg': ImageResourceFactory,
- '.pt': PageTemplateResourceFactory,
- '.zpt': PageTemplateResourceFactory,
- '.html': PageTemplateResourceFactory,
- }
-
default_factory = FileResourceFactory
directory_factory = None
@@ -88,8 +80,9 @@
return default
if isfile:
- ext = os.path.splitext(os.path.normcase(name))[1]
- factory = self.resource_factories.get(ext, self.default_factory)
+ ext = os.path.splitext(os.path.normcase(name))[1][1:]
+ factory = queryUtility(IResourceFactoryFactory, ext,
+ self.default_factory)
else:
factory = self.directory_factory
@@ -101,6 +94,9 @@
class DirectoryResourceFactory(object):
+ implements(IResourceFactory)
+ classProvides(IResourceFactoryFactory)
+
factoryClass = DirectoryResource
def __init__(self, path, checker, name):
@@ -114,5 +110,4 @@
resource.__name__ = self.__name
return resource
-
DirectoryResource.directory_factory = DirectoryResourceFactory
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/fileresource.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/fileresource.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/fileresource.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -25,12 +25,14 @@
from zope.contenttype import guess_content_type
from zope.datetime import time as timeFromDateTimeString
-from zope.interface import implements
+from zope.interface import implements, classProvides
from zope.publisher.browser import BrowserView
from zope.publisher.interfaces import NotFound
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.browserresource.resource import Resource
+from zope.browserresource.interfaces import IResourceFactory
+from zope.browserresource.interfaces import IResourceFactoryFactory
class File(object):
@@ -157,6 +159,9 @@
resourceClass = FileResource
+ implements(IResourceFactory)
+ classProvides(IResourceFactoryFactory)
+
def __init__(self, path, checker, name):
self.__file = File(path, name)
self.__checker = checker
@@ -172,6 +177,9 @@
class ImageResourceFactory(object):
resourceClass = FileResource
+
+ implements(IResourceFactory)
+ classProvides(IResourceFactoryFactory)
def __init__(self, path, checker, name):
self.__file = Image(path, name)
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/i18nfileresource.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/i18nfileresource.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/i18nfileresource.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -17,9 +17,11 @@
"""
from zope.i18n.interfaces import II18nAware
from zope.i18n.negotiator import negotiator
-from zope.interface import implements
+from zope.interface import implements, classProvides
from zope.browserresource.fileresource import FileResource
+from zope.browserresource.interfaces import IResourceFactory
+from zope.browserresource.interfaces import IResourceFactoryFactory
class I18nFileResource(FileResource):
@@ -79,6 +81,9 @@
class I18nFileResourceFactory(object):
+ implements(IResourceFactory)
+ classProvides(IResourceFactoryFactory)
+
def __init__(self, data, defaultLanguage):
self.__data = data
self.__defaultLanguage = defaultLanguage
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/icon.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/icon.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/icon.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -35,8 +35,7 @@
# 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 src
+ return resource()
class IconViewFactory(object):
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/interfaces.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/interfaces.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/interfaces.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -24,3 +24,23 @@
def __call__():
"""return the absolute URL of this resource."""
+
+class IResourceFactory(Interface):
+
+ def __call__(request):
+ pass
+
+class IResourceFactoryFactory(Interface):
+ """A factory for IResourceFactory objects
+
+ These factories are registered as named utilities that can be selected
+ for creating resource factories in a pluggable way.
+
+ Resource directories and browser:resource directive use these utilities
+ to choose what resource to create, depending on the file extension, so
+ third-party packages could easily plug-in additional resource types.
+
+ """
+
+ def __call__(path, checker, name):
+ """Return an IResourceFactory"""
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/metaconfigure.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/metaconfigure.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/metaconfigure.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -17,10 +17,11 @@
"""
import os
+from zope.component import queryUtility
from zope.component.interface import provideInterface
from zope.component.zcml import handler
from zope.configuration.exceptions import ConfigurationError
-from zope.interface import Interface
+from zope.interface import Interface, implements, classProvides
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.security.checker import CheckerPublic, NamesChecker, Checker
@@ -33,12 +34,17 @@
from zope.browserresource.i18nfileresource import I18nFileResourceFactory
from zope.browserresource.pagetemplateresource import PageTemplateResourceFactory
from zope.browserresource.icon import IconViewFactory
+from zope.browserresource.interfaces import IResourceFactory
+from zope.browserresource.interfaces import IResourceFactoryFactory
allowed_names = ('GET', 'HEAD', 'publishTraverse', 'browserDefault',
'request', '__call__')
class ResourceFactoryWrapper(object):
+ implements(IResourceFactory)
+ classProvides(IResourceFactoryFactory)
+
def __init__(self, factory, checker, name):
self.__factory = factory
self.__checker = checker
@@ -69,21 +75,27 @@
" attributes for resource directives"
)
+ _context.action(
+ discriminator = ('resource', name, IBrowserRequest, layer),
+ callable = resourceHandler,
+ args = (name, layer, checker, factory, file, image, template, _context.info),
+ )
+
+
+def resourceHandler(name, layer, checker, factory, file, image, template, context_info):
if factory is not None:
factory = ResourceFactoryWrapper(factory, checker, name)
elif file:
- factory = FileResourceFactory(file, checker, name)
+ ext = os.path.splitext(os.path.normcase(file))[1][1:]
+ factory_factory = queryUtility(IResourceFactoryFactory, ext,
+ FileResourceFactory)
+ factory = factory_factory(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),
- )
+ handler('registerAdapter', factory, (layer,), Interface, name, context_info)
def resourceDirectory(_context, name, directory, layer=IDefaultBrowserLayer,
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/metadirectives.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/metadirectives.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/metadirectives.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -72,7 +72,12 @@
file = Path(
title=u"File",
- description=u"The file containing the resource data.",
+ description=u"The file containing the resource data. The resource "
+ u"type that will be created depends on file extension. "
+ u"The named IResourceFactoryFactory utilities are "
+ u"registered per extension. If no factory is registered "
+ u"for given file extension, the default FileResource "
+ u"factory will be used.",
required=False
)
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/pagetemplateresource.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/pagetemplateresource.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/pagetemplateresource.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -16,7 +16,7 @@
$Id$
"""
-from zope.interface import implements
+from zope.interface import implements, classProvides
from zope.pagetemplate.engine import TrustedAppPT
from zope.pagetemplate.pagetemplatefile import PageTemplateFile
from zope.publisher.browser import BrowserView
@@ -24,6 +24,8 @@
from zope.publisher.interfaces.browser import IBrowserPublisher
from zope.browserresource.resource import Resource
+from zope.browserresource.interfaces import IResourceFactory
+from zope.browserresource.interfaces import IResourceFactoryFactory
class PageTemplate(TrustedAppPT, PageTemplateFile):
"""
@@ -70,6 +72,9 @@
class PageTemplateResourceFactory(object):
+ implements(IResourceFactory)
+ classProvides(IResourceFactoryFactory)
+
def __init__(self, path, checker, name):
self.__pt = PageTemplate(path)
self.__checker = checker
Added: Sandbox/nadako/zope.browserresource/src/zope/browserresource/resourcefactories.zcml
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/resourcefactories.zcml (rev 0)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/resourcefactories.zcml 2009-08-23 16:05:54 UTC (rev 103110)
@@ -0,0 +1,39 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+ <utility
+ name="gif"
+ component=".fileresource.ImageResourceFactory"
+ provides=".interfaces.IResourceFactoryFactory"
+ />
+
+ <utility
+ name="png"
+ component=".fileresource.ImageResourceFactory"
+ provides=".interfaces.IResourceFactoryFactory"
+ />
+
+ <utility
+ name="jpg"
+ component=".fileresource.ImageResourceFactory"
+ provides=".interfaces.IResourceFactoryFactory"
+ />
+
+ <utility
+ name="pt"
+ component=".pagetemplateresource.PageTemplateResourceFactory"
+ provides=".interfaces.IResourceFactoryFactory"
+ />
+
+ <utility
+ name="zpt"
+ component=".pagetemplateresource.PageTemplateResourceFactory"
+ provides=".interfaces.IResourceFactoryFactory"
+ />
+
+ <utility
+ name="html"
+ component=".pagetemplateresource.PageTemplateResourceFactory"
+ provides=".interfaces.IResourceFactoryFactory"
+ />
+
+</configure>
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directives.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directives.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directives.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -42,7 +42,7 @@
import zope.publisher.defaultview
import zope.browserresource
from zope.component import provideAdapter, provideUtility
-from zope.component.testfiles.views import IC, V1, VZMI, R1, IV
+from zope.component.testfiles.views import R1, IV
from zope.browserresource.fileresource import FileResource
from zope.browserresource.i18nfileresource import I18nFileResource
from zope.testing import cleanup
@@ -61,44 +61,6 @@
request = TestRequest()
-class V2(V1, object):
-
- def action(self):
- return self.action2()
-
- def action2(self):
- return "done"
-
-class VT(V1, object):
- def publishTraverse(self, request, name):
- try:
- return int(name)
- except:
- return super(VT, self).publishTraverse(request, name)
-
-class Ob(object):
- implements(IC)
-
-ob = Ob()
-
-class NCV(object):
- "non callable view"
-
- def __init__(self, context, request):
- pass
-
-class CV(NCV):
- "callable view"
- def __call__(self):
- pass
-
-
-class C_w_implements(NCV):
- implements(Interface)
-
- def index(self):
- return self
-
class ITestLayer(IBrowserRequest):
"""Test Layer."""
Modified: Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directoryresource.py
===================================================================
--- Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directoryresource.py 2009-08-23 15:29:26 UTC (rev 103109)
+++ Sandbox/nadako/zope.browserresource/src/zope/browserresource/tests/test_directoryresource.py 2009-08-23 16:05:54 UTC (rev 103110)
@@ -28,6 +28,7 @@
from zope.traversing.browser.absoluteurl import AbsoluteURL
from zope.traversing.browser.interfaces import IAbsoluteURL
from zope.component import provideAdapter
+from zope.configuration.xmlconfig import XMLConfig
from zope.testing import cleanup
@@ -56,6 +57,10 @@
def setUp(self):
super(Test, self).setUp()
provideAdapter(AbsoluteURL, (None, None), IAbsoluteURL)
+ import zope.browserresource
+ import zope.component
+ XMLConfig('meta.zcml', zope.component)()
+ XMLConfig('resourcefactories.zcml', zope.browserresource)()
def testNotFound(self):
path = os.path.join(test_directory, 'testfiles')
More information about the Checkins
mailing list