zope.traversing-3.14.0/bootstrap.py0000644000000000000000000000733011401757504015463 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.traversing-3.14.0/buildout.cfg0000644000000000000000000000061411141553604015376 0ustar 00000000000000[buildout] develop = . parts = test coverage-test coverage-report [test] recipe = zc.recipe.testrunner eggs = zope.traversing [test] [coverage-test] recipe = zc.recipe.testrunner eggs = zope.traversing [test] defaults = ['--coverage', '../../coverage'] [coverage-report] recipe = zc.recipe.egg eggs = z3c.coverage scripts = coverage=coverage-report arguments = ('coverage', 'coverage/report') zope.traversing-3.14.0/CHANGES.txt0000644000000000000000000001516611533525572014717 0ustar 00000000000000======= Changes ======= 3.14.0 (2011-03-02) ------------------- - Re-release of 3.13.1 as a feature version as it introduces dependencies on new feature releases. 3.13.1 (2010-12-14) ------------------- - Fixed ZCML-related dependencies. 3.13 (2010-07-09) ----------------- - When a ``__parent__`` attribute is available on an object, it is always used for absolute URL construction, and no ILocation adapter lookup is performed for it. This was the previous behavior but was broken (around 3.5?) due to dependency refactoring. If the object provides no ``__parent__`` then an ILocation adapter lookup will be performed. This will always succeed as zope.location provides a default LocationProxy for everything, but more specific ILocation adapters can also be provided. 3.12.1 (2010-04-30) ------------------- - Removed use of 'zope.testing.doctestunit' in favor of stdlib's doctest. 3.12.0 (2009-12-29) ------------------- - Avoid testing dependencies on zope.securitypolicies and zope.principalregistry. 3.11.0 (2009-12-27) ------------------- - Removed testing dependency on zope.app.publication. 3.10.0 (2009-12-16) ------------------- - Removed stray test claiming a no longer existing dependency on zope.app.applicationcontrol. - Refactored functional tests to loose dependency on both zope.app.appsetup and zope.app.testing. - Simplified tests for the browser sub-package by using PlacelessSetup from zope.component.testing instead of zope.app.testing. - Simplified test_dependencies module by using zope.configuration instead of zope.app.testing.functional. - Removed testing dependency on zope.app.publisher. - Replaced testing dependency on zope.app.security with zope.securitypolicy. - Removed testing dependency on zope.app.zcmlfiles in favor of more explicit dependencies. - Removed testing dependency on zope.app.component. - Replaced a test dependency on zope.app.zptpage with a dependency on zope.pagetemplate. 3.9.0 (2009-12-15) ------------------ - Moved IBeforeTraverseEvent from zope.app.publication into this package, as we already deal with publication traversal. 3.8.0 (2009-09-29) ------------------ - In zope.traversing.api.getParent(), try to delegate to zope.location.interfaces.ILocationInfo.getParent(), analogous to getParents(). Keep returning the traversal parent as a fallback. - Brought ITraverser back from zope.location where it had been moved to invert the package interdependency, but is no longer used now. 3.7.2 (2009-08-29) ------------------ - Made virtual hosting tests compatible with zope.publisher 3.9. Redirecting to a different host requires an explicit `trusted` redirect now. 3.7.1 (2009-06-16) ------------------ - AbsoluteURL now implements the fact that __call__ returns the same as __str__ in a manner that it applies for subclasses, too, so they only have to override __str__ and not both. 3.7.0 (2009-05-23) ------------------ - Moved the publicationtraverse module to zope.traversing, removing the zope.app.publisher -> zope.app.publication dependency (which was a cycle). - Look up the application controller through a utility registration rather than a direct reference. 3.6.0 (2009-04-06) ------------------ - Change configure.zcml to not depend on zope.app.component. - This release includes the BBB-incompatible ``zope.publisher.skinnable`` change from 3.5.3. 3.5.4 (2009-04-06) ------------------ - Revert BBB-incompatible use of ``zope.publisher.skinnable``: that change belongs in a 3.6.0 release, because it requires a BBB-incompatible version of ``zope.publisher``. 3.5.3 (2009-03-10) ------------------ - Use applySkin from new location. zope.publisher.skinnable instead of zope.publisher.browser. - Use IAbsoluteURL lookup instead of the "absolute_url" view in the recursive AbsoluteURL adapters (LP: #338101). 3.5.2 (2009-02-04) ------------------ - The RootPhysicallyLocatable is not the same as LocationPhysicallyLocatable now in zope.location. Fix the import and testing setups. 3.5.1 (2009-02-02) ------------------ - The ``RootPhysicallyLocatable`` adapter has been superseded by the refactored ``zope.location.traversing.LocationPhysicallyLocatable`` that we depend on since 3.5.0a4. Remove the adapter and its registration, and making its import place pointing to ``zope.location.traversing.LocationPhysicallyLocatable`` to maintain backward-compatibility. This also fixes a bug introduced in version 3.5.0a4 when trying to call ``getParents`` function for the root object. - Use direct imports instead of compatibility ones for things that were moved to ``zope.location``. - Remove the ``zope.traversing.interfaces.INamespaceHandler`` interface, as it seems not to be used for years. - Change package's mailing list address to zope-dev at zope.org instead of retired zope3-dev at zope.org 3.5.0 (2009-01-31) ------------------ - Use zope.container instead of zope.app.container. - Use zope.site instead of zope.app.folder in the unit tests. - Reduced, but did not eliminate, test dependencies on zope.app.component. 3.5.0a4 (2008-08-01) -------------------- - Reverse dependencies between zope.location and zope.traversing. - Updated (test) dependencies and tests to expect and work with a spec compliant TAL interpreter as available in zope.tal >= 3.5.0. - Fixed deprecation warning caused by using an old module name for ZopeSecurityPolicy in ftesting.zcml - Made sure traversing doesn't raise an TypeError but a TraversalError when the traversal step before yielded a string. 3.5.0a3 (2007-12-28) -------------------- - backed out the controversial `++skin++` traverser for XML-RPC. 3.5.0a2 (2007-11-28) -------------------- - ported 3.4.1a1 to trunk - Do not use unicode strings to set the application server in the virtual host namespace. This caused absolute_url to create unicode URL's. - Added a traverer for ++skin++ for XMLRPC skins (IXMLRPCSkinType). This also means that the normal ++skin++ namespace handler is only bound to IBrowserRequest. - Resolved the dependency on zope.app.applicationcontrol by importing the application controller only if the package is available. 3.4.1 (2008-07-30) ------------------ - Fixed deprecation warning caused by using an old module name for ZopeSecurityPolicy in ftesting.zcml 3.4.1a1 (2007-11-13) -------------------- Do not use unicode strings to set the application server in the virtual host namespace. This caused absolute_url to create unicode URL's. 3.4.0 (2007-09-29) ------------------ No further changes since 3.4.0a1. 3.4.0a1 (2007-04-22) -------------------- Initial release as a separate project, corresponds to zope.traversing from Zope 3.4.0a1 zope.traversing-3.14.0/COPYRIGHT.txt0000644000000000000000000000004011370335540015171 0ustar 00000000000000Zope Foundation and Contributorszope.traversing-3.14.0/LICENSE.txt0000644000000000000000000000402611370335540014713 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.traversing-3.14.0/PKG-INFO0000644000000000000000000002201711533525656014177 0ustar 00000000000000Metadata-Version: 1.0 Name: zope.traversing Version: 3.14.0 Summary: Resolving paths in the object hierarchy Home-page: http://pypi.python.org/pypi/zope.traversing Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: The ``zope.traversing`` package provides adapteres for resolving object paths by traversing an object hierarchy. This also includes support for traversal namespaces (e.g. ``++view++``, ``++skin++``, etc.) as well as computing URLs via the ``@@absolute_url`` view. ======= Changes ======= 3.14.0 (2011-03-02) ------------------- - Re-release of 3.13.1 as a feature version as it introduces dependencies on new feature releases. 3.13.1 (2010-12-14) ------------------- - Fixed ZCML-related dependencies. 3.13 (2010-07-09) ----------------- - When a ``__parent__`` attribute is available on an object, it is always used for absolute URL construction, and no ILocation adapter lookup is performed for it. This was the previous behavior but was broken (around 3.5?) due to dependency refactoring. If the object provides no ``__parent__`` then an ILocation adapter lookup will be performed. This will always succeed as zope.location provides a default LocationProxy for everything, but more specific ILocation adapters can also be provided. 3.12.1 (2010-04-30) ------------------- - Removed use of 'zope.testing.doctestunit' in favor of stdlib's doctest. 3.12.0 (2009-12-29) ------------------- - Avoid testing dependencies on zope.securitypolicies and zope.principalregistry. 3.11.0 (2009-12-27) ------------------- - Removed testing dependency on zope.app.publication. 3.10.0 (2009-12-16) ------------------- - Removed stray test claiming a no longer existing dependency on zope.app.applicationcontrol. - Refactored functional tests to loose dependency on both zope.app.appsetup and zope.app.testing. - Simplified tests for the browser sub-package by using PlacelessSetup from zope.component.testing instead of zope.app.testing. - Simplified test_dependencies module by using zope.configuration instead of zope.app.testing.functional. - Removed testing dependency on zope.app.publisher. - Replaced testing dependency on zope.app.security with zope.securitypolicy. - Removed testing dependency on zope.app.zcmlfiles in favor of more explicit dependencies. - Removed testing dependency on zope.app.component. - Replaced a test dependency on zope.app.zptpage with a dependency on zope.pagetemplate. 3.9.0 (2009-12-15) ------------------ - Moved IBeforeTraverseEvent from zope.app.publication into this package, as we already deal with publication traversal. 3.8.0 (2009-09-29) ------------------ - In zope.traversing.api.getParent(), try to delegate to zope.location.interfaces.ILocationInfo.getParent(), analogous to getParents(). Keep returning the traversal parent as a fallback. - Brought ITraverser back from zope.location where it had been moved to invert the package interdependency, but is no longer used now. 3.7.2 (2009-08-29) ------------------ - Made virtual hosting tests compatible with zope.publisher 3.9. Redirecting to a different host requires an explicit `trusted` redirect now. 3.7.1 (2009-06-16) ------------------ - AbsoluteURL now implements the fact that __call__ returns the same as __str__ in a manner that it applies for subclasses, too, so they only have to override __str__ and not both. 3.7.0 (2009-05-23) ------------------ - Moved the publicationtraverse module to zope.traversing, removing the zope.app.publisher -> zope.app.publication dependency (which was a cycle). - Look up the application controller through a utility registration rather than a direct reference. 3.6.0 (2009-04-06) ------------------ - Change configure.zcml to not depend on zope.app.component. - This release includes the BBB-incompatible ``zope.publisher.skinnable`` change from 3.5.3. 3.5.4 (2009-04-06) ------------------ - Revert BBB-incompatible use of ``zope.publisher.skinnable``: that change belongs in a 3.6.0 release, because it requires a BBB-incompatible version of ``zope.publisher``. 3.5.3 (2009-03-10) ------------------ - Use applySkin from new location. zope.publisher.skinnable instead of zope.publisher.browser. - Use IAbsoluteURL lookup instead of the "absolute_url" view in the recursive AbsoluteURL adapters (LP: #338101). 3.5.2 (2009-02-04) ------------------ - The RootPhysicallyLocatable is not the same as LocationPhysicallyLocatable now in zope.location. Fix the import and testing setups. 3.5.1 (2009-02-02) ------------------ - The ``RootPhysicallyLocatable`` adapter has been superseded by the refactored ``zope.location.traversing.LocationPhysicallyLocatable`` that we depend on since 3.5.0a4. Remove the adapter and its registration, and making its import place pointing to ``zope.location.traversing.LocationPhysicallyLocatable`` to maintain backward-compatibility. This also fixes a bug introduced in version 3.5.0a4 when trying to call ``getParents`` function for the root object. - Use direct imports instead of compatibility ones for things that were moved to ``zope.location``. - Remove the ``zope.traversing.interfaces.INamespaceHandler`` interface, as it seems not to be used for years. - Change package's mailing list address to zope-dev at zope.org instead of retired zope3-dev at zope.org 3.5.0 (2009-01-31) ------------------ - Use zope.container instead of zope.app.container. - Use zope.site instead of zope.app.folder in the unit tests. - Reduced, but did not eliminate, test dependencies on zope.app.component. 3.5.0a4 (2008-08-01) -------------------- - Reverse dependencies between zope.location and zope.traversing. - Updated (test) dependencies and tests to expect and work with a spec compliant TAL interpreter as available in zope.tal >= 3.5.0. - Fixed deprecation warning caused by using an old module name for ZopeSecurityPolicy in ftesting.zcml - Made sure traversing doesn't raise an TypeError but a TraversalError when the traversal step before yielded a string. 3.5.0a3 (2007-12-28) -------------------- - backed out the controversial `++skin++` traverser for XML-RPC. 3.5.0a2 (2007-11-28) -------------------- - ported 3.4.1a1 to trunk - Do not use unicode strings to set the application server in the virtual host namespace. This caused absolute_url to create unicode URL's. - Added a traverer for ++skin++ for XMLRPC skins (IXMLRPCSkinType). This also means that the normal ++skin++ namespace handler is only bound to IBrowserRequest. - Resolved the dependency on zope.app.applicationcontrol by importing the application controller only if the package is available. 3.4.1 (2008-07-30) ------------------ - Fixed deprecation warning caused by using an old module name for ZopeSecurityPolicy in ftesting.zcml 3.4.1a1 (2007-11-13) -------------------- Do not use unicode strings to set the application server in the virtual host namespace. This caused absolute_url to create unicode URL's. 3.4.0 (2007-09-29) ------------------ No further changes since 3.4.0a1. 3.4.0a1 (2007-04-22) -------------------- Initial release as a separate project, corresponds to zope.traversing from Zope 3.4.0a1 Platform: UNKNOWN zope.traversing-3.14.0/README.txt0000644000000000000000000000041110723216570014562 0ustar 00000000000000The ``zope.traversing`` package provides adapteres for resolving object paths by traversing an object hierarchy. This also includes support for traversal namespaces (e.g. ``++view++``, ``++skin++``, etc.) as well as computing URLs via the ``@@absolute_url`` view. zope.traversing-3.14.0/setup.cfg0000644000000000000000000000007311533525656014721 0ustar 00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.traversing-3.14.0/setup.py0000644000000000000000000000523111533525556014612 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. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.traversing package """ from setuptools import setup, find_packages long_description = (open('README.txt').read() + '\n\n' + open('CHANGES.txt').read()) setup(name='zope.traversing', version='3.14.0', url='http://pypi.python.org/pypi/zope.traversing', license='ZPL 2.1', author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', description="Resolving paths in the object hierarchy", long_description=long_description, packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope',], extras_require = dict(test=['zope.browserpage', 'zope.browserresource[zcml]>=3.12', 'zope.component[zcml]', 'zope.configuration', 'zope.container', 'zope.pagetemplate', 'zope.security[zcml]>=3.8', 'zope.site', 'zope.tal >= 3.5.0', 'zope.testing', 'ZODB3', ]), install_requires=['setuptools', 'zope.component', 'zope.i18n', 'zope.i18nmessageid', 'zope.interface', 'zope.proxy', 'zope.publisher', 'zope.security', 'zope.location>=3.7.0', ], include_package_data = True, zip_safe = False, ) zope.traversing-3.14.0/src/zope/__init__.py0000644000000000000000000000007011155754662016753 0ustar 00000000000000__import__('pkg_resources').declare_namespace(__name__) zope.traversing-3.14.0/src/zope/traversing/__init__.py0000644000000000000000000000000210054672002021112 0ustar 00000000000000# zope.traversing-3.14.0/src/zope/traversing/adapters.py0000644000000000000000000001047711401757504021207 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. # ############################################################################## """Adapters for the traversing mechanism """ from types import StringTypes import zope.interface import zope.component from zope.location.interfaces import ILocationInfo, LocationError from zope.traversing.interfaces import ITraversable, ITraverser from zope.traversing.namespace import namespaceLookup from zope.traversing.namespace import UnexpectedParameters from zope.traversing.namespace import nsParse from zope.location.traversing import RootPhysicallyLocatable # BBB _marker = object() # opaque marker that doesn't get security proxied class DefaultTraversable(object): """Traverses objects via attribute and item lookup""" zope.interface.implements(ITraversable) def __init__(self, subject): self._subject = subject def traverse(self, name, furtherPath): subject = self._subject __traceback_info__ = (subject, name, furtherPath) attr = getattr(subject, name, _marker) if attr is not _marker: return attr if hasattr(subject, '__getitem__'): try: return subject[name] except (KeyError, TypeError): pass raise LocationError(subject, name) class Traverser(object): """Provide traverse features""" zope.interface.implements(ITraverser) # This adapter can be used for any object. def __init__(self, wrapper): self.context = wrapper def traverse(self, path, default=_marker, request=None): if not path: return self.context if isinstance(path, StringTypes): path = path.split('/') if len(path) > 1 and not path[-1]: # Remove trailing slash path.pop() else: path = list(path) path.reverse() pop = path.pop curr = self.context if not path[-1]: # Start at the root pop() curr = ILocationInfo(self.context).getRoot() try: while path: name = pop() curr = traversePathElement(curr, name, path, request=request) return curr except LocationError: if default == _marker: raise return default def traversePathElement(obj, name, further_path, default=_marker, traversable=None, request=None): """Traverse a single step 'name' relative to the given object. 'name' must be a string. '.' and '..' are treated specially, as well as names starting with '@' or '+'. Otherwise 'name' will be treated as a single path segment. 'further_path' is a list of names still to be traversed. This method is allowed to change the contents of 'further_path'. You can explicitly pass in an ITraversable as the 'traversable' argument. If you do not, the given object will be adapted to ITraversable. 'request' is passed in when traversing from presentation code. This allows paths like @@foo to work. Raises LocationError if path cannot be found and 'default' was not provided. """ __traceback_info__ = (obj, name) if name == '.': return obj if name == '..': return obj.__parent__ if name and name[:1] in '@+': ns, nm = nsParse(name) if ns: return namespaceLookup(ns, nm, obj, request) else: nm = name if traversable is None: traversable = ITraversable(obj, None) if traversable is None: raise LocationError('No traversable adapter found', obj) try: return traversable.traverse(nm, further_path) except LocationError: if default is not _marker: return default else: raise return obj zope.traversing-3.14.0/src/zope/traversing/api.py0000644000000000000000000001636311401757504020155 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. # ############################################################################## """Convenience functions for traversing the object tree. """ from zope.interface import moduleProvides from zope.location.interfaces import ILocationInfo, IRoot, LocationError from zope.traversing.interfaces import ITraversalAPI, ITraverser moduleProvides(ITraversalAPI) __all__ = tuple(ITraversalAPI) _marker = object() def joinPath(path, *args): """Join the given relative paths to the given path. Returns a unicode path. The path should be well-formed, and not end in a '/' unless it is the root path. It can be either a string (ascii only) or unicode. The positional arguments are relative paths to be added to the path as new path segments. The path may be absolute or relative. A segment may not start with a '/' because that would be confused with an absolute path. A segment may not end with a '/' because we do not allow '/' at the end of relative paths. A segment may consist of . or .. to mean "the same place", or "the parent path" respectively. A '.' should be removed and a '..' should cause the segment to the left to be removed. joinPath('/', '..') should raise an exception. """ if not args: # Concatenating u'' is much quicker than unicode(path) return u'' + path if path != '/' and path.endswith('/'): raise ValueError('path must not end with a "/": %s' % path) if path != '/': path += u'/' for arg in args: if arg.startswith('/') or arg.endswith('/'): raise ValueError("Leading or trailing slashes in path elements") return _normalizePath(path + u'/'.join(args)) def getPath(obj): """Returns a string representing the physical path to the object. """ return ILocationInfo(obj).getPath() def getRoot(obj): """Returns the root of the traversal for the given object. """ return ILocationInfo(obj).getRoot() def traverse(object, path, default=_marker, request=None): """Traverse 'path' relative to the given object. 'path' is a string with path segments separated by '/'. 'request' is passed in when traversing from presentation code. This allows paths like @@foo to work. Raises LocationError if path cannot be found Note: calling traverse with a path argument taken from an untrusted source, such as an HTTP request form variable, is a bad idea. It could allow a maliciously constructed request to call code unexpectedly. Consider using traverseName instead. """ traverser = ITraverser(object) if default is _marker: return traverser.traverse(path, request=request) else: return traverser.traverse(path, default=default, request=request) def traverseName(obj, name, default=_marker, traversable=None, request=None): """Traverse a single step 'name' relative to the given object. 'name' must be a string. '.' and '..' are treated specially, as well as names starting with '@' or '+'. Otherwise 'name' will be treated as a single path segment. You can explicitly pass in an ITraversable as the 'traversable' argument. If you do not, the given object will be adapted to ITraversable. 'request' is passed in when traversing from presentation code. This allows paths like @@foo to work. Raises LocationError if path cannot be found and 'default' was not provided. """ further_path = [] if default is _marker: obj = traversePathElement(obj, name, further_path, traversable=traversable, request=request) else: obj = traversePathElement(obj, name, further_path, default=default, traversable=traversable, request=request) if further_path: raise NotImplementedError('further_path returned from traverse') else: return obj def getName(obj): """Get the name an object was traversed via """ return ILocationInfo(obj).getName() def getParent(obj): """Returns the container the object was traversed via. Returns None if the object is a containment root. Raises TypeError if the object doesn't have enough context to get the parent. """ try: location_info = ILocationInfo(obj) except TypeError: pass else: return location_info.getParent() # XXX Keep the old implementation as the fallback behaviour in the case # that obj doesn't have a location parent. This seems advisable as the # 'parent' is sometimes taken to mean the traversal parent, and the # __parent__ attribute is used for both. if IRoot.providedBy(obj): return None parent = getattr(obj, '__parent__', None) if parent is not None: return parent raise TypeError("Not enough context information to get parent", obj) def getParents(obj): """Returns a list starting with the given object's parent followed by each of its parents. Raises a TypeError if the context doesn't go all the way down to a containment root. """ return ILocationInfo(obj).getParents() def _normalizePath(path): """Normalize a path by resolving '.' and '..' path elements.""" # Special case for the root path. if path == u'/': return path new_segments = [] prefix = u'' if path.startswith('/'): prefix = u'/' path = path[1:] for segment in path.split(u'/'): if segment == u'.': continue if segment == u'..': new_segments.pop() # raises IndexError if there is nothing to pop continue if not segment: raise ValueError('path must not contain empty segments: %s' % path) new_segments.append(segment) return prefix + u'/'.join(new_segments) def canonicalPath(path_or_object): """Returns a canonical absolute unicode path for the given path or object. Resolves segments that are '.' or '..'. Raises ValueError if a badly formed path is given. """ if isinstance(path_or_object, (str, unicode)): path = path_or_object if not path: raise ValueError("path must be non-empty: %s" % path) else: path = getPath(path_or_object) path = u'' + path # Special case for the root path. if path == u'/': return path if path[0] != u'/': raise ValueError('canonical path must start with a "/": %s' % path) if path[-1] == u'/': raise ValueError('path must not end with a "/": %s' % path) # Break path into segments. Process '.' and '..' segments. return _normalizePath(path) # import this down here to avoid circular imports from zope.traversing.adapters import traversePathElement zope.traversing-3.14.0/src/zope/traversing/configure.zcml0000644000000000000000000000667711445373362021715 0ustar 00000000000000 zope.traversing-3.14.0/src/zope/traversing/interfaces.py0000644000000000000000000001432111401757504021517 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. # ############################################################################## """Interfaces to do with traversing. """ from zope.interface import Attribute from zope.interface import Interface from zope.interface import implements from zope.component.interfaces import IObjectEvent # BBB: Re-import symbols to their old location. from zope.location.interfaces import LocationError as TraversalError from zope.location.interfaces import IRoot as IContainmentRoot from zope.location.interfaces import ILocationInfo as IPhysicallyLocatable _RAISE_KEYERROR = object() class ITraversable(Interface): """To traverse an object, this interface must be provided""" def traverse(name, furtherPath): """Get the next item on the path Should return the item corresponding to 'name' or raise LocationError where appropriate. 'name' is an ASCII string or Unicode object. 'furtherPath' is a list of names still to be traversed. This method is allowed to change the contents of furtherPath. """ class ITraverser(Interface): """Provide traverse features""" # XXX This is used like a utility but implemented as an adapter: The # traversal policy is only implemented once and repeated for all objects # along the path. def traverse(path, default=_RAISE_KEYERROR): """Return an object given a path. Path is either an immutable sequence of strings or a slash ('/') delimited string. If the first string in the path sequence is an empty string, or the path begins with a '/', start at the root. Otherwise the path is relative to the current context. If the object is not found, return 'default' argument. """ class ITraversalAPI(Interface): """Common API functions to ease traversal computations """ def joinPath(path, *args): """Join the given relative paths to the given path. Returns a unicode path. The path should be well-formed, and not end in a '/' unless it is the root path. It can be either a string (ascii only) or unicode. The positional arguments are relative paths to be added to the path as new path segments. The path may be absolute or relative. A segment may not start with a '/' because that would be confused with an absolute path. A segment may not end with a '/' because we do not allow '/' at the end of relative paths. A segment may consist of . or .. to mean "the same place", or "the parent path" respectively. A '.' should be removed and a '..' should cause the segment to the left to be removed. joinPath('/', '..') should raise an exception. """ def getPath(obj): """Returns a string representing the physical path to the object. """ def getRoot(obj): """Returns the root of the traversal for the given object. """ def traverse(object, path, default=None, request=None): """Traverse 'path' relative to the given object. 'path' is a string with path segments separated by '/'. 'request' is passed in when traversing from presentation code. This allows paths like @@foo to work. Raises LocationError if path cannot be found Note: calling traverse with a path argument taken from an untrusted source, such as an HTTP request form variable, is a bad idea. It could allow a maliciously constructed request to call code unexpectedly. Consider using traverseName instead. """ def traverseName(obj, name, default=None, traversable=None, request=None): """Traverse a single step 'name' relative to the given object. 'name' must be a string. '.' and '..' are treated specially, as well as names starting with '@' or '+'. Otherwise 'name' will be treated as a single path segment. You can explicitly pass in an ITraversable as the 'traversable' argument. If you do not, the given object will be adapted to ITraversable. 'request' is passed in when traversing from presentation code. This allows paths like @@foo to work. Raises LocationError if path cannot be found and 'default' was not provided. """ def getName(obj): """Get the name an object was traversed via """ def getParent(obj): """Returns the container the object was traversed via. Returns None if the object is a containment root. Raises TypeError if the object doesn't have enough context to get the parent. """ def getParents(obj): """Returns a list starting with the given object's parent followed by each of its parents. Raises a TypeError if the context doesn't go all the way down to a containment root. """ def canonicalPath(path_or_object): """Returns a canonical absolute unicode path for the path or object. Resolves segments that are '.' or '..'. Raises ValueError if a badly formed path is given. """ class IPathAdapter(Interface): """Marker interface for adapters to be used in paths """ class IEtcNamespace(Interface): """Marker for utility registrations in the ++etc++ namespace """ class IBeforeTraverseEvent(IObjectEvent): """An event which gets sent on publication traverse""" request = Attribute("The current request") class BeforeTraverseEvent(object): """An event which gets sent on publication traverse""" implements(IBeforeTraverseEvent) def __init__(self, ob, request): self.object = ob self.request = request zope.traversing-3.14.0/src/zope/traversing/namespace.py0000644000000000000000000004147711401757504021344 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. # ############################################################################## """URL Namespace Implementations """ __docformat__ = 'restructuredtext' import re import zope.component import zope.interface from zope.i18n.interfaces import IModifiableUserPreferredLanguages from zope.component.interfaces import ComponentLookupError from zope.interface import providedBy, directlyProvides, directlyProvidedBy from zope.location.interfaces import IRoot, LocationError from zope.publisher.interfaces.browser import IBrowserSkinType from zope.publisher.skinnable import applySkin from zope.security.proxy import removeSecurityProxy from zope.traversing.interfaces import IEtcNamespace from zope.traversing.interfaces import IPathAdapter from zope.traversing.interfaces import ITraversable class UnexpectedParameters(LocationError): "Unexpected namespace parameters were provided." class ExcessiveDepth(LocationError): "Too many levels of containment. We don't believe them." def namespaceLookup(ns, name, object, request=None): """Lookup a value from a namespace We look up a value using a view or an adapter, depending on whether a request is passed. Let's start with adapter-based transersal: >>> class I(zope.interface.Interface): ... 'Test interface' >>> class C(object): ... zope.interface.implements(I) We'll register a simple testing adapter: >>> class Adapter(object): ... def __init__(self, context): ... self.context = context ... def traverse(self, name, remaining): ... return name+'42' >>> zope.component.provideAdapter(Adapter, (I,), ITraversable, 'foo') Then given an object, we can traverse it with a namespace-qualified name: >>> namespaceLookup('foo', 'bar', C()) 'bar42' If we give an invalid namespace, we'll get a not found error: >>> namespaceLookup('fiz', 'bar', C()) # doctest: +ELLIPSIS Traceback (most recent call last): ... LocationError: (, '++fiz++bar') We'll get the same thing if we provide a request: >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> namespaceLookup('foo', 'bar', C(), request) # doctest: +ELLIPSIS Traceback (most recent call last): ... LocationError: (, '++foo++bar') We need to provide a view: >>> class View(object): ... def __init__(self, context, request): ... pass ... def traverse(self, name, remaining): ... return name+'fromview' >>> from zope.traversing.testing import browserView >>> browserView(I, 'foo', View, providing=ITraversable) >>> namespaceLookup('foo', 'bar', C(), request) 'barfromview' Clean up: >>> from zope.testing.cleanup import cleanUp >>> cleanUp() """ if request is not None: traverser = zope.component.queryMultiAdapter((object, request), ITraversable, ns) else: traverser = zope.component.queryAdapter(object, ITraversable, ns) if traverser is None: raise LocationError(object, "++%s++%s" % (ns, name)) return traverser.traverse(name, ()) namespace_pattern = re.compile('[+][+]([a-zA-Z0-9_]+)[+][+]') def nsParse(name): """Parse a namespace-qualified name into a namespace name and a name. Returns the namespace name and a name. A namespace-qualified name is usually of the form ++ns++name, as in: >>> nsParse('++acquire++foo') ('acquire', 'foo') The part inside the +s must be an identifier, so: >>> nsParse('++hello world++foo') ('', '++hello world++foo') >>> nsParse('+++acquire+++foo') ('', '+++acquire+++foo') But it may also be a @@foo, which implies the view namespace: >>> nsParse('@@foo') ('view', 'foo') >>> nsParse('@@@foo') ('view', '@foo') >>> nsParse('@foo') ('', '@foo') """ ns = '' if name.startswith('@@'): ns = 'view' name = name[2:] else: match = namespace_pattern.match(name) if match: prefix, ns = match.group(0, 1) name = name[len(prefix):] return ns, name def getResource(site, name, request): resource = queryResource(site, name, request) if resource is None: raise LocationError(site, name) return resource def queryResource(site, name, request, default=None): resource = zope.component.queryAdapter(request, name=name) if resource is None: return default # We need to set the __parent__ and __name__. We need the unproxied # resource to do this. We still return the proxied resource. r = removeSecurityProxy(resource) r.__parent__ = site r.__name__ = name return resource # ---- namespace processors below ---- class SimpleHandler(object): zope.interface.implements(ITraversable) def __init__(self, context, request=None): """Simple handlers can be used as adapters or views They ignore their second constructor arg and store the first one in their context attr: >>> SimpleHandler(42).context 42 >>> SimpleHandler(42, 43).context 42 """ self.context = context class acquire(SimpleHandler): """Traversal adapter for the acquire namespace """ def traverse(self, name, remaining): """Acquire a name Let's set up some example data: >>> class testcontent(object): ... zope.interface.implements(ITraversable) ... def traverse(self, name, remaining): ... v = getattr(self, name, None) ... if v is None: ... raise LocationError(self, name) ... return v ... def __repr__(self): ... return 'splat' >>> ob = testcontent() >>> ob.a = 1 >>> ob.__parent__ = testcontent() >>> ob.__parent__.b = 2 >>> ob.__parent__.__parent__ = testcontent() >>> ob.__parent__.__parent__.c = 3 And acquire some names: >>> adapter = acquire(ob) >>> adapter.traverse('a', ()) 1 >>> adapter.traverse('b', ()) 2 >>> adapter.traverse('c', ()) 3 >>> adapter.traverse('d', ()) Traceback (most recent call last): ... LocationError: (splat, 'd') """ i = 0 ob = self.context while i < 200: i += 1 traversable = ITraversable(ob, None) if traversable is not None: try: # ??? what do we do if the path gets bigger? path = [] next = traversable.traverse(name, path) if path: continue except LocationError: pass else: return next ob = getattr(ob, '__parent__', None) if ob is None: raise LocationError(self.context, name) raise ExcessiveDepth(self.context, name) class attr(SimpleHandler): def traverse(self, name, ignored): """Attribute traversal adapter This adapter just provides traversal to attributes: >>> ob = {'x': 1} >>> adapter = attr(ob) >>> adapter.traverse('keys', ())() ['x'] """ return getattr(self.context, name) class item(SimpleHandler): def traverse(self, name, ignored): """Item traversal adapter This adapter just provides traversal to items: >>> ob = {'x': 42} >>> adapter = item(ob) >>> adapter.traverse('x', ()) 42 """ return self.context[name] class etc(SimpleHandler): def traverse(self, name, ignored): utility = zope.component.queryUtility(IEtcNamespace, name) if utility is not None: return utility ob = self.context if name not in ('site',): raise LocationError(ob, name) method_name = "getSiteManager" method = getattr(ob, method_name, None) if method is None: raise LocationError(ob, name) try: return method() except ComponentLookupError: raise LocationError(ob, name) class view(object): zope.interface.implements(ITraversable) def __init__(self, context, request): self.context = context self.request = request def traverse(self, name, ignored): view = zope.component.queryMultiAdapter((self.context, self.request), name=name) if view is None: raise LocationError(self.context, name) return view class resource(view): def traverse(self, name, ignored): # The context is important here, since it becomes the parent of the # resource, which is needed to generate the absolute URL. return getResource(self.context, name, self.request) class lang(view): def traverse(self, name, ignored): self.request.shiftNameToApplication() languages = IModifiableUserPreferredLanguages(self.request) languages.setPreferredLanguages([name]) return self.context class skin(view): def traverse(self, name, ignored): self.request.shiftNameToApplication() try: skin = zope.component.getUtility(IBrowserSkinType, name) except ComponentLookupError: raise LocationError("++skin++%s" % name) applySkin(self.request, skin) return self.context class vh(view): def traverse(self, name, ignored): request = self.request traversal_stack = request.getTraversalStack() app_names = [] name = name.encode('utf8') if name: try: proto, host, port = name.split(":") except ValueError: raise ValueError("Vhost directive should have the form " "++vh++protocol:host:port") request.setApplicationServer(host, proto, port) if '++' in traversal_stack: segment = traversal_stack.pop() while segment != '++': app_names.append(segment) segment = traversal_stack.pop() request.setTraversalStack(traversal_stack) else: raise ValueError( "Must have a path element '++' after a virtual host " "directive.") request.setVirtualHostRoot(app_names) return self.context class adapter(SimpleHandler): def traverse(self, name, ignored): """Adapter traversal adapter This adapter provides traversal to named adapters registered to provide IPathAdapter. To demonstrate this, we need to register some adapters: >>> def adapter1(ob): ... return 1 >>> def adapter2(ob): ... return 2 >>> zope.component.provideAdapter( ... adapter1, (None,), IPathAdapter, 'a1') >>> zope.component.provideAdapter( ... adapter2, (None,), IPathAdapter, 'a2') Now, with these adapters in place, we can use the traversal adapter: >>> ob = object() >>> adapter = adapter(ob) >>> adapter.traverse('a1', ()) 1 >>> adapter.traverse('a2', ()) 2 >>> try: ... adapter.traverse('bob', ()) ... except LocationError: ... print 'no adapter' no adapter Clean up: >>> from zope.testing.cleanup import cleanUp >>> cleanUp() """ try: return zope.component.getAdapter(self.context, IPathAdapter, name) except ComponentLookupError: raise LocationError(self.context, name) class debug(view): def traverse(self, name, ignored): """Debug traversal adapter This adapter allows debugging flags to be set in the request. See IDebugFlags. Setup for demonstration: >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> ob = object() >>> adapter = debug(ob, request) in debug mode, ++debug++source enables source annotations >>> request.debug.sourceAnnotations False >>> adapter.traverse('source', ()) is ob True >>> request.debug.sourceAnnotations True ++debug++tal enables TAL markup in output >>> request.debug.showTAL False >>> adapter.traverse('tal', ()) is ob True >>> request.debug.showTAL True ++debug++errors enables tracebacks (by switching to debug skin) >>> from zope.publisher.interfaces.browser import IBrowserRequest >>> class Debug(IBrowserRequest): ... pass >>> directlyProvides(Debug, IBrowserSkinType) >>> zope.component.provideUtility( ... Debug, IBrowserSkinType, name='Debug') >>> Debug.providedBy(request) False >>> adapter.traverse('errors', ()) is ob True >>> Debug.providedBy(request) True You can specify several flags separated by commas >>> adapter.traverse('source,tal', ()) is ob True Unknown flag names cause exceptions >>> try: ... adapter.traverse('badflag', ()) ... except ValueError: ... print 'unknown debugging flag' unknown debugging flag """ if __debug__: request = self.request for flag in name.split(','): if flag == 'source': request.debug.sourceAnnotations = True elif flag == 'tal': request.debug.showTAL = True elif flag == 'errors': # TODO: I am not sure this is the best solution. What # if we want to enable tracebacks when also trying to # debug a different skin? skin = zope.component.getUtility(IBrowserSkinType, 'Debug') directlyProvides(request, providedBy(request)+skin) else: raise ValueError("Unknown debug flag: %s" % flag) return self.context else: raise ValueError("Debug flags only allowed in debug mode") if not __debug__: # If not in debug mode, we should get an error: traverse.__doc__ = """Disabled debug traversal adapter This adapter allows debugging flags to be set in the request, but it is disabled because Python was run with -O. Setup for demonstration: >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> ob = object() >>> adapter = debug(ob, request) in debug mode, ++debug++source enables source annotations >>> request.debug.sourceAnnotations False >>> adapter.traverse('source', ()) is ob Traceback (most recent call last): ... ValueError: Debug flags only allowed in debug mode ++debug++tal enables TAL markup in output >>> request.debug.showTAL False >>> adapter.traverse('tal', ()) is ob Traceback (most recent call last): ... ValueError: Debug flags only allowed in debug mode ++debug++errors enables tracebacks (by switching to debug skin) >>> Debug.providedBy(request) False >>> adapter.traverse('errors', ()) is ob Traceback (most recent call last): ... ValueError: Debug flags only allowed in debug mode You can specify several flags separated by commas >>> adapter.traverse('source,tal', ()) is ob Traceback (most recent call last): ... ValueError: Debug flags only allowed in debug mode """ zope.traversing-3.14.0/src/zope/traversing/publicationtraverse.py0000644000000000000000000000776411401757504023476 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. # ############################################################################## """Publication Traverser """ __docformat__ = 'restructuredtext' from types import StringTypes from zope.component import queryMultiAdapter from zope.publisher.interfaces import NotFound from zope.security.checker import ProxyFactory from zope.traversing.namespace import namespaceLookup from zope.traversing.namespace import nsParse from zope.traversing.interfaces import TraversalError from zope.publisher.interfaces import IPublishTraverse from zope.publisher.interfaces.browser import IBrowserPublisher class PublicationTraverser(object): """Traversal used for publication. The significant differences from zope.traversing.adapters.traversePathElement() are: - Instead of adapting each traversed object to ITraversable, this version multi-adapts (ob, request) to IPublishTraverse. - This version wraps a security proxy around each traversed object. - This version raises NotFound rather than LocationError. - This version has a method, traverseRelativeURL(), that supports "browserDefault" traversal. """ def proxy(self, ob): return ProxyFactory(ob) def traverseName(self, request, ob, name): nm = name # the name to look up the object with if name and name[:1] in '@+': # Process URI segment parameters. ns, nm = nsParse(name) if ns: try: ob2 = namespaceLookup(ns, nm, ob, request) except TraversalError: raise NotFound(ob, name) return self.proxy(ob2) if nm == '.': return ob if IPublishTraverse.providedBy(ob): ob2 = ob.publishTraverse(request, nm) else: # self is marker adapter = queryMultiAdapter((ob, request), IPublishTraverse, default=self) if adapter is not self: ob2 = adapter.publishTraverse(request, nm) else: raise NotFound(ob, name, request) return self.proxy(ob2) def traversePath(self, request, ob, path): if isinstance(path, StringTypes): path = path.split('/') if len(path) > 1 and not path[-1]: # Remove trailing slash path.pop() else: path = list(path) # Remove single dots path = [x for x in path if x != '.'] path.reverse() # Remove double dots while '..' in path: l = path.index('..') if l < 0 or l+2 > len(path): break del path[l:l+2] pop = path.pop while path: name = pop() ob = self.traverseName(request, ob, name) return ob def traverseRelativeURL(self, request, ob, path): """Path traversal that includes browserDefault paths""" ob = self.traversePath(request, ob, path) while True: adapter = IBrowserPublisher(ob, None) if adapter is None: return ob ob, path = adapter.browserDefault(request) ob = self.proxy(ob) if not path: return ob ob = self.traversePath(request, ob, path) # alternate spelling PublicationTraverse = PublicationTraverser class PublicationTraverserWithoutProxy(PublicationTraverse): def proxy(self, ob): return ob zope.traversing-3.14.0/src/zope/traversing/testing.py0000644000000000000000000000473711401757504021063 0ustar 00000000000000############################################################################## # # Copyright (c) 2005 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. # ############################################################################## """Traversing test fixtures """ __docformat__ = "reStructuredText" import zope.component import zope.interface from zope.publisher.interfaces.browser import IDefaultBrowserLayer from zope.location.traversing \ import LocationPhysicallyLocatable, RootPhysicallyLocatable from zope.location.interfaces import ILocationInfo, IRoot from zope.traversing.interfaces import ITraversable, ITraverser from zope.traversing.adapters import DefaultTraversable from zope.traversing.adapters import Traverser from zope.traversing.browser import SiteAbsoluteURL, AbsoluteURL from zope.traversing.browser.interfaces import IAbsoluteURL from zope.traversing.namespace import etc def setUp(): zope.component.provideAdapter(Traverser, (None,), ITraverser) zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable) zope.component.provideAdapter(LocationPhysicallyLocatable, (None,), ILocationInfo) zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot,), ILocationInfo) # set up the 'etc' namespace zope.component.provideAdapter(etc, (None,), ITraversable, name="etc") zope.component.provideAdapter(etc, (None, None), ITraversable, name="etc") browserView(None, "absolute_url", AbsoluteURL) browserView(IRoot, "absolute_url", SiteAbsoluteURL) browserView(None, '', AbsoluteURL, providing=IAbsoluteURL) browserView(IRoot, '', SiteAbsoluteURL, providing=IAbsoluteURL) def browserView(for_, name, factory, providing=zope.interface.Interface): zope.component.provideAdapter(factory, (for_, IDefaultBrowserLayer), providing, name=name) def browserResource(name, factory, providing=zope.interface.Interface): zope.component.provideAdapter(factory, (IDefaultBrowserLayer,), providing, name=name) zope.traversing-3.14.0/src/zope/traversing/browser/__init__.py0000644000000000000000000000153511401757504022621 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 # ############################################################################## """Absolute URL View components """ from zope.traversing.browser.absoluteurl import absoluteURL from zope.traversing.browser.absoluteurl import AbsoluteURL from zope.traversing.browser.absoluteurl import SiteAbsoluteURL zope.traversing-3.14.0/src/zope/traversing/browser/absoluteurl.py0000644000000000000000000001261011415571436023422 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 # ############################################################################## """Absolute URL View components """ import urllib import zope.component from zope.interface import implements from zope.location.interfaces import ILocation from zope.proxy import sameProxiedObjects from zope.publisher.browser import BrowserView from zope.traversing.browser.interfaces import IAbsoluteURL from zope.i18nmessageid import MessageFactory _ = MessageFactory('zope') _insufficientContext = _("There isn't enough context to get URL information. " "This is probably due to a bug in setting up location " "information.") _safe = '@+' # Characters that we don't want to have quoted def absoluteURL(ob, request): return zope.component.getMultiAdapter((ob, request), IAbsoluteURL)() class AbsoluteURL(BrowserView): implements(IAbsoluteURL) def __unicode__(self): return urllib.unquote(self.__str__()).decode('utf-8') def __str__(self): context = self.context request = self.request # The application URL contains all the namespaces that are at the # beginning of the URL, such as skins, virtual host specifications and # so on. if (context is None or sameProxiedObjects(context, request.getVirtualHostRoot())): return request.getApplicationURL() # first try to get the __parent__ of the object, no matter whether # it provides ILocation or not. If this fails, look up an ILocation # adapter. This will always work, as a general ILocation adapter # is registered for interface in zope.location (a LocationProxy) # This proxy will return a parent of None, causing this to fail # More specific ILocation adapters can be provided however. try: container = context.__parent__ except AttributeError: # we need to assign to context here so we can get # __name__ from it below context = ILocation(context) container = context.__parent__ if container is None: raise TypeError(_insufficientContext) url = str(zope.component.getMultiAdapter((container, request), IAbsoluteURL)) name = getattr(context, '__name__', None) if name is None: raise TypeError(_insufficientContext) if name: url += '/' + urllib.quote(name.encode('utf-8'), _safe) return url def __call__(self): return self.__str__() def breadcrumbs(self): context = self.context request = self.request # We do this here do maintain the rule that we must be wrapped context = ILocation(context, context) container = getattr(context, '__parent__', None) if container is None: raise TypeError(_insufficientContext) if sameProxiedObjects(context, request.getVirtualHostRoot()) or \ isinstance(context, Exception): return ({'name':'', 'url': self.request.getApplicationURL()}, ) base = tuple(zope.component.getMultiAdapter( (container, request), IAbsoluteURL).breadcrumbs()) name = getattr(context, '__name__', None) if name is None: raise TypeError(_insufficientContext) if name: base += ({'name': name, 'url': ("%s/%s" % (base[-1]['url'], urllib.quote(name.encode('utf-8'), _safe))) }, ) return base class SiteAbsoluteURL(BrowserView): implements(IAbsoluteURL) def __unicode__(self): return urllib.unquote(self.__str__()).decode('utf-8') def __str__(self): context = self.context request = self.request if sameProxiedObjects(context, request.getVirtualHostRoot()): return request.getApplicationURL() url = request.getApplicationURL() name = getattr(context, '__name__', None) if name: url += '/' + urllib.quote(name.encode('utf-8'), _safe) return url def __call__(self): return self.__str__() def breadcrumbs(self): context = self.context request = self.request if sameProxiedObjects(context, request.getVirtualHostRoot()): return ({'name':'', 'url': self.request.getApplicationURL()}, ) base = ({'name':'', 'url': self.request.getApplicationURL()}, ) name = getattr(context, '__name__', None) if name: base += ({'name': name, 'url': ("%s/%s" % (base[-1]['url'], urllib.quote(name.encode('utf-8'), _safe))) }, ) return base zope.traversing-3.14.0/src/zope/traversing/browser/configure.zcml0000644000000000000000000000276311445373362023370 0ustar 00000000000000 zope.traversing-3.14.0/src/zope/traversing/browser/interfaces.py0000644000000000000000000000264011401757504023203 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 traversal interfaces """ from zope.interface import Interface class IAbsoluteURL(Interface): def __unicode__(): """Returns the URL as a unicode string.""" def __str__(): """Returns an ASCII string with all unicode characters url quoted.""" def __repr__(): """Get a string representation """ def __call__(): """Returns an ASCII string with all unicode characters url quoted.""" def breadcrumbs(): """Returns a tuple like ({'name':name, 'url':url}, ...) Name is the name to display for that segment of the breadcrumbs. URL is the link for that segment of the breadcrumbs. """ class IAbsoluteURLAPI(Interface): def absoluteURL(ob, request): """Compute the absolute URL of an object """ zope.traversing-3.14.0/src/zope/traversing/browser/tests.py0000644000000000000000000002761711415571436022240 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 the AbsoluteURL view """ from unittest import TestCase, main, makeSuite import zope.component from zope.component import getMultiAdapter, adapts from zope.component.testing import PlacelessSetup from zope.traversing.browser.absoluteurl import absoluteURL from zope.traversing.browser.interfaces import IAbsoluteURL from zope.traversing.testing import browserView from zope.i18n.interfaces import IUserPreferredCharsets from zope.interface import Interface, implements from zope.interface.verify import verifyObject from zope.publisher.browser import TestRequest from zope.publisher.http import IHTTPRequest, HTTPCharsets from zope.location.interfaces import ILocation from zope.location.location import LocationProxy from zope.container.contained import contained class IRoot(Interface): pass class Root(object): implements(IRoot) class TrivialContent(object): """Trivial content object, used because instances of object are rocks.""" class AdaptedContent(object): """A simple content object that has an ILocation adapter for it.""" class FooContent(object): """Class whose location will be provided by an adapter.""" class FooLocation(object): """Adapts FooAdapter to the ILocation protocol.""" implements(ILocation) adapts(FooContent) def __init__(self, context): self.context = context @property def __name__(self): return 'foo' @property def __parent__(self): return contained(TrivialContent(), Root(), name='bar') class TestAbsoluteURL(PlacelessSetup, TestCase): def setUp(self): PlacelessSetup.setUp(self) from zope.traversing.browser import AbsoluteURL, SiteAbsoluteURL browserView(None, 'absolute_url', AbsoluteURL) browserView(IRoot, 'absolute_url', SiteAbsoluteURL) browserView(None, '', AbsoluteURL, providing=IAbsoluteURL) browserView(IRoot, '', SiteAbsoluteURL, providing=IAbsoluteURL) zope.component.provideAdapter(FooLocation) zope.component.provideAdapter(HTTPCharsets, (IHTTPRequest,), IUserPreferredCharsets) # LocationProxy as set by zope.location # this makes a default LocationProxy for all objects that # don't define a more specific adapter zope.component.provideAdapter(LocationProxy, (Interface,), ILocation) def tearDown(self): PlacelessSetup.tearDown(self) def test_interface(self): request = TestRequest() content = contained(TrivialContent(), Root(), name='a') view = getMultiAdapter((content, request), name='absolute_url') verifyObject(IAbsoluteURL, view) def testBadObject(self): request = TestRequest() view = getMultiAdapter((42, request), name='absolute_url') self.assertRaises(TypeError, view.__str__) self.assertRaises(TypeError, absoluteURL, 42, request) def testNoContext(self): request = TestRequest() view = getMultiAdapter((Root(), request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1') self.assertEqual(absoluteURL(Root(), request), 'http://127.0.0.1') def testBasicContext(self): request = TestRequest() content = contained(TrivialContent(), Root(), name='a') content = contained(TrivialContent(), content, name='b') content = contained(TrivialContent(), content, name='c') view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/a/b/c') self.assertEqual(absoluteURL(content, request), 'http://127.0.0.1/a/b/c') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': 'http://127.0.0.1'}, {'name': 'a', 'url': 'http://127.0.0.1/a'}, {'name': 'b', 'url': 'http://127.0.0.1/a/b'}, {'name': 'c', 'url': 'http://127.0.0.1/a/b/c'}, )) def testParentButNoLocation(self): request = TestRequest() content1 = TrivialContent() content1.__parent__ = Root() content1.__name__ = 'a' content2 = TrivialContent() content2.__parent__ = content1 content2.__name__ = 'b' content3 = TrivialContent() content3.__parent__ = content2 content3.__name__ = 'c' view = getMultiAdapter((content3, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/a/b/c') self.assertEqual(absoluteURL(content3, request), 'http://127.0.0.1/a/b/c') def testAdaptedContext(self): request = TestRequest() content = FooContent() view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/bar/foo') self.assertEqual(absoluteURL(content, request), 'http://127.0.0.1/bar/foo') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': 'http://127.0.0.1'}, {'name': 'bar', 'url': 'http://127.0.0.1/bar'}, {'name': 'foo', 'url': 'http://127.0.0.1/bar/foo'}, )) def testParentTrumpsAdapter(self): # if we have a location adapter for a content object but # the object also has its own __parent__, this will trump the # adapter request = TestRequest() content = FooContent() content.__parent__ = Root() content.__name__ = 'foo' view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/foo') self.assertEqual(absoluteURL(content, request), 'http://127.0.0.1/foo') def testBasicContext_unicode(self): #Tests so that AbsoluteURL handle unicode names as well request = TestRequest() root = Root() root.__name__ = u'\u0439' content = contained(TrivialContent(), root, name=u'\u0442') content = contained(TrivialContent(), content, name=u'\u0435') content = contained(TrivialContent(), content, name=u'\u0441') view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81') self.assertEqual(view(), 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81') self.assertEqual(unicode(view), u'http://127.0.0.1/\u0439/\u0442/\u0435/\u0441') self.assertEqual(absoluteURL(content, request), 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': 'http://127.0.0.1'}, {'name': u'\u0439', 'url': 'http://127.0.0.1/%D0%B9'}, {'name': u'\u0442', 'url': 'http://127.0.0.1/%D0%B9/%D1%82'}, {'name': u'\u0435', 'url': 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5'}, {'name': u'\u0441', 'url': 'http://127.0.0.1/%D0%B9/%D1%82/%D0%B5/%D1%81'}, )) def testRetainSkin(self): request = TestRequest() request._traversed_names = ('a', 'b') request._app_names = ('++skin++test', ) content = contained(TrivialContent(), Root(), name='a') content = contained(TrivialContent(), content, name='b') content = contained(TrivialContent(), content, name='c') view = getMultiAdapter((content, request), name='absolute_url') base = 'http://127.0.0.1/++skin++test' self.assertEqual(str(view), base + '/a/b/c') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': base + ''}, {'name': 'a', 'url': base + '/a'}, {'name': 'b', 'url': base + '/a/b'}, {'name': 'c', 'url': base + '/a/b/c'}, )) def testVirtualHosting(self): request = TestRequest() vh_root = TrivialContent() content = contained(vh_root, Root(), name='a') request._vh_root = content content = contained(TrivialContent(), content, name='b') content = contained(TrivialContent(), content, name='c') view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/b/c') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': 'http://127.0.0.1'}, {'name': 'b', 'url': 'http://127.0.0.1/b'}, {'name': 'c', 'url': 'http://127.0.0.1/b/c'}, )) def testVirtualHostingWithVHElements(self): request = TestRequest() vh_root = TrivialContent() content = contained(vh_root, Root(), name='a') request._vh_root = content content = contained(TrivialContent(), content, name='b') content = contained(TrivialContent(), content, name='c') view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/b/c') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': 'http://127.0.0.1'}, {'name': 'b', 'url': 'http://127.0.0.1/b'}, {'name': 'c', 'url': 'http://127.0.0.1/b/c'}, )) def testVirtualHostingInFront(self): request = TestRequest() root = Root() request._vh_root = contained(root, root, name='') content = contained(root, None) content = contained(TrivialContent(), content, name='a') content = contained(TrivialContent(), content, name='b') content = contained(TrivialContent(), content, name='c') view = getMultiAdapter((content, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1/a/b/c') breadcrumbs = view.breadcrumbs() self.assertEqual(breadcrumbs, ({'name': '', 'url': 'http://127.0.0.1'}, {'name': 'a', 'url': 'http://127.0.0.1/a'}, {'name': 'b', 'url': 'http://127.0.0.1/a/b'}, {'name': 'c', 'url': 'http://127.0.0.1/a/b/c'}, )) def testNoContextInformation(self): request = TestRequest() view = getMultiAdapter((None, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1') self.assertEqual(absoluteURL(None, request), 'http://127.0.0.1') def testVirtualHostingWithoutContextInformation(self): request = TestRequest() request._vh_root = contained(TrivialContent(), Root(), name='a') view = getMultiAdapter((None, request), name='absolute_url') self.assertEqual(str(view), 'http://127.0.0.1') self.assertEqual(absoluteURL(None, request), 'http://127.0.0.1') def test_suite(): return makeSuite(TestAbsoluteURL) if __name__=='__main__': main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/__init__.py0000644000000000000000000000007510050206152022261 0ustar 00000000000000# # This file is necessary to make this directory a package. zope.traversing-3.14.0/src/zope/traversing/tests/ftesting.zcml0000644000000000000000000000265011445373362022704 0ustar 00000000000000 zope.traversing-3.14.0/src/zope/traversing/tests/test_conveniencefunctions.py0000644000000000000000000002525311401757504026030 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 traversal convenience functions. """ from unittest import TestCase, main, makeSuite import zope.component from zope.component.testing import PlacelessSetup from zope.interface import directlyProvides from zope.location.traversing \ import LocationPhysicallyLocatable, RootPhysicallyLocatable from zope.location.interfaces import ILocationInfo, IRoot, LocationError from zope.security.proxy import Proxy from zope.security.checker import selectChecker from zope.traversing.adapters import Traverser, DefaultTraversable from zope.traversing.interfaces import ITraversable, ITraverser from zope.container.contained import contained class C(object): __parent__ = None __name__ = None def __init__(self, name): self.name = name def _proxied(*args): return Proxy(args, selectChecker(args)) class Test(PlacelessSetup, TestCase): def setUp(self): PlacelessSetup.setUp(self) # Build up a wrapper chain root = C('root') directlyProvides(root, IRoot) folder = C('folder') item = C('item') self.root = root # root is not usually wrapped self.folder = contained(folder, self.root, name='folder') self.item = contained(item, self.folder, name='item') self.unwrapped_item = item self.broken_chain_folder = contained(folder, None) self.broken_chain_item = contained(item, self.broken_chain_folder, name='item' ) root.folder = folder folder.item = item self.tr = Traverser(root) zope.component.provideAdapter(Traverser, (None,), ITraverser) zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable) zope.component.provideAdapter(LocationPhysicallyLocatable, (None,), ILocationInfo) zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot,), ILocationInfo) def testTraverse(self): from zope.traversing.api import traverse self.assertEqual( traverse(self.item, '/folder/item'), self.tr.traverse('/folder/item') ) def testTraverseFromUnwrapped(self): from zope.traversing.api import traverse self.assertRaises( TypeError, traverse, self.unwrapped_item, '/folder/item' ) def testTraverseName(self): from zope.traversing.api import traverseName self.assertEqual( traverseName(self.folder, 'item'), self.tr.traverse('/folder/item') ) self.assertEqual( traverseName(self.item, '.'), self.tr.traverse('/folder/item') ) self.assertEqual( traverseName(self.item, '..'), self.tr.traverse('/folder') ) # TODO test that ++names++ and @@names work too def testTraverseNameBadValue(self): from zope.traversing.api import traverseName self.assertRaises( LocationError, traverseName, self.folder, '../root' ) self.assertRaises( LocationError, traverseName, self.folder, '/root' ) self.assertRaises( LocationError, traverseName, self.folder, './item' ) def testGetName(self): from zope.traversing.api import getName self.assertEqual( getName(self.item), 'item' ) def testGetParent(self): from zope.traversing.api import getParent self.assertEqual( getParent(self.item), self.folder ) def testGetParentFromRoot(self): from zope.traversing.api import getParent self.assertEqual( getParent(self.root), None ) def testGetParentBrokenChain(self): from zope.traversing.api import getParent self.assertRaises( TypeError, getParent, self.broken_chain_folder ) def testGetParentFromUnwrapped(self): from zope.traversing.api import getParent self.assertRaises( TypeError, getParent, self.unwrapped_item ) def testGetParents(self): from zope.traversing.api import getParents self.assertEqual( getParents(self.item), [self.folder, self.root] ) def testGetParentsBrokenChain(self): from zope.traversing.api import getParents self.assertRaises( TypeError, getParents, self.broken_chain_item ) def testGetPath(self): from zope.traversing.api import getPath self.assertEqual( getPath(self.item), u'/folder/item' ) def testGetPathOfRoot(self): from zope.traversing.api import getPath self.assertEqual( getPath(self.root), u'/', ) def testGetNameOfRoot(self): from zope.traversing.api import getName self.assertEqual( getName(self.root), u'', ) def testGetRoot(self): from zope.traversing.api import getRoot self.assertEqual( getRoot(self.item), self.root ) def testCanonicalPath(self): _bad_locations = ( (ValueError, '\xa323'), (ValueError, ''), (ValueError, '//'), (ValueError, '/foo//bar'), # regarding the next two errors: # having a trailing slash on a location is undefined. # we might want to give it a particular meaning for zope3 later # for now, it is an invalid location identifier (ValueError, '/foo/bar/'), (ValueError, 'foo/bar/'), (IndexError, '/a/../..'), (ValueError, '/a//v'), ) # sequence of N-tuples: # (loc_returned_as_string, input, input, ...) # The string and tuple are tested as input as well as being the # specification for output. _good_locations = ( # location returned as string ( u'/xx/yy/zz', # arguments to try in addition to the above '/xx/yy/zz', '/xx/./yy/ww/../zz', ), ( u'/xx/yy/zz', '/xx/yy/zz', ), ( u'/xx', '/xx', ), ( u'/', '/', ), ) from zope.traversing.api import canonicalPath for error_type, value in _bad_locations: self.assertRaises(error_type, canonicalPath, value) for spec in _good_locations: correct_answer = spec[0] for argument in spec: self.assertEqual(canonicalPath(argument), correct_answer, "failure on %s" % argument) def test_normalizePath(self): _bad_locations = ( (ValueError, '//'), (ValueError, '/foo//bar'), (IndexError, '/a/../..'), (IndexError, '/a/./../..'), ) # sequence of N-tuples: # (loc_returned_as_string, input, input, ...) # The string and tuple are tested as input as well as being the # specification for output. _good_locations = ( # location returned as string ( '/xx/yy/zz', # arguments to try in addition to the above '/xx/yy/zz', '/xx/./yy/ww/../zz', '/xx/./yy/ww/./../zz', ), ( 'xx/yy/zz', # arguments to try in addition to the above 'xx/yy/zz', 'xx/./yy/ww/../zz', 'xx/./yy/ww/./../zz', ), ( '/xx/yy/zz', '/xx/yy/zz', ), ( '/xx', '/xx', ), ( '/', '/', ), ) from zope.traversing.api import _normalizePath for error_type, value in _bad_locations: self.assertRaises(error_type, _normalizePath, value) for spec in _good_locations: correct_answer = spec[0] for argument in spec: self.assertEqual(_normalizePath(argument), correct_answer, "failure on %s" % argument) def test_joinPath_slashes(self): from zope.traversing.api import joinPath path = u'/' args = ('/test', 'bla', '/foo', 'bar') self.assertRaises(ValueError, joinPath, path, *args) args = ('/test', 'bla', 'foo/', '/bar') self.assertRaises(ValueError, joinPath, path, *args) def test_joinPath(self): from zope.traversing.api import joinPath path = u'/bla' args = ('foo', 'bar', 'baz', 'bone') self.assertEqual(joinPath(path, *args), u'/bla/foo/bar/baz/bone') path = u'bla' args = ('foo', 'bar', 'baz', 'bone') self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone') path = u'bla' args = ('foo', 'bar/baz', 'bone') self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone') path = u'bla/' args = ('foo', 'bar', 'baz', 'bone') self.assertRaises(ValueError, joinPath, path, *args) def test_joinPath_normalize(self): from zope.traversing.api import joinPath path = u'/bla' args = ('foo', 'bar', '..', 'baz', 'bone') self.assertEqual(joinPath(path, *args), u'/bla/foo/baz/bone') path = u'bla' args = ('foo', 'bar', '.', 'baz', 'bone') self.assertEqual(joinPath(path, *args), u'bla/foo/bar/baz/bone') path = u'/' args = ('foo', 'bar', '.', 'baz', 'bone') self.assertEqual(joinPath(path, *args), u'/foo/bar/baz/bone') def test_suite(): return makeSuite(Test) if __name__=='__main__': main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/test_dependencies.py0000644000000000000000000000140311445373774024233 0ustar 00000000000000import unittest import zope.component from zope.configuration.xmlconfig import XMLConfig from zope.publisher.browser import TestRequest from zope.traversing.interfaces import ITraversable class ZCMLDependencies(unittest.TestCase): def test_zcml_can_load(self): import zope.traversing XMLConfig('configure.zcml', zope.traversing)() request = TestRequest() res = zope.component.getMultiAdapter( (self, request), ITraversable, 'lang') import zope.traversing.namespace self.failUnless(isinstance(res, zope.traversing.namespace.lang)) self.failUnless(res.context is self) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ZCMLDependencies)) return suite zope.traversing-3.14.0/src/zope/traversing/tests/test_lang.py0000644000000000000000000000460411401757504022521 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 lang traversal. """ import unittest import zope.component from zope.annotation import IAttributeAnnotatable, IAnnotations from zope.annotation.attribute import AttributeAnnotations from zope.interface import directlyProvides from zope.publisher.browser import ModifiableBrowserLanguages from zope.publisher.interfaces.http import IHTTPRequest from zope.publisher.tests import test_browserlanguages from zope.i18n.interfaces import IModifiableUserPreferredLanguages from zope.traversing.namespace import lang from zope.testing.cleanup import CleanUp class TestRequest(test_browserlanguages.TestRequest): def shiftNameToApplication(self): self.shifted = True class Test(CleanUp, unittest.TestCase): def setUp(self): super(Test, self).setUp() self.request = TestRequest("en") directlyProvides(self.request, IHTTPRequest, IAttributeAnnotatable) zope.component.provideAdapter(AttributeAnnotations, (IAttributeAnnotatable,), IAnnotations) zope.component.provideAdapter(ModifiableBrowserLanguages, (IHTTPRequest,), IModifiableUserPreferredLanguages) def test_adapter(self): request = self.request browser_languages = IModifiableUserPreferredLanguages(request) self.failUnlessEqual(["en"], browser_languages.getPreferredLanguages()) ob = object() ob2 = lang(ob, request).traverse('ru', ()) self.failUnless(ob is ob2) self.failUnless(request.shifted) self.failUnlessEqual(["ru"], browser_languages.getPreferredLanguages()) def test_suite(): return unittest.makeSuite(Test) if __name__=='__main__': unittest.main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/test_namespacetrversal.py0000644000000000000000000000171711401757504025321 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 # ############################################################################## """Traversal Namespace Tests """ from unittest import main from doctest import DocTestSuite from zope.component.testing import setUp, tearDown def test_suite(): return DocTestSuite('zope.traversing.namespace', setUp=setUp, tearDown=tearDown) if __name__ == '__main__': main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/test_physicallocationadapters.py0000644000000000000000000000352711401757504026674 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. # ############################################################################## """Physical Location Adapter Tests """ from unittest import TestCase, main, makeSuite from zope.container.contained import contained from zope.interface import implements from zope.location.interfaces import ILocationInfo, IRoot from zope.site.site import LocalSiteManager from zope.site.site import SiteManagerContainer from zope.testing.cleanup import CleanUp import zope.traversing.testing class Root(object): implements(IRoot) __parent__ = None class C(object): pass class Test(CleanUp, TestCase): def test(self): zope.traversing.testing.setUp() root = Root() f1 = contained(C(), root, name='f1') f2 = contained(SiteManagerContainer(), f1, name='f2') f3 = contained(C(), f2, name='f3') adapter = ILocationInfo(f3) self.assertEqual(adapter.getPath(), '/f1/f2/f3') self.assertEqual(adapter.getName(), 'f3') self.assertEqual(adapter.getRoot(), root) self.assertEqual(adapter.getNearestSite(), root) f2.setSiteManager(LocalSiteManager(f2)) self.assertEqual(adapter.getNearestSite(), f2) def test_suite(): return makeSuite(Test) if __name__=='__main__': main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/test_presentation.py0000644000000000000000000000334711401757504024316 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 # ############################################################################## """Presentation Traverser Tests """ from unittest import TestCase, main, makeSuite from zope.testing.cleanup import CleanUp from zope.interface import Interface, implements from zope.publisher.browser import TestRequest from zope.traversing.namespace import view, resource from zope.traversing.testing import browserView, browserResource class IContent(Interface): pass class Content(object): implements(IContent) class Resource(object): def __init__(self, request): pass class View(object): def __init__(self, content, request): self.content = content class Test(CleanUp, TestCase): def testView(self): browserView(IContent, 'foo', View) ob = Content() v = view(ob, TestRequest()).traverse('foo', ()) self.assertEqual(v.__class__, View) def testResource(self): browserResource('foo', Resource) ob = Content() r = resource(ob, TestRequest()).traverse('foo', ()) self.assertEqual(r.__class__, Resource) def test_suite(): return makeSuite(Test) if __name__=='__main__': main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/test_publicationtraverse.py0000644000000000000000000001524711401757504025672 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. # ############################################################################## """Tests of PublicationTraverser """ from unittest import TestCase, main, makeSuite from zope.testing.cleanup import CleanUp from zope.component import provideAdapter from zope.interface import Interface, implements from zope.publisher.browser import TestRequest from zope.publisher.interfaces import IPublishTraverse from zope.publisher.interfaces import NotFound from zope.publisher.interfaces.browser import IBrowserPublisher from zope.security.proxy import removeSecurityProxy from zope.traversing.interfaces import ITraversable class TestPublicationTraverser(CleanUp, TestCase): def testViewNotFound(self): ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() self.assertRaises(NotFound, t.traverseName, request, ob, '@@foo') def testViewFound(self): provideAdapter(DummyViewTraverser, (Interface, Interface), ITraversable, name='view') ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() proxy = t.traverseName(request, ob, '@@foo') view = removeSecurityProxy(proxy) self.assertTrue(proxy is not view) self.assertEqual(view.__class__, View) self.assertEqual(view.name, 'foo') def testDot(self): ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() self.assertEqual(ob, t.traverseName(request, ob, '.')) def testNameNotFound(self): ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() self.assertRaises(NotFound, t.traverseName, request, ob, 'foo') def testNameFound(self): provideAdapter(DummyPublishTraverse, (Interface, Interface), IPublishTraverse) ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() proxy = t.traverseName(request, ob, 'foo') view = removeSecurityProxy(proxy) self.assertTrue(proxy is not view) self.assertEqual(view.__class__, View) self.assertEqual(view.name, 'foo') def testDirectTraversal(self): request = TestRequest() ob = DummyPublishTraverse(Content(), request) from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() proxy = t.traverseName(request, ob, 'foo') view = removeSecurityProxy(proxy) self.assertTrue(proxy is not view) self.assertEqual(view.__class__, View) self.assertEqual(view.name, 'foo') def testPathNotFound(self): ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() self.assertRaises(NotFound, t.traversePath, request, ob, 'foo/bar') def testPathFound(self): provideAdapter(DummyPublishTraverse, (Interface, Interface), IPublishTraverse) ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() proxy = t.traversePath(request, ob, 'foo/bar') view = removeSecurityProxy(proxy) self.assertTrue(proxy is not view) self.assertEqual(view.__class__, View) self.assertEqual(view.name, 'bar') def testComplexPath(self): provideAdapter(DummyPublishTraverse, (Interface, Interface), IPublishTraverse) ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() proxy = t.traversePath(request, ob, 'foo/../alpha//beta/./bar') view = removeSecurityProxy(proxy) self.assertTrue(proxy is not view) self.assertEqual(view.__class__, View) self.assertEqual(view.name, 'bar') def testTraverseRelativeURL(self): provideAdapter(DummyPublishTraverse, (Interface, Interface), IPublishTraverse) provideAdapter(DummyBrowserPublisher, (Interface,), IBrowserPublisher) ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() proxy = t.traverseRelativeURL(request, ob, 'foo/bar') view = removeSecurityProxy(proxy) self.assertTrue(proxy is not view) self.assertEqual(view.__class__, View) self.assertEqual(view.name, 'more') def testMissingSkin(self): ob = Content() from zope.traversing.publicationtraverse import PublicationTraverser t = PublicationTraverser() request = TestRequest() self.assertRaises( NotFound, t.traversePath, request, ob, '/++skin++missingskin') class IContent(Interface): pass class Content(object): implements(IContent) class View(object): def __init__(self, name): self.name = name class DummyViewTraverser(object): implements(ITraversable) def __init__(self, content, request): self.content = content def traverse(self, name, furtherPath): return View(name) class DummyPublishTraverse(object): implements(IPublishTraverse) def __init__(self, context, request): pass def publishTraverse(self, request, name): return View(name) class DummyBrowserPublisher(object): implements(IBrowserPublisher) def __init__(self, context): self.context = removeSecurityProxy(context) def browserDefault(self, request): if self.context.name != 'more': return self.context, ['more'] else: return self.context, () def test_suite(): return makeSuite(TestPublicationTraverser) if __name__ == '__main__': main() zope.traversing-3.14.0/src/zope/traversing/tests/test_skin.py0000644000000000000000000000363211401757504022544 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 skin traversal. """ from unittest import TestCase, main, makeSuite import zope.component from zope.testing.cleanup import CleanUp from zope.interface import Interface, directlyProvides from zope.publisher.interfaces.browser import IBrowserSkinType class FauxRequest(object): def shiftNameToApplication(self): self.shifted = 1 class IFoo(Interface): pass directlyProvides(IFoo, IBrowserSkinType) class Test(CleanUp, TestCase): def setUp(self): super(Test, self).setUp() zope.component.provideUtility(IFoo, IBrowserSkinType, name='foo') def test(self): from zope.traversing.namespace import skin request = FauxRequest() ob = object() ob2 = skin(ob, request).traverse('foo', ()) self.assertEqual(ob, ob2) self.assert_(IFoo.providedBy(request)) self.assertEqual(request.shifted, 1) def test_missing_skin(self): from zope.traversing.namespace import skin from zope.location.interfaces import LocationError request = FauxRequest() ob = object() traverser = skin(ob, request) self.assertRaises(LocationError, traverser.traverse, 'bar', ()) def test_suite(): return makeSuite(Test) if __name__=='__main__': main(defaultTest='test_suite') zope.traversing-3.14.0/src/zope/traversing/tests/test_traverser.py0000644000000000000000000002152511401757504023616 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. # ############################################################################## """Traverser Adapter tests. """ import unittest import zope.component from zope.component.testing import PlacelessSetup from zope.interface import directlyProvides, implementedBy from zope.interface.verify import verifyClass from zope.location.traversing \ import LocationPhysicallyLocatable, RootPhysicallyLocatable from zope.location.interfaces \ import ILocationInfo, IRoot, LocationError from zope.security.interfaces import Unauthorized from zope.security.checker \ import ProxyFactory, defineChecker, CheckerPublic, Checker from zope.security.management import newInteraction, endInteraction from zope.traversing.adapters import Traverser, DefaultTraversable from zope.traversing.interfaces import ITraversable, ITraverser from zope.container.contained import Contained, contained class ParticipationStub(object): def __init__(self, principal): self.principal = principal self.interaction = None class C(Contained): def __init__(self, name): self.name = name class TraverserTests(PlacelessSetup, unittest.TestCase): def setUp(self): PlacelessSetup.setUp(self) # Build up a wrapper chain self.root = C('root') self.folder = contained(C('folder'), self.root, name='folder') self.item = contained(C('item'), self.folder, name='item') self.tr = Traverser(self.item) def testImplementsITraverser(self): self.failUnless(ITraverser.providedBy(self.tr)) def testVerifyInterfaces(self): for interface in implementedBy(Traverser): verifyClass(interface, Traverser) class UnrestrictedNoTraverseTests(unittest.TestCase): def setUp(self): self.root = root = C('root') directlyProvides(self.root, IRoot) self.folder = folder = C('folder') self.item = item = C('item') root.folder = folder folder.item = item self.tr = Traverser(root) def testNoTraversable(self): self.assertRaises(LocationError, self.tr.traverse, 'folder') class UnrestrictedTraverseTests(PlacelessSetup, unittest.TestCase): def setUp(self): PlacelessSetup.setUp(self) zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable) zope.component.provideAdapter(LocationPhysicallyLocatable, (None,), ILocationInfo) zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot,), ILocationInfo) # Build up a wrapper chain self.root = root = C('root') directlyProvides(self.root, IRoot) self.folder = folder = contained(C('folder'), root, 'folder') self.item = item = contained(C('item'), folder, 'item') root.folder = folder folder.item = item self.tr = Traverser(root) def testSimplePathString(self): tr = self.tr item = self.item self.assertEquals(tr.traverse('/folder/item'), item) self.assertEquals(tr.traverse('folder/item'), item) self.assertEquals(tr.traverse('/folder/item/'), item) def testSimplePathUnicode(self): tr = self.tr item = self.item self.assertEquals(tr.traverse(u'/folder/item'), item) self.assertEquals(tr.traverse(u'folder/item'), item) self.assertEquals(tr.traverse(u'/folder/item/'), item) def testSimplePathTuple(self): tr = self.tr item = self.item self.assertEquals(tr.traverse(('', 'folder', 'item')), item) self.assertEquals(tr.traverse(('folder', 'item')), item) def testComplexPathString(self): tr = self.tr item = self.item self.assertEquals(tr.traverse('/folder/../folder/./item'), item) def testNotFoundDefault(self): self.assertEquals(self.tr.traverse('foo', 'notFound'), 'notFound') def testNotFoundNoDefault(self): self.assertRaises(LocationError, self.tr.traverse, 'foo') def testTraverseOldStyleClass(self): class AnOldStyleClass: x = object() container = {} container['theclass'] = AnOldStyleClass tr = Traverser(container) self.assert_(tr.traverse('theclass/x') is AnOldStyleClass.x) def testTraversingDictSeesDictAPI(self): adict = { 'foo': 'bar', 'anotherdict': {'bar': 'foo'}, 'items': '123', } tr = Traverser(adict) self.assertEqual(tr.traverse('items'), adict.items) self.assertEqual(tr.traverse('anotherdict/bar'), 'foo') self.assertEqual(tr.traverse('anotherdict/items'), adict['anotherdict'].items) def testTraversingDoesntFailOnStrings(self): adict = {'foo': 'bar'} tr = Traverser(adict) # This used to raise type error before self.assertRaises(LocationError, tr.traverse, 'foo/baz') class RestrictedTraverseTests(PlacelessSetup, unittest.TestCase): _oldPolicy = None _deniedNames = () def setUp(self): PlacelessSetup.setUp(self) zope.component.provideAdapter(DefaultTraversable, (None,), ITraversable) zope.component.provideAdapter(LocationPhysicallyLocatable, (None,), ILocationInfo) zope.component.provideAdapter(RootPhysicallyLocatable, (IRoot,), ILocationInfo) self.root = root = C('root') directlyProvides(root, IRoot) self.folder = folder = contained(C('folder'), root, 'folder') self.item = item = contained(C('item'), folder, 'item') root.folder = folder folder.item = item self.tr = Traverser(ProxyFactory(root)) def testAllAllowed(self): defineChecker(C, Checker({'folder': CheckerPublic, 'item': CheckerPublic, })) tr = Traverser(ProxyFactory(self.root)) item = self.item self.assertEquals(tr.traverse(('', 'folder', 'item')), item) self.assertEquals(tr.traverse(('folder', 'item')), item) def testItemDenied(self): endInteraction() newInteraction(ParticipationStub('no one')) defineChecker(C, Checker({'item': 'Waaaa', 'folder': CheckerPublic})) tr = Traverser(ProxyFactory(self.root)) folder = self.folder self.assertRaises(Unauthorized, tr.traverse, ('', 'folder', 'item')) self.assertRaises(Unauthorized, tr.traverse, ('folder', 'item')) self.assertEquals(tr.traverse(('', 'folder')), folder) self.assertEquals(tr.traverse(('folder', '..', 'folder')), folder) self.assertEquals(tr.traverse(('folder',)), folder) class DefaultTraversableTests(unittest.TestCase): def testImplementsITraversable(self): self.failUnless(ITraversable.providedBy(DefaultTraversable(None))) def testVerifyInterfaces(self): for interface in implementedBy(DefaultTraversable): verifyClass(interface, DefaultTraversable) def testAttributeTraverse(self): root = C('root') item = C('item') root.item = item df = DefaultTraversable(root) further = [] next = df.traverse('item', further) self.failUnless(next is item) self.assertEquals(further, []) def testDictionaryTraverse(self): dict = {} foo = C('foo') dict['foo'] = foo df = DefaultTraversable(dict) further = [] next = df.traverse('foo', further) self.failUnless(next is foo) self.assertEquals(further, []) def testNotFound(self): df = DefaultTraversable(C('dummy')) self.assertRaises(LocationError, df.traverse, 'bar', []) def test_suite(): loader = unittest.TestLoader() suite = loader.loadTestsFromTestCase(TraverserTests) suite.addTest(loader.loadTestsFromTestCase(DefaultTraversableTests)) suite.addTest(loader.loadTestsFromTestCase(UnrestrictedNoTraverseTests)) suite.addTest(loader.loadTestsFromTestCase(UnrestrictedTraverseTests)) suite.addTest(loader.loadTestsFromTestCase(RestrictedTraverseTests)) return suite if __name__=='__main__': unittest.TextTestRunner().run(test_suite()) zope.traversing-3.14.0/src/zope/traversing/tests/test_vh.py0000644000000000000000000000610511401757504022213 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. # ############################################################################## """Virtual hosting namespace tests. """ import unittest class TestRequest(object): def __init__(self, names=None, stack=None): self._traversal_stack = stack self._traversed_names = names self._app_server = 'http://server' self._app_url = '' def getTraversalStack(self): return list(self._traversal_stack) def setTraversalStack(self, stack): self._traversal_stack[:] = list(stack) def setApplicationServer(self, host, proto='http', port=None): host = "%s://%s" % (proto, host) if port: host = "%s:%s" % (host, port) self._app_server = host def setVirtualHostRoot(self, names=None): del self._traversed_names[:] self._app_names = names or [] class TestVHNamespace(unittest.TestCase): def test_vh(self): from zope.traversing.namespace import vh # GET /folder1/++vh++/x/y/z/++/folder1_1 request = TestRequest(['folder1'], ['folder1_1', '++', 'z', 'y', 'x']) ob = object() result = vh(ob, request).traverse('', ()) self.assertEqual(result, ob) self.assertEqual(request._traversal_stack, ['folder1_1']) self.assertEqual(request._traversed_names, []) self.assertEqual(request._app_names, ['x', 'y', 'z']) self.assertEqual(request._app_server, 'http://server') def test_vh_noPlusPlus(self): from zope.traversing.namespace import vh # GET /folder1/folder2/++vh++http:host:80/folder1_1 request = TestRequest(['folder1', 'folder2'], ['folder1_1']) ob = object() handler = vh(ob, request) self.assertRaises(ValueError, handler.traverse, 'http:host:80', ()) def test_vh_host(self): from zope.traversing.namespace import vh request = TestRequest(['folder1'], ['folder1_1', '++']) ob = object() result = vh(ob, request).traverse('http:www.fubarco.com:80', ()) self.assertEqual(request._app_server, 'http://www.fubarco.com:80') def test_unicode_vh_host(self): from zope.traversing.namespace import vh request = TestRequest(['folder1'], ['folder1_1', '++']) ob = object() result = vh(ob, request).traverse(u'http:www.fubarco.com:80', ()) assert(isinstance(request._app_server, str)) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestVHNamespace)) return suite if __name__ == '__main__': unittest.main() zope.traversing-3.14.0/src/zope/traversing/tests/test_vhosting.py0000644000000000000000000002451711401757504023446 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. # ############################################################################## """Functional tests for virtual hosting. """ import os import unittest from StringIO import StringIO import transaction from zope.browserresource.resource import Resource from zope.configuration import xmlconfig from zope.container.contained import Contained from zope.pagetemplate.pagetemplate import PageTemplate from zope.pagetemplate.engine import AppPT from zope.publisher.browser import BrowserRequest from zope.publisher.publish import publish from zope.publisher.skinnable import setDefaultSkin from zope.security.checker import defineChecker, NamesChecker, NoProxy from zope.security.checker import _checkers, undefineChecker from zope.site.folder import Folder from zope.site.folder import rootFolder from zope.testing.cleanup import cleanUp from zope.traversing.api import traverse from zope.traversing.testing import browserResource class MyObj(Contained): def __getitem__(self, key): return traverse(self, '/foo/bar/' + key) class MyPageTemplate(AppPT, PageTemplate): def pt_getContext(self, instance, request, **_kw): # instance is a View component namespace = super(MyPageTemplate, self).pt_getContext(**_kw) namespace['template'] = self namespace['request'] = request namespace['container'] = namespace['context'] = instance return namespace def render(self, instance, request, *args, **kw): return self.pt_render(self.pt_getContext(instance, request)) class MyPageEval(object): def index(self, **kw): """Call a Page Template""" template = self.context request = self.request return template.render(template.__parent__, request, **kw) class MyFolderPage(object): def index(self, **kw): """My folder page""" self.request.response.redirect('index.html') return '' class TestVirtualHosting(unittest.TestCase): def setUp(self): f = os.path.join(os.path.split(__file__)[0], 'ftesting.zcml') xmlconfig.file(f) self.app = rootFolder() defineChecker(MyObj, NoProxy) def tearDown(self): undefineChecker(MyObj) cleanUp() def makeRequest(self, path=''): env = {"HTTP_HOST": 'localhost', "HTTP_REFERER": 'localhost'} p = path.split('?') if len(p) == 1: env['PATH_INFO'] = p[0] request = BrowserRequest(StringIO(''), env) request.setPublication(DummyPublication(self.app)) setDefaultSkin(request) return request def publish(self, path): return publish(self.makeRequest(path)).response def test_request_url(self): self.addPage('/pt', u'') self.verify('/pt', 'http://localhost/pt/index.html') self.verify('/++vh++/++/pt', 'http://localhost/pt/index.html') self.verify('/++vh++https:localhost:443/++/pt', 'https://localhost/pt/index.html') self.verify('/++vh++https:localhost:443/fake/folders/++/pt', 'https://localhost/fake/folders/pt/index.html') self.addPage('/foo/bar/pt', u'') self.verify('/foo/bar/pt', 'http://localhost/foo/bar/pt/index.html') self.verify('/foo/bar/++vh++/++/pt', 'http://localhost/pt/index.html') self.verify('/foo/bar/++vh++https:localhost:443/++/pt', 'https://localhost/pt/index.html') self.verify('/foo/++vh++https:localhost:443/fake/folders/++/bar/pt', 'https://localhost/fake/folders/bar/pt/index.html') def test_request_redirect(self): self.addPage('/foo/index.html', u'Spam') self.verifyRedirect('/foo', 'http://localhost/foo/index.html') self.verifyRedirect('/++vh++https:localhost:443/++/foo', 'https://localhost/foo/index.html') self.verifyRedirect('/foo/++vh++https:localhost:443/bar/++', 'https://localhost/bar/index.html') def test_absolute_url(self): self.addPage('/pt', u'') self.verify('/pt', 'http://localhost') self.verify('/++vh++/++/pt', 'http://localhost') self.verify('/++vh++https:localhost:443/++/pt', 'https://localhost') self.verify('/++vh++https:localhost:443/fake/folders/++/pt', 'https://localhost/fake/folders') self.addPage('/foo/bar/pt', u'') self.verify('/foo/bar/pt', 'http://localhost/foo/bar') self.verify('/foo/bar/++vh++/++/pt', 'http://localhost') self.verify('/foo/bar/++vh++https:localhost:443/++/pt', 'https://localhost') self.verify('/foo/++vh++https:localhost:443/fake/folders/++/bar/pt', 'https://localhost/fake/folders/bar') def test_absolute_url_absolute_traverse(self): self.createObject('/foo/bar/obj', MyObj()) self.addPage('/foo/bar/pt', u'') self.verify('/foo/bar/pt', 'http://localhost/foo/bar/pt') self.verify('/foo/++vh++https:localhost:443/++/bar/pt', 'https://localhost/bar/pt') def test_resources(self): browserResource('quux', Resource) # Only register the checker once, so that multiple test runs pass. if Resource not in _checkers: defineChecker(Resource, NamesChecker(['__call__'])) self.addPage('/foo/bar/pt', u'') self.verify('/foo/bar/pt', 'http://localhost/@@/quux') self.verify('/foo/++vh++https:localhost:443/fake/folders/++/bar/pt', 'https://localhost/fake/folders/@@/quux') def createFolders(self, path): """addFolders('/a/b/c/d') would traverse and/or create three nested folders (a, b, c) and return a tuple (c, 'd') where c is a Folder instance at /a/b/c.""" folder = self.app #self.connection.root()['Application'] if path[0] == '/': path = path[1:] path = path.split('/') for id in path[:-1]: try: folder = folder[id] except KeyError: folder[id] = Folder() folder = folder[id] return folder, path[-1] def createObject(self, path, obj): folder, id = self.createFolders(path) folder[id] = obj transaction.commit() def addPage(self, path, content): page = MyPageTemplate() page.pt_edit(content, 'text/html') self.createObject(path, page) def verify(self, path, content): result = self.publish(path) self.assertEquals(result.getStatus(), 200) self.assertEquals(result.consumeBody(), content) def verifyRedirect(self, path, location): result = self.publish(path) self.assertEquals(result.getStatus(), 302) self.assertEquals(result.getHeader('Location'), location) class DummyPublication: def __init__(self, app): self.app = app def beforeTraversal(self, request): """Pre-traversal hook. This is called *once* before any traversal has been done. """ def getApplication(self, request): """Returns the object where traversal should commence. """ return self.app def callTraversalHooks(self, request, ob): """Invokes any traversal hooks associated with the object. This is called before traversing each object. The ob argument is the object that is about to be traversed. """ def traverseName(self, request, ob, name): """Traverses to the next object. Name must be an ASCII string or Unicode object.""" if name == 'index.html': from zope.component import queryMultiAdapter view = queryMultiAdapter((ob, request), name=name) if view is None: from zope.publisher.interfaces import NotFound raise NotFound(ob, name) return view else: from zope.traversing.publicationtraverse \ import PublicationTraverserWithoutProxy t = PublicationTraverserWithoutProxy() return t.traverseName(request, ob, name) def afterTraversal(self, request, ob): """Post-traversal hook. This is called after all traversal. """ def callObject(self, request, ob): """Call the object, returning the result. For GET/POST this means calling it, but for other methods (including those of WebDAV and FTP) this might mean invoking a method of an adapter. """ from zope.publisher.publish import mapply return mapply(ob, request.getPositionalArguments(), request) def afterCall(self, request, ob): """Post-callObject hook (if it was successful). """ def handleException(self, ob, request, exc_info, retry_allowed=1): """Handle an exception Either: - sets the body of the response, request.response, or - raises a Retry exception, or - throws another exception, which is a Bad Thing. """ import traceback traceback.print_exception(*exc_info) def endRequest(self, request, ob): """Do any end-of-request cleanup """ def getDefaultTraversal(self, request, ob): if hasattr(ob, 'index'): return ob, () else: return ob, ('index.html',) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestVirtualHosting)) return suite if __name__ == '__main__': unittest.main() zope.traversing-3.14.0/src/zope.traversing.egg-info/dependency_links.txt0000644000000000000000000000000111533525656024567 0ustar 00000000000000 zope.traversing-3.14.0/src/zope.traversing.egg-info/namespace_packages.txt0000644000000000000000000000000511533525656025047 0ustar 00000000000000zope zope.traversing-3.14.0/src/zope.traversing.egg-info/not-zip-safe0000644000000000000000000000000111533525412022735 0ustar 00000000000000 zope.traversing-3.14.0/src/zope.traversing.egg-info/PKG-INFO0000644000000000000000000002201711533525656021620 0ustar 00000000000000Metadata-Version: 1.0 Name: zope.traversing Version: 3.14.0 Summary: Resolving paths in the object hierarchy Home-page: http://pypi.python.org/pypi/zope.traversing Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: The ``zope.traversing`` package provides adapteres for resolving object paths by traversing an object hierarchy. This also includes support for traversal namespaces (e.g. ``++view++``, ``++skin++``, etc.) as well as computing URLs via the ``@@absolute_url`` view. ======= Changes ======= 3.14.0 (2011-03-02) ------------------- - Re-release of 3.13.1 as a feature version as it introduces dependencies on new feature releases. 3.13.1 (2010-12-14) ------------------- - Fixed ZCML-related dependencies. 3.13 (2010-07-09) ----------------- - When a ``__parent__`` attribute is available on an object, it is always used for absolute URL construction, and no ILocation adapter lookup is performed for it. This was the previous behavior but was broken (around 3.5?) due to dependency refactoring. If the object provides no ``__parent__`` then an ILocation adapter lookup will be performed. This will always succeed as zope.location provides a default LocationProxy for everything, but more specific ILocation adapters can also be provided. 3.12.1 (2010-04-30) ------------------- - Removed use of 'zope.testing.doctestunit' in favor of stdlib's doctest. 3.12.0 (2009-12-29) ------------------- - Avoid testing dependencies on zope.securitypolicies and zope.principalregistry. 3.11.0 (2009-12-27) ------------------- - Removed testing dependency on zope.app.publication. 3.10.0 (2009-12-16) ------------------- - Removed stray test claiming a no longer existing dependency on zope.app.applicationcontrol. - Refactored functional tests to loose dependency on both zope.app.appsetup and zope.app.testing. - Simplified tests for the browser sub-package by using PlacelessSetup from zope.component.testing instead of zope.app.testing. - Simplified test_dependencies module by using zope.configuration instead of zope.app.testing.functional. - Removed testing dependency on zope.app.publisher. - Replaced testing dependency on zope.app.security with zope.securitypolicy. - Removed testing dependency on zope.app.zcmlfiles in favor of more explicit dependencies. - Removed testing dependency on zope.app.component. - Replaced a test dependency on zope.app.zptpage with a dependency on zope.pagetemplate. 3.9.0 (2009-12-15) ------------------ - Moved IBeforeTraverseEvent from zope.app.publication into this package, as we already deal with publication traversal. 3.8.0 (2009-09-29) ------------------ - In zope.traversing.api.getParent(), try to delegate to zope.location.interfaces.ILocationInfo.getParent(), analogous to getParents(). Keep returning the traversal parent as a fallback. - Brought ITraverser back from zope.location where it had been moved to invert the package interdependency, but is no longer used now. 3.7.2 (2009-08-29) ------------------ - Made virtual hosting tests compatible with zope.publisher 3.9. Redirecting to a different host requires an explicit `trusted` redirect now. 3.7.1 (2009-06-16) ------------------ - AbsoluteURL now implements the fact that __call__ returns the same as __str__ in a manner that it applies for subclasses, too, so they only have to override __str__ and not both. 3.7.0 (2009-05-23) ------------------ - Moved the publicationtraverse module to zope.traversing, removing the zope.app.publisher -> zope.app.publication dependency (which was a cycle). - Look up the application controller through a utility registration rather than a direct reference. 3.6.0 (2009-04-06) ------------------ - Change configure.zcml to not depend on zope.app.component. - This release includes the BBB-incompatible ``zope.publisher.skinnable`` change from 3.5.3. 3.5.4 (2009-04-06) ------------------ - Revert BBB-incompatible use of ``zope.publisher.skinnable``: that change belongs in a 3.6.0 release, because it requires a BBB-incompatible version of ``zope.publisher``. 3.5.3 (2009-03-10) ------------------ - Use applySkin from new location. zope.publisher.skinnable instead of zope.publisher.browser. - Use IAbsoluteURL lookup instead of the "absolute_url" view in the recursive AbsoluteURL adapters (LP: #338101). 3.5.2 (2009-02-04) ------------------ - The RootPhysicallyLocatable is not the same as LocationPhysicallyLocatable now in zope.location. Fix the import and testing setups. 3.5.1 (2009-02-02) ------------------ - The ``RootPhysicallyLocatable`` adapter has been superseded by the refactored ``zope.location.traversing.LocationPhysicallyLocatable`` that we depend on since 3.5.0a4. Remove the adapter and its registration, and making its import place pointing to ``zope.location.traversing.LocationPhysicallyLocatable`` to maintain backward-compatibility. This also fixes a bug introduced in version 3.5.0a4 when trying to call ``getParents`` function for the root object. - Use direct imports instead of compatibility ones for things that were moved to ``zope.location``. - Remove the ``zope.traversing.interfaces.INamespaceHandler`` interface, as it seems not to be used for years. - Change package's mailing list address to zope-dev at zope.org instead of retired zope3-dev at zope.org 3.5.0 (2009-01-31) ------------------ - Use zope.container instead of zope.app.container. - Use zope.site instead of zope.app.folder in the unit tests. - Reduced, but did not eliminate, test dependencies on zope.app.component. 3.5.0a4 (2008-08-01) -------------------- - Reverse dependencies between zope.location and zope.traversing. - Updated (test) dependencies and tests to expect and work with a spec compliant TAL interpreter as available in zope.tal >= 3.5.0. - Fixed deprecation warning caused by using an old module name for ZopeSecurityPolicy in ftesting.zcml - Made sure traversing doesn't raise an TypeError but a TraversalError when the traversal step before yielded a string. 3.5.0a3 (2007-12-28) -------------------- - backed out the controversial `++skin++` traverser for XML-RPC. 3.5.0a2 (2007-11-28) -------------------- - ported 3.4.1a1 to trunk - Do not use unicode strings to set the application server in the virtual host namespace. This caused absolute_url to create unicode URL's. - Added a traverer for ++skin++ for XMLRPC skins (IXMLRPCSkinType). This also means that the normal ++skin++ namespace handler is only bound to IBrowserRequest. - Resolved the dependency on zope.app.applicationcontrol by importing the application controller only if the package is available. 3.4.1 (2008-07-30) ------------------ - Fixed deprecation warning caused by using an old module name for ZopeSecurityPolicy in ftesting.zcml 3.4.1a1 (2007-11-13) -------------------- Do not use unicode strings to set the application server in the virtual host namespace. This caused absolute_url to create unicode URL's. 3.4.0 (2007-09-29) ------------------ No further changes since 3.4.0a1. 3.4.0a1 (2007-04-22) -------------------- Initial release as a separate project, corresponds to zope.traversing from Zope 3.4.0a1 Platform: UNKNOWN zope.traversing-3.14.0/src/zope.traversing.egg-info/requires.txt0000644000000000000000000000051511533525656023122 0ustar 00000000000000setuptools zope.component zope.i18n zope.i18nmessageid zope.interface zope.proxy zope.publisher zope.security zope.location>=3.7.0 [test] zope.browserpage zope.browserresource[zcml]>=3.12 zope.component[zcml] zope.configuration zope.container zope.pagetemplate zope.security[zcml]>=3.8 zope.site zope.tal >= 3.5.0 zope.testing ZODB3zope.traversing-3.14.0/src/zope.traversing.egg-info/SOURCES.txt0000644000000000000000000000270611533525656022412 0ustar 00000000000000CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.traversing.egg-info/PKG-INFO src/zope.traversing.egg-info/SOURCES.txt src/zope.traversing.egg-info/dependency_links.txt src/zope.traversing.egg-info/namespace_packages.txt src/zope.traversing.egg-info/not-zip-safe src/zope.traversing.egg-info/requires.txt src/zope.traversing.egg-info/top_level.txt src/zope/traversing/__init__.py src/zope/traversing/adapters.py src/zope/traversing/api.py src/zope/traversing/configure.zcml src/zope/traversing/interfaces.py src/zope/traversing/namespace.py src/zope/traversing/publicationtraverse.py src/zope/traversing/testing.py src/zope/traversing/browser/__init__.py src/zope/traversing/browser/absoluteurl.py src/zope/traversing/browser/configure.zcml src/zope/traversing/browser/interfaces.py src/zope/traversing/browser/tests.py src/zope/traversing/tests/__init__.py src/zope/traversing/tests/ftesting.zcml src/zope/traversing/tests/test_conveniencefunctions.py src/zope/traversing/tests/test_dependencies.py src/zope/traversing/tests/test_lang.py src/zope/traversing/tests/test_namespacetrversal.py src/zope/traversing/tests/test_physicallocationadapters.py src/zope/traversing/tests/test_presentation.py src/zope/traversing/tests/test_publicationtraverse.py src/zope/traversing/tests/test_skin.py src/zope/traversing/tests/test_traverser.py src/zope/traversing/tests/test_vh.py src/zope/traversing/tests/test_vhosting.pyzope.traversing-3.14.0/src/zope.traversing.egg-info/top_level.txt0000644000000000000000000000000511533525656023246 0ustar 00000000000000zope