zope.app.wsgi-3.15.0/0000755000175000017500000000000011706030677012433 5ustar jimjimzope.app.wsgi-3.15.0/bootstrap.py0000644000175000017500000002352211706030370015014 0ustar jimjim############################################################################## # # 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, textwrap, urllib, urllib2, subprocess from optparse import OptionParser if sys.platform == 'win32': def quote(c): if ' ' in c: return '"%s"' % c # work around spawn lamosity on windows else: return c else: quote = str # See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. stdout, stderr = subprocess.Popen( [sys.executable, '-Sc', 'try:\n' ' import ConfigParser\n' 'except ImportError:\n' ' print 1\n' 'else:\n' ' print 0\n'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() has_broken_dash_S = bool(int(stdout.strip())) # In order to be more robust in the face of system Pythons, we want to # run without site-packages loaded. This is somewhat tricky, in # particular because Python 2.6's distutils imports site, so starting # with the -S flag is not sufficient. However, we'll start with that: if not has_broken_dash_S and 'site' in sys.modules: # We will restart with python -S. args = sys.argv[:] args[0:0] = [sys.executable, '-S'] args = map(quote, args) os.execv(sys.executable, args) # Now we are running with -S. We'll get the clean sys.path, import site # because distutils will do it later, and then reset the path and clean # out any namespace packages from site-packages that might have been # loaded by .pth files. clean_path = sys.path[:] import site sys.path[:] = clean_path for k, v in sys.modules.items(): if k in ('setuptools', 'pkg_resources') or ( hasattr(v, '__path__') and len(v.__path__)==1 and not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))): # This is a namespace package. Remove it. sys.modules.pop(k) is_jython = sys.platform.startswith('java') setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' distribute_source = 'http://python-distribute.org/distribute_setup.py' # parsing arguments def normalize_to_url(option, opt_str, value, parser): if value: if '://' not in value: # It doesn't smell like a URL. value = 'file://%s' % ( urllib.pathname2url( os.path.abspath(os.path.expanduser(value))),) if opt_str == '--download-base' and not value.endswith('/'): # Download base needs a trailing slash to make the world happy. value += '/' else: value = None name = opt_str[2:].replace('-', '_') setattr(parser.values, name, value) usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. Simply run this script in a directory containing a buildout.cfg, using the Python that you want bin/buildout to use. Note that by using --setup-source and --download-base to point to local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) parser.add_option("-v", "--version", dest="version", help="use a specific zc.buildout version") parser.add_option("-d", "--distribute", action="store_true", dest="use_distribute", default=False, help="Use Distribute rather than Setuptools.") parser.add_option("--setup-source", action="callback", dest="setup_source", callback=normalize_to_url, nargs=1, type="string", help=("Specify a URL or file location for the setup file. " "If you use Setuptools, this will default to " + setuptools_source + "; if you use Distribute, this " "will default to " + distribute_source +".")) parser.add_option("--download-base", action="callback", dest="download_base", callback=normalize_to_url, nargs=1, type="string", help=("Specify a URL or directory for downloading " "zc.buildout and either Setuptools or Distribute. " "Defaults to PyPI.")) parser.add_option("--eggs", help=("Specify a directory for storing eggs. Defaults to " "a temporary directory that is deleted when the " "bootstrap script completes.")) parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, help=("Normally, if you do not specify a --version, the " "bootstrap script and buildout gets the newest " "*final* versions of zc.buildout and its recipes and " "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) parser.add_option("-c", None, action="store", dest="config_file", help=("Specify the path to the buildout configuration " "file to be used.")) options, args = parser.parse_args() # if -c was provided, we push it back into args for buildout's main function if options.config_file is not None: args += ['-c', options.config_file] if options.eggs: eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) else: eggs_dir = tempfile.mkdtemp() if options.setup_source is None: if options.use_distribute: options.setup_source = distribute_source else: options.setup_source = setuptools_source if options.accept_buildout_test_releases: args.append('buildout:accept-buildout-test-releases=true') args.append('bootstrap') try: import pkg_resources import setuptools # A flag. Sometimes pkg_resources is installed alone. if not hasattr(pkg_resources, '_distribute'): raise ImportError except ImportError: ez_code = urllib2.urlopen( options.setup_source).read().replace('\r\n', '\n') ez = {} exec ez_code in ez setup_args = dict(to_dir=eggs_dir, download_delay=0) if options.download_base: setup_args['download_base'] = options.download_base if options.use_distribute: setup_args['no_fake'] = True ez['use_setuptools'](**setup_args) if 'pkg_resources' in sys.modules: reload(sys.modules['pkg_resources']) import pkg_resources # This does not (always?) update the default working set. We will # do it. for path in sys.path: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) cmd = [quote(sys.executable), '-c', quote('from setuptools.command.easy_install import main; main()'), '-mqNxd', quote(eggs_dir)] if not has_broken_dash_S: cmd.insert(1, '-S') find_links = options.download_base if not find_links: find_links = os.environ.get('bootstrap-testing-find-links') if find_links: cmd.extend(['-f', quote(find_links)]) if options.use_distribute: setup_requirement = 'distribute' else: setup_requirement = 'setuptools' ws = pkg_resources.working_set setup_requirement_path = ws.find( pkg_resources.Requirement.parse(setup_requirement)).location env = dict( os.environ, PYTHONPATH=setup_requirement_path) requirement = 'zc.buildout' version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' def _final_version(parsed_version): for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( search_path=[setup_requirement_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) if index.obtain(req) is not None: best = [] bestv = None for dist in index[req.project_name]: distv = dist.parsed_version if _final_version(distv): if bestv is None or distv > bestv: best = [dist] bestv = distv elif distv == bestv: best.append(dist) if best: best.sort() version = best[-1].version if version: requirement = '=='.join((requirement, version)) cmd.append(requirement) if is_jython: import subprocess exitcode = subprocess.Popen(cmd, env=env).wait() else: # Windows prefers this, apparently; otherwise we would prefer subprocess exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) if exitcode != 0: sys.stdout.flush() sys.stderr.flush() print ("An error occurred when trying to install zc.buildout. " "Look above this message for any errors that " "were output by easy_install.") sys.exit(exitcode) ws.add_entry(eggs_dir) ws.require(requirement) import zc.buildout.buildout zc.buildout.buildout.main(args) if not options.eggs: # clean up temporary egg directory shutil.rmtree(eggs_dir) zope.app.wsgi-3.15.0/setup.py0000644000175000017500000000613511706030637014146 0ustar jimjim############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## # This package is developed by the Zope Toolkit project, documented here: # http://docs.zope.org/zopetoolkit # When developing and releasing this package, please follow the documented # Zope Toolkit policies as described by this documentation. ############################################################################## """Setup for zope.app.wsgi package $Id: setup.py 124091 2012-01-19 15:07:11Z jim $ """ from setuptools import setup, find_packages setup(name='zope.app.wsgi', version='3.15.0', url='http://pypi.python.org/pypi/zope.app.wsgi', license='ZPL 2.1', description='WSGI application for the zope.publisher', long_description=\ open('README.txt').read() + \ '\n\n' + \ open('CHANGES.txt').read(), author='Zope Foundation and Contributors', author_email='zope-dev@zope.org', classifiers=['Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Zope Public License', 'Programming Language :: Python', 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', 'Framework :: Zope3', ], packages=find_packages('src'), package_dir = {'': 'src'}, namespace_packages=['zope', 'zope.app'], extras_require = dict(test=[ 'zope.annotation', 'zope.authentication', 'zope.browserpage', 'zope.login', 'zope.password', 'zope.principalregistry', 'zope.securitypolicy', 'zope.testing', 'zope.traversing', ]), install_requires=[ 'setuptools', 'WebTest', 'ZConfig', 'ZODB3', 'zope.app.appsetup >= 3.14', 'zope.processlifetime', 'zope.app.publication', 'zope.event', 'zope.interface', 'zope.publisher', 'zope.security', 'zope.component', 'zope.configuration', 'zope.container', 'zope.error', 'zope.lifecycleevent', 'zope.processlifetime', 'zope.session', 'zope.site', 'zope.testbrowser[wsgi] >= 4.0.0', 'zope.testing', 'zope.traversing', ], entry_points={ 'paste.app_factory': [ 'main = zope.app.wsgi.paste:ZopeApplication' ] }, include_package_data = True, zip_safe = False, ) zope.app.wsgi-3.15.0/PKG-INFO0000644000175000017500000002317211706030677013535 0ustar jimjimMetadata-Version: 1.0 Name: zope.app.wsgi Version: 3.15.0 Summary: WSGI application for the zope.publisher Home-page: http://pypi.python.org/pypi/zope.app.wsgi Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: This package provides the ``WSGIPublisherApplication`` class which exposes the object publishing machinery in ``zope.publisher`` as a WSGI application. It also lets us bring up the Zope application server (parsing ``zope.conf`` and ``site.zcml``) with a mere function call:: >>> db = zope.app.wsgi.config('zope.conf') This is especially useful for debugging. To bring up Zope and obtain the WSGI application object at the same time, use the ``getWSGIApplication`` function. This package also provides an easy to use application factory for PasteDeploy_. You can simply specify an application configuration like this in your Paste configuration file:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf Look for more documentation inside the package itself. .. _PasteDeploy: http://pythonpaste.org/deploy/ ======= CHANGES ======= 3.15.0 (2012-01-19) ------------------- - Fixed: zope.app.wsgi.paste.ZopeApplication didn't emit ProcessStarting events. **NOTE** If an application compensated for this by generating the event, it will need to stop or there will be multiple events emited. (Whether or not multiple events will do any harm is application specific.) 3.14.0 (2012-01-10) ------------------- - Set the WSGI environment's ``REMOTE_USER`` item (if not already set) with the Zope principal label. (This is the same data set in the ``wsgi.logging_info`` environment item.) This change allows user info to be used by `paste.translogger `_ middleware (or any similar middleware that uses ``REMOTE_USER``), which provides access logging. 3.13.0 (2011-03-15) ------------------- - Update to zope.testbrowser 4.0.0 which uses WebTest instead of wsgi_intercept. 3.12.0 (2011-01-25) ------------------- - Fixed ``zope.app.wsgi.testlayer.http`` to work with changes made in version 3.11.0. 3.11.0 (2011-01-24) ------------------- - Moved `wsgi_intercept` support to ``zope.testbrowser.wsgi``, thus requiring at least version 3.11 of this package: - Moved ``zope.app.wsgi.testlayer.Browser`` to ``zope.testbrowser.wsgi.Browser``, but left BBB import here. - Split up ``zope.app.wsgi.testlayer.BrowserLayer`` into generic WSGI browser layer (``zope.testbrowser.wsgi.Layer``) and ZODB/ZOPE specific part (``zope.app.wsgi.testlayer.BrowserLayer`` as before). 3.10.0 (2010-11-18) ------------------- - Add pluggability for setting up WSGI middleware in testlayer. 3.9.3 (2010-10-14) ------------------ - Python 2.7 compatibility for xmlrpc. Transplant of zope.app.testing r116141. 3.9.2 (2010-05-23) ------------------ - Fixed test breakage due to changes in mechanize 0.2.0. 3.9.1 (2010-04-24) ------------------ - Add support for testing XMLRPC using zope.app.wsgi.testlayer. - Fix a bug in the status string handling in zope.app.wsgi.testlayer's FakeResponse. 3.9.0 (2010-04-19) ------------------ - Return a FakeResponse object in zope.app.wsgi.testlayer.http, so it becomes easier to port over tests from zope.app.testing's HTTPCaller. - X-Powered-By header is now stripped by zope.app.wsgi.testlayer as it is by zope.app.testing. - Bugfix: initialize any defined in the config, as zope.app.server does. (Fixes #291147) 3.8.0 (2010-04-14) ------------------ - zope.app.wsgi.testlayer is now a lot more compatible with the HTTPCaller() functionality in zope.app.testing, which it can replace: - same transaction behavior - pending transactions are committed before request and synchronized afterwards. - support for browser.handleErrors (for zope.testbrowser). - support for clear-text (non-base64) Basic authentication headers, which are easier to read in the tests (though not correct in actual HTTP traffic). 3.7.0 (2010-04-13) ------------------ - Rewrite tests in order not to dependent on ``zope.app.testing`` and ``zope.app.zcmlfiles``. - ``zope.app.wsgi.testlayer`` introduces new testing functionality that can replace the old functionality in ``zope.app.testing``. In addition, it supports using ``zope.testbrowser`` with WSGI directly (instead of relying on ``zope.app.testing``, which pulls in a lot of dependencies). The interesting parts are: * ``zope.app.wsgi.testlayer.BrowserLayer``: this sets up a minimal layer that allows you to use the new WSGI-enabled Browser. * ``zope.app.wsgi.testlayer.Browser``: this is a subclass of Browser from ``zope.testbrowser.browser``. Use it instead of ``zope.testbrowser.browser`` directly to use the test browser with WSGI. You need to use ``BrowserLayer`` with your tests for this to work. * ``zope.app.wsgi.testlayer.http``: this is the equivalent to the ``http()`` function in ``zope.app.testing``. It allows low-level HTTP access through WSGI. You need to use ``BrowserLayer`` with your tests for this to work. 3.6.1 (2010-01-29) ------------------ - Support product configuration sections in Zope configuration files. 3.6.0 (2009-06-20) ------------------ - Import database events directly from ``zope.processlifetime`` instead of using BBB imports in ``zope.app.appsetup``. 3.5.2 (2009-04-03) ------------------ - The ``WSGIPublisherApplication`` uses now the ``ILoggingInfo`` concept given from zope.publisher.interfaces.logginginfo for log user infos usable for access logs. This allows you to implement your own access log user info message. See zope.publisher.interfaces.logginginfo.ILoggingInfo for more information. 3.5.1 (2009-03-31) ------------------ - The ``WSGIPublisherApplication`` call now provides a user name in the environment meant for use in logs. 3.5.0 (2009-02-10) ------------------ - Make devmode warning message more generic. We don't nesessary have the `etc/zope.conf` file nowadays when using buildout-based setups. - Add an application factory for Paste. So Zope application can now be easily deployed with Paste .ini configuration like this:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf handle_errors = false The config_file is a required argument, however the handle_errors defaults to True if not specified. Setting it to False allows you to make WSGIPublisherApplication not handle exceptions itself but propagate them to an upper middleware, like WebError or something. - The ``WSGIPublisherApplication`` constructor and ``getWSGIApplication`` function now accept optional ``handle_errors`` argument, described above. - Change mailing list address to zope-dev at zope.org instead of retired one. 3.4.1 (2008-07-30) ------------------ - Added Trove classifiers. - Notify ``WSGIPublisherApplicationCreated`` event when WSGI application is created. - Fixed deprecation warning in ``ftesting.zcml``: ZopeSecurityPolicy moved to ``zope.securitypolicy``. 3.4.0 (2007-09-14) ------------------ - Fixed the tests to run on Python 2.5 as well as Python 2.4. - Split ``getApplication`` into ``config`` and ``getApplication`` so that ``config`` could be reused, for example for debugging. 3.4.0a1 (2007-04-22) -------------------- Initial release as a separate project, corresponds to ``zope.app.wsgi`` from Zope 3.4.0a1 Platform: UNKNOWN Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application Classifier: Framework :: Zope3 zope.app.wsgi-3.15.0/LICENSE.txt0000644000175000017500000000402611706030370014246 0ustar jimjimZope 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.wsgi-3.15.0/CHANGES.txt0000644000175000017500000001444311706030370014240 0ustar jimjim======= CHANGES ======= 3.15.0 (2012-01-19) ------------------- - Fixed: zope.app.wsgi.paste.ZopeApplication didn't emit ProcessStarting events. **NOTE** If an application compensated for this by generating the event, it will need to stop or there will be multiple events emited. (Whether or not multiple events will do any harm is application specific.) 3.14.0 (2012-01-10) ------------------- - Set the WSGI environment's ``REMOTE_USER`` item (if not already set) with the Zope principal label. (This is the same data set in the ``wsgi.logging_info`` environment item.) This change allows user info to be used by `paste.translogger `_ middleware (or any similar middleware that uses ``REMOTE_USER``), which provides access logging. 3.13.0 (2011-03-15) ------------------- - Update to zope.testbrowser 4.0.0 which uses WebTest instead of wsgi_intercept. 3.12.0 (2011-01-25) ------------------- - Fixed ``zope.app.wsgi.testlayer.http`` to work with changes made in version 3.11.0. 3.11.0 (2011-01-24) ------------------- - Moved `wsgi_intercept` support to ``zope.testbrowser.wsgi``, thus requiring at least version 3.11 of this package: - Moved ``zope.app.wsgi.testlayer.Browser`` to ``zope.testbrowser.wsgi.Browser``, but left BBB import here. - Split up ``zope.app.wsgi.testlayer.BrowserLayer`` into generic WSGI browser layer (``zope.testbrowser.wsgi.Layer``) and ZODB/ZOPE specific part (``zope.app.wsgi.testlayer.BrowserLayer`` as before). 3.10.0 (2010-11-18) ------------------- - Add pluggability for setting up WSGI middleware in testlayer. 3.9.3 (2010-10-14) ------------------ - Python 2.7 compatibility for xmlrpc. Transplant of zope.app.testing r116141. 3.9.2 (2010-05-23) ------------------ - Fixed test breakage due to changes in mechanize 0.2.0. 3.9.1 (2010-04-24) ------------------ - Add support for testing XMLRPC using zope.app.wsgi.testlayer. - Fix a bug in the status string handling in zope.app.wsgi.testlayer's FakeResponse. 3.9.0 (2010-04-19) ------------------ - Return a FakeResponse object in zope.app.wsgi.testlayer.http, so it becomes easier to port over tests from zope.app.testing's HTTPCaller. - X-Powered-By header is now stripped by zope.app.wsgi.testlayer as it is by zope.app.testing. - Bugfix: initialize any defined in the config, as zope.app.server does. (Fixes #291147) 3.8.0 (2010-04-14) ------------------ - zope.app.wsgi.testlayer is now a lot more compatible with the HTTPCaller() functionality in zope.app.testing, which it can replace: - same transaction behavior - pending transactions are committed before request and synchronized afterwards. - support for browser.handleErrors (for zope.testbrowser). - support for clear-text (non-base64) Basic authentication headers, which are easier to read in the tests (though not correct in actual HTTP traffic). 3.7.0 (2010-04-13) ------------------ - Rewrite tests in order not to dependent on ``zope.app.testing`` and ``zope.app.zcmlfiles``. - ``zope.app.wsgi.testlayer`` introduces new testing functionality that can replace the old functionality in ``zope.app.testing``. In addition, it supports using ``zope.testbrowser`` with WSGI directly (instead of relying on ``zope.app.testing``, which pulls in a lot of dependencies). The interesting parts are: * ``zope.app.wsgi.testlayer.BrowserLayer``: this sets up a minimal layer that allows you to use the new WSGI-enabled Browser. * ``zope.app.wsgi.testlayer.Browser``: this is a subclass of Browser from ``zope.testbrowser.browser``. Use it instead of ``zope.testbrowser.browser`` directly to use the test browser with WSGI. You need to use ``BrowserLayer`` with your tests for this to work. * ``zope.app.wsgi.testlayer.http``: this is the equivalent to the ``http()`` function in ``zope.app.testing``. It allows low-level HTTP access through WSGI. You need to use ``BrowserLayer`` with your tests for this to work. 3.6.1 (2010-01-29) ------------------ - Support product configuration sections in Zope configuration files. 3.6.0 (2009-06-20) ------------------ - Import database events directly from ``zope.processlifetime`` instead of using BBB imports in ``zope.app.appsetup``. 3.5.2 (2009-04-03) ------------------ - The ``WSGIPublisherApplication`` uses now the ``ILoggingInfo`` concept given from zope.publisher.interfaces.logginginfo for log user infos usable for access logs. This allows you to implement your own access log user info message. See zope.publisher.interfaces.logginginfo.ILoggingInfo for more information. 3.5.1 (2009-03-31) ------------------ - The ``WSGIPublisherApplication`` call now provides a user name in the environment meant for use in logs. 3.5.0 (2009-02-10) ------------------ - Make devmode warning message more generic. We don't nesessary have the `etc/zope.conf` file nowadays when using buildout-based setups. - Add an application factory for Paste. So Zope application can now be easily deployed with Paste .ini configuration like this:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf handle_errors = false The config_file is a required argument, however the handle_errors defaults to True if not specified. Setting it to False allows you to make WSGIPublisherApplication not handle exceptions itself but propagate them to an upper middleware, like WebError or something. - The ``WSGIPublisherApplication`` constructor and ``getWSGIApplication`` function now accept optional ``handle_errors`` argument, described above. - Change mailing list address to zope-dev at zope.org instead of retired one. 3.4.1 (2008-07-30) ------------------ - Added Trove classifiers. - Notify ``WSGIPublisherApplicationCreated`` event when WSGI application is created. - Fixed deprecation warning in ``ftesting.zcml``: ZopeSecurityPolicy moved to ``zope.securitypolicy``. 3.4.0 (2007-09-14) ------------------ - Fixed the tests to run on Python 2.5 as well as Python 2.4. - Split ``getApplication`` into ``config`` and ``getApplication`` so that ``config`` could be reused, for example for debugging. 3.4.0a1 (2007-04-22) -------------------- Initial release as a separate project, corresponds to ``zope.app.wsgi`` from Zope 3.4.0a1 zope.app.wsgi-3.15.0/README.txt0000644000175000017500000000151611706030370014122 0ustar jimjimThis package provides the ``WSGIPublisherApplication`` class which exposes the object publishing machinery in ``zope.publisher`` as a WSGI application. It also lets us bring up the Zope application server (parsing ``zope.conf`` and ``site.zcml``) with a mere function call:: >>> db = zope.app.wsgi.config('zope.conf') This is especially useful for debugging. To bring up Zope and obtain the WSGI application object at the same time, use the ``getWSGIApplication`` function. This package also provides an easy to use application factory for PasteDeploy_. You can simply specify an application configuration like this in your Paste configuration file:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf Look for more documentation inside the package itself. .. _PasteDeploy: http://pythonpaste.org/deploy/ zope.app.wsgi-3.15.0/setup.cfg0000644000175000017500000000007311706030677014254 0ustar jimjim[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 zope.app.wsgi-3.15.0/src/0000755000175000017500000000000011706030677013222 5ustar jimjimzope.app.wsgi-3.15.0/src/zope/0000755000175000017500000000000011706030677014177 5ustar jimjimzope.app.wsgi-3.15.0/src/zope/__init__.py0000644000175000017500000000031011706030370016270 0ustar jimjim# 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.wsgi-3.15.0/src/zope/app/0000755000175000017500000000000011706030677014757 5ustar jimjimzope.app.wsgi-3.15.0/src/zope/app/__init__.py0000644000175000017500000000031011706030370017050 0ustar jimjim# 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.wsgi-3.15.0/src/zope/app/wsgi/0000755000175000017500000000000011706030677015730 5ustar jimjimzope.app.wsgi-3.15.0/src/zope/app/wsgi/ftesting.zcml0000644000175000017500000000327711706030370020441 0ustar jimjim zope.app.wsgi-3.15.0/src/zope/app/wsgi/__init__.py0000644000175000017500000001362411706030370020035 0ustar jimjim############################################################################## # # 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. # ############################################################################## """A WSGI Application wrapper for zope $Id: __init__.py 124018 2012-01-10 23:06:01Z jim $ """ import os import sys import logging import ZConfig import zope.processlifetime import zope.app.appsetup.product from zope.event import notify from zope.interface import implements from zope.publisher.publish import publish from zope.publisher.interfaces.logginginfo import ILoggingInfo from zope.app.appsetup import appsetup from zope.app.publication.httpfactory import HTTPPublicationRequestFactory from zope.app.wsgi import interfaces class WSGIPublisherApplication(object): """A WSGI application implementation for the zope publisher Instances of this class can be used as a WSGI application object. The class relies on a properly initialized request factory. """ implements(interfaces.IWSGIApplication) def __init__(self, db=None, factory=HTTPPublicationRequestFactory, handle_errors=True): self.requestFactory = None self.handleErrors = handle_errors if db is not None: self.requestFactory = factory(db) def __call__(self, environ, start_response): """See zope.app.wsgi.interfaces.IWSGIApplication""" request = self.requestFactory(environ['wsgi.input'], environ) # Let's support post-mortem debugging handle_errors = environ.get('wsgi.handleErrors', self.handleErrors) request = publish(request, handle_errors=handle_errors) response = request.response # Get logging info from principal for log use logging_info = ILoggingInfo(request.principal, None) if logging_info is None: message = '-' else: message = logging_info.getLogMessage() environ['wsgi.logging_info'] = message if 'REMOTE_USER' not in environ: environ['REMOTE_USER'] = message # Start the WSGI server response start_response(response.getStatusString(), response.getHeaders()) # Return the result body iterable. return response.consumeBodyIter() class PMDBWSGIPublisherApplication(WSGIPublisherApplication): def __init__(self, db=None, factory=HTTPPublicationRequestFactory, handle_errors=False): super(PMDBWSGIPublisherApplication, self).__init__(db, factory, handle_errors) def __call__(self, environ, start_response): environ['wsgi.handleErrors'] = self.handleErrors # Call the application to handle the request and write a response try: app = super(PMDBWSGIPublisherApplication, self) return app.__call__(environ, start_response) except Exception, error: import sys import pdb print "%s:" % sys.exc_info()[0] print sys.exc_info()[1] try: pdb.post_mortem(sys.exc_info()[2]) raise finally: pass def config(configfile, schemafile=None, features=()): # Load the configuration schema if schemafile is None: schemafile = os.path.join( os.path.dirname(appsetup.__file__), 'schema', 'schema.xml') # Let's support both, an opened file and path if isinstance(schemafile, basestring): schema = ZConfig.loadSchema(schemafile) else: schema = ZConfig.loadSchemaFile(schemafile) # Load the configuration file # Let's support both, an opened file and path try: if isinstance(configfile, basestring): options, handlers = ZConfig.loadConfig(schema, configfile) else: options, handlers = ZConfig.loadConfigFile(schema, configfile) except ZConfig.ConfigurationError, msg: sys.stderr.write("Error: %s\n" % str(msg)) sys.exit(2) # Insert all specified Python paths if options.path: sys.path[:0] = [os.path.abspath(p) for p in options.path] # Parse product configs zope.app.appsetup.product.setProductConfigurations( options.product_config) # Setup the event log options.eventlog() # Setup other defined loggers for logger in options.loggers: logger() # Insert the devmode feature, if turned on if options.devmode: features += ('devmode',) logging.warning("Developer mode is enabled: this is a security risk " "and should NOT be enabled on production servers. Developer mode " "can usually be turned off by setting the `devmode` option to " "`off` or by removing it from the instance configuration file " "completely.") # Execute the ZCML configuration. appsetup.config(options.site_definition, features=features) # Connect to and open the database, notify subscribers. db = appsetup.multi_database(options.databases)[0][0] notify(zope.processlifetime.DatabaseOpened(db)) return db def getWSGIApplication(configfile, schemafile=None, features=(), requestFactory=HTTPPublicationRequestFactory, handle_errors=True): db = config(configfile, schemafile, features) application = WSGIPublisherApplication(db, requestFactory, handle_errors) # Create the application, notify subscribers. notify(interfaces.WSGIPublisherApplicationCreated(application)) return application zope.app.wsgi-3.15.0/src/zope/app/wsgi/paste.py0000644000175000017500000000247311706030370017412 0ustar jimjim############################################################################## # # Copyright (c) 2009 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """An application factory for Paste $Id: paste.py 124089 2012-01-19 15:03:08Z jim $ """ from zope.app.wsgi import getWSGIApplication import zope.event import zope.processlifetime def asbool(obj): if isinstance(obj, basestring): obj = obj.lower() if obj in ('1', 'true', 'yes', 't', 'y'): return True if obj in ('0', 'false', 'no', 'f', 'n'): return False return bool(obj) def ZopeApplication(global_config, config_file, handle_errors=True, **options): handle_errors = asbool(handle_errors) app = getWSGIApplication(config_file, handle_errors=handle_errors) zope.event.notify(zope.processlifetime.ProcessStarting()) return app zope.app.wsgi-3.15.0/src/zope/app/wsgi/fileresult.txt0000644000175000017500000000622611706030370020643 0ustar jimjimFile results ============ The file results adapters provide adapters from Python file objects to and from temporary file objects to zope.publisher.interfaces.http.IResult. They also have the property that they can handle security proxied files and unproxy them in the result. Finally, if the request has a wsgi.file_wrapper environment variable, then that is used to wrap the file in the result. Lets look at an example with a regular file object: >>> from zope import component >>> import zope.app.wsgi.fileresult >>> component.provideAdapter(zope.app.wsgi.fileresult.FileResult) >>> component.provideAdapter(zope.app.wsgi.fileresult.TemporaryFileResult) >>> import tempfile >>> dir = tempfile.mkdtemp() >>> import os >>> f = open(os.path.join(dir, 'f'), 'w+b') >>> f.write('One\nTwo\nThree\nHa ha! I love to count!\n') >>> from zope.security.checker import ProxyFactory >>> from zope.publisher.interfaces.http import IResult >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> result = component.getMultiAdapter((ProxyFactory(f), request), IResult) >>> for line in result: ... print line One Two Three Ha ha! I love to count! >>> request.response.getHeader('content-length') '38' We'll see something similar with a temporary file: >>> t = tempfile.TemporaryFile() >>> t.write('Three\nTwo\nOne\nHa ha! I love to count down!\n') >>> request = TestRequest() >>> result = component.getMultiAdapter((ProxyFactory(t), request), IResult) >>> for line in result: ... print line Three Two One Ha ha! I love to count down! >>> request.response.getHeader('content-length') '43' If we provide a custom file wrapper: >>> class Wrapper: ... def __init__(self, file): ... self.file = file >>> request = TestRequest(environ={'wsgi.file_wrapper': Wrapper}) >>> result = component.getMultiAdapter((ProxyFactory(f), request), IResult) >>> result.__class__ is Wrapper True >>> result.file is f True >>> request.response.getHeader('content-length') '38' >>> request = TestRequest(environ={'wsgi.file_wrapper': Wrapper}) >>> result = component.getMultiAdapter((ProxyFactory(t), request), IResult) >>> result.__class__ is Wrapper True >>> result.file is t True >>> request.response.getHeader('content-length') '43' Normally, the file given to FileResult must be seekable and the entire file is used. The adapters figure out the file size to determine a content length and seek to the beginning of the file. You can suppress this behavior by setting the content length yourself: >>> request = TestRequest() >>> request.response.setHeader('content-length', '10') >>> f.seek(7) >>> result = component.getMultiAdapter((ProxyFactory(t), request), IResult) >>> print f.tell() 7 >>> request.response.getHeader('content-length') '10' Note that you should really only use file returns for large results. Files use file descriptors which can be somewhat scarce resources on some systems. Only use them when you need them. zope.app.wsgi-3.15.0/src/zope/app/wsgi/README.txt0000644000175000017500000001533211706030370017420 0ustar jimjim===================== Zope WSGI Application ===================== This package contains an interpretation of the WSGI specification (PEP-0333) for the Zope application server by providing a WSGI application object. The first step is to initialize the WSGI-compliant Zope application that is called from the server. To do that, we first have to create and open a ZODB connection: >>> from ZODB.MappingStorage import MappingStorage >>> from ZODB.DB import DB >>> storage = MappingStorage('test.db') >>> db = DB(storage, cache_size=4000) We can now initialize the application: >>> from zope.app import wsgi >>> app = wsgi.WSGIPublisherApplication(db) The callable ``app`` object accepts two positional arguments, the environment and the function that initializes the response and returns a function with which the output data can be written. Even though this is commonly done by the server, we now have to create an appropriate environment for the request. >>> import cStringIO >>> environ = { ... 'PATH_INFO': '/', ... 'wsgi.input': cStringIO.StringIO('')} Next we create a WSGI-compliant ``start_response()`` method that accepts the status of the response to the HTTP request and the headers that are part of the response stream. The headers are expected to be a list of 2-tuples. The ``start_response()`` method must also return a ``write()`` function that directly writes the output to the server. However, the Zope 3 implementation will not utilize this function, since it is strongly discouraged by PEP-0333. The second method of getting data to the server is by returning an iteratable from the application call. Sp we simply ignore all the arguments and return ``None`` as the write method. >>> def start_response(status, headers): ... return None Now we can send the fabricated HTTP request to the application for processing: >>> print ''.join(app(environ, start_response)) SystemError

