zope.browserresource-3.12.0/bootstrap.py0000644000000000000000000000733011401613004016512 0ustar 00000000000000############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os, shutil, sys, tempfile, urllib2 from optparse import OptionParser tmpeggs = tempfile.mkdtemp() is_jython = sys.platform.startswith('java') # parsing arguments parser = OptionParser() parser.add_option("-v", "--version", dest="version", help="use a specific zc.buildout version") parser.add_option("-d", "--distribute", action="store_true", dest="distribute", default=False, help="Use Disribute rather than Setuptools.") parser.add_option("-c", None, action="store", dest="config_file", help=("Specify the path to the buildout configuration " "file to be used.")) options, args = parser.parse_args() # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: args += ['-c', options.config_file] if options.version is not None: VERSION = '==%s' % options.version else: VERSION = '' USE_DISTRIBUTE = options.distribute args = args + ['bootstrap'] to_reload = False try: import pkg_resources if not hasattr(pkg_resources, '_distribute'): to_reload = True raise ImportError except ImportError: ez = {} if USE_DISTRIBUTE: exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True) else: exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) if to_reload: reload(pkg_resources) else: import pkg_resources if sys.platform == 'win32': def quote(c): if ' ' in c: return '"%s"' % c # work around spawn lamosity on windows else: return c else: def quote (c): return c cmd = 'from setuptools.command.easy_install import main; main()' ws = pkg_resources.working_set if USE_DISTRIBUTE: requirement = 'distribute' else: requirement = 'setuptools' if is_jython: import subprocess assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', quote(tmpeggs), 'zc.buildout' + VERSION], env=dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse(requirement)).location ), ).wait() == 0 else: assert os.spawnle( os.P_WAIT, sys.executable, quote (sys.executable), '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION, dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse(requirement)).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout' + VERSION) import zc.buildout.buildout zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) zope.browserresource-3.12.0/buildout.cfg0000644000000000000000000000066611470675670016467 0ustar 00000000000000[buildout] develop = . ../zope.security parts = test coverage-test coverage-report [test] recipe = zc.recipe.testrunner eggs = zope.browserresource [test,zcml] [coverage-test] recipe = zc.recipe.testrunner eggs = zope.browserresource [test] defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') zope.browserresource-3.12.0/CHANGES.txt0000644000000000000000000000641711501731204015745 0ustar 00000000000000======= CHANGES ======= 3.12.0 (2010-12-14) =================== - Added ``zcml`` extra dependencies and fixed dependencies of ``configure.zcml`` on other packages' ``meta.zcml``. - Added a test for including our own ``configure.zcml``. 3.11.0 (2010-08-13) =================== - Support the HTTP ETag header for file resources. ETag generation can be customized or disabled by providing an IETag multi-adapter on (IFileResource, your-application-skin). 3.10.3 (2010-04-30) =================== - Prefer the standard libraries doctest module to the one from zope.testing. 3.10.2 (2009-11-25) =================== - The previous release had a broken egg, sorry. 3.10.1 (2009-11-24) =================== - Import hooks functionality from zope.component after it was moved there from zope.site. This lifts the dependency on zope.site and thereby, ZODB. - Import ISite and IPossibleSite from zope.component after they were moved there from zope.location. 3.10.0 (2009-09-25) =================== - Add an ability to forbid publishing of some files in the resource directory, this is done by fnmatch'ing the wildcards in the ``forbidden_names``class attribute of ``DirectoryResource``. By default, the ``.svn`` is in that attribute, so directories won't publish subversion system directory that can contain private information. 3.9.0 (2009-08-27) ================== Initial release. This package was splitted off zope.app.publisher as a part of refactoring process. 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. * The Image resource class was removed, as they are actually simple files. To migrate, simply rename the "image" argument in browser:resource and browser:i18n-resource directives to "file", if you don't do this, resouces will work, but you'll get deprecation warnings. If you need custom behaviour for images, you can register a resource factory utility for needed file extensions. * The PageTemplateResource was moved into a separate package, "zope.ptresource", which is a plugin for this package now. Because of that, the "template" argument of browser:resource directive was deprecated and you should rename it to "file" to migrate. The PageTemplateResource will be created for "pt", "zpt" and "html" files automatically, if zope.ptresource package is included in your configuration. * Fix stripping the "I" from an interface name for icon title, if no title is specified. * When publishing a resource via Resources view, set resource parent to an ISite object, not to current site manager. * Clean up code and improve test coverage. zope.browserresource-3.12.0/COPYRIGHT.txt0000644000000000000000000000004011370317146016240 0ustar 00000000000000Zope Foundation and Contributorszope.browserresource-3.12.0/LICENSE.txt0000644000000000000000000000402611370317146015762 0ustar 00000000000000Zope Public License (ZPL) Version 2.1 A copyright notice accompanies this license document that identifies the copyright holders. This license has been certified as open source. It has also been designated as GPL compatible by the Free Software Foundation (FSF). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without prior written permission from the copyright holders. 4. The right to distribute this software or to use it for any purpose does not give you the right to use Servicemarks (sm) or Trademarks (tm) of the copyright holders. Use of them is covered by separate agreement with the copyright holders. 5. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. Disclaimer THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zope.browserresource-3.12.0/PKG-INFO0000644000000000000000000001673511501731312015235 0ustar 00000000000000Metadata-Version: 1.0 Name: zope.browserresource Version: 3.12.0 Summary: Browser resources implementation for Zope. Home-page: http://pypi.python.org/pypi/zope.browserresource/ Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ======== Overview ======== *This package is at present not reusable without depending on a large chunk of the Zope Toolkit and its assumptions. It is maintained by the* `Zope Toolkit project `_. This package provides an implementation of browser resources. It also provides directives for defining those resources using ZCML. 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 `` directive, and a whole directory with the `` directive, for example 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.browserresource) 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 ======= CHANGES ======= 3.12.0 (2010-12-14) =================== - Added ``zcml`` extra dependencies and fixed dependencies of ``configure.zcml`` on other packages' ``meta.zcml``. - Added a test for including our own ``configure.zcml``. 3.11.0 (2010-08-13) =================== - Support the HTTP ETag header for file resources. ETag generation can be customized or disabled by providing an IETag multi-adapter on (IFileResource, your-application-skin). 3.10.3 (2010-04-30) =================== - Prefer the standard libraries doctest module to the one from zope.testing. 3.10.2 (2009-11-25) =================== - The previous release had a broken egg, sorry. 3.10.1 (2009-11-24) =================== - Import hooks functionality from zope.component after it was moved there from zope.site. This lifts the dependency on zope.site and thereby, ZODB. - Import ISite and IPossibleSite from zope.component after they were moved there from zope.location. 3.10.0 (2009-09-25) =================== - Add an ability to forbid publishing of some files in the resource directory, this is done by fnmatch'ing the wildcards in the ``forbidden_names``class attribute of ``DirectoryResource``. By default, the ``.svn`` is in that attribute, so directories won't publish subversion system directory that can contain private information. 3.9.0 (2009-08-27) ================== Initial release. This package was splitted off zope.app.publisher as a part of refactoring process. 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. * The Image resource class was removed, as they are actually simple files. To migrate, simply rename the "image" argument in browser:resource and browser:i18n-resource directives to "file", if you don't do this, resouces will work, but you'll get deprecation warnings. If you need custom behaviour for images, you can register a resource factory utility for needed file extensions. * The PageTemplateResource was moved into a separate package, "zope.ptresource", which is a plugin for this package now. Because of that, the "template" argument of browser:resource directive was deprecated and you should rename it to "file" to migrate. The PageTemplateResource will be created for "pt", "zpt" and "html" files automatically, if zope.ptresource package is included in your configuration. * Fix stripping the "I" from an interface name for icon title, if no title is specified. * When publishing a resource via Resources view, set resource parent to an ISite object, not to current site manager. * Clean up code and improve test coverage. Platform: UNKNOWN Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.browserresource-3.12.0/README.txt0000644000000000000000000000464311244531310015631 0ustar 00000000000000======== Overview ======== *This package is at present not reusable without depending on a large chunk of the Zope Toolkit and its assumptions. It is maintained by the* `Zope Toolkit project `_. This package provides an implementation of browser resources. It also provides directives for defining those resources using ZCML. 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 `` directive, and a whole directory with the `` directive, for example 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.browserresource) 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 zope.browserresource-3.12.0/setup.cfg0000644000000000000000000000007311501731312015745 0ustar 00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.browserresource-3.12.0/setup.py0000644000000000000000000000450311501731254015645 0ustar 00000000000000############################################################################## # # Copyright (c) 2007 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """zope.browserresource setup """ from setuptools import setup, find_packages long_description = (open('README.txt').read() + '\n\n' + open('CHANGES.txt').read()) setup(name='zope.browserresource', version = '3.12.0', url='http://pypi.python.org/pypi/zope.browserresource/', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', classifiers = ['Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3', ], description='Browser resources implementation for Zope.', long_description=long_description, license='ZPL 2.1', packages=find_packages('src'), package_dir={'': 'src'}, namespace_packages=['zope'], include_package_data=True, install_requires=['setuptools', 'zope.component>=3.8.0', 'zope.configuration', 'zope.contenttype', 'zope.i18n', 'zope.interface', 'zope.location', 'zope.publisher>=3.8', 'zope.schema', 'zope.traversing>3.7', ], extras_require={ 'test': ['zope.testing'], 'zcml': ['zope.component[zcml]', 'zope.security[zcml]>=3.8'], }, zip_safe = False, ) zope.browserresource-3.12.0/src/zope/__init__.py0000644000000000000000000000007011244217222020001 0ustar 00000000000000__import__('pkg_resources').declare_namespace(__name__) zope.browserresource-3.12.0/src/zope/browserresource/__init__.py0000644000000000000000000000000011244217222023225 0ustar 00000000000000zope.browserresource-3.12.0/src/zope/browserresource/configure.zcml0000644000000000000000000000213411445370374024011 0ustar 00000000000000 zope.browserresource-3.12.0/src/zope/browserresource/directory.py0000644000000000000000000001006011401613004023472 0ustar 00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Resource Directory A 'resource directory' is an on-disk directory which is registered as a resource using the ZCML directive. The directory is treated as a source for individual resources; it can be traversed to retrieve resources represented by contained files, which can in turn be treated as resources. The contained files have __name__ values which include a '/' separating the __name__ of the resource directory from the name of the file within the directory. """ import fnmatch import os 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.file import FileResourceFactory from zope.browserresource.resource import Resource from zope.browserresource.interfaces import IResourceFactory from zope.browserresource.interfaces import IResourceFactoryFactory _marker = object() def empty(): return '' # 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) default_factory = FileResourceFactory directory_factory = None # this will be assigned later in the module forbidden_names = ('.svn', ) 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): for pat in self.forbidden_names: if fnmatch.fnmatch(name, pat): if default is _marker: raise NotFound(None, name) else: return default 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][1:] factory = queryUtility(IResourceFactoryFactory, ext, self.default_factory) else: factory = self.directory_factory rname = self.__name__ + '/' + name resource = factory(filename, self.context.checker, rname)(self.request) resource.__parent__ = self return resource class DirectoryResourceFactory(object): implements(IResourceFactory) classProvides(IResourceFactoryFactory) 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 zope.browserresource-3.12.0/src/zope/browserresource/file.py0000644000000000000000000002377511431247212022435 0ustar 00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """File-based browser resources. """ import os import time import re try: from email.utils import formatdate, parsedate_tz, mktime_tz except ImportError: # python 2.4 from email.Utils import formatdate, parsedate_tz, mktime_tz from zope.contenttype import guess_content_type from zope.interface import implements, classProvides from zope.component import adapts, getMultiAdapter from zope.publisher.browser import BrowserView from zope.publisher.interfaces import NotFound from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserPublisher from zope.browserresource.resource import Resource from zope.browserresource.interfaces import IETag from zope.browserresource.interfaces import IFileResource from zope.browserresource.interfaces import IResourceFactory from zope.browserresource.interfaces import IResourceFactoryFactory ETAG_RX = re.compile(r'[*]|(?:W/)?"(?:[^"\\]|[\\].)*"') def parse_etags(value): r"""Parse a list of entity tags. HTTP/1.1 specifies the following syntax for If-Match/If-None-Match headers:: If-Match = "If-Match" ":" ( "*" | 1#entity-tag ) If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag ) entity-tag = [ weak ] opaque-tag weak = "W/" opaque-tag = quoted-string quoted-string = ( <"> *(qdtext) <"> ) qdtext = > The backslash character ("\") may be used as a single-character quoting mechanism only within quoted-string and comment constructs. Examples: >>> parse_etags('*') ['*'] >>> parse_etags(r' "qwerty", ,"foo",W/"bar" , "baz","\""') ['"qwerty"', '"foo"', 'W/"bar"', '"baz"', '"\\""'] Ill-formed headers are ignored >>> parse_etags("not an etag at all") [] """ return ETAG_RX.findall(value) def etag_matches(etag, tags): """Check if the entity tag matches any of the given tags. >>> etag_matches('"xyzzy"', ['"abc"', '"xyzzy"', 'W/"woof"']) True >>> etag_matches('"woof"', ['"abc"', 'W/"woof"']) False >>> etag_matches('"xyzzy"', ['*']) True Note that you pass quoted etags in both arguments! """ for tag in tags: if tag == etag or tag == '*': return True return False def quote_etag(etag): r"""Quote an etag value >>> quote_etag("foo") '"foo"' Special characters are escaped >>> quote_etag('"') '"\\""' >>> quote_etag('\\') '"\\\\"' """ return '"%s"' % etag.replace('\\', '\\\\').replace('"', '\\"') class File(object): def __init__(self, path, name): self.path = path self.__name__ = name f = open(path, 'rb') self.data = f.read() f.close() self.content_type = guess_content_type(path, self.data)[0] self.lmt = float(os.path.getmtime(path)) or time.time() self.lmh = formatdate(self.lmt, usegmt=True) class FileResource(BrowserView, Resource): implements(IFileResource, IBrowserPublisher) cacheTimeout = 86400 def publishTraverse(self, request, name): '''File resources can't be traversed further, so raise NotFound if someone tries to traverse it. >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> request = TestRequest() >>> resource = factory(request) >>> resource.publishTraverse(request, '_testData') Traceback (most recent call last): ... NotFound: Object: None, name: '_testData' ''' raise NotFound(None, name) def browserDefault(self, request): '''Return a callable for processing browser requests. >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> request = TestRequest(REQUEST_METHOD='GET') >>> resource = factory(request) >>> view, next = resource.browserDefault(request) >>> view() == open(testFilePath, 'rb').read() True >>> next == () True >>> request = TestRequest(REQUEST_METHOD='HEAD') >>> resource = factory(request) >>> view, next = resource.browserDefault(request) >>> view() == '' True >>> next == () True ''' return getattr(self, request.method), () def chooseContext(self): '''Choose the appropriate context. This method can be overriden in subclasses, that need to choose appropriate file, based on current request or other condition, like, for example, i18n files. ''' return self.context def GET(self): '''Return a file data for downloading with GET requests >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> request = TestRequest() >>> resource = factory(request) >>> resource.GET() == open(testFilePath, 'rb').read() True >>> request.response.getHeader('Content-Type') == 'text/plain' True ''' file = self.chooseContext() request = self.request response = request.response etag = getMultiAdapter((self, request), IETag)(file.lmt, file.data) setCacheControl(response, self.cacheTimeout) can_return_304 = False all_cache_checks_passed = True # 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: can_return_304 = True 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(mktime_tz(parsedate_tz(header))) except: mod_since = None if getattr(file, 'lmt', None): last_mod = long(file.lmt) else: last_mod = 0L if mod_since is None or last_mod <= 0 or last_mod > mod_since: all_cache_checks_passed = False # HTTP If-None-Match header handling header = request.getHeader('If-None-Match', None) if header is not None: can_return_304 = True tags = parse_etags(header) if not etag or not etag_matches(quote_etag(etag), tags): all_cache_checks_passed = False # 304 responses MUST contain ETag, if one would've been sent with # a 200 response if etag: response.setHeader('ETag', quote_etag(etag)) if can_return_304 and all_cache_checks_passed: response.setStatus(304) return '' # 304 responses SHOULD NOT or MUST NOT include other entity headers, # depending on whether the conditional GET used a strong or a weak # validator. We only use strong validators, which makes it SHOULD # NOT. response.setHeader('Content-Type', file.content_type) response.setHeader('Last-Modified', file.lmh) return file.data def HEAD(self): '''Return proper headers and no content for HEAD requests >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> request = TestRequest() >>> resource = factory(request) >>> resource.HEAD() == '' True >>> request.response.getHeader('Content-Type') == 'text/plain' True ''' file = self.chooseContext() etag = getMultiAdapter((self, self.request), IETag)(file.lmt, file.data) response = self.request.response response.setHeader('Content-Type', file.content_type) response.setHeader('Last-Modified', file.lmh) if etag: response.setHeader('ETag', etag) setCacheControl(response, self.cacheTimeout) return '' # for unit tests def _testData(self): f = open(self.context.path, 'rb') data = f.read() f.close() return data class FileETag(object): adapts(IFileResource, IBrowserRequest) implements(IETag) def __init__(self, context, request): self.context = context self.request = request def __call__(self, mtime, content): return '%s-%s' % (mtime, len(content)) 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', formatdate(t, usegmt=True)) class FileResourceFactory(object): resourceClass = FileResource implements(IResourceFactory) classProvides(IResourceFactoryFactory) 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 zope.browserresource-3.12.0/src/zope/browserresource/i18nfile.py0000644000000000000000000000520111401613004023106 0ustar 00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Internationalized file resource. """ from zope.i18n.interfaces import II18nAware from zope.i18n.negotiator import negotiator from zope.interface import implements, classProvides from zope.browserresource.file import FileResource from zope.browserresource.interfaces import IResourceFactory from zope.browserresource.interfaces import IResourceFactoryFactory class I18nFileResource(FileResource): implements(II18nAware) def __init__(self, data, request, defaultLanguage='en'): """Creates an internationalized file resource. data should be a mapping from languages to File 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] def getDefaultLanguage(self): 'See II18nAware' return self.defaultLanguage def setDefaultLanguage(self, language): 'See II18nAware' if language not in self._data: raise ValueError( 'cannot set nonexistent language (%s) as default' % language) self.defaultLanguage = language def getAvailableLanguages(self): 'See II18nAware' return self._data.keys() # for unit tests def _testData(self, language): file = self._data[language] f=open(file.path,'rb') data=f.read() f.close() return data class I18nFileResourceFactory(object): implements(IResourceFactory) classProvides(IResourceFactoryFactory) def __init__(self, data, defaultLanguage): self.__data = data self.__defaultLanguage = defaultLanguage def __call__(self, request): return I18nFileResource(self.__data, request, self.__defaultLanguage) zope.browserresource-3.12.0/src/zope/browserresource/icon.py0000644000000000000000000000326011401613004022422 0ustar 00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Icon support """ import zope.component.hooks from zope.component import getAdapter from zope.location import locate 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): return ('%s' % (self.url(), self.alt, self.width, self.height)) def url(self): resource = getAdapter(self.request, name=self.rname) locate(resource, zope.component.hooks.getSite(), self.rname) return resource() 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) zope.browserresource-3.12.0/src/zope/browserresource/interfaces.py0000644000000000000000000000340411431247212023624 0ustar 00000000000000############################################################################## # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Resource interfaces """ 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.""" class IFileResource(IResource): pass class IResourceFactory(Interface): def __call__(request): """Return an IResource object""" 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""" class IETag(Interface): """An adapter for computing resource ETags.""" def __call__(mtime, content): """Compute an ETag for a resource. May return None to disable the ETag header. """ zope.browserresource-3.12.0/src/zope/browserresource/meta.zcml0000644000000000000000000000170511244220740022745 0ustar 00000000000000 zope.browserresource-3.12.0/src/zope/browserresource/metaconfigure.py0000644000000000000000000002215611401613004024327 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ZCML directive handlers for browser resources """ 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, implements, classProvides from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IDefaultBrowserLayer from zope.security.checker import CheckerPublic, NamesChecker, Checker from zope.security.proxy import Proxy from zope.browserresource.directory import DirectoryResourceFactory from zope.browserresource.file import File, FileResourceFactory from zope.browserresource.i18nfile import I18nFileResourceFactory 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 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 image or template: import warnings warnings.warn_explicit( 'The "template" and "image" attributes of resource ' 'directive are deprecated in favor of pluggable ' 'file resource factories based on file extensions. ' 'Use the "file" attribute instead.', DeprecationWarning, _context.info.file, _context.info.line) if image: file = image elif template: file = template _context.action( discriminator = ('resource', name, IBrowserRequest, layer), callable = resourceHandler, args = (name, layer, checker, factory, file, _context.info), ) def resourceHandler(name, layer, checker, factory, file, context_info): if factory is not None: factory = ResourceFactoryWrapper(factory, checker, name) else: ext = os.path.splitext(os.path.normcase(file))[1][1:] factory_factory = queryUtility(IResourceFactoryFactory, ext, FileResourceFactory) factory = factory_factory(file, checker, name) handler('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), ) def icon(_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 title.startswith('I'): 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 # give this module another name, so we can use the "resource" directive # in it that won't conflict with our local variable with the same name. from zope.browserresource import metaconfigure metaconfigure.resource(_context, file=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_) ) 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 = {} 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 None and image is None: raise ConfigurationError( "At least one of the file, and image " "attributes for resource directives must be specified" ) if image is not None: import warnings warnings.warn_explicit( 'The "image" attribute of i18n-resource directive is ' 'deprecated in favor of simple files. Use the "file" ' 'attribute instead.', DeprecationWarning, _context.info.file, _context.info.line) file = image self.__data[language] = File(_context.path(file), self.name) def __call__(self, require = None): if self.name is None: return if self.defaultLanguage not in self.__data: 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 zope.browserresource-3.12.0/src/zope/browserresource/metadirectives.py0000644000000000000000000001647511401613004024516 0ustar 00000000000000############################################################################# # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """ZCML directives for defining browser resources """ from zope.configuration.fields import GlobalObject, GlobalInterface from zope.configuration.fields import Path, MessageID from zope.interface import Interface from zope.schema import TextLine, Int from zope.security.zcml import Permission 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. 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 ) 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. This attribute is deprecated in favor of pluggable resource types, registered per extension. Use the "file" attribute instead. """, 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. This attribute is deprecated in favor of pluggable resource types, registered per extension. Use the "file" attribute instead. To use page template resources, you need to instal zope.ptresource package. """, 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. This attribute is deprecated, as images are now simply files. Use the "file" attribute instead. """, 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 ) 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 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 attribute. Defaults to 16.""", required=False, default=16 ) zope.browserresource-3.12.0/src/zope/browserresource/resource.py0000644000000000000000000000407511401613004023326 0ustar 00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Resource base class and AbsoluteURL adapter """ import zope.component.hooks from zope.component import adapts, getMultiAdapter, queryMultiAdapter from zope.interface import implements, implementsOnly from zope.location import Location from zope.publisher.interfaces.browser import IBrowserRequest from zope.traversing.browser.interfaces import IAbsoluteURL import zope.traversing.browser.absoluteurl from zope.browserresource.interfaces import IResource 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 _createUrl(self, baseUrl, name): return "%s/@@/%s" % (baseUrl, name) def __str__(self): name = self.context.__name__ if name.startswith('++resource++'): name = name[12:] site = zope.component.hooks.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 self._createUrl(url, name) zope.browserresource-3.12.0/src/zope/browserresource/resources.py0000644000000000000000000000776111401613004023516 0ustar 00000000000000############################################################################## # # Copyright (c) 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Resource URL access """ from zope.component import queryAdapter from zope.interface import implements from zope.location import locate from zope.publisher.browser import BrowserView from zope.publisher.interfaces import NotFound from zope.publisher.interfaces.browser import IBrowserPublisher class Resources(BrowserView): """A view that can be traversed further to access browser resources This view is usually registered for zope.component.interfaces.ISite objects with no name, so resources will be available at /@@/. Let's test how it's traversed to get registered resources. Let's create a sample resource class and register it. >>> from zope.component import provideAdapter >>> from zope.interface import Interface >>> from zope.publisher.interfaces import NotFound >>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer >>> from zope.publisher.browser import TestRequest >>> class Resource(object): ... def __init__(self,request): ... self.request = request ... def __call__(self): ... return 'http://localhost/testresource' >>> provideAdapter(Resource, (IDefaultBrowserLayer,), Interface, 'test') Now, create a site and request objects and get the Resources object to work with. >>> site = object() >>> request = TestRequest() >>> resources = Resources(site, request) Okay, let's test the publishTraverse method. It should traverse to our registered resource. >>> resource = resources.publishTraverse(request, 'test') >>> resource.__parent__ is site True >>> resource.__name__ == 'test' True >>> resource() 'http://localhost/testresource' However, it will raise NotFound exception if we try to traverse to an unregistered resource. >>> resources.publishTraverse(request, 'does-not-exist') Traceback (most recent call last): ... NotFound: Object: , name: 'does-not-exist' When accessed without further traversing, it returns an empty page and no futher traversing steps. >>> view, path = resources.browserDefault(request) >>> view() == '' True >>> path == () True The Resources view also provides __getitem__ method for use in templates. >>> resource = resources['test'] >>> resource.__parent__ is site True >>> resource.__name__ == 'test' True >>> resource() 'http://localhost/testresource' """ implements(IBrowserPublisher) def publishTraverse(self, request, name): '''See zope.publisher.interfaces.browser.IBrowserPublisher interface''' resource = queryAdapter(request, name=name) if resource is None: raise NotFound(self, name) locate(resource, self.context, name) return resource def browserDefault(self, request): '''See zope.publisher.interfaces.browser.IBrowserPublisher interface''' return empty, () def __getitem__(self, name): '''A helper method to make this view usable from templates, so resources can be acessed in template like context/@@/. ''' return self.publishTraverse(self.request, name) def empty(): return '' zope.browserresource-3.12.0/src/zope/browserresource/tests/__init__.py0000644000000000000000000000000011244456266024404 0ustar 00000000000000zope.browserresource-3.12.0/src/zope/browserresource/tests/configure.txt0000644000000000000000000000076011445374740025031 0ustar 00000000000000Package configuration ===================== The ``zope.browserresource`` package provides a ZCML file that configures some adapters and views and a couple of security declarations: >>> from zope.configuration.xmlconfig import XMLConfig >>> import zope.browserresource >>> XMLConfig('configure.zcml', zope.browserresource)() >>> len(list(zope.component.getGlobalSiteManager().registeredUtilities())) 9 >>> len(list(zope.component.getGlobalSiteManager().registeredAdapters())) 3 zope.browserresource-3.12.0/src/zope/browserresource/tests/support.py0000644000000000000000000000263111401613004024351 0ustar 00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Support for tests that need a simple site to be provided. """ import zope.component import zope.component.hooks import zope.component.interfaces from zope.interface import implements from zope.traversing.interfaces import IContainmentRoot import zope.browserresource.resource class Site: implements(zope.component.interfaces.ISite, IContainmentRoot) def getSiteManager(self): return zope.component.getGlobalSiteManager() site = Site() class SiteHandler(object): def setUp(self): super(SiteHandler, self).setUp() zope.component.hooks.setSite(site) zope.component.provideAdapter( zope.browserresource.resource.AbsoluteURL) def tearDown(self): zope.component.hooks.setSite() super(SiteHandler, self).tearDown() zope.browserresource-3.12.0/src/zope/browserresource/tests/test_configure.py0000644000000000000000000000037611445374740025704 0ustar 00000000000000from zope.component.testing import setUp, tearDown import doctest import unittest def test_suite(): suite = unittest.TestSuite() suite.addTest(doctest.DocFileSuite( 'configure.txt', setUp=setUp, tearDown=tearDown)) return suite zope.browserresource-3.12.0/src/zope/browserresource/tests/test_directives.py0000644000000000000000000002026111401613004026034 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """'browser' namespace directive tests """ import os import unittest from cStringIO import StringIO from zope import component from zope.interface import Interface, implements, directlyProvides, providedBy import zope.security.management from zope.configuration.xmlconfig import xmlconfig, XMLConfig from zope.configuration.exceptions import ConfigurationError from zope.publisher.browser import TestRequest from zope.publisher.interfaces import IDefaultViewName from zope.publisher.interfaces.browser import IBrowserPublisher from zope.publisher.interfaces.browser import IBrowserRequest from zope.publisher.interfaces.browser import IBrowserSkinType, IDefaultSkin from zope.security.proxy import removeSecurityProxy, ProxyFactory from zope.security.permission import Permission from zope.security.interfaces import IPermission from zope.traversing.adapters import DefaultTraversable from zope.traversing.interfaces import ITraversable import zope.publisher.defaultview import zope.browserresource from zope.component import provideAdapter, provideUtility from zope.component.testfiles.views import R1, IV from zope.browserresource.file import FileResource from zope.browserresource.i18nfile import I18nFileResource from zope.browserresource.directory import DirectoryResource from zope.testing import cleanup tests_path = os.path.join( os.path.dirname(zope.browserresource.__file__), 'tests') template = """ %s """ request = TestRequest() class ITestLayer(IBrowserRequest): """Test Layer.""" class ITestSkin(ITestLayer): """Test Skin.""" class MyResource(object): def __init__(self, request): self.request = request class Test(cleanup.CleanUp, unittest.TestCase): def setUp(self): super(Test, self).setUp() XMLConfig('meta.zcml', zope.browserresource)() provideAdapter(DefaultTraversable, (None,), ITraversable) def tearDown(self): super(Test, self).tearDown() def testI18nResource(self): self.assertEqual(component.queryAdapter(request, name='test'), None) path1 = os.path.join(tests_path, 'testfiles', 'test.pt') path2 = os.path.join(tests_path, 'testfiles', 'test2.pt') xmlconfig(StringIO(template % ( ''' ''' % (path1, path2) ))) v = component.getAdapter(request, name='test') self.assertEqual( component.queryAdapter(request, name='test').__class__, I18nFileResource) self.assertEqual(v._testData('en'), open(path1, 'rb').read()) self.assertEqual(v._testData('fr'), open(path2, 'rb').read()) # translation must be provided for the default language config = StringIO(template % ( ''' ''' % (path1, path2) )) self.assertRaises(ConfigurationError, xmlconfig, config) def testFactory(self): self.assertEqual( component.queryAdapter(request, name='index.html'), None) xmlconfig(StringIO(template % ''' ''' )) r = component.getAdapter(request, name='index.html') self.assertEquals(r.__class__, MyResource) r = ProxyFactory(r) self.assertEqual(r.__name__, "index.html") def testFile(self): path = os.path.join(tests_path, 'testfiles', 'test.pt') self.assertEqual(component.queryAdapter(request, name='test'), None) xmlconfig(StringIO(template % ''' ''' % path )) r = component.getAdapter(request, name='index.html') self.assertTrue(isinstance(r, FileResource)) r = ProxyFactory(r) self.assertEqual(r.__name__, "index.html") # Make sure we can access available attrs and not others for n in ('GET', 'HEAD', 'publishTraverse', 'request', '__call__'): getattr(r, n) self.assertRaises(Exception, getattr, r, '_testData') r = removeSecurityProxy(r) self.assertEqual(r._testData(), open(path, 'rb').read()) def testPluggableFactory(self): class ImageResource(object): def __init__(self, image, request): pass class ImageResourceFactory(object): def __init__(self, path, checker, name): pass def __call__(self, request): return ImageResource(None, request) from zope.browserresource.interfaces import IResourceFactoryFactory component.provideUtility(ImageResourceFactory, IResourceFactoryFactory, name='gif') xmlconfig(StringIO(template % ''' ''' % os.path.join(tests_path, 'testfiles', 'test.gif') )) r = component.getAdapter(request, name='test.gif') self.assertTrue(isinstance(r, ImageResource)) def testDirectory(self): path = os.path.join(tests_path, 'testfiles', 'subdir') self.assertEqual(component.queryAdapter(request, name='dir'), None) xmlconfig(StringIO(template % ''' ''' % path )) r = component.getAdapter(request, name='dir') self.assertTrue(isinstance(r, DirectoryResource)) r = ProxyFactory(r) self.assertEqual(r.__name__, "dir") # Make sure we can access available attrs and not others for n in ('publishTraverse', 'browserDefault', 'request', '__call__', 'get', '__getitem__'): getattr(r, n) self.assertRaises(Exception, getattr, r, 'directory_factory') inexistent_dir = StringIO(template % ''' ''') self.assertRaises(ConfigurationError, xmlconfig, inexistent_dir) def test_SkinResource(self): self.assertEqual(component.queryAdapter(request, name='test'), None) path = os.path.join(tests_path, 'testfiles', 'test.pt') xmlconfig(StringIO(template % ( ''' ''' % path ))) self.assertEqual(component.queryAdapter(request, name='test'), None) r = component.getAdapter(TestRequest(skin=ITestSkin), name='test') self.assertEqual(r._testData(), open(path, 'rb').read()) def test_suite(): return unittest.makeSuite(Test) zope.browserresource-3.12.0/src/zope/browserresource/tests/test_directory.py0000644000000000000000000001473311401613004025706 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Directory-based resources test """ import os import tempfile import shutil from unittest import TestCase, main, makeSuite from zope.publisher.interfaces import NotFound from zope.proxy import isProxy from zope.publisher.browser import TestRequest from zope.security import proxy from zope.security.checker import NamesChecker, ProxyFactory from zope.interface import implements from zope.location.interfaces import IContained from zope.traversing.browser.absoluteurl import AbsoluteURL from zope.traversing.browser.interfaces import IAbsoluteURL from zope.component import provideAdapter, provideUtility from zope.testing import cleanup from zope.browserresource.directory import \ DirectoryResourceFactory, DirectoryResource from zope.browserresource.file import FileResource import zope.browserresource.tests as p from zope.browserresource.tests import support test_directory = os.path.dirname(p.__file__) checker = NamesChecker( ('get', '__getitem__', 'request', 'publishTraverse') ) class Ob(object): implements(IContained) __parent__ = __name__ = None ob = Ob() class Test(support.SiteHandler, cleanup.CleanUp, TestCase): def setUp(self): super(Test, self).setUp() provideAdapter(AbsoluteURL, (None, None), IAbsoluteURL) def testNotFound(self): path = os.path.join(test_directory, 'testfiles') request = TestRequest() factory = DirectoryResourceFactory(path, checker, 'testfiles') resource = factory(request) self.assertRaises(NotFound, resource.publishTraverse, resource.request, 'doesnotexist') self.assertRaises(NotFound, resource.get, 'doesnotexist') def testBrowserDefault(self): path = os.path.join(test_directory, 'testfiles') request = TestRequest() factory = DirectoryResourceFactory(path, checker, 'testfiles') resource = factory(request) view, next = resource.browserDefault(request) self.assertEquals(view(), '') self.assertEquals(next, ()) def testGetitem(self): path = os.path.join(test_directory, 'testfiles') request = TestRequest() factory = DirectoryResourceFactory(path, checker, 'testfiles') resource = factory(request) self.assertRaises(KeyError, resource.__getitem__, 'doesnotexist') file = resource['test.txt'] def testForbiddenNames(self): request = TestRequest() old_forbidden_names = DirectoryResource.forbidden_names path = tempfile.mkdtemp() try: os.mkdir(os.path.join(path, '.svn')) open(os.path.join(path, 'test.txt'), 'w').write('') factory = DirectoryResourceFactory(path, checker, 'testfiles') resource = factory(request) self.assertEquals(resource.get('.svn', None), None) self.assertNotEquals(resource.get('test.txt', None), None) DirectoryResource.forbidden_names = ('*.txt', ) self.assertEquals(resource.get('test.txt', None), None) self.assertNotEquals(resource.get('.svn', None), None) finally: shutil.rmtree(path) DirectoryResource.forbidden_names = old_forbidden_names def testProxy(self): path = os.path.join(test_directory, 'testfiles') request = TestRequest() factory = DirectoryResourceFactory(path, checker, 'testfiles') resource = factory(request) file = ProxyFactory(resource['test.txt']) self.assert_(isProxy(file)) def testURL(self): request = TestRequest() request._vh_root = support.site path = os.path.join(test_directory, 'testfiles') files = DirectoryResourceFactory(path, checker, 'test_files')(request) files.__parent__ = support.site file = files['test.gif'] self.assertEquals(file(), 'http://127.0.0.1/@@/test_files/test.gif') def testURL2Level(self): request = TestRequest() request._vh_root = support.site ob.__parent__ = support.site ob.__name__ = 'ob' path = os.path.join(test_directory, 'testfiles') files = DirectoryResourceFactory(path, checker, 'test_files')(request) files.__parent__ = ob file = files['test.gif'] self.assertEquals(file(), 'http://127.0.0.1/@@/test_files/test.gif') def testURL3Level(self): request = TestRequest() request._vh_root = support.site ob.__parent__ = support.site ob.__name__ = 'ob' path = os.path.join(test_directory, 'testfiles') files = DirectoryResourceFactory(path, checker, 'test_files')(request) files.__parent__ = ob file = files['test.gif'] self.assertEquals(file(), 'http://127.0.0.1/@@/test_files/test.gif') subdir = files['subdir'] self.assert_(proxy.isinstance(subdir, DirectoryResource)) file = subdir['test.gif'] self.assertEquals(file(), 'http://127.0.0.1/@@/test_files/subdir/test.gif') def testPluggableFactories(self): path = os.path.join(test_directory, 'testfiles') request = TestRequest() resource = DirectoryResourceFactory(path, checker, 'files')(request) class ImageResource(object): def __init__(self, image, request): pass class ImageResourceFactory(object): def __init__(self, path, checker, name): pass def __call__(self, request): return ImageResource(None, request) from zope.browserresource.interfaces import IResourceFactoryFactory provideUtility(ImageResourceFactory, IResourceFactoryFactory, 'gif') image = resource['test.gif'] self.assert_(proxy.isinstance(image, ImageResource)) file = resource['test.txt'] self.assert_(proxy.isinstance(file, FileResource)) def test_suite(): return makeSuite(Test) zope.browserresource-3.12.0/src/zope/browserresource/tests/test_file.py0000644000000000000000000002111411431247212024617 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """File-based browser resource tests. """ import doctest import os import unittest import time try: from email.utils import formatdate, parsedate_tz, mktime_tz except ImportError: # python 2.4 from email.Utils import formatdate, parsedate_tz, mktime_tz from zope.testing import cleanup from zope.publisher.browser import TestRequest from zope.publisher.interfaces.browser import IBrowserRequest from zope.security.checker import NamesChecker from zope.component import provideAdapter, adapts from zope.interface import implements from zope.interface.verify import verifyObject from zope.browserresource.file import FileResourceFactory, FileETag from zope.browserresource.interfaces import IFileResource, IETag class MyETag(object): adapts(IFileResource, IBrowserRequest) implements(IETag) def __init__(self, context, request): pass def __call__(self, mtime, content): return 'myetag' class NoETag(object): adapts(IFileResource, IBrowserRequest) implements(IETag) def __init__(self, context, request): pass def __call__(self, mtime, content): return None def setUp(test): cleanup.setUp() data_dir = os.path.join(os.path.dirname(__file__), 'testfiles') test.globs['testFilePath'] = os.path.join(data_dir, 'test.txt') test.globs['nullChecker'] = NamesChecker() test.globs['TestRequest'] = TestRequest provideAdapter(MyETag) def tearDown(test): cleanup.tearDown() def doctest_FileETag(): """Tests for FileETag >>> etag_maker = FileETag(object(), TestRequest()) >>> verifyObject(IETag, etag_maker) True By default we constuct an ETag from the file's mtime and size >>> etag_maker(1234, 'abc') '1234-3' """ def doctest_FileResource_GET_sets_cache_headers(): """Test caching headers set by FileResource.GET >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> timestamp = time.time() >>> file = factory._FileResourceFactory__file # get mangled file >>> file.lmt = timestamp >>> file.lmh = formatdate(timestamp, usegmt=True) >>> request = TestRequest() >>> resource = factory(request) >>> bool(resource.GET()) True >>> request.response.getHeader('Last-Modified') == file.lmh True >>> request.response.getHeader('ETag') '"myetag"' >>> request.response.getHeader('Cache-Control') 'public,max-age=86400' >>> bool(request.response.getHeader('Expires')) True """ def doctest_FileResource_GET_if_modified_since(): """Test If-Modified-Since header support >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> timestamp = time.time() >>> file = factory._FileResourceFactory__file # get mangled file >>> file.lmt = timestamp >>> file.lmh = formatdate(timestamp, usegmt=True) >>> before = timestamp - 1000 >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(before, usegmt=True)) >>> resource = factory(request) >>> bool(resource.GET()) True >>> after = timestamp + 1000 >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(after, usegmt=True)) >>> resource = factory(request) >>> bool(resource.GET()) False >>> request.response.getStatus() 304 Cache control headers and ETag are set on 304 responses >>> request.response.getHeader('ETag') '"myetag"' >>> request.response.getHeader('Cache-Control') 'public,max-age=86400' >>> bool(request.response.getHeader('Expires')) True Other entity headers are not >>> request.response.getHeader('Last-Modified') >>> request.response.getHeader('Content-Type') It won't fail on bad If-Modified-Since headers. >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE='bad header') >>> resource = factory(request) >>> bool(resource.GET()) True it also won't fail if we don't have a last modification time for the resource >>> file.lmt = None >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(after, usegmt=True)) >>> resource = factory(request) >>> bool(resource.GET()) True """ def doctest_FileResource_GET_if_none_match(): """Test If-None-Match header support >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> timestamp = time.time() >>> file = factory._FileResourceFactory__file # get mangled file >>> file.lmt = timestamp >>> file.lmh = formatdate(timestamp, usegmt=True) >>> request = TestRequest(HTTP_IF_NONE_MATCH='"othertag"') >>> resource = factory(request) >>> bool(resource.GET()) True >>> request = TestRequest(HTTP_IF_NONE_MATCH='"myetag"') >>> resource = factory(request) >>> bool(resource.GET()) False >>> request.response.getStatus() 304 Cache control headers and ETag are set on 304 responses >>> request.response.getHeader('ETag') '"myetag"' >>> request.response.getHeader('Cache-Control') 'public,max-age=86400' >>> bool(request.response.getHeader('Expires')) True Other entity headers are not >>> request.response.getHeader('Last-Modified') >>> request.response.getHeader('Content-Type') It won't fail on bad If-None-Match headers. >>> request = TestRequest(HTTP_IF_NONE_MATCH='bad header') >>> resource = factory(request) >>> bool(resource.GET()) True it also won't fail if we don't have an etag for the resource >>> provideAdapter(NoETag) >>> request = TestRequest(HTTP_IF_NONE_MATCH='"someetag"') >>> resource = factory(request) >>> bool(resource.GET()) True """ def doctest_FileResource_GET_if_none_match_and_if_modified_since(): """Test combined If-None-Match and If-Modified-Since header support >>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt') >>> timestamp = time.time() >>> file = factory._FileResourceFactory__file # get mangled file >>> file.lmt = timestamp >>> file.lmh = formatdate(timestamp, usegmt=True) We've a match >>> after = timestamp + 1000 >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(after, usegmt=True), ... HTTP_IF_NONE_MATCH='"myetag"') >>> resource = factory(request) >>> bool(resource.GET()) False >>> request.response.getStatus() 304 Last-modified matches, but ETag doesn't >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(after, usegmt=True), ... HTTP_IF_NONE_MATCH='"otheretag"') >>> resource = factory(request) >>> bool(resource.GET()) True ETag matches but last-modified doesn't >>> before = timestamp - 1000 >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(before, usegmt=True), ... HTTP_IF_NONE_MATCH='"myetag"') >>> resource = factory(request) >>> bool(resource.GET()) True Both don't match >>> before = timestamp - 1000 >>> request = TestRequest(HTTP_IF_MODIFIED_SINCE=formatdate(before, usegmt=True), ... HTTP_IF_NONE_MATCH='"otheretag"') >>> resource = factory(request) >>> bool(resource.GET()) True """ def test_suite(): return unittest.TestSuite(( doctest.DocTestSuite( 'zope.browserresource.file', setUp=setUp, tearDown=tearDown, optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE), doctest.DocTestSuite( setUp=setUp, tearDown=tearDown, optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE), )) zope.browserresource-3.12.0/src/zope/browserresource/tests/test_i18nfile.py0000644000000000000000000001334011431247212025321 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """I18n File-Resource Tests """ from unittest import main, makeSuite import os from zope.publisher.interfaces import NotFound from zope.interface import implements from zope.component import provideAdapter, provideUtility, adapts from zope.testing import cleanup from zope.i18n.interfaces import IUserPreferredCharsets, IUserPreferredLanguages from zope.publisher.http import IHTTPRequest, HTTPCharsets from zope.publisher.browser import BrowserLanguages, TestRequest from zope.publisher.interfaces.browser import IBrowserRequest from zope.browserresource.interfaces import IFileResource, IETag from zope.browserresource.i18nfile import I18nFileResource from zope.browserresource.i18nfile import I18nFileResourceFactory from zope.browserresource.file import File import zope.browserresource.tests as p from zope.i18n.interfaces import INegotiator from zope.i18n.negotiator import negotiator from zope.i18n.tests.testii18naware import TestII18nAware test_directory = os.path.dirname(p.__file__) class MyETag(object): adapts(IFileResource, IBrowserRequest) implements(IETag) def __init__(self, context, request): pass def __call__(self, mtime, content): return 'myetag' class Test(cleanup.CleanUp, TestII18nAware): def setUp(self): super(Test, self).setUp() TestII18nAware.setUp(self) provideAdapter(HTTPCharsets, (IHTTPRequest,), IUserPreferredCharsets) provideAdapter(BrowserLanguages, (IHTTPRequest,), IUserPreferredLanguages) # Setup the negotiator utility provideUtility(negotiator, INegotiator) provideAdapter(MyETag) def _createObject(self): obj = I18nFileResource({'en':None, 'lt':None, 'fr':None}, TestRequest(), 'fr') return obj def test_setDefaultLanguage(self): ob = self._createObject() self.assertRaises(ValueError, ob.setDefaultLanguage, 'ru') def _createDict(self, filename1='test.pt', filename2='test2.pt'): path1 = os.path.join(test_directory, 'testfiles', filename1) path2 = os.path.join(test_directory, 'testfiles', filename2) return { 'en': File(path1, filename1), 'fr': File(path2, filename2) } def testNoTraversal(self): resource = I18nFileResourceFactory(self._createDict(), 'en')\ (TestRequest()) self.assertRaises(NotFound, resource.publishTraverse, resource.request, '_testData') def testFileGET(self): # case 1: no language preference, should get en path = os.path.join(test_directory, 'testfiles', 'test.txt') resource = I18nFileResourceFactory(self._createDict('test.txt'), 'en')\ (TestRequest()) self.assertEqual(resource.GET(), open(path, 'rb').read()) response = resource.request.response self.assertEqual(response.getHeader('Content-Type'), 'text/plain') # case 2: prefer lt, have only en and fr, should get en resource = I18nFileResourceFactory( self._createDict('test.txt'), 'en')\ (TestRequest(HTTP_ACCEPT_LANGUAGE='lt')) self.assertEqual(resource.GET(), open(path, 'rb').read()) response = resource.request.response self.assertEqual(response.getHeader('Content-Type'), 'text/plain') # case 3: prefer fr, have it, should get fr path = os.path.join(test_directory, 'testfiles', 'test2.pt') resource = I18nFileResourceFactory( self._createDict('test.pt', 'test2.pt'), 'en')\ (TestRequest(HTTP_ACCEPT_LANGUAGE='fr')) self.assertEqual(resource.GET(), open(path, 'rb').read()) response = resource.request.response self.assertEqual(response.getHeader('Content-Type'), 'text/html') def testFileHEAD(self): # case 1: no language preference, should get en resource = I18nFileResourceFactory(self._createDict('test.txt'), 'en')\ (TestRequest()) self.assertEqual(resource.HEAD(), '') response = resource.request.response self.assertEqual(response.getHeader('Content-Type'), 'text/plain') # case 2: prefer lt, have only en and fr, should get en resource = I18nFileResourceFactory( self._createDict('test.txt'), 'en')\ (TestRequest(HTTP_ACCEPT_LANGUAGE='lt')) self.assertEqual(resource.HEAD(), '') response = resource.request.response self.assertEqual(response.getHeader('Content-Type'), 'text/plain') # case 3: prefer fr, have it, should get fr resource = I18nFileResourceFactory( self._createDict('test.pt', 'test2.pt'), 'en')\ (TestRequest(HTTP_ACCEPT_LANGUAGE='fr')) self.assertEqual(resource.HEAD(), '') response = resource.request.response self.assertEqual(response.getHeader('Content-Type'), 'text/html') def test_suite(): return makeSuite(Test) zope.browserresource-3.12.0/src/zope/browserresource/tests/test_icondirective.py0000644000000000000000000001622611401613004026530 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test Icon-Directive """ import os from StringIO import StringIO from unittest import TestCase, main, makeSuite from zope import component from zope.configuration.exceptions import ConfigurationError from zope.configuration.xmlconfig import xmlconfig, XMLConfig from zope.interface import implements from zope.publisher.browser import TestRequest from zope.security.checker import ProxyFactory, CheckerPublic from zope.security.interfaces import Forbidden from zope.security.proxy import removeSecurityProxy from zope.traversing.interfaces import IContainmentRoot from zope.traversing.browser.absoluteurl import AbsoluteURL from zope.traversing.browser.interfaces import IAbsoluteURL import zope.location.interfaces import zope.browserresource from zope.component.testfiles.views import IC from zope.browserresource.tests import support from zope.testing import cleanup template = """ %s """ request = TestRequest() class Ob(object): implements(IC) ob = Ob() request._vh_root = support.site def defineCheckers(): # define the appropriate checker for a FileResource for these tests from zope.security.protectclass import protectName from zope.browserresource.file import FileResource protectName(FileResource, '__call__', 'zope.Public') class Test(support.SiteHandler, cleanup.CleanUp, TestCase): def setUp(self): super(Test, self).setUp() XMLConfig('meta.zcml', zope.browserresource)() defineCheckers() component.provideAdapter(AbsoluteURL, (None, None), IAbsoluteURL) def test(self): self.assertEqual( component.queryMultiAdapter((ob, request), name='zmi_icon'), None) import zope.browserresource.tests as p path = os.path.dirname(p.__file__) path = os.path.join(path, 'testfiles', 'test.gif') # Configure the icon and make sure we can render the resulting view: xmlconfig(StringIO(template % ( ''' ''' % path ))) view = component.getMultiAdapter((ob, request), name='zmi_icon') rname = 'zope-component-testfiles-views-IC-zmi_icon.gif' self.assertEqual( view(), 'C' % rname) self.assertEqual(view.url(), 'http://127.0.0.1/@@/' + rname) # Make sure that the title attribute works xmlconfig(StringIO(template % ( ''' ''' % path ))) view = component.getMultiAdapter( (ob, request), name='zmi_icon_w_title') rname = 'zope-component-testfiles-views-IC-zmi_icon_w_title.gif' self.assertEqual( view(), 'click this!' % rname) # Make sure that the width and height attributes work xmlconfig(StringIO(template % ( ''' ''' % path ))) view = component.getMultiAdapter((ob, request), name='zmi_icon_w_width_and_height') rname = ('zope-component-testfiles-views-IC-' 'zmi_icon_w_width_and_height.gif') self.assertEqual( view(), 'C' % rname) # Make sure that the image was installed as a resource: resource = ProxyFactory(component.getAdapter(request, name=rname)) self.assertRaises(Forbidden, getattr, resource, '_testData') resource = removeSecurityProxy(resource) self.assertEqual(resource._testData(), open(path, 'rb').read()) def testResource(self): self.assertEqual( component.queryMultiAdapter((ob, request), name='zmi_icon'), None) import zope.browserresource.tests as p path = os.path.dirname(p.__file__) path = os.path.join(path, 'testfiles', 'test.gif') xmlconfig(StringIO(template % ( ''' ''' % path ))) view = component.getMultiAdapter((ob, request), name='zmi_icon') rname = "zmi_icon_res" self.assertEqual( view(), 'C' % rname) resource = ProxyFactory(component.getAdapter(request, name=rname)) self.assertRaises(Forbidden, getattr, resource, '_testData') resource = removeSecurityProxy(resource) self.assertEqual(resource._testData(), open(path, 'rb').read()) def testResourceErrors(self): self.assertEqual( component.queryMultiAdapter((ob, request), name='zmi_icon'), None) import zope.browserresource.tests as p path = os.path.dirname(p.__file__) path = os.path.join(path, 'testfiles', 'test.gif') config = StringIO(template % ( ''' ''' % (path, path) )) self.assertRaises(ConfigurationError, xmlconfig, config) config = StringIO(template % ( """ """ )) self.assertRaises(ConfigurationError, xmlconfig, config) def test_suite(): return makeSuite(Test) zope.browserresource-3.12.0/src/zope/browserresource/tests/test_resource.py0000644000000000000000000000466711401613004025536 0ustar 00000000000000############################################################################## # # Copyright (c) 2003 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Unit tests for Resource """ import unittest from zope import component from zope.publisher.browser import TestRequest import zope.component.interfaces from zope.browserresource.resource import Resource from zope.browserresource.tests import support from zope.traversing.browser.interfaces import IAbsoluteURL from zope.traversing.browser.absoluteurl import AbsoluteURL from zope.testing import cleanup class TestResource(support.SiteHandler, cleanup.CleanUp, unittest.TestCase): def setUp(self): super(TestResource, self).setUp() component.provideAdapter(AbsoluteURL, (None, None), IAbsoluteURL) def testGlobal(self): req = TestRequest() r = Resource(req) req._vh_root = support.site r.__parent__ = support.site r.__name__ = 'foo' self.assertEquals(r(), 'http://127.0.0.1/@@/foo') r.__name__ = '++resource++foo' self.assertEquals(r(), 'http://127.0.0.1/@@/foo') def testGlobalInVirtualHost(self): req = TestRequest() req.setVirtualHostRoot(['x', 'y']) r = Resource(req) req._vh_root = support.site r.__parent__ = support.site r.__name__ = 'foo' self.assertEquals(r(), 'http://127.0.0.1/x/y/@@/foo') def testResourceUrl(self): # fake IAbsoluteURL adapter def resourceBase(site, request): return 'http://cdn.example.com' component.provideAdapter( resourceBase, (zope.component.interfaces.ISite, TestRequest), IAbsoluteURL, 'resource') req = TestRequest() r = Resource(req) req._vh_root = support.site r.__parent__ = support.site r.__name__ = 'foo' self.assertEquals(r(), 'http://cdn.example.com/@@/foo') def test_suite(): return unittest.makeSuite(TestResource) zope.browserresource-3.12.0/src/zope/browserresource/tests/test_resources.py0000644000000000000000000000206311401613004025705 0ustar 00000000000000############################################################################## # # Copyright (c) 2001, 2002 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test Browser Resources """ import doctest import unittest from zope.testing import cleanup def setUp(test): cleanup.setUp() def tearDown(test): cleanup.tearDown() def test_suite(): return unittest.TestSuite(( doctest.DocTestSuite( 'zope.browserresource.resources', setUp=setUp, tearDown=tearDown, optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE), )) zope.browserresource-3.12.0/src/zope/browserresource/tests/testfiles/test.gif0000644000000000000000000000161511243747776025770 0ustar 00000000000000GIF89aPPP@@@@@!,j@AxჅ*tpÄ)f8A= pa< dǓ A$r"L*iH1ʚ&{ӡO/G~s̙?RlTӫ-* ;zope.browserresource-3.12.0/src/zope/browserresource/tests/testfiles/test.pt0000644000000000000000000000004611243747776025643 0ustar 00000000000000

