zope.app.publication-3.14.0/0000755000175000017500000000000011726417516015171 5ustar adiadi00000000000000zope.app.publication-3.14.0/setup.cfg0000644000175000017500000000007311726417516017012 0ustar adiadi00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.app.publication-3.14.0/PKG-INFO0000644000175000017500000001634511726417516016277 0ustar adiadi00000000000000Metadata-Version: 1.0 Name: zope.app.publication Version: 3.14.0 Summary: Zope publication Home-page: http://pypi.python.org/pypi/zope.app.publication Author: Zope Corporation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: Publication and traversal components. ======= CHANGES ======= 3.14.0 (2012-03-09) ------------------- - Replace ZODB.POSException.ConflictError with transaction.interfaces.TransientError. The latter should be a more generic signal to retry a transaction/request. This requires ZODB3 >= 3.10.0 and transaction >= 1.1.0. - Get rid of ZODB dependency. 3.13.2 (2011-08-04) ------------------- - Add missing test dependency on zope.testing. - Remove test dependency on zope.app.exception. 3.13.1 (2011-03-14) ------------------- - Test fix: HTTP request should not have leading whitespace. 3.13.0 (2011-01-25) ------------------- - Reenabled a test which makes sure ``405 MethodNotAllowed`` is returned when PUT is not supported. This requires at least version 3.10 of `zope.app.http`. 3.12.0 (2010-09-14) ------------------- - Use the standard libraries doctest module. - Include the ``notfound.txt`` test again but reduce its scope to functionality relevant to this distribution. - Notify with IStartRequestEvent at the start of the request publication cycle. 3.11.1 (2010-04-19) ------------------- - Fix up tests to work with newer zope.app.wsgi release (3.9.0). 3.11.0 (2010-04-13) ------------------- - Don't depend on zope.app.testing and zope.app.zcmlfiles anymore in the tests. 3.10.2 (2010-01-08) ------------------- - Lift the test dependency on zope.app.zptpage. 3.10.1 (2010-01-08) ------------------- - make zope.testing an optional (test) dependency - Fix tests using a newer zope.publisher that requires zope.login. 3.10.0 (2009-12-15) ------------------- - Moved EndRequestEvent and IEndRequestEvent to zope.publisher. - Moved BeforeTraverseEvent and IBeforeTraverseEvent to zope.traversing. - Removed dependency on zope.i18n. - Import hooks functionality from zope.component after it was moved there from zope.site. - Import ISite from zope.component after it was moved there from zope.location. 3.9.0 (2009-09-29) ------------------ - An abort within handleExceptions could have failed without logging what caused the error. It now logs the original problem. - Moved registration of and tests for two publication-specific event handlers here from zope.site in order to invert the package dependency. - Declared the missing dependency on zope.location. 3.8.1 (2009-06-21) ------------------ - Bug fix: The publication traverseName method used ProxyFactory rather than the publication proxy method. 3.8.0 (2009-06-20) ------------------ - Added a proxy method that can be overridden in subclasses to control how/if security proxies are created. - Replaced zope.deprecation dependency with backward-compatible imports 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). - Moved IHTTPException to zope.publisher, removing the dependency on zope.app.http. - Moved the DefaultViewName API from zope.app.publisher.browser to zope.publisher.defaultview, making it accessible to other packages that need it. - Look up the application controller through a utility registration rather than a direct reference. 3.6.0 (2009-05-18) ------------------ - Use ``zope:adapter`` ZCML directive instead of ``zope:view``. This avoid dependency on ``zope.app.component``. - Update imports from ``zope.app.security`` to ``zope.authentication`` and ``zope.principalregistry``. - Use ``zope.browser.interfaces.ISystemError`` to avoid dependency on ``zope.app.exception``. - Refactored tests so they can run successfully with ZODB 3.8 and 3.9. 3.5.3 (2009-03-13) ------------------ - Adapt to the removal of IXMLPresentation from zope.app.publisher which was removed to adapt to removal of deprecated interfaces from zope.component. 3.5.2 (2009-03-10) ------------------ - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition for calling setDefaultSkin. This at the same time removes dependency to the browser part of zope.publisher. - Remove deprecated code. - Use built-in set class instead of the deprecated sets.Set and thus don't cause deprecation warning in Python 2.6. 3.5.1 (2009-01-31) ------------------ - Import ISite from zope.location.interfaces instead of deprecated place in zope.app.component.interfaces. 3.5.0 (2008-10-09) ------------------ - Now ``zope.app.publication.zopepublication.ZopePublication`` annotates the request with the connection to the main ZODB when ``getApplication`` is called. - Removed support for non-existent Zope versions. 3.4.3 (2007-11-01) ------------------ - Removed unused imports. - Resolve ``ZopeSecurityPolicy`` deprecation warning. 3.4.2 (2007-09-26) ------------------ - Added missing files to egg distribution. 3.4.1 (2007-09-26) ------------------ - Added missing files to egg distribution. 3.4.0 (2007-09-25) ------------------ - Initial documented release. - Reflect changes form ``zope.app.error`` refactoring. Keywords: zope publication Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.app.publication-3.14.0/setup.py0000644000175000017500000000602411726417511016700 0ustar adiadi00000000000000############################################################################## # # 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. ############################################################################## version = '3.14.0' import os from setuptools import setup, find_packages def read(*rnames): return open(os.path.join(os.path.dirname(__file__), *rnames)).read() setup(name='zope.app.publication', version=version, author='Zope Corporation and Contributors', author_email='zope-dev@zope.org', description='Zope publication', long_description=( read('README.txt') + '\n\n' + read('CHANGES.txt') ), license='ZPL 2.1', keywords = "zope publication", classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Natural Language :: English', 'Operating System :: OS Independent', 'Topic :: Internet :: WWW/HTTP', 'Framework :: Zope3'], url='http://pypi.python.org/pypi/zope.app.publication', packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope', 'zope.app'], extras_require = dict( test=['zope.annotation', 'zope.app.appsetup >= 3.14.0', 'zope.app.http >= 3.10', 'zope.app.wsgi <3.11, >= 3.12', 'zope.applicationcontrol>=3.5.0', 'zope.browserpage', 'zope.login', 'zope.password', 'zope.principalregistry', 'zope.security', 'zope.securitypolicy', 'zope.site', 'zope.testing', 'ZODB3>=3.10']), install_requires=['zope.interface', 'zope.authentication', 'zope.component', 'zope.error', 'zope.browser>=1.2', 'zope.location', 'zope.publisher>=3.12.4', 'zope.traversing>=3.9.0', 'transaction>=1.1.0', 'setuptools', ], include_package_data = True, zip_safe = False, ) zope.app.publication-3.14.0/buildout.cfg0000644000175000017500000000026211726417511017474 0ustar adiadi00000000000000[buildout] develop = . parts = test py [test] recipe = zc.recipe.testrunner eggs = zope.app.publication [test] [py] recipe = zc.recipe.egg eggs = ${test:eggs} interpreter = py zope.app.publication-3.14.0/bootstrap.py0000644000175000017500000000330211726417511017551 0ustar adiadi00000000000000############################################################################## # # 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 tmpeggs = tempfile.mkdtemp() ez = {} exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' ).read() in ez ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) import pkg_resources cmd = 'from setuptools.command.easy_install import main; main()' if sys.platform == 'win32': cmd = '"%s"' % cmd # work around spawn lamosity on windows ws = pkg_resources.working_set assert os.spawnle( os.P_WAIT, sys.executable, sys.executable, '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout', dict(os.environ, PYTHONPATH= ws.find(pkg_resources.Requirement.parse('setuptools')).location ), ) == 0 ws.add_entry(tmpeggs) ws.require('zc.buildout') import zc.buildout.buildout zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap']) shutil.rmtree(tmpeggs) zope.app.publication-3.14.0/README.txt0000644000175000017500000000004511726417511016661 0ustar adiadi00000000000000Publication and traversal components.zope.app.publication-3.14.0/LICENSE.txt0000644000175000017500000000402611726417511017011 0ustar adiadi00000000000000Zope 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.app.publication-3.14.0/COPYRIGHT.txt0000644000175000017500000000004011726417511017267 0ustar adiadi00000000000000Zope Foundation and Contributorszope.app.publication-3.14.0/CHANGES.txt0000644000175000017500000001162411726417511017001 0ustar adiadi00000000000000======= CHANGES ======= 3.14.0 (2012-03-09) ------------------- - Replace ZODB.POSException.ConflictError with transaction.interfaces.TransientError. The latter should be a more generic signal to retry a transaction/request. This requires ZODB3 >= 3.10.0 and transaction >= 1.1.0. - Get rid of ZODB dependency. 3.13.2 (2011-08-04) ------------------- - Add missing test dependency on zope.testing. - Remove test dependency on zope.app.exception. 3.13.1 (2011-03-14) ------------------- - Test fix: HTTP request should not have leading whitespace. 3.13.0 (2011-01-25) ------------------- - Reenabled a test which makes sure ``405 MethodNotAllowed`` is returned when PUT is not supported. This requires at least version 3.10 of `zope.app.http`. 3.12.0 (2010-09-14) ------------------- - Use the standard libraries doctest module. - Include the ``notfound.txt`` test again but reduce its scope to functionality relevant to this distribution. - Notify with IStartRequestEvent at the start of the request publication cycle. 3.11.1 (2010-04-19) ------------------- - Fix up tests to work with newer zope.app.wsgi release (3.9.0). 3.11.0 (2010-04-13) ------------------- - Don't depend on zope.app.testing and zope.app.zcmlfiles anymore in the tests. 3.10.2 (2010-01-08) ------------------- - Lift the test dependency on zope.app.zptpage. 3.10.1 (2010-01-08) ------------------- - make zope.testing an optional (test) dependency - Fix tests using a newer zope.publisher that requires zope.login. 3.10.0 (2009-12-15) ------------------- - Moved EndRequestEvent and IEndRequestEvent to zope.publisher. - Moved BeforeTraverseEvent and IBeforeTraverseEvent to zope.traversing. - Removed dependency on zope.i18n. - Import hooks functionality from zope.component after it was moved there from zope.site. - Import ISite from zope.component after it was moved there from zope.location. 3.9.0 (2009-09-29) ------------------ - An abort within handleExceptions could have failed without logging what caused the error. It now logs the original problem. - Moved registration of and tests for two publication-specific event handlers here from zope.site in order to invert the package dependency. - Declared the missing dependency on zope.location. 3.8.1 (2009-06-21) ------------------ - Bug fix: The publication traverseName method used ProxyFactory rather than the publication proxy method. 3.8.0 (2009-06-20) ------------------ - Added a proxy method that can be overridden in subclasses to control how/if security proxies are created. - Replaced zope.deprecation dependency with backward-compatible imports 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). - Moved IHTTPException to zope.publisher, removing the dependency on zope.app.http. - Moved the DefaultViewName API from zope.app.publisher.browser to zope.publisher.defaultview, making it accessible to other packages that need it. - Look up the application controller through a utility registration rather than a direct reference. 3.6.0 (2009-05-18) ------------------ - Use ``zope:adapter`` ZCML directive instead of ``zope:view``. This avoid dependency on ``zope.app.component``. - Update imports from ``zope.app.security`` to ``zope.authentication`` and ``zope.principalregistry``. - Use ``zope.browser.interfaces.ISystemError`` to avoid dependency on ``zope.app.exception``. - Refactored tests so they can run successfully with ZODB 3.8 and 3.9. 3.5.3 (2009-03-13) ------------------ - Adapt to the removal of IXMLPresentation from zope.app.publisher which was removed to adapt to removal of deprecated interfaces from zope.component. 3.5.2 (2009-03-10) ------------------ - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition for calling setDefaultSkin. This at the same time removes dependency to the browser part of zope.publisher. - Remove deprecated code. - Use built-in set class instead of the deprecated sets.Set and thus don't cause deprecation warning in Python 2.6. 3.5.1 (2009-01-31) ------------------ - Import ISite from zope.location.interfaces instead of deprecated place in zope.app.component.interfaces. 3.5.0 (2008-10-09) ------------------ - Now ``zope.app.publication.zopepublication.ZopePublication`` annotates the request with the connection to the main ZODB when ``getApplication`` is called. - Removed support for non-existent Zope versions. 3.4.3 (2007-11-01) ------------------ - Removed unused imports. - Resolve ``ZopeSecurityPolicy`` deprecation warning. 3.4.2 (2007-09-26) ------------------ - Added missing files to egg distribution. 3.4.1 (2007-09-26) ------------------ - Added missing files to egg distribution. 3.4.0 (2007-09-25) ------------------ - Initial documented release. - Reflect changes form ``zope.app.error`` refactoring. zope.app.publication-3.14.0/src/0000755000175000017500000000000011726417516015760 5ustar adiadi00000000000000zope.app.publication-3.14.0/src/zope.app.publication.egg-info/0000755000175000017500000000000011726417516023516 5ustar adiadi00000000000000zope.app.publication-3.14.0/src/zope.app.publication.egg-info/top_level.txt0000644000175000017500000000000511726417515026242 0ustar adiadi00000000000000zope zope.app.publication-3.14.0/src/zope.app.publication.egg-info/requires.txt0000644000175000017500000000066411726417515026123 0ustar adiadi00000000000000zope.interface zope.authentication zope.component zope.error zope.browser>=1.2 zope.location zope.publisher>=3.12.4 zope.traversing>=3.9.0 transaction>=1.1.0 setuptools [test] zope.annotation zope.app.appsetup >= 3.14.0 zope.app.http >= 3.10 zope.app.wsgi <3.11, >= 3.12 zope.applicationcontrol>=3.5.0 zope.browserpage zope.login zope.password zope.principalregistry zope.security zope.securitypolicy zope.site zope.testing ZODB3>=3.10zope.app.publication-3.14.0/src/zope.app.publication.egg-info/not-zip-safe0000644000175000017500000000000111726417511025737 0ustar adiadi00000000000000 zope.app.publication-3.14.0/src/zope.app.publication.egg-info/namespace_packages.txt0000644000175000017500000000001611726417515030045 0ustar adiadi00000000000000zope zope.app zope.app.publication-3.14.0/src/zope.app.publication.egg-info/dependency_links.txt0000644000175000017500000000000111726417515027563 0ustar adiadi00000000000000 zope.app.publication-3.14.0/src/zope.app.publication.egg-info/SOURCES.txt0000644000175000017500000000415211726417515025403 0ustar adiadi00000000000000CHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.app.publication.egg-info/PKG-INFO src/zope.app.publication.egg-info/SOURCES.txt src/zope.app.publication.egg-info/dependency_links.txt src/zope.app.publication.egg-info/namespace_packages.txt src/zope.app.publication.egg-info/not-zip-safe src/zope.app.publication.egg-info/requires.txt src/zope.app.publication.egg-info/top_level.txt src/zope/app/__init__.py src/zope/app/publication/__init__.py src/zope/app/publication/browser.py src/zope/app/publication/configure.zcml src/zope/app/publication/ftesting.zcml src/zope/app/publication/ftp.py src/zope/app/publication/http.py src/zope/app/publication/httpfactory.py src/zope/app/publication/httpfactory.txt src/zope/app/publication/interfaces.py src/zope/app/publication/meta.zcml src/zope/app/publication/metaconfigure.py src/zope/app/publication/metadirectives.py src/zope/app/publication/methodnotallowed.txt src/zope/app/publication/notfound.txt src/zope/app/publication/publicationtraverse.py src/zope/app/publication/requestpublicationfactories.py src/zope/app/publication/requestpublicationregistry.py src/zope/app/publication/site.txt src/zope/app/publication/soap.py src/zope/app/publication/testing.py src/zope/app/publication/traversers.py src/zope/app/publication/xmlrpc.py src/zope/app/publication/zopepublication.py src/zope/app/publication/tests/__init__.py src/zope/app/publication/tests/ftest_zcml_dependencies.zcml src/zope/app/publication/tests/support.py src/zope/app/publication/tests/test_browserpublication.py src/zope/app/publication/tests/test_dependencies.py src/zope/app/publication/tests/test_functional.py src/zope/app/publication/tests/test_http.py src/zope/app/publication/tests/test_httpfactory.py src/zope/app/publication/tests/test_proxycontrol.py src/zope/app/publication/tests/test_requestpublicationfactories.py src/zope/app/publication/tests/test_requestpublicationregistry.py src/zope/app/publication/tests/test_simplecomponenttraverser.py src/zope/app/publication/tests/test_xmlrpcpublication.py src/zope/app/publication/tests/test_zopepublication.pyzope.app.publication-3.14.0/src/zope.app.publication.egg-info/PKG-INFO0000644000175000017500000001634511726417515024623 0ustar adiadi00000000000000Metadata-Version: 1.0 Name: zope.app.publication Version: 3.14.0 Summary: Zope publication Home-page: http://pypi.python.org/pypi/zope.app.publication Author: Zope Corporation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: Publication and traversal components. ======= CHANGES ======= 3.14.0 (2012-03-09) ------------------- - Replace ZODB.POSException.ConflictError with transaction.interfaces.TransientError. The latter should be a more generic signal to retry a transaction/request. This requires ZODB3 >= 3.10.0 and transaction >= 1.1.0. - Get rid of ZODB dependency. 3.13.2 (2011-08-04) ------------------- - Add missing test dependency on zope.testing. - Remove test dependency on zope.app.exception. 3.13.1 (2011-03-14) ------------------- - Test fix: HTTP request should not have leading whitespace. 3.13.0 (2011-01-25) ------------------- - Reenabled a test which makes sure ``405 MethodNotAllowed`` is returned when PUT is not supported. This requires at least version 3.10 of `zope.app.http`. 3.12.0 (2010-09-14) ------------------- - Use the standard libraries doctest module. - Include the ``notfound.txt`` test again but reduce its scope to functionality relevant to this distribution. - Notify with IStartRequestEvent at the start of the request publication cycle. 3.11.1 (2010-04-19) ------------------- - Fix up tests to work with newer zope.app.wsgi release (3.9.0). 3.11.0 (2010-04-13) ------------------- - Don't depend on zope.app.testing and zope.app.zcmlfiles anymore in the tests. 3.10.2 (2010-01-08) ------------------- - Lift the test dependency on zope.app.zptpage. 3.10.1 (2010-01-08) ------------------- - make zope.testing an optional (test) dependency - Fix tests using a newer zope.publisher that requires zope.login. 3.10.0 (2009-12-15) ------------------- - Moved EndRequestEvent and IEndRequestEvent to zope.publisher. - Moved BeforeTraverseEvent and IBeforeTraverseEvent to zope.traversing. - Removed dependency on zope.i18n. - Import hooks functionality from zope.component after it was moved there from zope.site. - Import ISite from zope.component after it was moved there from zope.location. 3.9.0 (2009-09-29) ------------------ - An abort within handleExceptions could have failed without logging what caused the error. It now logs the original problem. - Moved registration of and tests for two publication-specific event handlers here from zope.site in order to invert the package dependency. - Declared the missing dependency on zope.location. 3.8.1 (2009-06-21) ------------------ - Bug fix: The publication traverseName method used ProxyFactory rather than the publication proxy method. 3.8.0 (2009-06-20) ------------------ - Added a proxy method that can be overridden in subclasses to control how/if security proxies are created. - Replaced zope.deprecation dependency with backward-compatible imports 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). - Moved IHTTPException to zope.publisher, removing the dependency on zope.app.http. - Moved the DefaultViewName API from zope.app.publisher.browser to zope.publisher.defaultview, making it accessible to other packages that need it. - Look up the application controller through a utility registration rather than a direct reference. 3.6.0 (2009-05-18) ------------------ - Use ``zope:adapter`` ZCML directive instead of ``zope:view``. This avoid dependency on ``zope.app.component``. - Update imports from ``zope.app.security`` to ``zope.authentication`` and ``zope.principalregistry``. - Use ``zope.browser.interfaces.ISystemError`` to avoid dependency on ``zope.app.exception``. - Refactored tests so they can run successfully with ZODB 3.8 and 3.9. 3.5.3 (2009-03-13) ------------------ - Adapt to the removal of IXMLPresentation from zope.app.publisher which was removed to adapt to removal of deprecated interfaces from zope.component. 3.5.2 (2009-03-10) ------------------ - Use ISkinnable.providedBy(request) instead of IBrowserRequest as condition for calling setDefaultSkin. This at the same time removes dependency to the browser part of zope.publisher. - Remove deprecated code. - Use built-in set class instead of the deprecated sets.Set and thus don't cause deprecation warning in Python 2.6. 3.5.1 (2009-01-31) ------------------ - Import ISite from zope.location.interfaces instead of deprecated place in zope.app.component.interfaces. 3.5.0 (2008-10-09) ------------------ - Now ``zope.app.publication.zopepublication.ZopePublication`` annotates the request with the connection to the main ZODB when ``getApplication`` is called. - Removed support for non-existent Zope versions. 3.4.3 (2007-11-01) ------------------ - Removed unused imports. - Resolve ``ZopeSecurityPolicy`` deprecation warning. 3.4.2 (2007-09-26) ------------------ - Added missing files to egg distribution. 3.4.1 (2007-09-26) ------------------ - Added missing files to egg distribution. 3.4.0 (2007-09-25) ------------------ - Initial documented release. - Reflect changes form ``zope.app.error`` refactoring. Keywords: zope publication Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Topic :: Internet :: WWW/HTTP Classifier: Framework :: Zope3 zope.app.publication-3.14.0/src/zope/0000755000175000017500000000000011726417516016735 5ustar adiadi00000000000000zope.app.publication-3.14.0/src/zope/__init__.py0000644000175000017500000000031011726417511021033 0ustar adiadi00000000000000# this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) zope.app.publication-3.14.0/src/zope/app/0000755000175000017500000000000011726417516017515 5ustar adiadi00000000000000zope.app.publication-3.14.0/src/zope/app/__init__.py0000644000175000017500000000031011726417511021613 0ustar adiadi00000000000000# this is a namespace package try: import pkg_resources pkg_resources.declare_namespace(__name__) except ImportError: import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) zope.app.publication-3.14.0/src/zope/app/publication/0000755000175000017500000000000011726417516022026 5ustar adiadi00000000000000zope.app.publication-3.14.0/src/zope/app/publication/zopepublication.py0000644000175000017500000004305111726417511025605 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## __docformat__ = 'restructuredtext' import sys import logging from new import instancemethod import transaction import zope.component import zope.component.interfaces from zope.component import queryMultiAdapter from zope.event import notify from zope.interface import implements, providedBy from zope.publisher.publish import mapply from zope.publisher.interfaces import IExceptionSideEffects, IHeld from zope.publisher.interfaces import IPublication, IPublishTraverse, IRequest from zope.publisher.interfaces import NotFound, Retry from zope.security.management import newInteraction, endInteraction from zope.security.checker import ProxyFactory from zope.security.proxy import removeSecurityProxy from zope.traversing.interfaces import BeforeTraverseEvent from zope.traversing.interfaces import IPhysicallyLocatable from zope.traversing.interfaces import IEtcNamespace from zope.traversing.interfaces import TraversalError from zope.traversing.namespace import namespaceLookup, nsParse from zope.location import LocationProxy from zope.error.interfaces import IErrorReportingUtility import zope.authentication.interfaces from zope.browser.interfaces import ISystemErrorView from zope.publisher.defaultview import queryDefaultViewName from zope.publisher.interfaces import EndRequestEvent, StartRequestEvent from zope.authentication.interfaces import IUnauthenticatedPrincipal from zope.authentication.interfaces import IFallbackUnauthenticatedPrincipal from zope.authentication.interfaces import IAuthentication class Cleanup(object): implements(IHeld) def __init__(self, f): self._f = f def release(self): self._f() self._f = None def __del__(self): if self._f is not None: logging.getLogger('SiteError').error( "Cleanup without request close") self._f() class ZopePublication(object): """Base Zope publication specification.""" implements(IPublication) root_name = 'Application' def __init__(self, db): # db is a ZODB.DB.DB object. self.db = db def proxy(self, ob): """Security-proxy an object Subclasses may override this to use a different proxy (or checker) implementation or to not proxy at all. """ return ProxyFactory(ob) def beforeTraversal(self, request): notify(StartRequestEvent(request)) # Try to authenticate against the root authentication utility. auth = zope.component.getGlobalSiteManager().getUtility( zope.authentication.interfaces.IAuthentication) principal = auth.authenticate(request) if principal is None: principal = auth.unauthenticatedPrincipal() if principal is None: # Get the fallback unauthenticated principal principal = zope.component.getUtility( IFallbackUnauthenticatedPrincipal) request.setPrincipal(principal) newInteraction(request) transaction.begin() def _maybePlacefullyAuthenticate(self, request, ob): if not IUnauthenticatedPrincipal.providedBy(request.principal): # We've already got an authenticated user. There's nothing to do. # Note that beforeTraversal guarentees that user is not None. return if not zope.component.interfaces.ISite.providedBy(ob): # We won't find an authentication utility here, so give up. return sm = removeSecurityProxy(ob).getSiteManager() auth = sm.queryUtility(IAuthentication) if auth is None: # No auth utility here return # Try to authenticate against the auth utility principal = auth.authenticate(request) if principal is None: principal = auth.unauthenticatedPrincipal() if principal is None: # nothing to do here return request.setPrincipal(principal) def callTraversalHooks(self, request, ob): # Call __before_publishing_traverse__ hooks notify(BeforeTraverseEvent(ob, request)) # This is also a handy place to try and authenticate. self._maybePlacefullyAuthenticate(request, ob) def afterTraversal(self, request, ob): #recordMetaData(object, request) self._maybePlacefullyAuthenticate(request, ob) def openedConnection(self, conn): # Hook for auto-refresh pass def getApplication(self, request): # If '++etc++process' is in the path, then we should # get the parent of the application controller rather than # open the database. stack = request.getTraversalStack() if '++etc++process' in stack: obj = zope.component.getUtility(IEtcNamespace, 'process') return obj.__parent__ # Open the database. conn = self.db.open() cleanup = Cleanup(conn.close) request.hold(cleanup) # Close the connection on request.close() request.annotations['ZODB.interfaces.IConnection'] = conn self.openedConnection(conn) #conn.setDebugInfo(getattr(request, 'environ', None), request.other) root = conn.root() app = root.get(self.root_name, None) if app is None: raise SystemError("Zope Application Not Found") return self.proxy(app) 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 callObject(self, request, ob): return mapply(ob, request.getPositionalArguments(), request) def afterCall(self, request, ob): txn = transaction.get() if txn.isDoomed(): txn.abort() else: self.annotateTransaction(txn, request, ob) txn.commit() def endRequest(self, request, ob): endInteraction() notify(EndRequestEvent(ob, request)) def annotateTransaction(self, txn, request, ob): """Set some useful meta-information on the transaction. This information is used by the undo framework, for example. This method is not part of the `IPublication` interface, since it's specific to this particular implementation. """ if request.principal is not None: txn.setUser(request.principal.id) # Work around methods that are usually used for views bare = removeSecurityProxy(ob) if isinstance(bare, instancemethod): ob = bare.im_self # set the location path path = None locatable = IPhysicallyLocatable(ob, None) if locatable is not None: # Views are made children of their contexts, but that # doesn't necessarily mean that we can fully resolve the # path. E.g. the family tree of a resource cannot be # resolved completely, as the site manager is a dead end. try: path = locatable.getPath() except (AttributeError, TypeError): pass if path is not None: txn.setExtendedInfo('location', path) # set the request type iface = IRequest for iface in providedBy(request): if iface.extends(IRequest): break iface_dotted = iface.__module__ + '.' + iface.getName() txn.setExtendedInfo('request_type', iface_dotted) return txn def _logErrorWithErrorReportingUtility(self, object, request, exc_info): # Record the error with the ErrorReportingUtility self.beginErrorHandlingTransaction(request, object, 'error reporting utility') try: errUtility = zope.component.getUtility(IErrorReportingUtility) # It is important that an error in errUtility.raising # does not propagate outside of here. Otherwise, nothing # meaningful will be returned to the user. # # The error reporting utility should not be doing database # stuff, so we shouldn't get a conflict error. # Even if we do, it is more important that we log this # error, and proceed with the normal course of events. # We should probably (somehow!) append to the standard # error handling that this error occurred while using # the ErrorReportingUtility, and that it will be in # the zope log. errUtility.raising(exc_info, request) transaction.commit() except: tryToLogException( 'Error while reporting an error to the Error Reporting utility' ) transaction.abort() def handleException(self, object, request, exc_info, retry_allowed=True): # This transaction had an exception that reached the publisher. # It must definitely be aborted. try: transaction.abort() except: # Hm, a catastrophe. We might want to know what preceded it. self._logErrorWithErrorReportingUtility(object, request, exc_info) raise # Reraise Retry exceptions for the publisher to deal with. if retry_allowed and isinstance(exc_info[1], Retry): raise # Convert ConflictErrors to Retry exceptions. # where transaction.interfaces.TransientError is a more generic exception if retry_allowed and isinstance(exc_info[1], transaction.interfaces.TransientError): tryToLogWarning( 'ZopePublication', 'Competing writes/reads at %s: %s' % (request.get('PATH_INFO', '???'), exc_info[1], ), ) raise Retry(exc_info) # Are there any reasons why we'd want to let application-level error # handling determine whether a retry is allowed or not? # Assume not for now. # Record the error with the ErrorReportingUtility. self._logErrorWithErrorReportingUtility(object, request, exc_info) response = request.response response.reset() exception = None legacy_exception = not isinstance(exc_info[1], Exception) if legacy_exception: response.handleException(exc_info) if isinstance(exc_info[1], str): tryToLogWarning( 'Publisher received a legacy string exception: %s.' ' This will be handled by the request.' % exc_info[1]) else: tryToLogWarning( 'Publisher received a legacy classic class exception: %s.' ' This will be handled by the request.' % exc_info[1].__class__) else: # We definitely have an Exception # Set the request body, and abort the current transaction. self.beginErrorHandlingTransaction( request, object, 'application error-handling') view = None try: # We need to get a location, because some template content of # the exception view might require one. # # The object might not have a parent, because it might be a # method. If we don't have a `__parent__` attribute but have # an im_self or a __self__, use it. loc = object if not hasattr(object, '__parent__'): loc = removeSecurityProxy(object) # Try to get an object, since we apparently have a method # Note: We are guaranteed that an object has a location, # so just getting the instance the method belongs to is # sufficient. loc = getattr(loc, 'im_self', loc) loc = getattr(loc, '__self__', loc) # Protect the location with a security proxy loc = self.proxy(loc) # Give the exception instance its location and look up the # view. exception = LocationProxy(exc_info[1], loc, '') name = queryDefaultViewName(exception, request) if name is not None: view = zope.component.queryMultiAdapter( (exception, request), name=name) except: # Problem getting a view for this exception. Log an error. tryToLogException( 'Exception while getting view on exception') if view is not None: try: # We use mapply instead of self.callObject here # because we don't want to pass positional # arguments. The positional arguments were meant # for the published object, not an exception view. body = mapply(view, (), request) response.setResult(body) transaction.commit() if (ISystemErrorView.providedBy(view) and view.isSystemError()): # Got a system error, want to log the error # Lame hack to get around logging missfeature # that is fixed in Python 2.4 try: raise exc_info[0], exc_info[1], exc_info[2] except: logging.getLogger('SiteError').exception( str(request.URL), ) except: # Problem rendering the view for this exception. # Log an error. tryToLogException( 'Exception while rendering view on exception') # Record the error with the ErrorReportingUtility self._logErrorWithErrorReportingUtility( object, request, sys.exc_info()) view = None if view is None: # Either the view was not found, or view was set to None # because the view couldn't be rendered. In either case, # we let the request handle it. response.handleException(exc_info) transaction.abort() # See if there's an IExceptionSideEffects adapter for the # exception try: adapter = IExceptionSideEffects(exception, None) except: tryToLogException( 'Exception while getting IExceptionSideEffects adapter') adapter = None if adapter is not None: self.beginErrorHandlingTransaction( request, object, 'application error-handling side-effect') try: # Although request is passed in here, it should be # considered read-only. adapter(object, request, exc_info) transaction.commit() except: tryToLogException( 'Exception while calling' ' IExceptionSideEffects adapter') transaction.abort() def beginErrorHandlingTransaction(self, request, ob, note): txn = transaction.begin() txn.note(note) self.annotateTransaction(txn, request, ob) return txn def tryToLogException(arg1, arg2=None): if arg2 is None: subsystem = 'SiteError' message = arg1 else: subsystem = arg1 message = arg2 try: logging.getLogger(subsystem).exception(message) # Bare except, because we want to swallow any exception raised while # logging an exception. except: pass def tryToLogWarning(arg1, arg2=None, exc_info=False): if arg2 is None: subsystem = 'SiteError' message = arg1 else: subsystem = arg1 message = arg2 try: logging.getLogger(subsystem).warn(message, exc_info=exc_info) # Bare except, because we want to swallow any exception raised while # logging a warning. except: pass zope.app.publication-3.14.0/src/zope/app/publication/xmlrpc.py0000644000175000017500000000210611726417511023677 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """XML-RPC Publication Handler. This module specifically implements a custom `nameTraverse()` method. """ __docformat__ = 'restructuredtext' from zope.app.publication.http import BaseHTTPPublication # Don't need any special handling for xml-rpc XMLRPCPublication = BaseHTTPPublication class XMLRPCPublicationFactory(object): def __init__(self, db): self.__pub = XMLRPCPublication(db) def __call__(self): return self.__pub zope.app.publication-3.14.0/src/zope/app/publication/traversers.py0000644000175000017500000000667611726417511024612 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """Generic object traversers """ __docformat__ = 'restructuredtext' import zope.component from zope.interface import providedBy, implements from zope.publisher.interfaces import Unauthorized, NotFound from zope.publisher.interfaces.browser import IBrowserPublisher from zope.publisher.interfaces.xmlrpc import IXMLRPCPublisher from zope.publisher.defaultview import getDefaultViewName class SimpleComponentTraverser(object): """Browser traverser for simple components that can only traverse to views """ implements(IBrowserPublisher, IXMLRPCPublisher) def __init__(self, context, request): self.context = context self.request = request def browserDefault(self, request): ob = self.context view_name = getDefaultViewName(ob, request) return ob, (view_name,) def publishTraverse(self, request, name): ob = self.context view = zope.component.queryMultiAdapter((ob, request), name=name) if view is None: raise NotFound(ob, name) return view class FileContentTraverser(SimpleComponentTraverser): """Browser traverser for file content. The default view for file content has effective URLs that don't end in /. In particular, if the content inclused HTML, relative links in the HTML are relative to the container the content is in. """ def browserDefault(self, request): ob = self.context view_name = getDefaultViewName(ob, request) view = self.publishTraverse(request, view_name) if hasattr(view, 'browserDefault'): view, path = view.browserDefault(request) if len(path) == 1: view = view.publishTraverse(request, path[0]) path = () else: path = () return view, path def NoTraverser(ob, request): return None class TestTraverser(object): """Bobo-style traverser, mostly useful for testing""" implements(IBrowserPublisher) def __init__(self, context, request): self.context = context def browserDefault(self, request): ob = self.context if list(providedBy(ob)): view_name = getDefaultViewName(ob, request) return ob, (("@@%s" % view_name),) return ob, () def publishTraverse(self, request, name): ob = self.context if name.startswith('@@'): return zope.component.getMultiAdapter((ob, request), name=name[6:]) if name.startswith('_'): raise Unauthorized(name) subob = getattr(ob, name, self) # self is marker here if subob is self: # no attribute try: subob = ob[name] except (KeyError, IndexError, TypeError, AttributeError): raise NotFound(ob, name, request) return subob zope.app.publication-3.14.0/src/zope/app/publication/testing.py0000644000175000017500000000221111726417511024044 0ustar adiadi00000000000000############################################################################## # # Copyright (c) 2007 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """zope.app.publication common test related classes/functions/objects. """ __docformat__ = "reStructuredText" from zope.app.wsgi.testlayer import BrowserLayer from zope.publisher.browser import BrowserPage import zope.app.publication class DefaultTestView(BrowserPage): def __call__(self): self.request.response.setHeader( 'Content-Type', 'text/html;charset=utf-8') return "Test" PublicationLayer = BrowserLayer(zope.app.publication, name='PublicationLayer') zope.app.publication-3.14.0/src/zope/app/publication/soap.py0000644000175000017500000000250211726417511023334 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """ SOAP Publication Handler. Note that there is no *standard* SOAP implementation that is currently appropriate for the Zope3 core. The current architecture allows external packages to register a utility for zope.app.publication.interfaces.SOAPRequestFactory in order to implement SOAP support. If no utility is registered for this interface, SOAP requests are handled as if they were browser requests. """ from zope.app.publication.http import BaseHTTPPublication # Don't need any special handling for SOAP SOAPPublication = BaseHTTPPublication class SOAPPublicationFactory(object): def __init__(self, db): self.__pub = SOAPPublication(db) def __call__(self): return self.__pub zope.app.publication-3.14.0/src/zope/app/publication/site.txt0000644000175000017500000000206611726417511023532 0ustar adiadi00000000000000====================== Using the site manager ====================== This test ensures that the site is correctly set and cleared in a thread during traversal using event subscribers. Before we start, no site is set: >>> from zope.component import hooks >>> hooks.getSite() is None True >>> request = object() >>> from zope.app.publication import interfaces >>> from zope import site On the other hand, if a site is traversed, >>> from zope.site.tests.test_site import SiteManagerStub, CustomFolder >>> sm = SiteManagerStub() >>> mysite = CustomFolder('mysite') >>> mysite.setSiteManager(sm) >>> from zope.traversing.interfaces import BeforeTraverseEvent >>> ev = BeforeTraverseEvent(mysite, request) >>> site.threadSiteSubscriber(mysite, ev) >>> hooks.getSite() Once the request is completed, >>> from zope.publisher.interfaces import EndRequestEvent >>> ev = EndRequestEvent(mysite, request) >>> site.clearThreadSiteSubscriber(ev) the site assignment is cleared again: >>> hooks.getSite() is None True zope.app.publication-3.14.0/src/zope/app/publication/requestpublicationregistry.py0000644000175000017500000001052211726417511030106 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """A registry for Request-Publication factories. """ __docformat__ = 'restructuredtext' from zope.interface import implements from zope.app.publication.interfaces import IRequestPublicationRegistry from zope.configuration.exceptions import ConfigurationError class RequestPublicationRegistry(object): """The registry implements a three stage lookup for registered factories that have to deal with requests:: {method > { mimetype -> [{'priority' : some_int, 'factory' : factory, 'name' : some_name }, ... ] }, } The `priority` is used to define a lookup-order when multiple factories are registered for the same method and mime-type. """ implements(IRequestPublicationRegistry) def __init__(self): self._d = {} # method -> { mimetype -> {factories_data}} def register(self, method, mimetype, name, priority, factory): """Register a factory for method+mimetype """ # initialize the two-level deep nested datastructure if necessary if not self._d.has_key(method): self._d[method] = {} if not self._d[method].has_key(mimetype): self._d[method][mimetype] = [] l = self._d[method][mimetype] # Check if there is already a registered publisher factory (check by # name). If yes then it will be removed and replaced by a new # publisher. for pos, d in enumerate(l): if d['name'] == name: del l[pos] break # add the publisher factory + additional informations l.append({'name' : name, 'factory' : factory, 'priority' : priority}) # order by descending priority l.sort(lambda x,y: -cmp(x['priority'], y['priority'])) # check if the priorities are unique priorities = [item['priority'] for item in l] if len(set(priorities)) != len(l): raise ConfigurationError('All registered publishers for a given ' 'method+mimetype must have distinct ' 'priorities. Please check your ZCML ' 'configuration') def getFactoriesFor(self, method, mimetype): if ';' in mimetype: # `mimetype` might be something like 'text/xml; charset=utf8'. In # this case we are only interested in the first part. mimetype = mimetype.split(';')[0] try: return self._d[method][mimetype.strip()] except KeyError: return None def lookup(self, method, mimetype, environment): """Lookup a factory for a given method+mimetype and a environment.""" for m,mt in ((method, mimetype), (method, '*'), ('*', '*')): factory_lst = self.getFactoriesFor(m, mt) if factory_lst: break else: raise ConfigurationError('No registered publisher found ' 'for (%s/%s)' % (method, mimetype)) # now iterate over all factory candidates and let them introspect # the request environment to figure out if they can handle the # request for d in factory_lst: factory = d['factory'] if factory.canHandle(environment): return factory # Actually we should never get here unless of improper # configuration (no default handler for method=* and mimetype=*) return None factoryRegistry = RequestPublicationRegistry() try: import zope.testing.cleanup except ImportError: pass else: zope.testing.cleanup.addCleanUp(lambda : factoryRegistry.__init__()) zope.app.publication-3.14.0/src/zope/app/publication/requestpublicationfactories.py0000644000175000017500000000510511726417511030216 0ustar adiadi00000000000000############################################################################## # # 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 factories. This module provides factories for tuples (request, publication). """ __docformat__ = 'restructuredtext' from zope import component from zope.interface import implements from zope.app.publication.interfaces import IRequestPublicationFactory from zope.app.publication import interfaces from zope.app.publication.soap import SOAPPublication from zope.app.publication.xmlrpc import XMLRPCPublication from zope.app.publication.http import HTTPPublication from zope.publisher.xmlrpc import XMLRPCRequest from zope.app.publication.browser import BrowserPublication from zope.publisher.http import HTTPRequest from zope.publisher.browser import BrowserRequest class SOAPFactory(object): implements(IRequestPublicationFactory) def canHandle(self, environment): self.soap_req = component.queryUtility(interfaces.ISOAPRequestFactory) return bool(environment.get('HTTP_SOAPACTION') and self.soap_req) def __call__(self): return self.soap_req, SOAPPublication class XMLRPCFactory(object): implements(IRequestPublicationFactory) def canHandle(self, environment): return True def __call__(self): request_class = component.queryUtility( interfaces.IXMLRPCRequestFactory, default=XMLRPCRequest) return request_class, XMLRPCPublication class HTTPFactory(object): implements(IRequestPublicationFactory) def canHandle(self, environment): return True def __call__(self): request_class = component.queryUtility( interfaces.IHTTPRequestFactory, default=HTTPRequest) return request_class, HTTPPublication class BrowserFactory(object): implements(IRequestPublicationFactory) def canHandle(self, environment): return True def __call__(self): request_class = component.queryUtility( interfaces.IBrowserRequestFactory, default=BrowserRequest) return request_class, BrowserPublication zope.app.publication-3.14.0/src/zope/app/publication/publicationtraverse.py0000644000175000017500000000235111726417511026461 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## import warnings warnings.warn("""%s is deprecated If you want PublicationTraverser, it's now in zope.traversing.publicationtraverse. Anything else that was here is deprecated. """ % __name__, DeprecationWarning, stacklevel=1) from zope.traversing.publicationtraverse import PublicationTraverse #BBB import from zope.traversing.publicationtraverse import PublicationTraverser #BBB import #BBB: do not use class DuplicateNamespaces(Exception): """More than one namespace was specified in a request""" #BBB: do not use class UnknownNamespace(Exception): """A parameter specified an unknown namespace""" zope.app.publication-3.14.0/src/zope/app/publication/notfound.txt0000644000175000017500000000050111726417511024412 0ustar adiadi00000000000000NotFound errors and traversal errors ==================================== Not found errors should only be displayed when someone provides a URL to an object that doesn't exist, as in: >>> from zope.app.wsgi.testlayer import http >>> print http("""\ ... GET /eek HTTP/1.1 ... """) HTTP/1.0 404 Not Found ... zope.app.publication-3.14.0/src/zope/app/publication/methodnotallowed.txt0000644000175000017500000000234111726417511026133 0ustar adiadi00000000000000Method Not Allowed errors ========================= If we get a request with a method that does not have a corresponding view, HTTP 405 Method Not Allowed response is returned: >>> from zope.app.wsgi.testlayer import http >>> print http("""\ ... FROG / HTTP/1.1 ... """) HTTP/1.0 405 Method Not Allowed Content-Length: 18 Allow: DELETE, OPTIONS, PUT ... >>> print http("""\ ... DELETE / HTTP/1.1 ... """) HTTP/1.0 405 Method Not Allowed ... Trying to PUT on an object which does not support PUT leads to 405: >>> print http("""\ ... PUT / HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.0 405 Method Not Allowed ... Trying to PUT a not existing object on a container which does not support PUT leads to 405: >>> print http("""\ ... PUT /asdf HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """) HTTP/1.0 405 Method Not Allowed ... When ``handle_errors`` is set to ``False`` a traceback is displayed: >>> print http("""\ ... PUT / HTTP/1.1 ... Authorization: Basic mgr:mgrpw ... """, handle_errors=False) Traceback (most recent call last): MethodNotAllowed: , zope.app.publication-3.14.0/src/zope/app/publication/metadirectives.py0000644000175000017500000000435211726417511025407 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """Directive schema, for publication factory This module provides the schema for the new zcml directive, that let the developer associate a publication factory to a given request, based on its method and mimetype. Each directive also has a name and a sortkey. The sortkey helps when several directives can handle a request: they are sorted by this key and the highest one is taken. """ __docformat__ = 'restructuredtext' from zope.interface import Interface from zope.configuration.fields import GlobalObject, Tokens from zope.schema import TextLine, Int class IRequestPublicationDirective(Interface): """Link a request type to a request and publication factory""" name = TextLine( title=u'Name', description=u'The name of the publication factory.') factory = GlobalObject( title=u'Factory', description=u'The request-publication factory') methods = Tokens( title=u'Methods', description=(u'A list of HTTP method names. If the method is a "*", ' u'then all methods will match. Example: "GET POST"'), value_type=TextLine(), required=False) mimetypes = Tokens( title=u'Mime Types', description=(u'A list of content/mime types of the request. If the ' u'type is a "*" then all types will be matched. ' u'Example: "text/html text/xml"'), value_type=TextLine(), required=False) priority = Int( title=u'Priority', description=(u'A priority key used to concurrent' ' publication factories.'), required=False) zope.app.publication-3.14.0/src/zope/app/publication/metaconfigure.py0000644000175000017500000000233211726417511025223 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """ Directive handler for publication factory See metadirective.py """ __docformat__ = 'restructuredtext' from zope.app.publication.requestpublicationregistry import factoryRegistry def publisher(_context, name, factory, methods=['*'], mimetypes=['*'], priority=0): factory = factory() for method in methods: for mimetype in mimetypes: _context.action( discriminator = (method, mimetype, priority), callable = factoryRegistry.register, args = (method, mimetype, name, priority, factory) ) zope.app.publication-3.14.0/src/zope/app/publication/meta.zcml0000644000175000017500000000043111726417511023634 0ustar adiadi00000000000000 zope.app.publication-3.14.0/src/zope/app/publication/interfaces.py0000644000175000017500000000655011726417511024524 0ustar adiadi00000000000000############################################################################## # # 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 Interfaces """ __docformat__ = 'restructuredtext' from zope import interface # BBB: Re-import symbols to their old location. from zope.publisher.interfaces import IEndRequestEvent from zope.publisher.interfaces import EndRequestEvent from zope.traversing.interfaces import IBeforeTraverseEvent from zope.traversing.interfaces import BeforeTraverseEvent class IPublicationRequestFactory(interface.Interface): """Publication request factory""" def __call__(input_stream, env): """Create a request object to handle the given inputs A request is created and configured with a publication object. """ class IRequestFactory(interface.Interface): def __call__(input_stream, env): """Create a request object to handle input.""" class ISOAPRequestFactory(IRequestFactory): """SOAP request factory""" class IHTTPRequestFactory(IRequestFactory): # TODO: should SOAP, XMLRPC, and Browser extend this? """generic HTTP request factory""" class IXMLRPCRequestFactory(IRequestFactory): """XMLRPC request factory""" class IBrowserRequestFactory(IRequestFactory): """Browser request factory""" class IFileContent(interface.Interface): """Marker interface for content that can be managed as files. The default view for file content has effective URLs that don't end in `/`. In particular, if the content included HTML, relative links in the HTML are relative to the container the content is in. """ class IRequestPublicationFactory(interface.Interface): """ request-publication factory """ def canHandle(environment): """Return ``True`` if it can handle the request, otherwise ``False``. `environment` can be used by the factory to make a decision based on the HTTP headers. """ def __call__(): """Return a tuple (request, publication)""" class IRequestPublicationRegistry(interface.Interface): """A registry to lookup a RequestPublicationFactory by request method + mime-type. Multiple factories can be configured for the same method+mimetype. The factory itself can introspect the environment to decide if it can handle the request as given by the environment or not. Factories are sorted in the order of their registration in ZCML. """ def register(method, mimetype, name, priority, factory): """Registers a factory for method+mimetype.""" def lookup(method, mimetype, environment): """Lookup a factory for a given method+mimetype and a environment. """ def getFactoriesFor(method, mimetype): """Return the internal datastructure representing the configured factories (basically for testing, not for introspection). """ zope.app.publication-3.14.0/src/zope/app/publication/httpfactory.txt0000644000175000017500000000303311726417511025130 0ustar adiadi00000000000000================= HTTPFactory tests ================= This tests that httpfactory provide the right publication class, for each request type, defined in the configure.zcml with publisher directive. The publication class is chosen upon the method name, the mime type and sometimes some request headers A regular GET, POST or HEAD >>> from zope.app.wsgi.testlayer import http >>> print http("""\ ... GET / HTTP/1.1 ... """) HTTP/1.0 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 ... >>> print http("""\ ... POST / HTTP/1.1 ... """) HTTP/1.0 200 OK Content-Length: ... Content-Type: text/html;charset=utf-8 ... >>> print http("""\ ... HEAD / HTTP/1.1 ... """) HTTP/1.0 200 OK Content-Length: 0 Content-Type: text/html;charset=utf-8 A text/xml POST request, wich is an xml-rpc call >>> print http("""\ ... POST /RPC2 HTTP/1.0 ... Content-Type: text/xml ... """) HTTP/1.0 200 OK Content-Length: ... Content-Type: text/xml;charset=utf-8 ... A text/xml POST request, with a HTTP_SOAPACTION in the headers, wich is an xml-rpc call: TODO need to create a real SOAP exchange test here >>> print http("""\ ... POST /RPC2 HTTP/1.0 ... Content-Type: text/xml ... HTTP_SOAPACTION: soap#action ... """) HTTP/1.0 200 OK Content-Length: ... Content-Type: text/xml;charset=utf-8 ... Unknown request types: TODO need more testing here >>> print http("""\ ... POST /BUBA HTTP/1.0 ... Content-Type: text/topnotch ... """) HTTP/1.0 404 Not Found ... zope.app.publication-3.14.0/src/zope/app/publication/httpfactory.py0000644000175000017500000000437411726417511024752 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """HTTP Factory """ __docformat__ = 'restructuredtext' from zope import interface from zope.publisher.interfaces import ISkinnable from zope.publisher.skinnable import setDefaultSkin from zope.app.publication import interfaces from zope.app.publication.requestpublicationregistry import factoryRegistry def chooseClasses(method, environment): """Given the method and environment, choose the correct request and publication factory.""" content_type = environment.get('CONTENT_TYPE', '') factory = factoryRegistry.lookup(method, content_type, environment) request_class, publication = factory() return request_class, publication class HTTPPublicationRequestFactory(object): interface.implements(interfaces.IPublicationRequestFactory) def __init__(self, db): """See `zope.app.publication.interfaces.IPublicationRequestFactory`""" self._db = db self._publication_cache = {} def __call__(self, input_stream, env): """See `zope.app.publication.interfaces.IPublicationRequestFactory`""" method = env.get('REQUEST_METHOD', 'GET').upper() request_class, publication_class = chooseClasses(method, env) publication = self._publication_cache.get(publication_class) if publication is None: publication = publication_class(self._db) self._publication_cache[publication_class] = publication request = request_class(input_stream, env) request.setPublication(publication) if ISkinnable.providedBy(request): # only ISkinnable requests have skins setDefaultSkin(request) return request zope.app.publication-3.14.0/src/zope/app/publication/http.py0000644000175000017500000000403611726417511023355 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """HTTP Publication """ __docformat__ = 'restructuredtext' from zope.interface import Attribute from zope.interface import implements from zope.publisher.interfaces.http import IHTTPException from zope.publisher.interfaces.http import MethodNotAllowed from zope.publisher.publish import mapply import zope.component from zope.app.publication.zopepublication import ZopePublication from zope.publisher.interfaces.http import IMethodNotAllowed #BBB import class BaseHTTPPublication(ZopePublication): """Base for HTTP-based protocol publications""" def annotateTransaction(self, txn, request, ob): txn = super(BaseHTTPPublication, self).annotateTransaction( txn, request, ob) request_info = request.method + ' ' + request.getURL() txn.setExtendedInfo('request_info', request_info) return txn class HTTPPublication(BaseHTTPPublication): """Non-browser HTTP publication""" def callObject(self, request, ob): # Exception handling, dont try to call request.method orig = ob if not IHTTPException.providedBy(ob): ob = zope.component.queryMultiAdapter((ob, request), name=request.method) ob = getattr(ob, request.method, None) if ob is None: raise MethodNotAllowed(orig, request) return mapply(ob, request.getPositionalArguments(), request) zope.app.publication-3.14.0/src/zope/app/publication/ftp.py0000644000175000017500000000351311726417511023166 0ustar adiadi00000000000000############################################################################## # # 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 FTP Publication. """ __docformat__ = 'restructuredtext' import zope.component from zope.publisher.interfaces import NotFound from zope.publisher.publish import mapply from zope.app.publication.zopepublication import ZopePublication class FTPPublication(ZopePublication): """The Publication will do all the work for the FTP""" def callObject(self, request, ob): method = request['command'] view = zope.component.queryMultiAdapter((ob, request), name=method, default=self) if view is self: raise NotFound(ob, method, request) return mapply(getattr(view, method), (), request) def annotateTransaction(self, txn, request, ob): txn = super(FTPPublication, self).annotateTransaction(txn, request, ob) request_info = [request['command']] path = request.get('path', '') if path: request_info.append(path) name = request.get('name', '') if name: request_info.append(name) request_info = ' '.join(request_info) txn.setExtendedInfo('request_info', request_info) return txn zope.app.publication-3.14.0/src/zope/app/publication/ftesting.zcml0000644000175000017500000000404511726417511024536 0ustar adiadi00000000000000 zope.app.publication-3.14.0/src/zope/app/publication/configure.zcml0000644000175000017500000000432311726417511024673 0ustar adiadi00000000000000 zope.app.publication-3.14.0/src/zope/app/publication/browser.py0000644000175000017500000000405711726417511024064 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """Browser Publication Code This module implements browser-specific publication and traversal components for the publisher. """ __docformat__ = 'restructuredtext' from zope.component import queryMultiAdapter from zope.publisher.interfaces.browser import IBrowserPublisher from zope.app.publication.http import BaseHTTPPublication from zope.traversing.publicationtraverse import PublicationTraverser #BBB import class BrowserPublication(BaseHTTPPublication): """Web browser publication handling.""" def getDefaultTraversal(self, request, ob): if IBrowserPublisher.providedBy(ob): # ob is already proxied, so the result of calling a method will be return ob.browserDefault(request) else: adapter = queryMultiAdapter((ob, request), IBrowserPublisher) if adapter is not None: ob, path = adapter.browserDefault(request) ob = self.proxy(ob) return ob, path else: # ob is already proxied return ob, None def afterCall(self, request, ob): super(BrowserPublication, self).afterCall(request, ob) if request.method == 'HEAD': request.response.setResult('') # For now, have a factory that returns a singleton class PublicationFactory(object): def __init__(self, db): self.__pub = BrowserPublication(db) def __call__(self): return self.__pub zope.app.publication-3.14.0/src/zope/app/publication/__init__.py0000644000175000017500000000007511726417511024134 0ustar adiadi00000000000000# # This file is necessary to make this directory a package. zope.app.publication-3.14.0/src/zope/app/publication/tests/0000755000175000017500000000000011726417516023170 5ustar adiadi00000000000000zope.app.publication-3.14.0/src/zope/app/publication/tests/test_zopepublication.py0000644000175000017500000006575411726417511030024 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """Zope Publication Tests """ import unittest import sys from cStringIO import StringIO from persistent import Persistent from ZODB.DB import DB from ZODB.DemoStorage import DemoStorage import transaction from zope.interface.verify import verifyClass from zope.interface import implements, classImplements, implementedBy from zope.component.interfaces import ComponentLookupError, ISite from zope.error.interfaces import IErrorReportingUtility from zope.location import Location from zope.publisher.base import TestPublication, TestRequest from zope.publisher.interfaces import IRequest, IPublishTraverse from zope.security import simplepolicies from zope.security.management import setSecurityPolicy, queryInteraction from zope.security.management import endInteraction from zope.traversing.interfaces import IPhysicallyLocatable from zope.location.interfaces import ILocation from zope.testing.cleanup import cleanUp from zope.site.site import LocalSiteManager from zope import component from zope.app.publication.tests import support from zope.authentication.interfaces import IAuthentication from zope.authentication.interfaces import IFallbackUnauthenticatedPrincipal from zope.authentication.interfaces import IUnauthenticatedPrincipal from zope.security.interfaces import IPrincipal from zope.principalregistry.principalregistry import principalRegistry from zope.app.publication.zopepublication import ZopePublication from zope.site.folder import Folder, rootFolder class Principal(object): implements(IPrincipal) def __init__(self, id): self.id = id self.title = '' self.description = '' class UnauthenticatedPrincipal(Principal): implements(IUnauthenticatedPrincipal) class AuthUtility1(object): def authenticate(self, request): return None def unauthenticatedPrincipal(self): return UnauthenticatedPrincipal('test.anonymous') def unauthorized(self, id, request): pass def getPrincipal(self, id): return UnauthenticatedPrincipal(id) class AuthUtility2(AuthUtility1): def authenticate(self, request): return Principal('test.bob') def getPrincipal(self, id): return Principal(id) class AuthUtility3(AuthUtility1): def unauthenticatedPrincipal(self): return None class ErrorReportingUtility(object): implements(IErrorReportingUtility) def __init__(self): self.exceptions = [] def raising(self, info, request=None): self.exceptions.append([info, request]) class LocatableObject(Location): def foo(self): pass class TestRequest(TestRequest): URL='http://test.url' def addUtility(sitemanager, name, iface, utility, suffix=''): """Add a utility to a site manager This helper function is useful for tests that need to set up utilities. """ folder_name = (name or (iface.__name__ + 'Utility')) + suffix default = sitemanager['default'] default[folder_name] = utility utility = default[folder_name] sitemanager.registerUtility(utility, iface, name) return utility class BasePublicationTests(unittest.TestCase): def setUp(self): from zope.security.management import endInteraction endInteraction() self.policy = setSecurityPolicy( simplepolicies.PermissiveSecurityPolicy ) self.storage = DemoStorage('test_storage') self.db = db = DB(self.storage) component.provideUtility(principalRegistry, IAuthentication) connection = db.open() root = connection.root() app = getattr(root, ZopePublication.root_name, None) if app is None: from zope.site.folder import rootFolder app = rootFolder() root[ZopePublication.root_name] = app transaction.commit() connection.close() self.app = app from zope.traversing.namespace import view, resource, etc support.provideNamespaceHandler('view', view) support.provideNamespaceHandler('resource', resource) support.provideNamespaceHandler('etc', etc) self.request = TestRequest('/f1/f2') self.user = Principal('test.principal') self.request.setPrincipal(self.user) from zope.interface import Interface self.presentation_type = Interface self.request._presentation_type = self.presentation_type self.object = object() self.publication = ZopePublication(self.db) def tearDown(self): # Close the request, otherwise a Cleanup object will start logging # messages from its __del__ method at some inappropriate moment. self.request.close() cleanUp() class ZopePublicationErrorHandling(BasePublicationTests): def testInterfacesVerify(self): for interface in implementedBy(ZopePublication): verifyClass(interface, TestPublication) def testRetryAllowed(self): from zope.publisher.interfaces import Retry # a more generic version of ConflictError, but is the better thing from transaction.interfaces import TransientError try: raise TransientError except: self.assertRaises(Retry, self.publication.handleException, self.object, self.request, sys.exc_info(), retry_allowed=True) # be nice and check ZODB's ConflictError from ZODB.POSException import ConflictError try: raise ConflictError except: self.assertRaises(Retry, self.publication.handleException, self.object, self.request, sys.exc_info(), retry_allowed=True) try: raise Retry(sys.exc_info()) except: self.assertRaises(Retry, self.publication.handleException, self.object, self.request, sys.exc_info(), retry_allowed=True) def testRetryNotAllowed(self): from transaction.interfaces import TransientError try: raise TransientError except: self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) value = ''.join(self.request.response._result).split() self.assertEqual(' '.join(value[:6]), 'Traceback (most recent call last): File') self.assertEqual(' '.join(value[-5:]), 'in testRetryNotAllowed raise TransientError' ' TransientError') from ZODB.POSException import ConflictError try: raise ConflictError except: self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) value = ''.join(self.request.response._result).split() self.assertEqual(' '.join(value[:6]), 'Traceback (most recent call last): File') self.assertEqual(' '.join(value[-8:]), 'in testRetryNotAllowed raise ConflictError' ' ConflictError: database conflict error') from zope.publisher.interfaces import Retry try: raise Retry(sys.exc_info()) except: self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) value = ''.join(self.request.response._result).split() self.assertEqual(' '.join(value[:6]), 'Traceback (most recent call last): File') self.assertEqual(' '.join(value[-8:]), 'in testRetryNotAllowed raise Retry(sys.exc_info())' ' Retry: database conflict error') try: raise Retry except: self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) value = ''.join(self.request.response._result).split() self.assertEqual(' '.join(value[:6]), 'Traceback (most recent call last): File') self.assertEqual(' '.join(value[-6:]), 'in testRetryNotAllowed raise Retry' ' Retry: None') def testViewOnException(self): from zope.interface import Interface class E1(Exception): pass support.setDefaultViewName(E1, 'name', layer=None, type=self.presentation_type) view_text = 'You had a conflict error' def _view(obj, request): return lambda: view_text component.provideAdapter(_view, (E1, self.presentation_type), Interface, name='name') try: raise E1 except: pass self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) self.assertEqual(self.request.response._result, view_text) def testHandlingSystemErrors(self): # Generally, when there is a view for an excepton, we assume # it is a user error, not a system error and we don't log it. from zope.testing import loggingsupport handler = loggingsupport.InstalledHandler('SiteError') self.testViewOnException() self.assertEqual( str(handler), 'SiteError ERROR\n' ' Error while reporting an error to the Error Reporting utility') # Here we got a single log record, because we haven't # installed an error reporting utility. That's OK. handler.uninstall() handler = loggingsupport.InstalledHandler('SiteError') # Now, we'll register an exception view that indicates that we # have a system error. from zope.interface import Interface, implements class E2(Exception): pass support.setDefaultViewName(E2, 'name', layer=self.presentation_type, type=self.presentation_type) view_text = 'You had a conflict error' from zope.browser.interfaces import ISystemErrorView class MyView: implements(ISystemErrorView) def __init__(self, context, request): pass def isSystemError(self): return True def __call__(self): return view_text component.provideAdapter(MyView, (E2, self.presentation_type), Interface, name='name') try: raise E2 except: self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) # Now, since the view was a system error view, we should have # a log entry for the E2 error (as well as the missing # error reporting utility). self.assertEqual( str(handler), 'SiteError ERROR\n' ' Error while reporting an error to the Error Reporting utility\n' 'SiteError ERROR\n' ' http://test.url' ) handler.uninstall() def testNoViewOnClassicClassException(self): from zope.interface import Interface from types import ClassType class ClassicError: __metaclass__ = ClassType class IClassicError(Interface): pass classImplements(ClassicError, IClassicError) support.setDefaultViewName(IClassicError, 'name', self.presentation_type) view_text = 'You made a classic error ;-)' def _view(obj, request): return lambda: view_text component.provideAdapter( _view, (ClassicError, self.presentation_type), Interface, name='name') try: raise ClassicError except: pass self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) # check we don't get the view we registered self.failIf(''.join(self.request.response._result) == view_text) # check we do actually get something self.failIf(''.join(self.request.response._result) == '') def testExceptionSideEffects(self): from zope.publisher.interfaces import IExceptionSideEffects class SideEffects(object): implements(IExceptionSideEffects) def __init__(self, exception): self.exception = exception def __call__(self, obj, request, exc_info): self.obj = obj self.request = request self.exception_type = exc_info[0] self.exception_from_info = exc_info[1] class SideEffectsFactory: def __call__(self, exception): self.adapter = SideEffects(exception) return self.adapter factory = SideEffectsFactory() from ZODB.POSException import ConflictError from zope.interface import Interface class IConflictError(Interface): pass classImplements(ConflictError, IConflictError) component.provideAdapter(factory, (IConflictError,), IExceptionSideEffects) exception = ConflictError() try: raise exception except: pass self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) adapter = factory.adapter self.assertEqual(exception, adapter.exception) self.assertEqual(exception, adapter.exception_from_info) self.assertEqual(ConflictError, adapter.exception_type) self.assertEqual(self.object, adapter.obj) self.assertEqual(self.request, adapter.request) def testExceptionResetsResponseTransientError(self): from zope.publisher.browser import TestRequest request = TestRequest() request.response.setHeader('Content-Type', 'application/pdf') request.response.setCookie('spam', 'eggs') from transaction.interfaces import TransientError try: raise TransientError except: pass self.publication.handleException( self.object, request, sys.exc_info(), retry_allowed=False) self.assertEqual(request.response.getHeader('Content-Type'), 'text/html;charset=utf-8') self.assertEqual(request.response._cookies, {}) def testExceptionResetsResponse(self): from zope.publisher.browser import TestRequest request = TestRequest() request.response.setHeader('Content-Type', 'application/pdf') request.response.setCookie('spam', 'eggs') from ZODB.POSException import ConflictError try: raise ConflictError except: pass self.publication.handleException( self.object, request, sys.exc_info(), retry_allowed=False) self.assertEqual(request.response.getHeader('Content-Type'), 'text/html;charset=utf-8') self.assertEqual(request.response._cookies, {}) def testAbortOrCommitTransaction(self): txn = transaction.get() try: raise Exception except: pass self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) # assert that we get a new transaction self.assert_(txn is not transaction.get()) def testAbortTransactionWithErrorReportingUtility(self): # provide our fake error reporting utility component.provideUtility(ErrorReportingUtility()) class FooError(Exception): pass last_txn_info = self.storage.lastTransaction() try: raise FooError except FooError: pass self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) # assert that the last transaction is NOT our transaction new_txn_info = self.storage.lastTransaction() self.assertEqual(last_txn_info, new_txn_info) # instead, we expect a message in our logging utility error_log = component.getUtility(IErrorReportingUtility) self.assertEqual(len(error_log.exceptions), 1) error_info, request = error_log.exceptions[0] self.assertEqual(error_info[0], FooError) self.assert_(isinstance(error_info[1], FooError)) self.assert_(request is self.request) def testLogBeforeAbort(self): # If we get an exception, and then (a catastrophe, but one that has # been experienced) transaction.abort fails, we really want to know # what happened before that abort. # (Set up:) component.provideUtility(ErrorReportingUtility()) abort = transaction.abort class AbortError(Exception): pass class AnEarlierError(Exception): pass def faux_abort(): raise AbortError try: raise AnEarlierError() except AnEarlierError: pass transaction.abort = faux_abort try: # (Test:) try: self.publication.handleException( self.object, self.request, sys.exc_info(), retry_allowed=False) except AbortError: pass else: self.fail('Aborting should have failed') # we expect a message in our logging utility error_log = component.getUtility(IErrorReportingUtility) self.assertEqual(len(error_log.exceptions), 1) error_info, request = error_log.exceptions[0] self.assertEqual(error_info[0], AnEarlierError) self.failUnless(isinstance(error_info[1], AnEarlierError)) self.failUnless(request is self.request) finally: # (Tear down:) transaction.abort = abort class ZopePublicationTests(BasePublicationTests): def testGlobalAuth(self): # Replace the global registry with a stub that doesn't return an # unauthenticated principal. authentication = AuthUtility3() component.provideUtility(authentication, IAuthentication) # We need a fallback unauthenticated principal, otherwise we'll get a # ComponentLookupError: self.assertRaises(ComponentLookupError, self.publication.beforeTraversal, self.request) # Let's register an unauthenticated principal instance for the lookup: principal = UnauthenticatedPrincipal('fallback') component.provideUtility(principal, IFallbackUnauthenticatedPrincipal) self.publication.beforeTraversal(self.request) self.failUnless(self.request.principal is principal) def testTransactionCommitAfterCall(self): root = self.db.open().root() txn = transaction.get() # we just need a change in the database to make the # transaction notable in the undo log root['foo'] = object() last_txn_info = self.storage.lastTransaction() self.publication.afterCall(self.request, self.object) self.assert_(txn is not transaction.get()) new_txn_info = self.storage.lastTransaction() self.failIfEqual(last_txn_info, new_txn_info) def testDoomedTransaction(self): # Test that a doomed transaction is aborted without error in afterCall root = self.db.open().root() txn = transaction.get() # we just need a change in the database to make the # transaction notable in the undo log root['foo'] = object() last_txn_info = self.storage.lastTransaction() # doom the transaction txn.doom() self.publication.afterCall(self.request, self.object) # assert that we get a new transaction self.assert_(txn is not transaction.get()) new_txn_info = self.storage.lastTransaction() # No transaction should be committed self.assertEqual(last_txn_info, new_txn_info) def testTransactionAnnotation(self): from zope.interface import directlyProvides from zope.location.traversing import LocationPhysicallyLocatable from zope.location.interfaces import ILocation from zope.traversing.interfaces import IPhysicallyLocatable from zope.traversing.interfaces import IContainmentRoot component.provideAdapter(LocationPhysicallyLocatable, (ILocation,), IPhysicallyLocatable) def get_txn_info(): if hasattr(self.storage, 'iterator'): # ZODB 3.9 txn_id = self.storage.lastTransaction() txn = list(self.storage.iterator(txn_id, txn_id))[0] txn_info = dict(location=txn.extension['location'], user_name=txn.user, request_type=txn.extension['request_type']) else: # ZODB 3.8 txn_info = self.storage.undoInfo()[0] return txn_info root = self.db.open().root() root['foo'] = foo = LocatableObject() root['bar'] = bar = LocatableObject() bar.__name__ = 'bar' foo.__name__ = 'foo' bar.__parent__ = foo foo.__parent__ = root directlyProvides(root, IContainmentRoot) from zope.publisher.interfaces import IRequest expected_path = "/foo/bar" expected_user = "/ " + self.user.id expected_request = IRequest.__module__ + '.' + IRequest.getName() self.publication.afterCall(self.request, bar) txn_info = get_txn_info() self.assertEqual(txn_info['location'], expected_path) self.assertEqual(txn_info['user_name'], expected_user) self.assertEqual(txn_info['request_type'], expected_request) # also, assert that we still get the right location when # passing an instance method as object. self.publication.afterCall(self.request, bar.foo) txn_info = get_txn_info() self.assertEqual(txn_info['location'], expected_path) def testSiteEvents(self): from zope.publisher.interfaces import ( IEndRequestEvent, IStartRequestEvent, ) from zope.traversing.interfaces import IBeforeTraverseEvent start = [] set = [] clear = [] component.provideHandler(start.append, (IStartRequestEvent,)) component.provideHandler(set.append, (IBeforeTraverseEvent,)) component.provideHandler(clear.append, (IEndRequestEvent,)) ob = object() # The request is started at the top of publication, which tries to do # auth. Let's register an unauthenticated principal instance. principal = UnauthenticatedPrincipal('fallback') component.provideUtility(principal, IFallbackUnauthenticatedPrincipal) # Start publication. self.publication.beforeTraversal(self.request) self.assertEqual(len(start), 1) self.assertEqual(start[0].request, self.request) # This should fire the BeforeTraverseEvent. self.publication.callTraversalHooks(self.request, ob) self.assertEqual(len(set), 1) self.assertEqual(len(clear), 0) self.assertEqual(set[0].object, ob) ob2 = object() # This should fire the EndRequestEvent self.publication.endRequest(self.request, ob2) self.assertEqual(len(start), 1) self.assertEqual(len(set), 1) self.assertEqual(len(clear), 1) self.assertEqual(clear[0].object, ob2) def testConnectionAnnotation(self): """The request is annotated with the connection to the main ZODB. """ self.assertRaises( KeyError, lambda: self.request.annotations['ZODB.interfaces.IConnection']) app = self.publication.getApplication(self.request) conn = self.request.annotations['ZODB.interfaces.IConnection'] self.assertEqual(conn.db(), self.db) class AuthZopePublicationTests(BasePublicationTests): def setUp(self): super(AuthZopePublicationTests, self).setUp() principalRegistry.defineDefaultPrincipal('anonymous', '') root = self.db.open().root() app = root[ZopePublication.root_name] app['f1'] = rootFolder() f1 = app['f1'] f1['f2'] = Folder() if not ISite.providedBy(f1): f1.setSiteManager(LocalSiteManager(f1)) sm1 = f1.getSiteManager() addUtility(sm1, '', IAuthentication, AuthUtility1()) f2 = f1['f2'] if not ISite.providedBy(f2): f2.setSiteManager(LocalSiteManager(f2)) sm2 = f2.getSiteManager() addUtility(sm2, '', IAuthentication, AuthUtility2()) transaction.commit() from zope.container.interfaces import ISimpleReadContainer from zope.container.traversal import ContainerTraverser component.provideAdapter(ContainerTraverser, (ISimpleReadContainer, IRequest), IPublishTraverse, name='') from zope.site.interfaces import IFolder from zope.security.checker import defineChecker, InterfaceChecker defineChecker(Folder, InterfaceChecker(IFolder)) def testPlacefulAuth(self): self.publication.beforeTraversal(self.request) self.assertEqual(list(queryInteraction().participations), [self.request]) self.assertEqual(self.request.principal.id, 'anonymous') root = self.publication.getApplication(self.request) self.publication.callTraversalHooks(self.request, root) self.assertEqual(self.request.principal.id, 'anonymous') ob = self.publication.traverseName(self.request, root, 'f1') self.publication.callTraversalHooks(self.request, ob) self.assertEqual(self.request.principal.id, 'test.anonymous') ob = self.publication.traverseName(self.request, ob, 'f2') self.publication.afterTraversal(self.request, ob) self.assertEqual(self.request.principal.id, 'test.bob') self.assertEqual(list(queryInteraction().participations), [self.request]) self.publication.endRequest(self.request, ob) self.assertEqual(queryInteraction(), None) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(ZopePublicationTests), unittest.makeSuite(AuthZopePublicationTests), unittest.makeSuite(ZopePublicationErrorHandling), )) if __name__ == '__main__': unittest.TextTestRunner().run(test_suite()) zope.app.publication-3.14.0/src/zope/app/publication/tests/test_xmlrpcpublication.py0000644000175000017500000001026211726417511030334 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """XML-RPC Publication Tests """ import unittest from zope.app.publication.tests.test_zopepublication import \ BasePublicationTests from zope.app.publication.traversers import TestTraverser from zope.app.publication.traversers import SimpleComponentTraverser from zope.app.publication.xmlrpc import XMLRPCPublication from zope.interface import Interface, implements from zope.proxy import removeAllProxies from zope.publisher.interfaces import NotFound from zope.publisher.interfaces.xmlrpc import IXMLRPCView from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest from zope.publisher.interfaces.xmlrpc import IXMLRPCPublisher from zope.publisher.xmlrpc import TestRequest from zope.app.publication.tests import support from zope import component class SimpleObject(object): def __init__(self, v): self.v = v class XMLRPCPublicationTests(BasePublicationTests): klass = XMLRPCPublication def _createRequest(self, path, publication, **kw): request = TestRequest(PATH_INFO=path, **kw) request.setPublication(publication) return request def testTraverseName(self): pub = self.klass(self.db) class C(object): x = SimpleObject(1) ob = C() r = self._createRequest('/x', pub) component.provideAdapter(TestTraverser, (None, IXMLRPCRequest), IXMLRPCPublisher) ob2 = pub.traverseName(r, ob, 'x') self.assertEqual(removeAllProxies(ob2).v, 1) def testDenyDirectMethodAccess(self): pub = self.klass(self.db) class I(Interface): pass class C(object): implements(I) def foo(self): return 'bar' class V(object): def __init__(self, context, request): pass implements(IXMLRPCView) ob = C() r = self._createRequest('/foo', pub) component.provideAdapter(V, (I, IXMLRPCView), Interface, name='view') support.setDefaultViewName(I, 'view', type=IXMLRPCView) self.assertRaises(NotFound, pub.traverseName, r, ob, 'foo') def testTraverseNameView(self): pub = self.klass(self.db) class I(Interface): pass class C(object): implements(I) ob = C() class V(object): def __init__(self, context, request): pass implements(IXMLRPCView) # Register the simple traverser so we can traverse without @@ component.provideAdapter(SimpleComponentTraverser, (Interface, IXMLRPCRequest), IXMLRPCPublisher) r = self._createRequest('/@@spam', pub) component.provideAdapter(V, (I, IXMLRPCRequest), Interface, name='spam') ob2 = pub.traverseName(r, ob, '@@spam') self.assertEqual(removeAllProxies(ob2).__class__, V) ob2 = pub.traverseName(r, ob, 'spam') self.assertEqual(removeAllProxies(ob2).__class__, V) def testTraverseNameSiteManager(self): pub = self.klass(self.db) class C(object): def getSiteManager(self): return SimpleObject(1) ob = C() r = self._createRequest('/++etc++site',pub) ob2 = pub.traverseName(r, ob, '++etc++site') self.assertEqual(removeAllProxies(ob2).v, 1) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(XMLRPCPublicationTests), )) if __name__ == '__main__': unittest.main() zope.app.publication-3.14.0/src/zope/app/publication/tests/test_simplecomponenttraverser.py0000644000175000017500000000432611726417511031753 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """Sample Component Traverser Test """ import unittest from zope.publisher.interfaces import NotFound from zope.interface import Interface, directlyProvides from zope.app.publication.traversers import SimpleComponentTraverser from zope import component class I(Interface): pass class Container(object): def __init__(self, **kw): for k in kw: setattr(self, k , kw[k]) def get(self, name, default=None): return getattr(self, name, default) class Request(object): def __init__(self, type): directlyProvides(self, type) def getEffectiveURL(self): return '' class View(object): def __init__(self, comp, request): self._comp = comp class Test(unittest.TestCase): def testAttr(self): # test container traver foo = Container() c = Container(foo=foo) req = Request(I) T = SimpleComponentTraverser(c, req) self.assertRaises(NotFound , T.publishTraverse, req ,'foo') def testView(self): # test getting a view foo = Container() c = Container(foo=foo) req = Request(I) T = SimpleComponentTraverser(c, req) component.provideAdapter(View, (None, I), Interface, name='foo') self.failUnless(T.publishTraverse(req, 'foo').__class__ is View) self.assertRaises(NotFound, T.publishTraverse, req , 'morebar') def test_suite(): loader = unittest.TestLoader() return loader.loadTestsFromTestCase(Test) if __name__ == '__main__': unittest.TextTestRunner().run(test_suite()) zope.app.publication-3.14.0/src/zope/app/publication/tests/test_requestpublicationregistry.py0000644000175000017500000001203011726417511032303 0ustar adiadi00000000000000############################################################################## # # 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 for the HTTP Publication Request Factory. """ from unittest import TestCase, TestSuite, main, makeSuite from StringIO import StringIO from zope import component, interface from zope.interface.verify import verifyClass from zope.component.testing import PlacelessSetup from zope.configuration.exceptions import ConfigurationError from zope.app.publication import interfaces from zope.app.publication.interfaces import IRequestPublicationRegistry from zope.app.publication.requestpublicationregistry import \ RequestPublicationRegistry from zope.app.publication.requestpublicationfactories import \ HTTPFactory, SOAPFactory, BrowserFactory, XMLRPCFactory def DummyFactory(): return object class DummyRequestFactory(object): def __call__(self, input_stream, env): self.input_stream = input_stream self.env = env return self def setPublication(self, pub): self.pub = pub class Test(PlacelessSetup, TestCase): def test_interface(self): verifyClass(IRequestPublicationRegistry, RequestPublicationRegistry) def test_registration(self): r = RequestPublicationRegistry() xmlrpc_f = DummyFactory() r.register('POST', 'text/xml', 'xmlrpc', 0, xmlrpc_f) soap_f = DummyFactory() r.register('POST', 'text/xml', 'soap', 1, soap_f) browser_f = DummyFactory() r.register('*', '*', 'browser_default', 0, browser_f) l = r.getFactoriesFor('POST', 'text/xml') self.assertEqual( l, [{'name' : 'soap', 'priority' : 1, 'factory' : object}, {'name' : 'xmlrpc', 'priority' : 0, 'factory' : object}]) self.assertEqual(r.getFactoriesFor('POST', 'text/html'), None) def test_configuration_same_priority(self): r = RequestPublicationRegistry() xmlrpc_f = DummyFactory() r.register('POST', 'text/xml', 'xmlrpc', 0, DummyFactory) r.register('POST', 'text/xml', 'soap', 1, DummyFactory()) # try to register a factory with the same priority self.assertRaises(ConfigurationError, r.register, 'POST', 'text/xml', 'soap2', 1, DummyFactory()) def test_configuration_reregistration(self): r = RequestPublicationRegistry() xmlrpc_f = DummyFactory() r.register('POST', 'text/xml', 'xmlrpc', 0, DummyFactory) r.register('POST', 'text/xml', 'soap', 1, DummyFactory()) # re-register 'soap' but with priority 2 r.register('POST', 'text/xml', 'soap', 2, DummyFactory()) factory_data = r.getFactoriesFor('POST', 'text/xml') priorities = [item['priority'] for item in factory_data] self.assertEqual(priorities, [2, 0]) def test_realfactories(self): r = RequestPublicationRegistry() r.register('POST', '*', 'post_fallback', 0, HTTPFactory()) r.register('POST', 'text/xml', 'xmlrpc', 1, XMLRPCFactory()) r.register('POST', 'text/xml', 'soap', 2, SOAPFactory()) r.register('GET', '*', 'http', 0, HTTPFactory()) r.register('PUT', '*', 'http', 0, HTTPFactory()) r.register('HEAD', '*', 'http', 0, HTTPFactory()) r.register('*', '*', 'http', 1, BrowserFactory()) self.assertEqual(len(r.getFactoriesFor('POST', 'text/xml')) , 2) self.assertEqual(len(r.getFactoriesFor('POST', 'text/xml; charset=utf-8')) , 2) self.assertEqual(len(r.getFactoriesFor('POST', '*')) , 1) self.assertEqual(r.getFactoriesFor('GET', 'text/html') , None) self.assertEqual(len(r.getFactoriesFor('HEAD', '*')) , 1) env = { 'SERVER_URL': 'http://127.0.0.1', 'HTTP_HOST': '127.0.0.1', 'CONTENT_LENGTH': '0', 'GATEWAY_INTERFACE': 'TestFooInterface/1.0', } soaprequestfactory = DummyRequestFactory() interface.directlyProvides( soaprequestfactory, interfaces.ISOAPRequestFactory) component.provideUtility(soaprequestfactory) self.assert_( isinstance(r.lookup('POST', 'text/xml', env), XMLRPCFactory)) env['HTTP_SOAPACTION'] = 'foo' self.assert_( isinstance(r.lookup('POST', 'text/xml', env), SOAPFactory)) self.assert_( isinstance(r.lookup('FOO', 'zope/sucks', env), BrowserFactory)) def test_suite(): return TestSuite(( makeSuite(Test), )) if __name__=='__main__': main(defaultTest='test_suite') zope.app.publication-3.14.0/src/zope/app/publication/tests/test_requestpublicationfactories.py0000644000175000017500000001036111726417511032417 0ustar adiadi00000000000000############################################################################## # # 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 for the HTTP Publication Request Factory. """ from unittest import TestCase, TestSuite, main, makeSuite from zope import component, interface from zope.publisher.browser import BrowserRequest from zope.publisher.http import HTTPRequest from zope.publisher.xmlrpc import XMLRPCRequest from zope.component.testing import PlacelessSetup from zope.app.publication.browser import BrowserPublication from zope.app.publication.http import HTTPPublication from zope.app.publication.xmlrpc import XMLRPCPublication from zope.app.publication import interfaces from zope.app.publication.requestpublicationfactories import \ SOAPFactory, XMLRPCFactory, HTTPFactory, BrowserFactory from zope.app.publication.soap import SOAPPublication from zope.app.publication.browser import BrowserPublication class DummyRequestFactory(object): def __call__(self, input_stream, env): self.input_stream = input_stream self.env = env return self def setPublication(self, pub): self.pub = pub class Test(PlacelessSetup, TestCase): def setUp(self): super(Test, self).setUp() self.__env = { 'SERVER_URL': 'http://127.0.0.1', 'HTTP_HOST': '127.0.0.1', 'CONTENT_LENGTH': '0', 'GATEWAY_INTERFACE': 'TestFooInterface/1.0', } def test_soapfactory(self): soaprequestfactory = DummyRequestFactory() interface.directlyProvides( soaprequestfactory, interfaces.ISOAPRequestFactory) component.provideUtility(soaprequestfactory) env = self.__env factory = SOAPFactory() self.assertEqual(factory.canHandle(env), False) env['HTTP_SOAPACTION'] = 'server:foo' self.assertEqual(factory.canHandle(env), True) request, publication = factory() self.assertEqual(isinstance(request, DummyRequestFactory), True) self.assertEqual(publication, SOAPPublication) def test_xmlrpcfactory(self): xmlrpcrequestfactory = DummyRequestFactory() interface.directlyProvides( xmlrpcrequestfactory, interfaces.IXMLRPCRequestFactory) component.provideUtility(xmlrpcrequestfactory) env = self.__env factory = XMLRPCFactory() self.assertEqual(factory.canHandle(env), True) request, publication = factory() self.assertEqual(isinstance(request, DummyRequestFactory), True) self.assertEqual(publication, XMLRPCPublication) def test_httpfactory(self): httprequestfactory = DummyRequestFactory() interface.directlyProvides( httprequestfactory, interfaces.IHTTPRequestFactory) component.provideUtility(httprequestfactory) env = self.__env factory = HTTPFactory() self.assertEqual(factory.canHandle(env), True) request, publication = factory() self.assertEqual(isinstance(request, DummyRequestFactory), True) self.assertEqual(publication, HTTPPublication) def test_browserfactory(self): browserrequestfactory = DummyRequestFactory() interface.directlyProvides( browserrequestfactory, interfaces.IBrowserRequestFactory) component.provideUtility(browserrequestfactory) env = self.__env factory = BrowserFactory() self.assertEqual(factory.canHandle(env), True) request, publication = factory() self.assertEqual(isinstance(request, DummyRequestFactory), True) self.assertEqual(publication, BrowserPublication) def test_suite(): return TestSuite(( makeSuite(Test), )) if __name__=='__main__': main(defaultTest='test_suite') zope.app.publication-3.14.0/src/zope/app/publication/tests/test_proxycontrol.py0000644000175000017500000000701011726417511027354 0ustar adiadi00000000000000############################################################################## # # Copyright (c) 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. # ############################################################################## import doctest import unittest import zope.app.publication.browser import zope.component import zope.interface import zope.publisher.interfaces.browser from zope.testing import cleanup import zope.traversing.namespace class Proxy: def __init__(self, context): print "Proxy called" self.context = context class Publication(zope.app.publication.browser.BrowserPublication): def proxy(self, ob): return Proxy(ob) class Sample: "Sample object for testing" class Response: def reset(self): pass def handleException(self, *args): pass class Request: principal = None method = 'GET' def __init__(self): self.annotations = {} self.response = Response() def hold(self, ob): pass def getTraversalStack(self): return [] def getURL(self): return '/' class DB: def open(self): return self def root(self): return self def get(self, key, default=None): assert key == 'Application' return Sample() def close(self): pass class Publisher: zope.interface.implements( zope.publisher.interfaces.browser.IBrowserPublisher) def __init__(self, context, request): self.context = context def publishTraverse(self, request, name): result = Sample() result.__name__ = name return result def browserDefault(self, request): return self.context, ['foo'] def proxy_control(): """You can override proxy control in a subclass This test makes sure the override is called in the cases where the publication wants to call ProxyFactory. >>> cleanup.cleanUp() >>> zope.component.provideAdapter(Publisher, (Sample, Request)) >>> zope.component.provideAdapter(Publisher, (Sample, Request), name='foo') >>> zope.component.provideAdapter(zope.traversing.namespace.view, ... (Sample, Request), name='view') >>> pub = Publication(DB()) >>> request = Request() >>> ob = pub.getApplication(request) Proxy called >>> isinstance(ob, Proxy) and isinstance(ob.context, Sample) True >>> sample = Sample() >>> ob = pub.traverseName(request, sample, 'x') Proxy called >>> isinstance(ob, Proxy) and ob.context.__name__ == 'x' True >>> ob = pub.traverseName(request, sample, '@@foo') Proxy called >>> isinstance(ob, Proxy) and isinstance(ob.context, Publisher) True >>> ob, path = pub.getDefaultTraversal(request, sample) Proxy called >>> isinstance(ob, Proxy) and ob.context == sample and path == ['foo'] True >>> pub.handleException(sample, request, (ValueError, ValueError(), None)) Proxy called >>> cleanup.cleanUp() """ def test_suite(): return unittest.TestSuite(( doctest.DocTestSuite(), )) if __name__ == '__main__': unittest.main(defaultTest='test_suite') zope.app.publication-3.14.0/src/zope/app/publication/tests/test_httpfactory.py0000644000175000017500000001431711726417511027151 0ustar adiadi00000000000000############################################################################## # # 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 for the HTTP Publication Request Factory. """ from unittest import TestCase, TestSuite, main, makeSuite from StringIO import StringIO from zope import component, interface from zope.publisher.browser import BrowserRequest from zope.publisher.http import HTTPRequest from zope.publisher.xmlrpc import XMLRPCRequest from zope.component.testing import PlacelessSetup from zope.app.publication.httpfactory import HTTPPublicationRequestFactory from zope.app.publication.browser import BrowserPublication from zope.app.publication.http import HTTPPublication from zope.app.publication.xmlrpc import XMLRPCPublication from zope.app.publication import interfaces from zope.app.publication.requestpublicationregistry import factoryRegistry from zope.app.publication.requestpublicationfactories import \ HTTPFactory, SOAPFactory, BrowserFactory, XMLRPCFactory class DummyRequestFactory(object): def __call__(self, input_stream, env): self.input_stream = input_stream self.env = env return self def setPublication(self, pub): self.pub = pub class Test(PlacelessSetup, TestCase): def setUp(self): super(Test, self).setUp() self.__factory = HTTPPublicationRequestFactory(None) self.__env = { 'SERVER_URL': 'http://127.0.0.1', 'HTTP_HOST': '127.0.0.1', 'CONTENT_LENGTH': '0', 'GATEWAY_INTERFACE': 'TestFooInterface/1.0', } # Simulate standard configuration factoryRegistry.register('GET', '*', 'browser', 0, BrowserFactory()) factoryRegistry.register('POST', '*', 'browser', 0, BrowserFactory()) factoryRegistry.register('HEAD', '*', 'browser', 0, BrowserFactory()) factoryRegistry.register('*', '*', 'http', 0, HTTPFactory()) factoryRegistry.register('POST', 'text/xml', 'xmlrpc', 20, XMLRPCFactory()) factoryRegistry.register('POST', 'text/xml', 'soap', 30, SOAPFactory()) def test_override(self): # TODO: making a SOAP request without configuring a SOAP request # currently generates an XMLRPC request. Not sure what the right thing # is, but that doesn't seem to be the right thing. soaprequestfactory = DummyRequestFactory() interface.directlyProvides( soaprequestfactory, interfaces.ISOAPRequestFactory) component.provideUtility(soaprequestfactory) xmlrpcrequestfactory = DummyRequestFactory() interface.directlyProvides( xmlrpcrequestfactory, interfaces.IXMLRPCRequestFactory) component.provideUtility(xmlrpcrequestfactory) httprequestfactory = DummyRequestFactory() interface.directlyProvides( httprequestfactory, interfaces.IHTTPRequestFactory) component.provideUtility(httprequestfactory) browserrequestfactory = DummyRequestFactory() interface.directlyProvides( browserrequestfactory, interfaces.IBrowserRequestFactory) component.provideUtility(browserrequestfactory) httpfactory = HTTPPublicationRequestFactory(None) env = self.__env env['REQUEST_METHOD'] = 'POST' env['CONTENT_TYPE'] = 'text/xml' input = StringIO('') env['HTTP_SOAPACTION'] = 'foo' self.assertEqual(httpfactory(input, env), soaprequestfactory) del env['HTTP_SOAPACTION'] self.assertEqual(httpfactory(input, env), xmlrpcrequestfactory) env['CONTENT_TYPE'] = 'text/foo' self.assertEqual( httpfactory(input, env), browserrequestfactory) env['REQUEST_METHOD'] = 'FLOO' self.assertEqual(httpfactory(input, env), httprequestfactory) def test_browser(self): r = self.__factory(StringIO(''), self.__env) self.assertEqual(r.__class__, BrowserRequest) self.assertEqual(r.publication.__class__, BrowserPublication) for method in ('GET', 'HEAD', 'POST', 'get', 'head', 'post'): self.__env['REQUEST_METHOD'] = method r = self.__factory(StringIO(''), self.__env) self.assertEqual(r.__class__, BrowserRequest) self.assertEqual(r.publication.__class__, BrowserPublication) def test_http(self): for method in ('PUT', 'put', 'ZZZ'): self.__env['REQUEST_METHOD'] = method r = self.__factory(StringIO(''), self.__env) self.assertEqual(r.__class__, HTTPRequest) self.assertEqual(r.publication.__class__, HTTPPublication) def test_xmlrpc(self): self.__env['CONTENT_TYPE'] = 'text/xml' for method in ('POST', 'post'): self.__env['REQUEST_METHOD'] = method r = self.__factory(StringIO(''), self.__env) self.assertEqual(r.__class__, XMLRPCRequest) self.assertEqual(r.publication.__class__, XMLRPCPublication) # content type doesn't matter for non post for method in ('GET', 'HEAD', 'get', 'head'): self.__env['REQUEST_METHOD'] = method r = self.__factory(StringIO(''), self.__env) self.assertEqual(r.__class__, BrowserRequest) self.assertEqual(r.publication.__class__, BrowserPublication) for method in ('PUT', 'put', 'ZZZ'): self.__env['REQUEST_METHOD'] = method r = self.__factory(StringIO(''), self.__env) self.assertEqual(r.__class__, HTTPRequest) self.assertEqual(r.publication.__class__, HTTPPublication) def test_suite(): return TestSuite(( makeSuite(Test), )) if __name__=='__main__': main(defaultTest='test_suite') zope.app.publication-3.14.0/src/zope/app/publication/tests/test_http.py0000644000175000017500000000336511726417511025562 0ustar adiadi00000000000000############################################################################## # # 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. # ############################################################################## """Test HTTP Publication """ from unittest import TestCase, TestSuite, main, makeSuite from StringIO import StringIO from zope.interface import Interface, implements from zope.publisher.http import HTTPRequest from zope.publisher.interfaces.http import IHTTPRequest import zope.app.publication.http from zope import component class I(Interface): pass class C(object): spammed = 0 implements(I) class V(object): def __init__(self, context, request): self.context = context def SPAM(self): self.context.spammed += 1 class Test(TestCase): # Note that zope publication tests cover all of the code but callObject def test_callObject(self): pub = zope.app.publication.http.HTTPPublication(None) request = HTTPRequest(StringIO(''), {}) request.method = 'SPAM' component.provideAdapter(V, (I, IHTTPRequest), Interface, name='SPAM') ob = C() pub.callObject(request, ob) self.assertEqual(ob.spammed, 1) def test_suite(): return TestSuite(( makeSuite(Test), )) if __name__=='__main__': main(defaultTest='test_suite') zope.app.publication-3.14.0/src/zope/app/publication/tests/test_functional.py0000644000175000017500000000335611726417511026745 0ustar adiadi00000000000000############################################################################## # # Copyright (c) 2004 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Test not found errors """ import doctest import re import unittest from zope.testing import renormalizing from zope.app.publication.testing import PublicationLayer checker = renormalizing.RENormalizing([ (re.compile(r"HTTP/1\.([01]) (\d\d\d) .*"), r"HTTP/1.\1 \2 "), ]) optionflags = doctest.ELLIPSIS+doctest.NORMALIZE_WHITESPACE def test_suite(): methodnotallowed = doctest.DocFileSuite( '../methodnotallowed.txt', optionflags=optionflags) methodnotallowed.layer = PublicationLayer notfound = doctest.DocFileSuite( '../notfound.txt', optionflags=optionflags) notfound.layer = PublicationLayer httpfactory = doctest.DocFileSuite( '../httpfactory.txt', checker=checker, optionflags=optionflags) httpfactory.layer = PublicationLayer site = doctest.DocFileSuite( '../site.txt', optionflags=optionflags) site.layer = PublicationLayer return unittest.TestSuite(( methodnotallowed, notfound, httpfactory, site,)) if __name__ == '__main__': unittest.main(defaultTest='test_suite') zope.app.publication-3.14.0/src/zope/app/publication/tests/test_dependencies.py0000644000175000017500000000222611726417511027224 0ustar adiadi00000000000000import os import unittest from zope.app.publication.traversers import SimpleComponentTraverser from zope.component import getMultiAdapter from zope.component.testlayer import ZCMLFileLayer from zope.interface import implements from zope.publisher.browser import TestRequest from zope.publisher.interfaces.browser import IBrowserPublisher import zope.app.publication.tests class ZCMLDependencies(unittest.TestCase): layer = ZCMLFileLayer(zope.app.publication.tests, zcml_file='ftest_zcml_dependencies.zcml', name='PublicationDependenciesLayer') def test_zcml_can_load_with_only_zope_component_meta(self): # this is just an example. It is supposed to show that the # configure.zcml file has loaded successfully. request = TestRequest() sample = object() res = getMultiAdapter( (sample, request), IBrowserPublisher) self.failUnless(isinstance(res, SimpleComponentTraverser)) self.failUnless(res.context is sample) def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(ZCMLDependencies)) return suite zope.app.publication-3.14.0/src/zope/app/publication/tests/test_browserpublication.py0000644000175000017500000002702311726417511030515 0ustar adiadi00000000000000############################################################################## # # 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 Publication Tests """ import unittest from StringIO import StringIO from zope import component from zope.security.interfaces import ForbiddenAttribute from zope.interface import Interface, implements from zope.publisher.publish import publish from zope.publisher.browser import TestRequest, BrowserView from zope.publisher.interfaces.browser import (IBrowserPublisher, IDefaultBrowserLayer) from zope.proxy import getProxiedObject from zope.security.proxy import Proxy, removeSecurityProxy from zope.security.checker import defineChecker, NamesChecker from zope.principalregistry.principalregistry import principalRegistry from zope.app.publication.browser import BrowserPublication from zope.app.publication.httpfactory import HTTPPublicationRequestFactory from zope.app.publication.traversers import TestTraverser from zope.app.publication.tests.test_zopepublication \ import BasePublicationTests as BasePublicationTests_ from zope.app.publication.tests import support from persistent import Persistent def foo(): "I am an otherwise empty docstring." return 'hello base fans' class DummyPublished(object): implements(IBrowserPublisher) def publishTraverse(self, request, name): if name == 'bruce': return foo raise KeyError(name) def browserDefault(self, request): return self, ['bruce'] class DummyView(DummyPublished, BrowserView): __Security_checker__ = NamesChecker(["browserDefault", "publishTraverse"]) class BasePublicationTests(BasePublicationTests_): def _createRequest(self, path, publication, **kw): request = TestRequest(PATH_INFO=path, **kw) request.setPublication(publication) return request class SimpleObject(object): def __init__(self, v): self.v = v class I1(Interface): pass class mydict(dict): implements(I1) class O1(Persistent): implements(I1) class BrowserDefaultTests(BasePublicationTests): """ test browser default many views lead to a default view """ klass = BrowserPublication def testBaseTagNoBase(self): self._testBaseTags('/somepath/@@view/', '') def testBaseTag1(self): self._testBaseTags('/somepath/@@view', 'http://127.0.0.1/somepath/@@view/bruce') def testBaseTag2(self): self._testBaseTags('/somepath/', 'http://127.0.0.1/somepath/@@view/bruce') def testBaseTag3(self): self._testBaseTags('/somepath', 'http://127.0.0.1/somepath/@@view/bruce') def _testBaseTags(self, url, expected): # Make sure I1 and O1 are visible in the module namespace # so that the classes can be pickled. import transaction pub = BrowserPublication(self.db) component.provideAdapter(DummyView, (I1, IDefaultBrowserLayer), Interface, name='view') support.setDefaultViewName(I1, 'view') component.provideAdapter(TestTraverser, (None, IDefaultBrowserLayer), IBrowserPublisher) ob = O1() ## the following is for running the tests standalone principalRegistry.defineDefaultPrincipal( 'tim', 'timbot', 'ai at its best') # now place our object inside the application connection = self.db.open() app = connection.root()['Application'] app.somepath = ob transaction.commit() connection.close() defineChecker(app.__class__, NamesChecker(somepath='xxx')) req = self._createRequest(url, pub) response = req.response publish(req, handle_errors=0) self.assertEqual(response.getBase(), expected) def _createRequest(self, path, publication, **kw): request = TestRequest(PATH_INFO=path, **kw) request.setPublication(publication) return request class BrowserPublicationTests(BasePublicationTests): klass = BrowserPublication def testAdaptedTraverseNameWrapping(self): class Adapter(object): implements(IBrowserPublisher) def __init__(self, context, request): self.context = context self.counter = 0 def publishTraverse(self, request, name): self.counter += 1 return self.context[name] component.provideAdapter(Adapter, (I1, IDefaultBrowserLayer), IBrowserPublisher) ob = mydict() ob['bruce'] = SimpleObject('bruce') ob['bruce2'] = SimpleObject('bruce2') pub = self.klass(self.db) ob2 = pub.traverseName(self._createRequest('/bruce', pub), ob, 'bruce') self.assertRaises(ForbiddenAttribute, getattr, ob2, 'v') self.assertEqual(removeSecurityProxy(ob2).v, 'bruce') def testAdaptedTraverseDefaultWrapping(self): # Test default content and make sure that it's wrapped. class Adapter(object): implements(IBrowserPublisher) def __init__(self, context, request): self.context = context def browserDefault(self, request): return (self.context['bruce'], 'dummy') component.provideAdapter(Adapter, (I1, IDefaultBrowserLayer), IBrowserPublisher) ob = mydict() ob['bruce'] = SimpleObject('bruce') ob['bruce2'] = SimpleObject('bruce2') pub = self.klass(self.db) ob2, x = pub.getDefaultTraversal(self._createRequest('/bruce',pub), ob) self.assertEqual(x, 'dummy') self.assertRaises(ForbiddenAttribute, getattr, ob2, 'v') self.assertEqual(removeSecurityProxy(ob2).v, 'bruce') def testTraverseName(self): pub = self.klass(self.db) class C(object): x = SimpleObject(1) ob = C() r = self._createRequest('/x',pub) component.provideAdapter(TestTraverser, (None, IDefaultBrowserLayer), IBrowserPublisher) ob2 = pub.traverseName(r, ob, 'x') self.assertRaises(ForbiddenAttribute, getattr, ob2, 'v') self.assertEqual(removeSecurityProxy(ob2).v, 1) self.assert_(pub.traverseName(r, ob, '.') is ob) def testTraverseNameView(self): pub = self.klass(self.db) class I(Interface): pass class C(object): implements(I) ob = C() class V(object): def __init__(self, context, request): pass r = self._createRequest('/@@spam',pub) component.provideAdapter(V, (I, IDefaultBrowserLayer), Interface, name='spam') ob2 = pub.traverseName(r, ob, '@@spam') self.assertEqual(ob2.__class__, V) def testTraverseNameSiteManager(self): pub = self.klass(self.db) class C(object): def getSiteManager(self): return SimpleObject(1) ob = C() r = self._createRequest('/++etc++site',pub) ob2 = pub.traverseName(r, ob, '++etc++site') self.assertRaises(ForbiddenAttribute, getattr, ob2, 'v') self.assertEqual(removeSecurityProxy(ob2).v, 1) def testTraverseNameApplicationControl(self): from zope.applicationcontrol.applicationcontrol \ import applicationController, applicationControllerRoot from zope.traversing.interfaces import IEtcNamespace component.provideUtility(applicationController, IEtcNamespace, name='process') pub = self.klass(self.db) r = self._createRequest('/++etc++process',pub) ac = pub.traverseName(r, applicationControllerRoot, '++etc++process') self.assertEqual(ac, applicationController) r = self._createRequest('/++etc++process',pub) app = r.publication.getApplication(r) self.assertEqual(app, applicationControllerRoot) def testHEADFuxup(self): pub = self.klass(None) class User(object): id = 'bob' # With a normal request, we should get a body: request = TestRequest(StringIO(''), {'PATH_INFO': '/'}) request.setPrincipal(User()) request.response.setResult(u"spam") pub.afterCall(request, None) self.assertEqual(request.response.consumeBody(), 'spam' ) # But with a HEAD request, the body should be empty request = TestRequest(StringIO(''), {'PATH_INFO': '/'}) request.setPrincipal(User()) request.method = 'HEAD' request.response.setResult(u"spam") pub.afterCall(request, None) self.assertEqual(request.response.consumeBody(), '') def testUnicode_NO_HTTP_CHARSET(self): # Test so that a unicode body doesn't cause a UnicodeEncodeError request = TestRequest(StringIO(''), {}) request.response.setResult(u"\u0442\u0435\u0441\u0442") headers = request.response.getHeaders() headers.sort() self.assertEqual( headers, [('Content-Length', '8'), ('Content-Type', 'text/plain;charset=utf-8'), ('X-Content-Type-Warning', 'guessed from content'), ('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)')]) self.assertEqual( request.response.consumeBody(), '\xd1\x82\xd0\xb5\xd1\x81\xd1\x82') class HTTPPublicationRequestFactoryTests(BasePublicationTests): def setUp(self): super(BasePublicationTests, self).setUp() from zope.app.publication.requestpublicationregistry import \ factoryRegistry from zope.app.publication.requestpublicationfactories \ import SOAPFactory, XMLRPCFactory, HTTPFactory, BrowserFactory factoryRegistry.register('*', '*', 'HTTP', 0, HTTPFactory()) factoryRegistry.register('POST', 'text/xml', 'SOAP', 20, SOAPFactory()) factoryRegistry.register('POST', 'text/xml', 'XMLRPC', 10, XMLRPCFactory()) factoryRegistry.register('GET', '*', 'BROWSER', 10, BrowserFactory()) factoryRegistry.register('POST', '*', 'BROWSER', 10, BrowserFactory()) factoryRegistry.register('HEAD', '*', 'BROWSER', 10, BrowserFactory()) def testGetBackSamePublication(self): factory = HTTPPublicationRequestFactory(db=None) args = (StringIO(''), {}) self.assert_(id(factory(*args).publication) == id(factory(*args).publication)) def test_suite(): return unittest.TestSuite(( unittest.makeSuite(BrowserPublicationTests, 'test'), unittest.makeSuite(BrowserDefaultTests, 'test'), unittest.makeSuite(HTTPPublicationRequestFactoryTests, 'test'), )) if __name__ == '__main__': unittest.TextTestRunner().run(test_suite()) zope.app.publication-3.14.0/src/zope/app/publication/tests/support.py0000644000175000017500000000256011726417511025254 0ustar adiadi00000000000000# an API to help us do some component registrations for # the publisher to help with the testing. # This functionality is also implemented in zope.app.testing. # this functionality has two problems: # * the code is extremely hard to understand as it papers over # the zope.component APIs # * we want to lift the dependency on zope.app.testing for other reasons # it's possible that this code should end up in published test support modules # in other packages deeper down (zope.publisher, zope.traversing). The # fact that we have to import interfaces from these gives us this # clue. We will investigate pushing them down to these packages # later. from zope import component from zope.traversing.interfaces import ITraversable from zope.publisher.interfaces import IDefaultViewName from zope.publisher.interfaces.browser import (IDefaultBrowserLayer, IBrowserRequest) def provideNamespaceHandler(name, handler): component.provideAdapter(handler, (None,), ITraversable, name=name) component.provideAdapter(handler, (None, None), ITraversable, name=name) def setDefaultViewName(for_, name, layer=IDefaultBrowserLayer, type=IBrowserRequest): if layer is None: layer = type component.provideAdapter(name, (for_, layer), IDefaultViewName) zope.app.publication-3.14.0/src/zope/app/publication/tests/ftest_zcml_dependencies.zcml0000644000175000017500000000045411726417511030735 0ustar adiadi00000000000000 zope.app.publication-3.14.0/src/zope/app/publication/tests/__init__.py0000644000175000017500000000007511726417511025276 0ustar adiadi00000000000000# # This file is necessary to make this directory a package.