SystemError

A server error occurred. We can see that application really crashed and did not know what to do. This is okay, since we have not setup anything. Getting a request successfully processed would require us to bring up a lot of Zope 3's system, which would be just a little bit too much for this demonstration. Now that we have seen the manual way of initializing and using the publisher application, here is the way it is done using all of Zope 3's setup machinery:: from zope.app.server.main import setup, load_options from zope.app.wsgi import PublisherApp # Read all configuration files and bring up the component architecture args = ["-C/path/to/zope.conf"] db = setup(load_options(args)) # Initialize the WSGI-compliant publisher application with the database wsgiApplication = PublisherApp(db) # Here is an example on how the application could be registered with a # WSGI-compliant server. Note that the ``setApplication()`` method is not # part of the PEP 333 specification. wsgiServer.setApplication(wsgiApplication) The code above assumes, that Zope is available on the ``PYTHONPATH``. Note that you may have to edit ``zope.conf`` to provide an absolute path for ``site.zcml``. Unfortunately we do not have enough information about the directory structure to make this code a doctest. In summary, to use Zope as a WSGI application, the following steps must be taken: * configure and setup Zope * an instance of ``zope.app.wsgi.PublisherApp`` must be created with a refernce to the opened database * this application instance must be somehow communicated to the WSGI server, i.e. by calling a method on the server that sets the application. Access logging -------------- But let's test at least the user info logging feature. We can check the environ after being sent to the app and also see that a key has been set to store user names for use in access logs. This logging information is provided by an adapter registered for `ILoggingInfo`. Out-of-the-box, `zope.publisher` registers a base adapter that returns the principal id as value:: >>> from pprint import pprint >>> pprint(environ) {'PATH_INFO': '/', 'REMOTE_USER': 'zope.anybody', 'wsgi.input': , 'wsgi.logging_info': 'zope.anybody'} .. edge case If remote user is already set, don't update it: >>> environ = { ... 'PATH_INFO': '/', ... 'REMOTE_USER': 'someoneelse', ... 'wsgi.input': cStringIO.StringIO('')} >>> _ = list(app(environ, start_response)) >>> pprint(environ) {'PATH_INFO': '/', 'REMOTE_USER': 'someoneelse', 'wsgi.input': , 'wsgi.logging_info': 'zope.anybody'} Creating A WSGI Application --------------------------- We do not always want Zope to control the startup process. People want to be able to start their favorite server and then register Zope simply as a WSGI application. For those cases we provide a very high-level function called ``getWSGIApplication()`` that only requires the configuration file to set up the Zope 3 application server and returns a WSGI application. Here is a simple example: # We have to create our own site definition file -- which will simply be # empty -- to provide a minimal test. >>> import os, tempfile >>> temp_dir = tempfile.mkdtemp() >>> sitezcml = os.path.join(temp_dir, 'site.zcml') >>> open(sitezcml, 'w').write('') >>> from cStringIO import StringIO >>> configFile = StringIO(''' ... site-definition %s ... ... ... ... ... ... ... ... path STDOUT ... ... ... ... ... key1 val1 ... ... ''' %sitezcml) Create an handler for the event. >>> import zope.component >>> from zope.app.wsgi.interfaces import IWSGIPublisherApplicationCreatedEvent >>> called = [] >>> @zope.component.adapter(IWSGIPublisherApplicationCreatedEvent) ... def handler(event): ... called.append(event) >>> zope.component.provideHandler(handler) Create an WSGI application. >>> app = wsgi.getWSGIApplication(configFile) >>> app >>> called[0].application is app True The product configs were parsed: >>> import zope.app.appsetup.product as zapp >>> print zapp.getProductConfiguration('sample') {'key1': 'val1'} >>> import shutil >>> shutil.rmtree(temp_dir) About WSGI ---------- WSGI is the Python Web Server Gateway Interface, a PEP to standardize the interface between web servers and python applications to promote portability. For more information, refer to the WSGI specification: http://www.python.org/peps/pep-0333.html zope.app.wsgi-3.15.0/src/zope/app/wsgi/testing.py0000644000175000017500000000511711706030370017751 0ustar jimjim############################################################################## # # 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.wsgi common test related classes/functions/objects. $Id: testing.py 120960 2011-03-15 22:41:30Z janjaapdriessen $ """ import tempfile from zope import interface, component import zope.publisher.interfaces.browser from zope.app.wsgi.testlayer import BrowserLayer class FileView: interface.implements(zope.publisher.interfaces.browser.IBrowserPublisher) component.adapts(interface.Interface, zope.publisher.interfaces.browser.IBrowserRequest) def __init__(self, _, request): self.request = request def browserDefault(self, *_): return self, () def __call__(self): self.request.response.setHeader('content-type', 'text/plain') f = tempfile.TemporaryFile() f.write("Hello\nWorld!\n") return f class IndexView(FileView): def __call__(self): self.request.response.setHeader('content-type', 'text/html') return '''