test

zope.browserresource-3.12.0/src/zope/browserresource/tests/testfiles/test.txt0000644000000000000000000000001211243747776026030 0ustar 00000000000000test data zope.browserresource-3.12.0/src/zope/browserresource/tests/testfiles/test2.pt0000644000000000000000000000007611243747776025730 0ustar 00000000000000

test

zope.browserresource-3.12.0/src/zope/browserresource/tests/testfiles/subdir/test.gif0000644000000000000000000000161511243747776027260 0ustar 00000000000000GIF89aPPP@@@@@!,j@AxჅ*tpÄ)f8A= pa< dǓ A$r"L*iH1ʚ&{ӡO/G~s̙?RlTӫ-* ;zope.browserresource-3.12.0/src/zope.browserresource.egg-info/dependency_links.txt0000644000000000000000000000000111501731312026662 0ustar 00000000000000 zope.browserresource-3.12.0/src/zope.browserresource.egg-info/namespace_packages.txt0000644000000000000000000000000511501731312027142 0ustar 00000000000000zope zope.browserresource-3.12.0/src/zope.browserresource.egg-info/not-zip-safe0000644000000000000000000000000111501731310025040 0ustar 00000000000000 zope.browserresource-3.12.0/src/zope.browserresource.egg-info/PKG-INFO0000644000000000000000000001673511501731312023725 0ustar 00000000000000Metadata-Version: 1.0 Name: zope.browserresource Version: 3.12.0 Summary: Browser resources implementation for Zope. Home-page: http://pypi.python.org/pypi/zope.browserresource/ Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: ======== Overview ======== *This package is at present not reusable without depending on a large chunk of the Zope Toolkit and its assumptions. It is maintained by the* `Zope Toolkit project `_. This package provides an implementation of browser resources. It also provides directives for defining those resources using ZCML. 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 `` directive, and a whole directory with the `` directive, for example 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.browserresource) 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 ======= CHANGES ======= 3.12.0 (2010-12-14) =================== - Added ``zcml`` extra dependencies and fixed dependencies of ``configure.zcml`` on other packages' ``meta.zcml``. - Added a test for including our own ``configure.zcml``. 3.11.0 (2010-08-13) =================== - Support the HTTP ETag header for file resources. ETag generation can be customized or disabled by providing an IETag multi-adapter on (IFileResource, your-application-skin). 3.10.3 (2010-04-30) =================== - Prefer the standard libraries doctest module to the one from zope.testing. 3.10.2 (2009-11-25) =================== - The previous release had a broken egg, sorry. 3.10.1 (2009-11-24) =================== - Import hooks functionality from zope.component after it was moved there from zope.site. This lifts the dependency on zope.site and thereby, ZODB. - Import ISite and IPossibleSite from zope.component after they were moved there from zope.location. 3.10.0 (2009-09-25) =================== - Add an ability to forbid publishing of some files in the resource directory, this is done by fnmatch'ing the wildcards in the ``forbidden_names``class attribute of ``DirectoryResource``. By default, the ``.svn`` is in that attribute, so directories won't publish subversion system directory that can contain private information. 3.9.0 (2009-08-27) ================== Initial release. This package was splitted off zope.app.publisher as a part of refactoring process. 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. * The Image resource class was removed, as they are actually simple files. To migrate, simply rename the "image" argument in browser:resource and browser:i18n-resource directives to "file", if you don't do this, resouces will work, but you'll get deprecation warnings. If you need custom behaviour for images, you can register a resource factory utility for needed file extensions. * The PageTemplateResource was moved into a separate package, "zope.ptresource", which is a plugin for this package now. Because of that, the "template" argument of browser:resource directive was deprecated and you should rename it to "file" to migrate. The PageTemplateResource will be created for "pt", "zpt" and "html" files automatically, if zope.ptresource package is included in your configuration. * Fix stripping the "I" from an interface name for icon title, if no title is specified. * When publishing a resource via Resources view, set resource parent to an ISite object, not to current site manager. * Clean up code and improve test coverage. Platform: UNKNOWN Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.browserresource-3.12.0/src/zope.browserresource.egg-info/requires.txt0000644000000000000000000000035211501731312025214 0ustar 00000000000000setuptools zope.component>=3.8.0 zope.configuration zope.contenttype zope.i18n zope.interface zope.location zope.publisher>=3.8 zope.schema zope.traversing>3.7 [test] zope.testing [zcml] zope.component[zcml] zope.security[zcml]>=3.8zope.browserresource-3.12.0/src/zope.browserresource.egg-info/SOURCES.txt0000644000000000000000000000321311501731312024477 0ustar 00000000000000CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.browserresource.egg-info/PKG-INFO src/zope.browserresource.egg-info/SOURCES.txt src/zope.browserresource.egg-info/dependency_links.txt src/zope.browserresource.egg-info/namespace_packages.txt src/zope.browserresource.egg-info/not-zip-safe src/zope.browserresource.egg-info/requires.txt src/zope.browserresource.egg-info/top_level.txt src/zope/browserresource/__init__.py src/zope/browserresource/configure.zcml src/zope/browserresource/directory.py src/zope/browserresource/file.py src/zope/browserresource/i18nfile.py src/zope/browserresource/icon.py src/zope/browserresource/interfaces.py src/zope/browserresource/meta.zcml src/zope/browserresource/metaconfigure.py src/zope/browserresource/metadirectives.py src/zope/browserresource/resource.py src/zope/browserresource/resources.py src/zope/browserresource/tests/__init__.py src/zope/browserresource/tests/configure.txt src/zope/browserresource/tests/support.py src/zope/browserresource/tests/test_configure.py src/zope/browserresource/tests/test_directives.py src/zope/browserresource/tests/test_directory.py src/zope/browserresource/tests/test_file.py src/zope/browserresource/tests/test_i18nfile.py src/zope/browserresource/tests/test_icondirective.py src/zope/browserresource/tests/test_resource.py src/zope/browserresource/tests/test_resources.py src/zope/browserresource/tests/testfiles/test.gif src/zope/browserresource/tests/testfiles/test.pt src/zope/browserresource/tests/testfiles/test.txt src/zope/browserresource/tests/testfiles/test2.pt src/zope/browserresource/tests/testfiles/subdir/test.gifzope.browserresource-3.12.0/src/zope.browserresource.egg-info/top_level.txt0000644000000000000000000000000511501731312025341 0ustar 00000000000000zope