This is the index

''' class ErrorRaisingView(FileView): def __call__(self): return 1/0 class SillyMiddleWare(object): def __init__(self, application): self.application = application def __call__(self, environ, start_response): def drop_content_length_response(status, headers, exc_info=None): for name, value in headers: if name.lower() == 'content-length': headers.remove((name, value)) return start_response(status, headers, exc_info=exc_info) app_iter = self.application(environ, drop_content_length_response) # Very silly indeed: result = ''.join(app_iter) return [result.replace( '', '

Hello from the silly middleware

')] class SillyMiddleWareBrowserLayer(BrowserLayer): def setup_middleware(self, app): return SillyMiddleWare(app) zope.app.wsgi-3.15.0/src/zope/app/wsgi/testlayer.py0000644000175000017500000001417611706030370020315 0ustar jimjim############################################################################## # # Copyright (c) 2010 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. # ############################################################################## from StringIO import StringIO import httplib import xmlrpclib import transaction from zope.app.appsetup.testlayer import ZODBLayer from zope.app.wsgi import WSGIPublisherApplication import zope.testbrowser.wsgi from webtest import TestRequest # BBB from zope.testbrowser.wsgi import Browser class TransactionMiddleware(object): """This middleware makes the WSGI application compatible with the HTTPCaller behavior defined in zope.app.testing.functional: - It commits and synchronises the current transaction before and after the test. """ def __init__(self, root_factory, wsgi_stack): # ZODBLayer creates DB in testSetUp method, but the middleware is # set up already in the `setUp` method, so we have only the # `root_factory` not the root itself: self.root_factory = root_factory self.wsgi_stack = wsgi_stack def __call__(self, environ, start_response): transaction.commit() for entry in self.wsgi_stack(environ, start_response): yield entry self.root_factory()._p_jar.sync() class BrowserLayer(zope.testbrowser.wsgi.Layer, ZODBLayer): """This create a test layer with a test database and register a wsgi application to use that test database. You can use a WSGI version of zope.testbrowser Browser instance to access the application. """ def setup_middleware(self, app): # Override this method in subclasses of this layer in order to set up # WSGI middleware. return app def make_wsgi_app(self): # Since the request factory class is only a parameter default of # WSGIPublisherApplication and not easily accessible otherwise, we fake # it into creating a requestFactory instance, so we can read the class # off of that in testSetUp() fake_db = object() self._application = WSGIPublisherApplication(fake_db) return zope.testbrowser.wsgi.AuthorizationMiddleware( TransactionMiddleware( self.getRootFolder, self.setup_middleware(self._application))) def testSetUp(self): super(BrowserLayer, self).testSetUp() # Tell the publisher to use ZODBLayer's current database factory = type(self._application.requestFactory) self._application.requestFactory = factory(self.db) class NotInBrowserLayer(Exception): """The current test is not running in a layer inheriting from BrowserLayer. """ class FakeResponse(object): """This behave like a Response object returned by HTTPCaller of zope.app.testing.functional. """ def __init__(self, response): self.response = response def getStatus(self): return self.response.status_int def getStatusString(self): return self.response.status def getHeader(self, name, default=None): return self.response.headers.get(name, default) def getHeaders(self): return self.response.headerlist def getBody(self): return self.response.body def getOutput(self): parts = ['HTTP/1.0 ' + self.response.status] parts += map('%s: %s'.__mod__, self.response.headerlist) if self.response.body: parts += ['', self.response.body] return '\n'.join(parts) __str__ = getOutput def http(string, handle_errors=True): app = zope.testbrowser.wsgi.Layer.get_app() if app is None: raise NotInBrowserLayer(NotInBrowserLayer.__doc__) request = TestRequest.from_file(StringIO(string)) request.environ['wsgi.handleErrors'] = handle_errors response = request.get_response(app) return FakeResponse(response) class FakeSocket(object): def __init__(self, data): self.data = data def makefile(self, mode, bufsize=None): return StringIO(self.data) class XMLRPCTestTransport(xmlrpclib.Transport): """xmlrpclib transport that delegates to http(). It can be used like a normal transport, including support for basic authentication. """ verbose = False handleErrors = True def request(self, host, handler, request_body, verbose=0): request = "POST %s HTTP/1.0\n" % (handler,) request += "Content-Length: %i\n" % len(request_body) request += "Content-Type: text/xml\n" host, extra_headers, x509 = self.get_host_info(host) if extra_headers: request += "Authorization: %s\n" % ( dict(extra_headers)["Authorization"],) request += "\n" + request_body response = http(request, handle_errors=self.handleErrors) errcode = response.getStatus() errmsg = response.getStatusString() # This is not the same way that the normal transport deals with the # headers. headers = response.getHeaders() if errcode != 200: raise xmlrpclib.ProtocolError( host + handler, errcode, errmsg, headers ) res = httplib.HTTPResponse(FakeSocket(response.getBody())) res.begin() return self.parse_response(res) def XMLRPCServerProxy(uri, transport=None, encoding=None, verbose=0, allow_none=0, handleErrors=True): """A factory that creates a server proxy using the XMLRPCTestTransport by default. """ if transport is None: transport = XMLRPCTestTransport() if isinstance(transport, XMLRPCTestTransport): transport.handleErrors = handleErrors return xmlrpclib.ServerProxy(uri, transport, encoding, verbose, allow_none) zope.app.wsgi-3.15.0/src/zope/app/wsgi/testlayer.txt0000644000175000017500000000510311706030370020472 0ustar jimjimIt is possible to inject a wsgi stack by subclassing from BrowserLayer:: First, create and register a view to test: >>> from zope import component, interface >>> from zope.app.wsgi.testing import IndexView >>> component.provideAdapter(IndexView, name='index.html') >>> from zope.security import checker >>> checker.defineChecker( ... IndexView, ... checker.NamesChecker(['browserDefault', '__call__']), ... ) >>> from zope.app.wsgi.testing import ErrorRaisingView >>> component.provideAdapter(ErrorRaisingView, name='error.html') >>> checker.defineChecker( ... ErrorRaisingView, ... checker.NamesChecker(['browserDefault', '__call__']), ... ) The `silly middleware` has injected information into the page: >>> from zope.app.wsgi.testlayer import Browser >>> browser = Browser() >>> browser.open('http://localhost/index.html') >>> print browser.contents

Hello from the silly middleware

This is the index

The default behavior of the browser is to handle errors:: >>> browser.open('http://localhost/error.html') Traceback (most recent call last): ... HTTPError: HTTP Error 500: Internal Server Error One can set error handling behavior:: >>> browser.handleErrors = False >>> browser.open('http://localhost/error.html') Traceback (most recent call last): ... ZeroDivisionError: integer division or modulo by zero The http caller is more low level than the Browser. It exposes the same error handling parameter:: >>> from zope.app.wsgi.testlayer import http >>> response = http('GET /error.html HTTP/1.1') >>> response.getStatus() == 500 True >>> http('GET /error.html HTTP/1.1', handle_errors=False) Traceback (most recent call last): ... ZeroDivisionError: integer division or modulo by zero Clean up: >>> import zope.publisher.interfaces.browser >>> checker.undefineChecker(IndexView) >>> component.provideAdapter( ... None, ... (interface.Interface, ... zope.publisher.interfaces.browser.IBrowserRequest), ... zope.publisher.interfaces.browser.IBrowserPublisher, ... 'index.html', ... ) >>> checker.undefineChecker(ErrorRaisingView) >>> component.provideAdapter( ... None, ... (interface.Interface, ... zope.publisher.interfaces.browser.IBrowserRequest), ... zope.publisher.interfaces.browser.IBrowserPublisher, ... 'error.html', ... ) zope.app.wsgi-3.15.0/src/zope/app/wsgi/interfaces.py0000644000175000017500000000622511706030370020420 0ustar jimjim############################################################################## # # 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. # ############################################################################## """WSGI-specific and compatible interfaces See PEP-0333 for details. $Id: interfaces.py 119207 2010-12-28 19:49:21Z menesis $ """ __docformat__ = "reStructuredText" import zope.interface from zope.publisher.interfaces.http import IHeaderOutput class IWSGIOutput(IHeaderOutput): """This class handles the output generated by the publisher. It is used to collect the headers and as an outstream to output the response body. """ def getHeaders(): """Return the response headers. The headers will be returned as a list of tuples according to the WSGI specification. """ def write(data): """Write the response to the server. If the reponse has not begun, call the WSGI server's ``start_response()`` callable to begin the response. """ class IWSGIApplication(zope.interface.Interface): """A WSGI application.""" def __call__(environ, start_response): """Called by a WSGI server. The ``environ`` parameter is a dictionary object, containing CGI-style environment variables. This object must be a builtin Python dictionary (not a subclass, UserDict or other dictionary emulation), and the application is allowed to modify the dictionary in any way it desires. The dictionary must also include certain WSGI-required variables (described in a later section), and may also include server-specific extension variables, named according to a convention that will be described below. The ``start_response`` parameter is a callable accepting two required positional arguments, and one optional argument. For the sake of illustration, we have named these arguments ``status``, ``response_headers``, and ``exc_info``, but they are not required to have these names, and the application must invoke the ``start_response`` callable using positional arguments (e.g. ``start_response(status, response_headers)``). """ class IWSGIServer(zope.interface.Interface): """A WSGI server.""" def set_application(app): """Tells the server about the application to use.""" class IWSGIPublisherApplicationCreatedEvent(zope.interface.Interface): """A WSGI application has been created.""" application = zope.interface.Attribute("The WSGI application.") class WSGIPublisherApplicationCreated(object): zope.interface.implements(IWSGIPublisherApplicationCreatedEvent) def __init__(self, application): self.application = application zope.app.wsgi-3.15.0/src/zope/app/wsgi/configure.zcml0000644000175000017500000000025311706030370020566 0ustar jimjim zope.app.wsgi-3.15.0/src/zope/app/wsgi/paste.txt0000644000175000017500000000537311706030370017603 0ustar jimjim================================================== Zope WSGI application integration with PasteDeploy ================================================== PasteDeploy provides a framework for defining WSGI component factories that are used for assembling an application using simple configuration files. The ``zope.app.wsgi.paste`` package provides an paste application factory for the Zope WSGI application server, created using the configuration file, typically the ``zope.conf``. To use in Paste, you include a configuration section like this:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf This example defines a "main" application using the zope.app.wsgi factory. The only option that is required by zope.app.wsgi is the path to a configuration file. That file typically defines a path to a site definition file (the ``site.zcml``) and things like eventlog configuration or enabling developer mode. The factory also accepts the ``handle_errors`` boolean argument. It's useful, when you don't want Zope application to handle exceptions and want it to propagate them to upper WSGI middlewares. The application factory only creates the WSGI application using the ``zope.app.wsgi.getWSGIApplication`` function. So we don't test it here. Instead, we'll only examine the Paste application factory provided by ``zope.app.wsgi.paste.ZopeApplication``. Let's create testing site.zcml and zope.conf file. >>> import os, tempfile >>> temp_dir = tempfile.mkdtemp() >>> sitezcml = os.path.join(temp_dir, 'site.zcml') >>> open(sitezcml, 'w').write('') >>> zopeconf = os.path.join(temp_dir, 'zope.conf') >>> open(zopeconf, 'w').write(''' ... site-definition %s ... ... ... ... ... ... ... ... path STDOUT ... ... ... ''' % sitezcml) Let's end any security interaction we have, as application will try to create new interaction for its tasks. >>> from zope.security import management >>> if management.queryInteraction(): management.endInteraction() Now, let's create the application using our application factory as Paste does. >>> from zope.app.wsgi.paste import ZopeApplication >>> app = ZopeApplication({}, zopeconf) >>> app >>> app.handleErrors True We can also specify handle_errors as false using boolean or strings: >>> app = ZopeApplication({}, zopeconf, handle_errors=False) >>> app.handleErrors False >>> for v in ('0', 'false', 'no', 'f', 'n'): ... print ZopeApplication({}, zopeconf, handle_errors=v).handleErrors False False False False False Okay, remove the temporary files. >>> import shutil >>> shutil.rmtree(temp_dir) zope.app.wsgi-3.15.0/src/zope/app/wsgi/filereturns.txt0000644000175000017500000000227211706030370021024 0ustar jimjimWe want to make sure that file returns work Let's register a view that returns a temporary file and make sure that nothing bad happens. :) >>> from zope import component, interface >>> from zope.app.wsgi.testing import FileView >>> component.provideAdapter(FileView, name='test-file-view.html') >>> from zope.security import checker >>> checker.defineChecker( ... FileView, ... checker.NamesChecker(['browserDefault', '__call__']), ... ) >>> from zope.app.wsgi.testlayer import Browser >>> browser = Browser() >>> browser.handleErrors = False >>> browser.open('http://localhost/@@test-file-view.html') >>> browser.headers['content-type'] 'text/plain' >>> browser.headers['content-length'] '13' >>> print browser.contents Hello World! Clean up: >>> import zope.publisher.interfaces.browser >>> checker.undefineChecker(FileView) >>> component.provideAdapter( ... None, ... (interface.Interface, ... zope.publisher.interfaces.browser.IBrowserRequest), ... zope.publisher.interfaces.browser.IBrowserPublisher, ... 'test-file-view.html', ... ) zope.app.wsgi-3.15.0/src/zope/app/wsgi/tests.py0000644000175000017500000000626511706030370017443 0ustar jimjim############################################################################## # # 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. # ############################################################################## """WSGI tests""" from zope.app.wsgi.testing import SillyMiddleWareBrowserLayer from zope.app.wsgi.testlayer import BrowserLayer from zope.component.testlayer import ZCMLFileLayer from zope.testing import renormalizing import doctest import re import unittest import zope.app.wsgi import zope.event def cleanEvents(s): zope.event.subscribers.pop() def creating_app_w_paste_emits_ProcessStarting_event(): """ >>> import zope.event >>> events = [] >>> subscriber = events.append >>> zope.event.subscribers.append(subscriber) >>> import os, tempfile >>> temp_dir = tempfile.mkdtemp() >>> sitezcml = os.path.join(temp_dir, 'site.zcml') >>> open(sitezcml, 'w').write('') >>> zopeconf = os.path.join(temp_dir, 'zope.conf') >>> open(zopeconf, 'w').write(''' ... site-definition %s ... ... ... ... ... ... ... ... path STDOUT ... ... ... ''' % sitezcml) >>> import zope.app.wsgi.paste, zope.processlifetime >>> app = zope.app.wsgi.paste.ZopeApplication( ... {}, zopeconf, handle_errors=False) >>> len([e for e in events ... if isinstance(e, zope.processlifetime.ProcessStarting)]) == 1 True >>> zope.event.subscribers.remove(subscriber) """ def test_suite(): checker = renormalizing.RENormalizing([ (re.compile( r"<class 'zope.component.interfaces.ComponentLookupError'>"), r'ComponentLookupError'), ]) filereturns_suite = doctest.DocFileSuite('filereturns.txt') filereturns_suite.layer = BrowserLayer(zope.app.wsgi) dt_suite = doctest.DocTestSuite() dt_suite.layer = BrowserLayer(zope.app.wsgi) readme_test = doctest.DocFileSuite( 'README.txt', checker=checker, tearDown=cleanEvents, optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS) doctest_suite = doctest.DocFileSuite( 'fileresult.txt', 'paste.txt', checker=checker, optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS) readme_test.layer = ZCMLFileLayer(zope.app.wsgi) doctest_suite.layer = ZCMLFileLayer(zope.app.wsgi) testlayer_suite = doctest.DocFileSuite( 'testlayer.txt', optionflags=doctest.NORMALIZE_WHITESPACE) testlayer_suite.layer = SillyMiddleWareBrowserLayer(zope.app.wsgi) return unittest.TestSuite(( filereturns_suite, readme_test, doctest_suite, testlayer_suite, dt_suite, )) zope.app.wsgi-3.15.0/src/zope/app/wsgi/fileresult.py0000644000175000017500000000454011706030370020451 0ustar jimjim############################################################################## # # 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. # ############################################################################## """IResult adapters for files. $Id: fileresult.py 119207 2010-12-28 19:49:21Z menesis $ """ import tempfile from zope import component, interface import zope.publisher.interfaces.http import zope.publisher.http from zope.publisher.interfaces.http import IResult from zope.security.proxy import removeSecurityProxy class FallbackWrapper: interface.implements(IResult) def __init__(self, f): self.close = f.close self._file = f def __iter__(self): f = self._file while 1: v = f.read(32768) if v: yield v else: break @component.adapter(file, zope.publisher.interfaces.http.IHTTPRequest) @interface.implementer(zope.publisher.http.IResult) def FileResult(f, request): f = removeSecurityProxy(f) if request.response.getHeader('content-length') is None: f.seek(0, 2) size = f.tell() f.seek(0) request.response.setHeader('Content-Length', str(size)) wrapper = request.environment.get('wsgi.file_wrapper') if wrapper is not None: f = wrapper(f) else: f = FallbackWrapper(f) return f # We need to provide an adapter for temporary files *if* they are different # than regular files. Whether they are is system dependent. Sigh. # If temporary files are the same type, we'll create a fake type just # to make the registration work. _tfile = tempfile.TemporaryFile() _tfile.close() _tfile = _tfile.__class__ if _tfile is file: # need a fake one. Sigh class _tfile: pass @component.adapter(_tfile, zope.publisher.interfaces.http.IHTTPRequest) @interface.implementer(zope.publisher.http.IResult) def TemporaryFileResult(f, request): return FileResult(f, request) zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/0000755000175000017500000000000011706030677017420 5ustar jimjimzope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/namespace_packages.txt0000644000175000017500000000001611706030677023750 0ustar jimjimzope zope.app zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/dependency_links.txt0000644000175000017500000000000111706030677023466 0ustar jimjim zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/PKG-INFO0000644000175000017500000002317211706030677020522 0ustar jimjimMetadata-Version: 1.0 Name: zope.app.wsgi Version: 3.15.0 Summary: WSGI application for the zope.publisher Home-page: http://pypi.python.org/pypi/zope.app.wsgi Author: Zope Foundation and Contributors Author-email: zope-dev@zope.org License: ZPL 2.1 Description: This package provides the ``WSGIPublisherApplication`` class which exposes the object publishing machinery in ``zope.publisher`` as a WSGI application. It also lets us bring up the Zope application server (parsing ``zope.conf`` and ``site.zcml``) with a mere function call:: >>> db = zope.app.wsgi.config('zope.conf') This is especially useful for debugging. To bring up Zope and obtain the WSGI application object at the same time, use the ``getWSGIApplication`` function. This package also provides an easy to use application factory for PasteDeploy_. You can simply specify an application configuration like this in your Paste configuration file:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf Look for more documentation inside the package itself. .. _PasteDeploy: http://pythonpaste.org/deploy/ ======= CHANGES ======= 3.15.0 (2012-01-19) ------------------- - Fixed: zope.app.wsgi.paste.ZopeApplication didn't emit ProcessStarting events. **NOTE** If an application compensated for this by generating the event, it will need to stop or there will be multiple events emited. (Whether or not multiple events will do any harm is application specific.) 3.14.0 (2012-01-10) ------------------- - Set the WSGI environment's ``REMOTE_USER`` item (if not already set) with the Zope principal label. (This is the same data set in the ``wsgi.logging_info`` environment item.) This change allows user info to be used by `paste.translogger `_ middleware (or any similar middleware that uses ``REMOTE_USER``), which provides access logging. 3.13.0 (2011-03-15) ------------------- - Update to zope.testbrowser 4.0.0 which uses WebTest instead of wsgi_intercept. 3.12.0 (2011-01-25) ------------------- - Fixed ``zope.app.wsgi.testlayer.http`` to work with changes made in version 3.11.0. 3.11.0 (2011-01-24) ------------------- - Moved `wsgi_intercept` support to ``zope.testbrowser.wsgi``, thus requiring at least version 3.11 of this package: - Moved ``zope.app.wsgi.testlayer.Browser`` to ``zope.testbrowser.wsgi.Browser``, but left BBB import here. - Split up ``zope.app.wsgi.testlayer.BrowserLayer`` into generic WSGI browser layer (``zope.testbrowser.wsgi.Layer``) and ZODB/ZOPE specific part (``zope.app.wsgi.testlayer.BrowserLayer`` as before). 3.10.0 (2010-11-18) ------------------- - Add pluggability for setting up WSGI middleware in testlayer. 3.9.3 (2010-10-14) ------------------ - Python 2.7 compatibility for xmlrpc. Transplant of zope.app.testing r116141. 3.9.2 (2010-05-23) ------------------ - Fixed test breakage due to changes in mechanize 0.2.0. 3.9.1 (2010-04-24) ------------------ - Add support for testing XMLRPC using zope.app.wsgi.testlayer. - Fix a bug in the status string handling in zope.app.wsgi.testlayer's FakeResponse. 3.9.0 (2010-04-19) ------------------ - Return a FakeResponse object in zope.app.wsgi.testlayer.http, so it becomes easier to port over tests from zope.app.testing's HTTPCaller. - X-Powered-By header is now stripped by zope.app.wsgi.testlayer as it is by zope.app.testing. - Bugfix: initialize any defined in the config, as zope.app.server does. (Fixes #291147) 3.8.0 (2010-04-14) ------------------ - zope.app.wsgi.testlayer is now a lot more compatible with the HTTPCaller() functionality in zope.app.testing, which it can replace: - same transaction behavior - pending transactions are committed before request and synchronized afterwards. - support for browser.handleErrors (for zope.testbrowser). - support for clear-text (non-base64) Basic authentication headers, which are easier to read in the tests (though not correct in actual HTTP traffic). 3.7.0 (2010-04-13) ------------------ - Rewrite tests in order not to dependent on ``zope.app.testing`` and ``zope.app.zcmlfiles``. - ``zope.app.wsgi.testlayer`` introduces new testing functionality that can replace the old functionality in ``zope.app.testing``. In addition, it supports using ``zope.testbrowser`` with WSGI directly (instead of relying on ``zope.app.testing``, which pulls in a lot of dependencies). The interesting parts are: * ``zope.app.wsgi.testlayer.BrowserLayer``: this sets up a minimal layer that allows you to use the new WSGI-enabled Browser. * ``zope.app.wsgi.testlayer.Browser``: this is a subclass of Browser from ``zope.testbrowser.browser``. Use it instead of ``zope.testbrowser.browser`` directly to use the test browser with WSGI. You need to use ``BrowserLayer`` with your tests for this to work. * ``zope.app.wsgi.testlayer.http``: this is the equivalent to the ``http()`` function in ``zope.app.testing``. It allows low-level HTTP access through WSGI. You need to use ``BrowserLayer`` with your tests for this to work. 3.6.1 (2010-01-29) ------------------ - Support product configuration sections in Zope configuration files. 3.6.0 (2009-06-20) ------------------ - Import database events directly from ``zope.processlifetime`` instead of using BBB imports in ``zope.app.appsetup``. 3.5.2 (2009-04-03) ------------------ - The ``WSGIPublisherApplication`` uses now the ``ILoggingInfo`` concept given from zope.publisher.interfaces.logginginfo for log user infos usable for access logs. This allows you to implement your own access log user info message. See zope.publisher.interfaces.logginginfo.ILoggingInfo for more information. 3.5.1 (2009-03-31) ------------------ - The ``WSGIPublisherApplication`` call now provides a user name in the environment meant for use in logs. 3.5.0 (2009-02-10) ------------------ - Make devmode warning message more generic. We don't nesessary have the `etc/zope.conf` file nowadays when using buildout-based setups. - Add an application factory for Paste. So Zope application can now be easily deployed with Paste .ini configuration like this:: [app:main] use = egg:zope.app.wsgi config_file = %(here)s/zope.conf handle_errors = false The config_file is a required argument, however the handle_errors defaults to True if not specified. Setting it to False allows you to make WSGIPublisherApplication not handle exceptions itself but propagate them to an upper middleware, like WebError or something. - The ``WSGIPublisherApplication`` constructor and ``getWSGIApplication`` function now accept optional ``handle_errors`` argument, described above. - Change mailing list address to zope-dev at zope.org instead of retired one. 3.4.1 (2008-07-30) ------------------ - Added Trove classifiers. - Notify ``WSGIPublisherApplicationCreated`` event when WSGI application is created. - Fixed deprecation warning in ``ftesting.zcml``: ZopeSecurityPolicy moved to ``zope.securitypolicy``. 3.4.0 (2007-09-14) ------------------ - Fixed the tests to run on Python 2.5 as well as Python 2.4. - Split ``getApplication`` into ``config`` and ``getApplication`` so that ``config`` could be reused, for example for debugging. 3.4.0a1 (2007-04-22) -------------------- Initial release as a separate project, corresponds to ``zope.app.wsgi`` from Zope 3.4.0a1 Platform: UNKNOWN Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Zope Public License Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application Classifier: Framework :: Zope3 zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/requires.txt0000644000175000017500000000076211706030677022025 0ustar jimjimsetuptools WebTest ZConfig ZODB3 zope.app.appsetup >= 3.14 zope.processlifetime zope.app.publication zope.event zope.interface zope.publisher zope.security zope.component zope.configuration zope.container zope.error zope.lifecycleevent zope.processlifetime zope.session zope.site zope.testbrowser[wsgi] >= 4.0.0 zope.testing zope.traversing [test] zope.annotation zope.authentication zope.browserpage zope.login zope.password zope.principalregistry zope.securitypolicy zope.testing zope.traversingzope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/top_level.txt0000644000175000017500000000000511706030677022145 0ustar jimjimzope zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/not-zip-safe0000644000175000017500000000000111706030677021646 0ustar jimjim zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/entry_points.txt0000644000175000017500000000010011706030677022705 0ustar jimjim[paste.app_factory] main = zope.app.wsgi.paste:ZopeApplication zope.app.wsgi-3.15.0/src/zope.app.wsgi.egg-info/SOURCES.txt0000644000175000017500000000160011706030677021301 0ustar jimjimCHANGES.txt COPYRIGHT.txt LICENSE.txt README.txt bootstrap.py buildout.cfg setup.py src/zope/__init__.py src/zope.app.wsgi.egg-info/PKG-INFO src/zope.app.wsgi.egg-info/SOURCES.txt src/zope.app.wsgi.egg-info/dependency_links.txt src/zope.app.wsgi.egg-info/entry_points.txt src/zope.app.wsgi.egg-info/namespace_packages.txt src/zope.app.wsgi.egg-info/not-zip-safe src/zope.app.wsgi.egg-info/requires.txt src/zope.app.wsgi.egg-info/top_level.txt src/zope/app/__init__.py src/zope/app/wsgi/README.txt src/zope/app/wsgi/__init__.py src/zope/app/wsgi/configure.zcml src/zope/app/wsgi/fileresult.py src/zope/app/wsgi/fileresult.txt src/zope/app/wsgi/filereturns.txt src/zope/app/wsgi/ftesting.zcml src/zope/app/wsgi/interfaces.py src/zope/app/wsgi/paste.py src/zope/app/wsgi/paste.txt src/zope/app/wsgi/testing.py src/zope/app/wsgi/testlayer.py src/zope/app/wsgi/testlayer.txt src/zope/app/wsgi/tests.pyzope.app.wsgi-3.15.0/buildout.cfg0000644000175000017500000000043511706030370014733 0ustar jimjim[buildout] extends = http://download.zope.org/zopetoolkit/index/1.1/zopeapp-versions.cfg http://download.zope.org/zopetoolkit/index/1.1/ztk-versions.cfg develop = . parts = test [test] recipe = zc.recipe.testrunner eggs = zope.app.wsgi [test] [versions] zope.testbrowser = 4.0.0 zope.app.wsgi-3.15.0/COPYRIGHT.txt0000644000175000017500000000004011706030370014524 0ustar jimjimZope Foundation and Contributors