[Checkins] SVN: Zope/branches/regebro-wsgi_support2/ Complete WSGI support rewrite.

Lennart Regebro regebro at gmail.com
Sun Apr 30 04:25:21 EDT 2006


Log message for revision 67758:
  Complete WSGI support rewrite.
  

Changed:
  A   Zope/branches/regebro-wsgi_support2/
  D   Zope/branches/regebro-wsgi_support2/doc/CHANGES.txt
  A   Zope/branches/regebro-wsgi_support2/doc/CHANGES.txt
  D   Zope/branches/regebro-wsgi_support2/lib/python/OFS/Traversable.py
  A   Zope/branches/regebro-wsgi_support2/lib/python/OFS/Traversable.py
  D   Zope/branches/regebro-wsgi_support2/lib/python/Products/
  A   Zope/branches/regebro-wsgi_support2/lib/python/Products/
  D   Zope/branches/regebro-wsgi_support2/lib/python/Products/PageTemplates/Expressions.py
  A   Zope/branches/regebro-wsgi_support2/lib/python/Products/PageTemplates/Expressions.py
  D   Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/BaseRequest.py
  A   Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/BaseRequest.py
  U   Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/Publish.py
  U   Zope/branches/regebro-wsgi_support2/lib/python/ZServer/HTTPResponse.py
  U   Zope/branches/regebro-wsgi_support2/lib/python/ZServer/HTTPServer.py
  U   Zope/branches/regebro-wsgi_support2/lib/python/ZServer/PubCore/ZServerPublisher.py
  U   Zope/branches/regebro-wsgi_support2/lib/python/ZServer/component.xml
  U   Zope/branches/regebro-wsgi_support2/lib/python/ZServer/datatypes.py

-=-
Copied: Zope/branches/regebro-wsgi_support2 (from rev 67723, Zope/trunk)

Deleted: Zope/branches/regebro-wsgi_support2/doc/CHANGES.txt
===================================================================
--- Zope/trunk/doc/CHANGES.txt	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/doc/CHANGES.txt	2006-04-30 08:25:20 UTC (rev 67758)
@@ -1,1214 +0,0 @@
-Zope Changes
-
-  This file contains change information for the current Zope release.
-  Change information for previous versions of Zope can be found in the
-  file HISTORY.txt.
-
-  To-do
-
-   - Add cyclic-garbage collection support to C extension classes,
-     especially to acquisition wrappers.
-
-     N.B:  ExtensionClassType already declares that it supports GC
-     (via the Py_TPFLAGS_HAVE_GC flag), but does not appear to conform
-     to the rules for such a type laid out in the Python docs:
-     http://docs.python.org/api/supporting-cycle-detection.html
-
-  Trunk only (unreleased)
-
-    Restructuring
-
-      - ZCatalog: removed manage_deleteIndex(), manage_delColumns()
-        which were deprecated since Zope 2.4
-
-      - deprecated the zLOG module. Use Pythons 'logging' module instead.
-
-      - replaced all zLOG occurences (expect the zLOG module itself) with 
-        the 'logging' module
-
-      - PluginIndexes/TextIndex is deprecated. Use ZCTextIndex instead
-
-      - the 'StructuredText' module is deprecated. Use zope.structuredtext
-        instead
-
-      - removed ZopeTutorial (Elvis is now really dead)
-
-      - ZClasses are deprecated and should no longer be used. In addition
-        any code related to the ZClasses (re)distribution mechanism is
-        removed.
-
-      - ZGadyFlyDA/Gadfly is deprecated
-
-      - deprecated OFS.content_types (to be removed in Zope 2.11) and
-        replaced all occurences with zope.app.content_types 
-
-      - OFS.content_types: moved code to zope.app.content_types and added
-        method aliases
-
-      - Using FastCGI is offically deprecated.
-
-    Features added
-
-      - Testing.makerequest: Added an 'environ' argument so
-        clients can use mappings other than os.environ.
-
-      - Updated to Docutils 0.4.0 
-
-      - reStructuredText: The default value for the 'stylesheet'
-        property has been changed from 'default.css' to None because
-        there is no 'default.css' file by default. 
-
-      - ZReST: rewritten render() method to integrate it smoothly
-        with Docutils 0.4.0. The default value for the 'stylesheet'
-        property has been changed from 'default.css' to None because
-        there is no 'default.css' file by default. 
-
-      - Added a "clock server" servertype which allows users to
-        configure methods that should be called periodically as if
-        they were being called by a remote user agent on one of Zope's
-        HTTP ports.  This is meant to replace wget+cron for some class
-        of periodic callables.
-
-        To use, create a "clock-server" directive section anywhere
-        in your zope.conf file, like so:
-
-         <clock-server>
-            method /do_stuff
-            period 60
-            user admin
-            password 123
-            host localhost
-         </clock-server>
-
-        Any number of clock-server sections may be defined within a
-        single zope.conf.  Note that you must specify a
-        username/password combination with the appropriate level of
-        access to call the method you've defined.  You can omit the
-        username and password if the method is anonymously callable.
-        Obviously the password is stored in the clear in the config
-        file, so you need to protect the config file with filesystem
-        security if the Zope account is privileged and those who have
-        filesystem access should not see the password.
-
-        Descriptions of the values within the clock-server section
-        follow::
-
-          method -- the traversal path (from the Zope root) to an
-          executable Zope method (Python Script, external method,
-          product method, etc).  The method must take no arguments or
-          must obtain its arguments from a query string.
-
-          period -- the number of seconds between each clock "tick" (and
-          thus each call to the above "method").  The lowest number
-          providable here is typically 30 (this is the asyncore mainloop
-          "timeout" value).
-
-          user -- a zope username.
-
-          password -- the password for the zope username provided above.
-
-          host -- the hostname passed in via the "Host:" header in the
-          faux request.  Could be useful if you have virtual host rules
-          set up inside Zope itself.
-
-        To make sure the clock is working, examine your Z2.log file.  It
-        should show requests incoming via a "Zope Clock Server"
-        useragent.
-
-      - Added a 'conflict-error-log-level' directive to zope.conf, to set
-        the level at which conflict errors (which are normally retried
-        automatically) are logged. The default is 'info'.
-
-      - The SiteErrorLog now copies exceptions to the event log by default.
-
-      - ObjectManager now has an hasObject method to test presence. This
-        brings it in line with BTreeFolder.
-
-      - Improved logging of ConflictErrors. All conflict errors are
-        logged at INFO, with counts of how many occurred and how many
-        were resolved. Tracebacks for all conflicts are logged a DEBUG
-        level, although these won't help anyone much. If a conflict
-        error is unresolved, it will now bubble up to error_log and
-        standard_error_message.
-
-      - Use new-style security declarations everywhere possible. This
-        means remove the use of __ac_permissions__, foo__roles__ and
-        default__class_init__. A few corner cases can't be converted
-        because of circular imports.
-
-      - Fixed unclear security declarations. Warn when an attempt is
-        made to have a security declaration on a nonexistent method.
-
-      - updated to ZPL 2.1
-
-      - interfaces: Added 'Interfaces' tab to basic core objects.
-        This is a Five feature and only available if the classes are made
-        five:traversable. It allows to inspect interfaces and to assign
-        marker interfaces through the ZMI.
-
-      - webdav: Added support for the z3 WriteLock interface.
-        It is no longer necessary to have the WriteLockInterface in the
-        __implements__ list of lockable objects. All classes inheriting from
-        LockableItem inherit also the IWriteLock interface. Note that this
-        enables webdav locking for all subclasses by default even if they
-        don't specify the WriteLockInterface explicitly.
-
-      - App ProductContext: Made registerClass aware of z3 interfaces.
-        Z2 and z3 interfaces are registered side by side in the same tuple in
-        Products.meta_types. IFAwareObjectManagers like the ZCatalog work now
-        with z3 interfaces as well.
-
-      - Zope now sends Zope 3 events when objects are added or removed
-        from standard containers. manage_afterAdd, manage_beforeDelete
-        and manage_afterClone are now deprecated. See
-        lib/python/Products/Five/tests/event.txt for details.
-
-      - Zope now utilizes ZODB 3.6.  It had previously used
-        ZODB 3.4.  As a result, the DBTab package was removed, as
-        ZODB 3.6 has multidatabase support that makes DBTab
-        unnecessary.
-
-      - Added a 'product-config' section type to zope.conf, allowing
-        arbitrary key-value mappings.  Products can look for such
-        confgiurations to set product-specific options.  Products mwy
-        also register their own section types, extending the
-        'zope.product.base' type. (see the example '<product-config>'
-        section in skel/etc/zope.conf.in for sample usage).
-
-      - Collector #1490: Added a new zope.conf option to control the
-        character set used to encode unicode data that reaches
-        ZPublisher without any specified encoding.
-
-      - AccessControl, Acquisition, App, OFS, webdav, PluginIndexes,
-        ZCatalog and ZCTextIndex: Added some Zope 3 style interfaces.
-        This makes the bridged interfaces shipped with Five obsolete.
-
-      - ZConfig extension, address now also accepts symbolic port names
-        from etc/services (unix) or etc\services (win32)
-
-      - ZPublisher.HTTPRequest.FileUpload now supports full file
-        object interface.  This means Iterator support was added. (for
-        line in fileobject: ..., as well as fileobject.next() and
-        fileobject.xreadlines() ) Collector #1837
-
-      - Switched the bundled Zope 3 to release 3.2 and upgraded the
-        Five product to version 1.3 (see Products/Five/CHANGES.txt).
-
-      - The PageTemplate implementation now uses Zope 3 message
-        catalogs by default for translation.  Old-style translation
-        services such as Localizer or PlacelessTranslationService are
-        still supported as fall-backs.  See Products/Five/doc/i18n.txt
-        for more information.
-
-      - Switched to the new improved test runner from Zope 3.  Run
-        test.py with -h to find out more.
-
-      - lib/python/docutils is now a reference to docutils package
-        from the Zope 3 source tree (to get rid of redundant packages)
-
-    Bugs Fixed
-
-      - Collector #2051: Applied patch by Yoshinori Okuji to fix some
-        XML export/import problems, including tests for that feature.
-
-      - Collector #2037: fixed broken ACTUAL_URL for '/'
-
-      - Missing import of NotFound in webdav.Resource
-
-      - Collector #1819: fixed method signature of
-        MountedObject.SimpleTrailblazer._construct()
-
-      - Collector #2019: removed validateValue() from cAccessControl (already
-        removed in former Zope versions from the AccessControl Python
-        implementation)
-
-      - Collector #1991: ZPublisher did not deal properly with a trailing
-        %20 in the URL
-
-      - zope.app.introspector was not included with the source archive
-
-      - Collector #2013: improved XHTML conformance of error messages,
-        some of which did not close '<p>' tags.
-
-      - Collector #2002: fixed broken 'ls -R' functionality (didn't
-        recurse properly subclasses of OFS.Folder)
-
-      - Collector #1992: unified the visible hostnames of the FTP and
-        HTTP servers
-
-      - Collector #1999: fixed broken FTP rename functionality
-        (RNFR now returns 350 as status code instead 250)
-
-      - HTTPResponse: for XML content the encoding specified within
-        the XML preamble is adjusted to the real encoding of the content
-        as specified through the 'charset' within the content-type
-        property.
-
-      - Collector #1939: When running as a service, Zope could
-        potentially collect too much log output filling the NT Event
-        Log. When that happened, a 'print' during exception handling
-        would cause an IOError in the restart code causing the service
-        not to restart automatically.
-
-        Problem is that a service/pythonw.exe process *always* has an
-        invalid sys.stdout.  But due to the magic of buffering, small
-        "print" statements would not fail - but once the file actually
-        got written to, the error happened.  Never a problem when
-        debugging, as the process has a console, and hence a valid
-        stdout.
-
-      - For content-type HTTP headers starting with 'text/' or 'application/'
-        the 'charset' field is automatically if not specified by the
-        application. The 'charset' is determined by the content-type header
-        specified by the application (if available) or from the
-        zpublisher_default_encoding value as configured in etc/zope.conf
-
-      - Collector #1976: FTP STOR command would load the file being
-        uploaded in memory. Changed to use a TemporaryFile.
-
-      - OFS ObjectManager: Fixed list_imports() to tolerate missing
-        import directories.
-
-      - Collector #1621, 1894:  Removed support for use of long-deprecated
-        'whrandom' module.
-
-      - OFS PropertySheets / webdav: Fixed dav__resourcetype.
-        __dav_collection__ with a false value was overridden by
-        isAnObjectManager.
-
-      - added missing Zope 3 imports: zope.app.intid, zope.app.keyreference, 
-        zope.app.session, zope.contentprovider, zope.viewlet
-
-    Other
-
-      - AccessControl.User: Use a better __repr__.
-
-      - ZSQLMethod.manage_main: Moved the error message that warns of a
-        non-existing or closed database connection next to the Connection ID
-        dropdown and present it using red to increase its visibility.
-
-      - The ImageFile module has finally been deprecated for good and
-        will be removed in Zope 2.11.  Use App.ImageFile instead.
-
-  after Zope 2.8.1
-
-      - The '@' character is now allowed in object ids (RFC 1738 allows it).
-
-    Bugs Fixed
-
-      - If a content object implemented any in-place numeric operators, 
-        untrusted code could call them, thus modifying the content.
-
-      - If Python 2.4 is used, despite the fact that Python 2.4 is
-        unsupported, untrusted code could use generator expressions to
-        gain access to container items.
-
-      - Collector #1895: testrunner: omitting the 'var' from recursive
-        directory walking
-
-      - OFS.Image.manage_FTPget() would str() it's .data attribute,
-        potentially loading the whole file in memory as a
-        string. Changed to use RESPONSE.write() iterating through the
-        Pdata chain, just like index_html().
-
-      - Collector #1863: Prevent possibly sensitive information to leak via
-        the TransientObject's __repr__ method.
-
-      - Repaired 'handle_errors' usage for doctests, along with the
-        supporting 'debug' argument passed to
-        'ZPublisher.Test.publish_module'.
-
-      - Collector #1879: applied patch by Dieter Maurer to fix a bug in 
-        ac_aquire() ignoring the default argument
-
-      - Collector #1864, #1906: fixed header normalization in appendHeader()
-
-      - Collector #1899: fixed migration issue when using export/import for
-        ZCatalog instances
-
-      - Collector #1871: Applied patch to support lists with records using
-        ZTUtils.make_query()
-
-      - AccessControl: creating a new user through "zpasswd inituser" did not
-        work properly with a top-level user folder with enabled password
-        encryption.
-
-      - ZCatalog: refreshCatalog() could not be called safely from a ZEO
-        client script
-
-      - Catalog.clear(): fixed handling of _length attribute (caused import
-        problems for some .zexp files e.g. Squishdot instances)
-
-      - DateIndex now properly removes documents from both indexes if
-        the value is None
-
-      - Collector #1888: Some parts of the TALInterpreter would not pass a 
-        default when  translating, yet expect a string back. This would cause 
-        an error (usually "NoneType has no attribute 'replace'") in the case 
-        the message was not translated.
-        
-  Zope 2.8.1 (2005/08/11)
-
-    Features added
-
-      - Interface: Added Z3 -> Z2 bridge utilities.
-        This allows to migrate interfaces to Zope 3 style interfaces and
-        bridge them back to oldstyle interfaces for backwards compatibility.
-
-    Bugs Fixed
-
-      - Zope2.Startup.zopectl: fork before execv when running unit tests
-        (don't exit the shell, if run from there).
-
-      - TAL: MassageIDs are now handled the same way as in zope.tal.
-
-      - DocumentTemplate: ustr no longer mangles MassageIDs.
-        Custom string types are now returned unchanged.
-
-      -  As developed in a long thread starting at
-         http://mail.zope.org/pipermail/zope/2005-July/160433.html
-         there appears to be a race bug in the Microsoft Windows socket
-         implementation, rarely visible in ZEO and/or in
-         ZServer/medusa/thread/select_trigger.py when multiple processes try
-         to create an "asyncore trigger" simultaneously, most often (in
-         stress tests) manifesting as a hung process.  Windows-specific
-         trigger code in both changed to work around this bug when it occurs.
-
-      - Collector #1807: fixed memory leak in cAccessControl.guarded_getattr()
-
-
-  Zope 2.8.1 b1 (2005/07/28)
-
-    Features Added
-
-      - PluginIndexes, ZCTextIndex and ZCatalog: Added some z3 interfaces.
-
-      - Verbose security exception reporting has been folded into Zope,
-        removing the need for the VerboseSecurity product.  See the
-        documentation for the "verbose-security" option in zope.conf.
-
-      - "TemporaryStorage" (the storage that is used mainly to back the
-        default sessioning database) is now MVCC capable, which essentially
-        means that its usage will no longer generate ZODB ReadConflictErrors.
-
-    Bugs Fixed
-
-      - Collector #1852: fixed wrong URL construction in webdav.davcmds
-
-      - Collector #1844: fixed whitespace handling in the ZMI "Find" tab
-
-      - Collector #1813: removed spurious inclusion of CMFBTreeFolder.
-        in Products/BTreeFolder2 (CMFCore will include it after 1.5, with
-        an appropriate module alias for backward compatibility).
-
-      - Replaced all transaction.commit(1) calls by  transaction.savepoint()
-
-      - Collector #1832: UnIndex swallowed ConflictErrors.
-
-      - Collector #1815: ZCTextIndex accepts (again) sequences of strings to
-        be indexed.
-
-      - Collector #1812: Fixed key error in ZSQL ZMI/Test
-
-      - Fixed CMFBTreeFolder for CMF 1.5+
-
-      - WebDAV COPY and MOVE did not call '_notifyOfCopyTo' and '_postCopy'
-        hooks like it was done in OFS.CopySupport. Additionally added
-        'manage_changeOwnershipType' to make MOVE behave even closer to
-        OFS.CopySupport.
-
-      - Collector #1548: Fix 'httplib' usage in ZPublisher.Client.
-
-      - Collector #1808: manage_convertIndexes no longer tries to change the
-        index types causing some trouble with CMF.
-
-      - manage_convertIndexes did not treat DateRangeIndexes and PathIndexes
-        properly.
-
-      - Updated Zope X3 to bugfix release 3.0.1
-
-      - Updated Five to bugfix release 1.0.2 (see Products/Five/CHANGES.txt)
-
-  Zope 2.8.0 (2005/06/11)
-
-    Bugs Fixed
-
-      - Collector #1792: applied patch for broken ZClasses
-
-      - doc/FAQ.txt updated: should bear some resemblance to reality now.
-        (PCGI stuff removed; error information updated; PID information
-        updated; upgrade procedure added; some common version questions added.)
-
-      - Collector #1770: Fixed RestructuredText subtitle
-
-      - Collector #1803: Fixed InitializeClass for some corner case.
-
-      - Collector #1798, issue 1: ZopeTestCase no longer tries to
-        install products that were installed by Zope during startup.
-
-      - Collector #1799: Avoid lying about parent's refcount when
-        calling back into Python code.
-
-      - Collector #889:  made 'and' operator for KeywordIndexes actually
-        restrict results as expected (thanks to 'aroda' for the patch!).
-
-      - Collector #1323: applied patch to fix umask problem in zdctl
-
-      - Updated Five to bugfix release 1.0.1 (see Products/Five/CHANGES.txt)
-
-  Zope 2.8.0 b2 (2005/05/22)
-
-    Features added
-
-      - Made WebDAV server distinguishable from the default HTTP
-        server both in the ZMI and in event.log.
-
-      - Included BTreeFolder2
-
-    Bugs fixed
-
-      - Collector #1507/1728: Server addresses are now handled the same way on
-        all platforms. This fixes the default binding on Windows.
-
-      - Collector #1781: made 'create_mount_points' ZConfig option actually
-        work (thanks to Dieter Maurer for the patch).
-
-      - Collector #1780: DateTime.strftime() now handles dates <= 1900 or
-        >= 2038
-
-      - Collector #1775: turning off debug mode by default
-
-      - Collector #1784: fixed handling of multiple attributes in ZCTextIndex
-
-      - Don't copy '.svn' directories from skeleton into an instance
-        (thanks to Dale Hirt for the patch).
-
-      - Collector #1776: Improved setup.py.
-        The Finder class is now used for the complete lib/python tree and has
-        a blacklist instead of a whitelist for file extensions. So there
-        should no longer be a need to update setup.py if modules or files are
-        added or removed in lib/python.
-
-      - Collector #1751: Improved error reporting reporting during the
-        startup phase
-
-      - Collector #1745: Fixed ZSQL error KeyError 'query'
-
-      - Collector #1735: fixed UnicodeDecodeError in Loader.py
-
-  Zope 2.8b1 (2005/04/24)
-
-    Features added
-
-      - Added lazy: TAL expression and fixed defer: expression for python
-        expression
-
-      - ZCatalog.CatalogBrains: An _unrestrictedGetObject method has
-        been added.
-
-      - ZODB transactions now support savepoints. See
-        transaction/savepoint.txt.  These will replace
-        subtransactions.
-
-    Bugs fixed
-
-      - Collector #1754: Fixed import of 'transaction' in
-        'zopectl adduser' (which wasy dying with a NameError).
-
-      - Collector #1750: StructuredText: fixed handling of image URLs
-        with query string
-
-      - Collector #1748: Fixed SIGSEGV in Acquisition
-
-      - Hotfix_20050405:  classes defined in untrusted code could shadow
-        the roles of methods defined as protected by their bases.
-
-      - Collector #1656: Fixed enumeration within untrusted code
-        (forward-port from 2.7 branch).
-
-      - Collector #1721: Fixed handling of an empty indexed_attrs parameter
-
-
-  Zope 2.8a2 (2005/04/02)
-
-    Features added
-
-      - ZCatalog.CatalogBrains:  'getObject' now raises errors, rather than
-        returning None, in cases where the path points either to a nonexistent
-        object (in which case it raises NotFound) or to one which the user
-        cannot access (raising Unauthorized).  Sites which rely on the old
-        behavior can restore setting a new zope.conf option,
-        'catalog-getObject-raises', to "off".
-
-        This compatibility option will be removed in Zope 2.10.
-
-      - PluginIndexes: the ZCatalog's "Indexes" tab now show the number of
-        distinct values indexed by each index instead of a mixture of indexed
-        objects versus number of distinct values. Indexes derived from UnIndex
-        show both values within their own ZMI screen. In addition most indexes
-        have now a "Browse" tab to browse through the list of indexed
-        values and their occurrences.
-
-      - FTPServer: a RNFR (rename from) request is now being responded
-        with a 550 error code if the source file does not exist
-
-      - Fixed ObjectManager to not swallow exceptions during object
-        deletion (in debug mode and if the user is not Manager). This
-        allows for better debugging, while still keeping the possibility
-        for a Manager to delete buggy objects.
-
-      - Added a ZConfig directive 'large-file-threshold' to control
-        the request content-size threshold at which a temporary file
-        gets created. Use the same value for deciding between reading
-        the whole request in memory or just a chunk inside
-        webdav.NullResource.PUT().
-
-      - RAMCacheManager: Allow invalidation of a cache entry from the
-        Statistics view in the ZMI
-
-      - Collector #1454/OFS.File: Accept content types ending with
-        "javascript" as editable through the File edit form, just like
-        text/<foo> types
-
-      - Zope X3 3.0.0's 'src/zope' package is included now.
-
-      - Five (Zope 3 integration technology for Zope 2) is included
-        now in Products/Five.
-
-    Bugs fixed
-
-      - Collector #1460: guarded_apply was too restrictive.
-
-      - OFS.Traversable still used a string 'NotFound' exception.
-
-      - ZPublisher would fail to recognize a XML-RPC request if the
-        content-type header included a 'charset' parameter.
-
-      - Forward-ported 'aq_acquire'-related fix and associated tests
-        from Zope 2.7.4.
-
-      - Collector #1730: XML page templates couldn't call aq_parent in
-        path expressions.
-
-      - Fixed brain.getObject() to correctly traverse to an object even
-        if one of its parents is not accessible, to be close to what the
-        Publisher does.
-
-      - Forward ported fix for OFS.CopySupport tests which corrected
-        signature of a faux security policy's 'validate' method.
-
-      - 'setup.py' did not install the 'Zope' compatibility module
-        (the old 'Zope' package has been renamed to 'Zope2').
-
-      - Fixed Shared.DC.ZRDB.Results to behave with the new-style
-        ExtensionClass. Added a test.
-
-      - 'setup.py' did not install the new 'Zope' compatibility module
-        (the 'Zope' package has been renamedd to 'Zope2').
-
-      - Collector #1507: Zope now binds again to all available IP addresses if
-        ip-address is unset
-
-      - Use 'del' instead of 'list.remove()' in
-        Catalog.delColumn(). There can be only one column with the
-        same name, and it could potentially break catalog metadata as
-        remove() may remove more than one element from the list if
-        they have the same value. Also, we already have the list index
-        we are interested in deleting so it doesn't make sense to look
-        up the value and call 'list.remove()' on it.
-
-      - Collector #1628: FTP server has been broken (directory
-        listings did not work)
-
-      - Collector #1705: CopySource._postCopy is never called
-
-      - Collector #1617: Fixed crash in ZPT code (caused by improper
-        checks in cAccessControl)
-
-      - Collector #1683: fixing batching in the DA "Test" tab
-
-      - Collector #1648: Fix bug in Medusa FTP
-
-      - Collector #1667: allow 'max-number-of-session-objects 0' to have
-        the same effect as setting the value via the web interface (i.e.,
-        make the number of session objects unlimited, rather than falling
-        back to the default).
-
-      - Collector: #1651: removed compiler warning
-
-      - Collector #1661: make 'python-check-interval' setting in zope.conf
-        actually work as documented.  This setting allows for important
-        tuning opportunities for production Zope servers.
-
-      - Collector #1657:  Don't break host-based virtual hosting when
-        purging an HTTP accelerator.
-
-      - DTML Methods were not interoperable with the new filestream_iterator
-        and caches based on it (FileCacheManager).
-
-      - Collector #1655: fixed severe memory leak in TemporaryStorage
-
-      - Collector #1407: fixed XML escaping problem introduced in 2.7.4 b1
-
-      - Collector #1151: HTTP compression was broken on error pages
-
-      - The REQUEST now contains a new entry ACTUAL_URL which contains the
-        full URL without query string as it appears within the location bar of
-        the browser. The key has been added to provide a single key that is
-        available for vhosted and non-vhosted installations.
-
-      - Collector #1605: VHM did not quote URLs
-
-      - webdav.Resource: during COPY, manage_afterClone was called way
-        too early, thus the object wasn't bound to the database and
-        couldn't find a context. Changed to behave the same way as
-        CopySupport.
-
-      - RAMCacheManager: opimized performance by using cPickle instead
-        of pickle and by using the highest pickle protocol available
-        instead of using ASCII pickles (patch by Dieter Maurer)
-
-      - Collector #631: Image URLs in StructuredText containing port
-        numbers were not rendered correctly
-
-      - Collector #1498: Don't choke on malformed cookies. Cookies of
-        the form "foo=bar; hmm; baz=gee" will give an empty value for
-        'hmm' instead of silently discarding it and the rest of the
-        string. (Thanks to 'sirilyan' for the patch.)
-
-      - bin/zopectl test now uses os.execv, instead os os.system,
-        so that options with characters that needs shell quoting
-        doesn't break the command.
-
-      - Collector #1219:  Make XML export sane again.
-
-      - Collector #945:  Allow adding empty PythonScript instances
-        programmatically.
-
-      - Updated doc/UNITTEST.txt and lib/python/Testing/README.txt to
-        reflect progress made since UNITTEST.txt was originally written.
-
-      - Removed Version objects from the add menu. Versions are agreed to be a
-        feature that should not be used as it is not well implemented and
-        allows for data loss.
-
-      - Collector #1510: Allow encoding of application/xhtml+xml pages
-        according to the charset specified in the Content-Type header
-        (thanks to Jacek Konieczny for the patch).
-
-      - Collector #1599: made sqltest work with unicode strings (thanks
-        to Peter Sabaini for the patch).
-
-      - zopectl: fixed handling of child processes (patch by Dieter Maurer)
-
-      - Collector #1593: fixed dumb _get_id() implementation in
-        OFS.CopySupport that produced copy_of_copy_of....files (thanks
-        to Alexandre Boeglin for the patch).
-
-      - Collector #1450: files in utilities/ZODBTools are now installed
-        during the installation process in the 'bin' directory
-
-      - Collector #1003: added new 'http-header-max-length' directive
-        to zope.conf to specific the maximum length of a HTTP request
-        header before it is considered as a possible DoS attack and
-        discarded.
-
-      - Collector #1371: added new 'cgi-maxlen' directive to zope.conf
-        to limit the amount of form data being processed by Zope
-        to prevent DoS attacks
-
-      - Collector #1407: changed WebDAV display name for objects
-        to title_or_id()
-
-      - the 'trusted-proxy' directive in zope.conf now also accepts
-        hostnames instead of IP addresses only (patch by Dieter Maurer)
-
-      - Fixed test.py to not over-resolve symbolic links. Needed to run
-        tests when the Products directory and a product are symlinks.
-
-      - Collector #1583/ZReST: Fixed handling of the title attribute
-        for non-ascii characters.
-
-      - Collector #1577: Fixed cryptic error message in ZPublisher if a
-        non-ASCII string is passed to a date, int, long or float property.
-
-      - Collector #1576: Fixed Z Search Interface to use proper HTML.
-
-      - Collector #1127: strftime did not take timezone into account.
-
-      - Collector #1569/DateTime: Added a new ISO8601-method that will
-        return correctly formatted ISO 8601-representations to augment
-        the ISO method which isn't compliant with ISO 8601.
-
-      - ZPublisher: changed some hardcoded 'latin1' arguments to 'iso-8859-15'
-        since latin1 is obsolete.
-
-      - Collector #1566: Installation of Zope on some older Solaris versions
-        could fail due to a broken "echo" implementation causing the
-        creation of a borked version.txt file.
-
-      - Collector #934: Image and File objects are now always internally
-        split into small chunks even when initialized from a string.
-
-      - docutils: updated to V 0.3.5. The Zope core now contains a full copy of
-        the docutils package except some GPLed files which can not be included
-        with the Zope distribution due to license constraints on svn.zope.org.
-
-      - docutils: moved from lib/python/docutils to
-        lib/python/third_party/docutils
-
-      - Collector #1557/OFS.Image: Introducing new 'alt' property. The 'alt'
-        attribute is no longer taken from the 'title' property but from the new
-        'alt' property.  The border="0" attribute is no longer part of the HTML
-        output except specified otherwise.
-
-      - Set a default value of '' for the new 'alt' property as not to
-        break existing content.
-
-      - Collector #1511: made IPCServer show up in the Control Panel under
-        "Network Services"
-
-      - Collector #1443: Applied patch by Simon Eisenmann that reimplements
-        the XML parser used in WebDAV fixing a memory leak.
-
-      - Always unescape element contents on webdav.xmltools
-
-      - Use saxutils to escape/unescape values for/from
-        PROPFIND/PROPPATCH.
-
-      - Make OFS.PropertySheet use the escaping function from
-        webdav.xmltools.
-
-      - Escape/unescape &quot; and &apos;
-
-      - Don't escape properties stored as XML (ie: having a
-        __xml_attrs__ metadata set by PROPPATCH) when building a
-        PROPFIND response.
-
-      - If a PROPPATCH element value contains only a CDATA section,
-        store the CDATA contents only.
-
-      - Catch AttributeErrors and KeyErrors raised from
-        __bobo_traverse__ and convert them to NotFound. In debug mode
-        a more verbose error message is issued, the same way it's done
-        on attribute/item traversal.
-
-      - Collector #1523: replace the text field for importing .zexp/.xml
-        files with a selection list
-
-      - Stitch newly-created object into it's container *before*
-        calling it's PUT() method. This fixes an issue with
-        OFS.File/OFS.Image that would result into reading the whole
-        file in memory and wrapping it into a *single* Pdata object.
-
-      - Import ZServer.CONNECTION_LIMIT variable *inside* the method
-        that uses it. Before this, the variable was imported at the
-        module level, thus binding it too early which would cause the
-        ZConfig handler to have no real effect.
-
-  Zope 2.8a1 (2004/10/17)
-
-    Features added
-
-     - Included Stefan Holek's ZopeTestCase 0.9
-
-     - The SiteErrorLog allows you to acknowledge (or delete) exceptions,
-       so you can reduce or clear the list without restarting your
-       Zope server. Additionally the SiteErrorLog is covered by unit tests
-       now.
-
-     - Unit tests added for the SiteErrorLog.
-
-     - UI improvement for the ZCatalog. The "catalog contents" allow
-       you to filter the cataloged objects by path now.
-
-     - Made test.py follow symbolic links on POSIX systems.
-
-     - added utilities/reindex_catalog.py to perform ZCatalog maintenance
-       operations from the command line (through zopectl)
-
-     - RESPONSE.setBody and RESPONSE.setStatus now accept lock
-       parameters in the same way as RESPONSE.redirect. These prevent
-       further calls to the methods from overwriting the previous value.
-       This is useful when writing http proxies.
-
-     - DateTime: new DateTime instance can be constructed from a given
-       DateTime instance: d_new = DateTime(d_old)
-
-     - The DateTime parser now throws a SyntaxError upon any parsing errors.
-
-     - ZCatalog: added a new configuration option in the "Advanced" tab
-       to provide optional logging of the progress of long running
-       reindexing or recataloging operations.
-
-     - made Zope.configure return the starter instance to enable other
-       methods to be called, such as starter.setupConfiguredLoggers()
-
-     - Improved Unicode handling in Page Templates. Template contents
-       and title will now be saved as a Unicode string if
-       the management_page_charset variable can be acquired and is true.
-       The character set of an uploaded file can now be specified.
-
-     - zopectl now accepts the -m argument to set a umask for files created
-       by the managed process (e.g. -m 002 or --umask 002).
-
-     - AccessControl/permission_settings() now has a new optional parameter
-       'permission' to retrieve the permission settings for a particular
-       permission.
-
-     - The obsolete 'SearchIndex' package has been removed
-
-     - Traversal now supports a "post traversal hook" that get's run
-       after traversal finished and the security context is established.
-
-     - Using "_usage" parameters in a ZCatalog query is deprecated and
-       logged as DeprecationWarning.
-
-     - MailHost now has two additional properties, a user id and a
-       password. These are used to attempt ESMTP authentication
-       before sending a mail.
-
-     - Folder listings in FTP now include "." as well as "..".
-
-     - When a VHM is activated, it adds the mapping
-       'VIRTUAL_URL_PARTS': (SERVER_URL, BASEPATH1, virtual_url_path)
-       to the request's 'other' dictionary.  If BASEPATH1 is empty, it
-       is omitted from the tuple.  The joined parts are also added
-       under the key 'VIRTUAL_URL'.  Since the parts are evaluated
-       before traversal continues, they will not reflect modifications
-       to the path during traversal or by the addition of a default
-       method such as 'index_html'.
-
-     - Extension Classes, a key Zope foundation, have been totally
-       rewritten based on Python new-style classes.
-
-       This change provides a number of advantages:
-
-       o Use of new-style class features (e.g. slots, descriptors,
-         etc.) in Zope objects. Support for object protocols (special
-         __ methods) added since Python 1.4.
-
-       o Support for cyclic garbage collection.
-
-       o Ability to use new-style classes as base classes of Zope objects.
-
-       o Pave the way for sharing code between Zope 2 and Zope 3.
-
-       Note -- Extension classes with __of__ methods are made into
-         Python read descriptors.
-
-         If an extension classes is used to implement a descriptor,
-         indirectly by implementing __of__ or directly by implementing
-         __get__, the behavior of the descriptor will differ from
-         ordinary descriptors in an important way. The descriptors
-         __get__ method will be called *even if* the descriptor is
-         stored on an instance of an extension class.  Normally
-         descritor __get__ methods are called only of the descriptor
-         is stored in a class.
-
-     - ZODB 3.3
-
-       This is the first version of ZODB that does not require
-       ExtensionClass.
-
-     - Add 'parity' method to ZTUtils Iterators.
-
-     - Allow untrusted code to mutate ZPublisher record objects.
-
-     - Added a "mime-types" configuration value which names a file
-       giving additional MIME type to filename extension mappings.
-       The "mime-types" setting may be given more than once in the
-       configuration file; the files have the same format at the
-       mime.types file distributed with Apache.
-
-     - Changed the ZEO server and control process to work with a
-       single configuration file; this is now the default way to
-       configure these processes.  (It's still possible to use
-       separate configuration files.)  The ZEO configuration file can
-       now include a "runner" section used by the control process and
-       ignored by the ZEO server process itself.  If present, the
-       control process can use the same configuration file.
-
-     - ZConfig was updated to version 2.0.  The new version includes
-       two new ways to perform schema extension; of particular
-       interest in Zope is the ability for a configuration file to
-       "import" new schema components to allow 3rd-party components
-       (such as storages, databases, or logging handlers) to be used.
-
-     - The testrunner.py script has been replaced with test.py which
-       is now installed into the 'bin' folder.
-
-    Bugs fixed
-
-     - Removed Python 2.3.3 as valid option. ZODB 3.3 requires Python
-       2.3.4 or later.
-
-     - Collector #1332: Added in-place migration of the Catalog.__len__
-       attribute to avoid new-style class caching problems. Instances of
-       ZCatalog or instances of classes with ZCatalog as base class will be
-       migrated automatically. Instances of Catalog or classes with Catalog
-       as base class must be migrated manually by calling the migrate__len__()
-       method on the every instance. In addition old BTree migration code
-       (for pre-Zope 2.5 instances) has been removed. If you want to migrate
-       from such an old version to Zope 2.8, you need to clear and reindex
-       your ZCatalog).
-
-     - Collector #1595: same as in Collector #1132 for indexes derived from
-       UnIndex. Exisiting ZCatalog instances must be converted manually
-       by calling the "manage_convertIndexes" method through-the-web for
-       every single ZCatalog instance. See also doc/FAQ.txt (Installation,
-       question #4)
-
-     - Collector #1457: ZCTextIndex's QueryError and ParseError
-       are now available for import from untrusted code.
-
-     - Collector #1473: zpasswd.py can now accept --username
-       without --password
-
-     - Collector #1491: talgettext.py did not create a proper header
-       for the generated .pot file if multiple pagetemplate files
-       were processed.
-
-     - Collector #1477: TaintedString.strip() now implements the
-       same signature as str.strip()
-
-     - TAL: tal:on-error does not trap ConflictError anymore.
-
-     - OFS.CopySupport: Enforced "Delete objects" permission during
-       move (CMF Collector #259).
-
-     - Removed DWIM'y attempt to filter acquired-but-not-aceessible
-       results from 'guarded_getattr'.
-
-     - Collector #1267: applied patch to fix segmentation faults on
-       x86_64 systems
-
-     - ZReST: the charset used in the rendered HTML was not set to the
-       corresponding output_encoding property of the ZReST instance. In addition
-       changing the encodings through the Properties tab did not re-render
-       the HTML.
-
-     - Collector #1234: an exception triple passed to LOG() was not
-       propagated properly to the logging module of Python
-
-     - Collector #1441: Removed headers introduced to make Microsoft
-       webfolders and office apps happy, since they make a lot of
-       standards-compliant things unhappy AND they trick MS Office
-       into trying to edit office files stored in Zope via WebDAV even
-       when the user isn't allowed to edit them and is only trying to
-       download them.
-
-     - Collector #1445: Fixed bad interaction between -p and -v(v)
-       options to test.py that resulted in exceptions being printed
-       when they shouldn't have been.
-
-     - Collector #729: manage_main doesn't display the correct page title
-       most of the time. It is not completely fixed but using title_or_id
-       makes folders display the correct id as a fallback.
-
-     - Collector #1370: Fixed html generated by Z Search interface.
-
-     - Collector #1295: Fixed minor niglet with the Elvis tutorial.
-
-     - added "version.txt" to setup.py to avoid untrue "unreleased version"
-       messages within the control panel
-
-     - Collector #1436: applied patch to fix a memory leak in
-       cAccessControl.
-
-     - Collector #1431: fixed NetBSD support in initgroups.c
-
-     - Collector #1406: fixed segmentation fault by acquisition
-
-     - Collector #1392: ExternalMethod ignored management_page_charset
-
-     - unrestrictedTraverse() refactored to remove hasattr calls (which mask
-       conflict errors) and for greater readability and maintainability.
-
-     - Zope can now be embedded in C/C++ without exceptions being raised
-       in zdoptions.
-
-     - Collector #1213: Fixed wrong labels of cache parameters
-
-     - Collector #1265: Fixed handling of orphans in ZTUtil.Batch
-
-     - Collector #1293: missing 'address' parameters within one of the server
-       sections raise an exception.
-
-     - Collector #1345: AcceleratedHTTPCacheManager now sends the
-       Last-Modified header.
-
-     - Collector #1126: ZPublisher.Converters.field2lines now using
-       splitlines() instead of split('\n').
-
-     - Collector #1322: fixed HTML quoting problem with ZSQL methods
-       in DA.py
-
-     - Collector #1124: The ZReST product now uses the same reST encoding
-       parameters from zope.conf as the low-level reStructuredText
-       implementation.
-
-     - Collector #1259: removed the "uninstall" target from the Makefile
-       since the uninstall routine could also remove non-Zope files. Because
-       this was to dangerous it has been removed completely.
-
-     - Collector #1299: Fixed bug in sequence.sort()
-
-     - Collector #1159: Added test for __MACH__ to initgroups.c so the
-       initgroups method becomes available on Mac OS X.
-
-     - Collector #1004: text,token properties were missing in
-       PropertyManager management page.
-
-     - Display index name on error message when index can't be used as
-       'sort_on'.
-
-     - PUT would fail if the created object had a __len__ = 0 (eg:
-       BTreeFolder2) and fallback to _default_put_factory. Fix by
-       checking if the returned object is None instead.
-
-     - Collector #1160: HTTPResponse.expireCookie() potentially didn't
-       when an 'expires' keyword argument was passed.
-
-     - Collector #1289: Allow ZSQL methods to be edited via WebDAV.
-
-     - WebDAV property values were not being properly escaped on
-       'propstat'.
-
-     - WebDAV 'supportedlock' was not checking if the object did
-       implement the WriteLockInterface before returning it's
-       value.
-
-     - reStructuredText ignored the encoding settings in zope.conf
-
-     - ObjectManager no longer raises string exceptions
-
-     - Collector #1260: Testing/__init__.py no longer changes the
-       INSTANCE_HOME.
-
-     - App.config.setConfiguration() did not update the legacy source
-       for debug_mode, Globals.DevelopmentMode.
-
-     - Script (Python) objects now have a _filepath attribute, also
-       used as the '__file__' global at runtime.  This prevents an
-       import problem caused by the fix to #1074.
-
-     - Minor usability tweaks:
-
-       * Increased FindSupport meta type selection widgets
-         height to 8 lines
-
-     - The DateTime module did not recognize the settings for
-       "datetime-format".
-
-     - Stop testrunner.py from recursing into the 'build-base' directory
-       created by setup.py.
-
-     - Collector #1074: Change Scripts' __name__ to None
-
-     - Range searches with KeywordIndexes did not work with record-style
-       query parameters
-
-     - Item_w__name__ now has a working getId() method
-
-     - PageTemplateFile now using Item_w__name__ mixin, fixing
-       its getId() and absolute_url() methods.
-
-     - Only one VirtualHostMonster is allowed per container.
-
-     - Collector #1133: TreeTag choked on Ids of type long.
-
-     - Collector #1012: A carefully crafted compressed tree state
-       could violate size limit.  Limit is no longer hardcoded.
-
-     - Collector #1139: tal:attributes didn't escape double quotes.
-
-     - Management interface of TopicIndexes has been completely broken
-
-     - Collector #1129: Improper parsing of ISO8601 in DateTime.
-
-     - Removed pervasive use of string exceptions (some may still be
-       hiding in the woodwork, but all raise's with string literals are
-       gone).
-
-     - AccessControl.User used a misleading string exeception,
-       'NotImplemented', which shadowed the Python builtin.
-
-     - Collector #426: Inconsistent, undocumented error() method.
-
-     - Collector #799: Eliminate improper uses of SCRIPT_NAME.
-
-     - Collector #445: Add internal global declaration for Script bindings.
-
-     - Collector #616: Make CONTEXTS available to TALES Python expressions.
-
-     - Collector #1074: Give Script execution context a __name__
-
-     - Collector #1095: Allow TAL paths starting with '/varname' as a
-       preferred spelling for 'CONTEXTS/varname'.
-
-     - Collector #391: Cut and paste now requires delete permissions.
-
-     - Collector #331: Referenses to URL in manage_tabs was changed
-       to REQUEST.URL to prevent accidental overriding.
-
-     - Made the control panel properly reflect the cache-size setting
-       of ZODB's object cache once again.
-
-     - ConflictError was swallowed in ObjectManager by
-       manage_beforeDelete and _delObject. This could break code
-       expecting to do cleanups before deletion.
-
-     - Python 2.3 BooleanType wasn't handled properly by ZTUtils
-       marshalling and ZPublisher's converters.
-
-     - Collector #1065: bin/ scripts didn't export HOME envars.
-
-     - Collector #572: WebDAV GET protected by 'FTP Access' permission.
-       Two new methods have been added to WebDAV resources, "manage_DAVget"
-       and "listDAVObjects". These are now used by WebDAV instead of the
-       earlier "manage_FTPget" and "objectValues". This separates the
-       permissions, and allows WebDAV specific overriding of these methods.
-
-     - Collector #904: Platform specific signals in zdaemon/Daemon.py
-       (fixed by removing the "fossil" module from 2.7 branch and head).
-
-     - Workaround for Collector #1081: The 'title' property for objects
-       derived from OFS.Folder or PropertyManager can now be
-       removed and replaced with a ustring property. This allows the usage
-       of non-ISO-8859-1 or ASCII charsets
-
-     - Collector #951: DateTime(None) is now equal to DateTime()
-
-     - Collector #1056: aq_acquire() ignored the default argument
-
-     - Collector #1087: ZPT: "repeat/item/length" did not work as documented
-       in the Zope Book.
-
-     - Collector #721: Entities in tal:attribute values weren't
-       properly escaped.
-
-     - Collector #851: Traversable.py: A bare try..except shadowed
-       conflict errors
-
-     - Collector #1058: Several fixes for PropertySheets when used
-       outside ZClasses
-
-     - Collector #1053: parseIndexRequest turned empty sequence of search
-       terms into unrestricted search.
-
-     - manage_tabs had a namespace problem with the acquisition of names from
-       the manage_options variable resulting to acquire "target" and "action"
-       from objects above in the hierachy.
-
-     - PathIndex and TopicIndex are now using a counter for the number
-       of indexed objects instead of using a very expensive calculation
-       based on the keys of their indexes.
-
-     - Collector #1039: Whitespace problem in Z2.log fixed
-
-     - changed some bare try: except:'s in Shared.DC.ZRDB.Connection
-       so that they now log exceptions that occur.
-
-     - ObjectManager will now attempt to set Owner local role keyed
-       to the user's id, rather than username.

Copied: Zope/branches/regebro-wsgi_support2/doc/CHANGES.txt (from rev 67730, Zope/trunk/doc/CHANGES.txt)

Deleted: Zope/branches/regebro-wsgi_support2/lib/python/OFS/Traversable.py
===================================================================
--- Zope/trunk/lib/python/OFS/Traversable.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/OFS/Traversable.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -1,261 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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 module implements a mix-in for traversable objects.
-
-$Id$
-"""
-
-from urllib import quote
-
-from Globals import InitializeClass
-from AccessControl import ClassSecurityInfo
-from AccessControl import getSecurityManager
-from AccessControl import Unauthorized
-from AccessControl.ZopeGuards import guarded_getattr
-from Acquisition import Acquired, aq_inner, aq_parent, aq_base
-from zExceptions import NotFound
-from ZODB.POSException import ConflictError
-from zope.interface import implements
-
-from interfaces import ITraversable
-
-_marker = object()
-
-
-class Traversable:
-
-    implements(ITraversable)
-
-    security = ClassSecurityInfo()
-
-    security.declarePublic('absolute_url')
-    def absolute_url(self, relative=0):
-        """Return the absolute URL of the object.
-
-        This a canonical URL based on the object's physical
-        containment path.  It is affected by the virtual host
-        configuration, if any, and can be used by external
-        agents, such as a browser, to address the object.
-
-        If the relative argument is provided, with a true value, then
-        the value of virtual_url_path() is returned.
-
-        Some Products incorrectly use '/'+absolute_url(1) as an
-        absolute-path reference.  This breaks in certain virtual
-        hosting situations, and should be changed to use
-        absolute_url_path() instead.
-        """
-        if relative:
-            return self.virtual_url_path()
-
-        spp = self.getPhysicalPath()
-        try:
-            toUrl = self.REQUEST.physicalPathToURL
-        except AttributeError:
-            return path2url(spp[1:])
-        return toUrl(spp)
-
-    security.declarePublic('absolute_url_path')
-    def absolute_url_path(self):
-        """Return the path portion of the absolute URL of the object.
-
-        This includes the leading slash, and can be used as an
-        'absolute-path reference' as defined in RFC 2396.
-        """
-        spp = self.getPhysicalPath()
-        try:
-            toUrl = self.REQUEST.physicalPathToURL
-        except AttributeError:
-            return path2url(spp) or '/'
-        return toUrl(spp, relative=1) or '/'
-
-    security.declarePublic('virtual_url_path')
-    def virtual_url_path(self):
-        """Return a URL for the object, relative to the site root.
-
-        If a virtual host is configured, the URL is a path relative to
-        the virtual host's root object.  Otherwise, it is the physical
-        path.  In either case, the URL does not begin with a slash.
-        """
-        spp = self.getPhysicalPath()
-        try:
-            toVirt = self.REQUEST.physicalPathToVirtualPath
-        except AttributeError:
-            return path2url(spp[1:])
-        return path2url(toVirt(spp))
-
-    security.declarePrivate('getPhysicalRoot')
-    getPhysicalRoot=Acquired
-
-    security.declarePublic('getPhysicalPath')
-    def getPhysicalPath(self):
-        """Get the physical path of the object.
-
-        Returns a path (an immutable sequence of strings) that can be used to
-        access this object again later, for example in a copy/paste operation.
-        getPhysicalRoot() and getPhysicalPath() are designed to operate
-        together.
-        """
-        path = (self.getId(),)
-
-        p = aq_parent(aq_inner(self))
-        if p is not None:
-            path = p.getPhysicalPath() + path
-
-        return path
-
-    security.declarePrivate('unrestrictedTraverse')
-    def unrestrictedTraverse(self, path, default=_marker, restricted=0):
-        """Lookup an object by path.
-
-        path -- The path to the object. May be a sequence of strings or a slash
-        separated string. If the path begins with an empty path element
-        (i.e., an empty string or a slash) then the lookup is performed
-        from the application root. Otherwise, the lookup is relative to
-        self. Two dots (..) as a path element indicates an upward traversal
-        to the acquisition parent.
-
-        default -- If provided, this is the value returned if the path cannot
-        be traversed for any reason (i.e., no object exists at that path or
-        the object is inaccessible).
-
-        restricted -- If false (default) then no security checking is performed.
-        If true, then all of the objects along the path are validated with
-        the security machinery. Usually invoked using restrictedTraverse().
-        """
-
-        if not path:
-            return self
-
-        _getattr = getattr
-        _none = None
-        marker = _marker
-
-        if isinstance(path, str):
-            # Unicode paths are not allowed
-            path = path.split('/')
-        else:
-            path = list(path)
-
-        REQUEST = {'TraversalRequestNameStack': path}
-        path.reverse()
-        path_pop=path.pop
-
-        if len(path) > 1 and not path[0]:
-            # Remove trailing slash
-            path.pop(0)
-
-        if restricted:
-            securityManager = getSecurityManager()
-        else:
-            securityManager = _none
-
-        if not path[-1]:
-            # If the path starts with an empty string, go to the root first.
-            path_pop()
-            self = self.getPhysicalRoot()
-            if (restricted
-                and not securityManager.validate(None, None, None, self)):
-                raise Unauthorized, name
-
-        try:
-            obj = self
-            while path:
-                name = path_pop()
-                __traceback_info__ = path, name
-
-                if name[0] == '_':
-                    # Never allowed in a URL.
-                    raise NotFound, name
-
-                if name == '..':
-                    next = aq_parent(obj)
-                    if next is not _none:
-                        if restricted and not securityManager.validate(
-                            obj, obj,name, next):
-                            raise Unauthorized, name
-                        obj = next
-                        continue
-
-                bobo_traverse = _getattr(obj, '__bobo_traverse__', _none)
-                if bobo_traverse is not _none:
-                    next = bobo_traverse(REQUEST, name)
-                    if restricted:
-                        if aq_base(next) is not next:
-                            # The object is wrapped, so the acquisition
-                            # context is the container.
-                            container = aq_parent(aq_inner(next))
-                        elif _getattr(next, 'im_self', _none) is not _none:
-                            # Bound method, the bound instance
-                            # is the container
-                            container = next.im_self
-                        elif _getattr(aq_base(obj), name, marker) == next:
-                            # Unwrapped direct attribute of the object so
-                            # object is the container
-                            container = obj
-                        else:
-                            # Can't determine container
-                            container = _none
-                        try:
-                            validated = securityManager.validate(
-                                                   obj, container, name, next)
-                        except Unauthorized:
-                            # If next is a simple unwrapped property, it's
-                            # parentage is indeterminate, but it may have been
-                            # acquired safely.  In this case validate will
-                            # raise an error, and we can explicitly check that
-                            # our value was acquired safely.
-                            validated = 0
-                            if container is _none and \
-                                   guarded_getattr(obj, name, marker) is next:
-                                validated = 1
-                        if not validated:
-                            raise Unauthorized, name
-                else:
-                    if restricted:
-                        next = guarded_getattr(obj, name, marker)
-                    else:
-                        next = _getattr(obj, name, marker)
-                    if next is marker:
-                        try:
-                            next=obj[name]
-                        except AttributeError:
-                            # Raise NotFound for easier debugging
-                            # instead of AttributeError: __getitem__
-                            raise NotFound, name
-                        if restricted and not securityManager.validate(
-                            obj, obj, _none, next):
-                            raise Unauthorized, name
-
-                obj = next
-
-            return obj
-
-        except ConflictError:
-            raise
-        except:
-            if default is not marker:
-                return default
-            else:
-                raise
-
-    security.declarePublic('restrictedTraverse')
-    def restrictedTraverse(self, path, default=_marker):
-        # Trusted code traversal code, always enforces securitys
-        return self.unrestrictedTraverse(path, default, restricted=1)
-
-InitializeClass(Traversable)
-
-
-def path2url(path):
-    return '/'.join(map(quote, path))

Copied: Zope/branches/regebro-wsgi_support2/lib/python/OFS/Traversable.py (from rev 67730, Zope/trunk/lib/python/OFS/Traversable.py)

Copied: Zope/branches/regebro-wsgi_support2/lib/python/Products (from rev 67730, Zope/trunk/lib/python/Products)

Deleted: Zope/branches/regebro-wsgi_support2/lib/python/Products/PageTemplates/Expressions.py
===================================================================
--- Zope/trunk/lib/python/Products/PageTemplates/Expressions.py	2006-04-28 18:07:58 UTC (rev 67730)
+++ Zope/branches/regebro-wsgi_support2/lib/python/Products/PageTemplates/Expressions.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -1,368 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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
-#
-##############################################################################
-
-"""Page Template Expression Engine
-
-Page Template-specific implementation of TALES, with handlers
-for Python expressions, string literals, and paths.
-"""
-
-__version__='$Revision: 1.45 $'[11:-2]
-
-import re, sys
-from TALES import Engine
-from TALES import CompilerError
-from TALES import _valid_name
-from TALES import NAME_RE
-from TALES import Undefined
-from TALES import Default
-from TALES import _parse_expr
-from Acquisition import aq_base, aq_inner, aq_parent
-from DeferExpr import LazyWrapper
-from DeferExpr import LazyExpr
-from DeferExpr import DeferWrapper
-from DeferExpr import DeferExpr
-
-_engine = None
-def getEngine():
-    global _engine
-    if _engine is None:
-        from PathIterator import Iterator
-        _engine = Engine(Iterator)
-        installHandlers(_engine)
-    return _engine
-
-def installHandlers(engine):
-    reg = engine.registerType
-    pe = PathExpr
-    for pt in ('standard', 'path', 'exists', 'nocall'):
-        reg(pt, pe)
-    reg('string', StringExpr)
-    reg('python', PythonExpr)
-    reg('not', NotExpr)
-    reg('defer', DeferExpr)
-    reg('lazy', LazyExpr)
-
-import AccessControl
-import AccessControl.cAccessControl
-acquisition_security_filter = AccessControl.cAccessControl.aq_validate
-from AccessControl import getSecurityManager
-from AccessControl.ZopeGuards import guarded_getattr
-from AccessControl import Unauthorized
-from ZRPythonExpr import PythonExpr
-from ZRPythonExpr import _SecureModuleImporter
-from ZRPythonExpr import call_with_ns
-
-SecureModuleImporter = _SecureModuleImporter()
-
-Undefs = (Undefined, AttributeError, KeyError,
-          TypeError, IndexError, Unauthorized)
-
-def render(ob, ns):
-    """
-    Calls the object, possibly a document template, or just returns it if
-    not callable.  (From DT_Util.py)
-    """
-    if hasattr(ob, '__render_with_namespace__'):
-        ob = call_with_ns(ob.__render_with_namespace__, ns)
-    else:
-        base = aq_base(ob)
-        if callable(base):
-            try:
-                if getattr(base, 'isDocTemp', 0):
-                    ob = call_with_ns(ob, ns, 2)
-                else:
-                    ob = ob()
-            except AttributeError, n:
-                if str(n) != '__call__':
-                    raise
-    return ob
-
-class SubPathExpr:
-    def __init__(self, path):
-        self._path = path = path.strip().split('/')
-        self._base = base = path.pop(0)
-        if base and not _valid_name(base):
-            raise CompilerError, 'Invalid variable name "%s"' % base
-        # Parse path
-        self._dp = dp = []
-        for i in range(len(path)):
-            e = path[i]
-            if e[:1] == '?' and _valid_name(e[1:]):
-                dp.append((i, e[1:]))
-        dp.reverse()
-
-    def _eval(self, econtext,
-              list=list, isinstance=isinstance, StringType=type('')):
-        vars = econtext.vars
-        path = self._path
-        if self._dp:
-            path = list(path) # Copy!
-            for i, varname in self._dp:
-                val = vars[varname]
-                if isinstance(val, StringType):
-                    path[i] = val
-                else:
-                    # If the value isn't a string, assume it's a sequence
-                    # of path names.
-                    path[i:i+1] = list(val)
-        __traceback_info__ = base = self._base
-        if base == 'CONTEXTS' or not base:
-            ob = econtext.contexts
-        else:
-            ob = vars[base]
-        if isinstance(ob, DeferWrapper):
-            ob = ob()
-        if path:
-            ob = restrictedTraverse(ob, path, getSecurityManager())
-        return ob
-
-class PathExpr:
-    def __init__(self, name, expr, engine):
-        self._s = expr
-        self._name = name
-        self._hybrid = 0
-        paths = expr.split('|')
-        self._subexprs = []
-        add = self._subexprs.append
-        for i in range(len(paths)):
-            path = paths[i].lstrip()
-            if _parse_expr(path):
-                # This part is the start of another expression type,
-                # so glue it back together and compile it.
-                add(engine.compile(('|'.join(paths[i:]).lstrip())))
-                self._hybrid = 1
-                break
-            add(SubPathExpr(path)._eval)
-
-    def _exists(self, econtext):
-        for expr in self._subexprs:
-            try:
-                expr(econtext)
-            except Undefs:
-                pass
-            else:
-                return 1
-        return 0
-
-    def _eval(self, econtext,
-              isinstance=isinstance,
-              BasicTypes=(str, unicode, dict, list, tuple, bool),
-              render=render):
-        for expr in self._subexprs[:-1]:
-            # Try all but the last subexpression, skipping undefined ones.
-            try:
-                ob = expr(econtext)
-            except Undefs:
-                pass
-            else:
-                break
-        else:
-            # On the last subexpression allow exceptions through, and
-            # don't autocall if the expression was not a subpath.
-            ob = self._subexprs[-1](econtext)
-            if self._hybrid:
-                return ob
-
-        if self._name == 'nocall' or isinstance(ob, BasicTypes):
-            return ob
-        # Return the rendered object
-        return render(ob, econtext.vars)
-
-    def __call__(self, econtext):
-        if self._name == 'exists':
-            return self._exists(econtext)
-        return self._eval(econtext)
-
-    def __str__(self):
-        return '%s expression %s' % (self._name, `self._s`)
-
-    def __repr__(self):
-        return '%s:%s' % (self._name, `self._s`)
-
-
-_interp = re.compile(r'\$(%(n)s)|\${(%(n)s(?:/[^}]*)*)}' % {'n': NAME_RE})
-
-class StringExpr:
-    def __init__(self, name, expr, engine):
-        self._s = expr
-        if '%' in expr:
-            expr = expr.replace('%', '%%')
-        self._vars = vars = []
-        if '$' in expr:
-            parts = []
-            for exp in expr.split('$$'):
-                if parts: parts.append('$')
-                m = _interp.search(exp)
-                while m is not None:
-                    parts.append(exp[:m.start()])
-                    parts.append('%s')
-                    vars.append(PathExpr('path', m.group(1) or m.group(2),
-                                         engine))
-                    exp = exp[m.end():]
-                    m = _interp.search(exp)
-                if '$' in exp:
-                    raise CompilerError, (
-                        '$ must be doubled or followed by a simple path')
-                parts.append(exp)
-            expr = ''.join(parts)
-        self._expr = expr
-
-    def __call__(self, econtext):
-        vvals = []
-        for var in self._vars:
-            v = var(econtext)
-            # I hope this isn't in use anymore.
-            ## if isinstance(v, Exception):
-            ##     raise v
-            vvals.append(v)
-        return self._expr % tuple(vvals)
-
-    def __str__(self):
-        return 'string expression %s' % `self._s`
-
-    def __repr__(self):
-        return 'string:%s' % `self._s`
-
-class NotExpr:
-    def __init__(self, name, expr, compiler):
-        self._s = expr = expr.lstrip()
-        self._c = compiler.compile(expr)
-
-    def __call__(self, econtext):
-        # We use the (not x) and 1 or 0 formulation to avoid changing
-        # the representation of the result in Python 2.3, where the
-        # result of "not" becomes an instance of bool.
-        return (not econtext.evaluateBoolean(self._c)) and 1 or 0
-
-    def __repr__(self):
-        return 'not:%s' % `self._s`
-
-from zope.interface import Interface, implements
-from zope.component import queryMultiAdapter
-from zope.app.traversing.namespace import nsParse
-from zope.app.traversing.namespace import namespaceLookup
-from zope.app.traversing.interfaces import TraversalError
-from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.app.publication.browser import setDefaultSkin
-
-class FakeRequest(dict):
-    implements(IBrowserRequest)
-
-    def getURL(self):
-        return "http://codespeak.net/z3/five"
-
-def restrictedTraverse(object, path, securityManager,
-                       get=getattr, has=hasattr, N=None, M=[],
-                       TupleType=type(()) ):
-
-    REQUEST = FakeRequest()
-    REQUEST['path'] = path
-    REQUEST['TraversalRequestNameStack'] = path = path[:] # Copy!
-    setDefaultSkin(REQUEST)
-    path.reverse()
-    validate = securityManager.validate
-    __traceback_info__ = REQUEST
-    while path:
-        name = path.pop()
-
-        if isinstance(name, TupleType):
-            object = object(*name)
-            continue
-
-        if not name or name[0] == '_':
-            # Skip directly to item access
-            o = object[name]
-            # Check access to the item.
-            if not validate(object, object, None, o):
-                raise Unauthorized, name
-            object = o
-            continue
-
-        if name=='..':
-            o = get(object, 'aq_parent', M)
-            if o is not M:
-                if not validate(object, object, name, o):
-                    raise Unauthorized, name
-                object=o
-                continue
-
-        t=get(object, '__bobo_traverse__', N)
-        if name and name[:1] in '@+':
-            import pdb
-            pdb.set_trace()
-            # Process URI segment parameters.
-            ns, nm = nsParse(name)
-            if ns:
-                try:
-                    o = namespaceLookup(ns, nm, object, 
-                                           REQUEST).__of__(object)
-                    if not validate(object, object, name, o):
-                        raise Unauthorized, name
-                except TraversalError:
-                    raise AttributeError(name)
-        elif t is not N:
-            o=t(REQUEST, name)
-
-            container = None
-            if aq_base(o) is not o:
-                # The object is wrapped, so the acquisition
-                # context determines the container.
-                container = aq_parent(aq_inner(o))
-            elif has(o, 'im_self'):
-                container = o.im_self
-            elif (has(aq_base(object), name) and get(object, name) == o):
-                container = object
-            if not validate(object, container, name, o):
-                raise Unauthorized, name
-        else:
-            # Try an attribute.
-            o = guarded_getattr(object, str(name), M) # failed on u'aq_parent'
-            if o is M:
-                # Try an item.
-                try:
-                    # XXX maybe in Python 2.2 we can just check whether
-                    # the object has the attribute "__getitem__"
-                    # instead of blindly catching exceptions.
-                    try:
-                        o = object[name]
-                    except (AttributeError, KeyError):
-                        # Try to look for a view
-                        o = queryMultiAdapter((object, REQUEST), 
-                                                 Interface, name)
-                        if o is None:
-                            # Didn't find one, reraise the error:
-                            raise
-                        o = o.__of__(object)
-                except AttributeError, exc:
-                    if str(exc).find('__getitem__') >= 0:
-                        # The object does not support the item interface.
-                        # Try to re-raise the original attribute error.
-                        # XXX I think this only happens with
-                        # ExtensionClass instances.
-                        guarded_getattr(object, name)
-                    raise
-                except TypeError, exc:
-                    if str(exc).find('unsubscriptable') >= 0:
-                        # The object does not support the item interface.
-                        # Try to re-raise the original attribute error.
-                        # XXX This is sooooo ugly.
-                        guarded_getattr(object, name)
-                    raise
-                else:
-                    # Check access to the item.
-                    if not validate(object, object, None, o):
-                        raise Unauthorized, name
-        object = o
-
-    return object

Copied: Zope/branches/regebro-wsgi_support2/lib/python/Products/PageTemplates/Expressions.py (from rev 67731, Zope/trunk/lib/python/Products/PageTemplates/Expressions.py)

Deleted: Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/BaseRequest.py
===================================================================
--- Zope/trunk/lib/python/ZPublisher/BaseRequest.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/BaseRequest.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -1,588 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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
-#
-##############################################################################
-""" Basic ZPublisher request management.
-
-$Id$
-"""
-from urllib import quote
-import xmlrpc
-from zExceptions import Forbidden
-
-from zope.event import notify
-from zope.app.publication.interfaces import EndRequestEvent
-
-UNSPECIFIED_ROLES=''
-
-try:
-    from ExtensionClass import Base
-    class RequestContainer(Base):
-        __roles__=None
-        def __init__(self,**kw):
-            for k,v in kw.items(): self.__dict__[k]=v
-
-        def manage_property_types(self):
-            return type_converters.keys()
-
-except ImportError:
-    class RequestContainer:
-        __roles__=None
-        def __init__(self,**kw):
-            for k,v in kw.items(): self.__dict__[k]=v
-
-try:
-    from AccessControl.ZopeSecurityPolicy import getRoles
-except ImportError:
-    def getRoles(container, name, value, default):
-        return getattr(value, '__roles__', default)
-
-
-_marker=[]
-class BaseRequest:
-    """Provide basic ZPublisher request management
-
-    This object provides access to request data. Request data may
-    vary depending on the protocol used.
-
-    Request objects are created by the object publisher and will be
-    passed to published objects through the argument name, REQUEST.
-
-    The request object is a mapping object that represents a
-    collection of variable to value mappings.
-    """
-
-    maybe_webdav_client = 1
-
-    # While the following assignment is not strictly necessary, it
-    # prevents alot of unnecessary searches because, without it,
-    # acquisition of REQUEST is disallowed, which penalizes access
-    # in DTML with tags.
-    __roles__ = None
-    _file=None
-    common={} # Common request data
-    _auth=None
-    _held=()
-
-    # Allow (reluctantly) access to unprotected attributes
-    __allow_access_to_unprotected_subobjects__=1
-
-    def __init__(self, other=None, **kw):
-        """The constructor is not allowed to raise errors
-        """
-        if other is None: other=kw
-        else: other.update(kw)
-        self.other=other
-
-    def close(self):
-        self.other.clear()
-        self._held=None
-        notify(EndRequestEvent(None, self))
-
-    def processInputs(self):
-        """Do any input processing that could raise errors
-        """
-
-    def __len__(self):
-        return 1
-
-    def __setitem__(self,key,value):
-        """Set application variables
-
-        This method is used to set a variable in the requests "other"
-        category.
-        """
-        self.other[key]=value
-
-    set=__setitem__
-
-    def get(self, key, default=None):
-        """Get a variable value
-
-        Return a value for the required variable name.
-        The value will be looked up from one of the request data
-        categories. The search order is environment variables,
-        other variables, form data, and then cookies.
-
-        """
-        if key=='REQUEST': return self
-
-        v=self.other.get(key, _marker)
-        if v is not _marker: return v
-        v=self.common.get(key, default)
-        if v is not _marker: return v
-
-        if key=='BODY' and self._file is not None:
-            p=self._file.tell()
-            self._file.seek(0)
-            v=self._file.read()
-            self._file.seek(p)
-            self.other[key]=v
-            return v
-
-        if key=='BODYFILE' and self._file is not None:
-            v=self._file
-            self.other[key]=v
-            return v
-
-        return default
-
-    def __getitem__(self, key, default=_marker):
-        v = self.get(key, default)
-        if v is _marker:
-            raise KeyError, key
-        return v
-
-    def __getattr__(self, key, default=_marker):
-        v = self.get(key, default)
-        if v is _marker:
-            raise AttributeError, key
-        return v
-
-    def set_lazy(self, key, callable):
-        pass            # MAYBE, we could do more, but let HTTPRequest do it
-
-    def has_key(self,key):
-        return self.get(key, _marker) is not _marker
-
-    def __contains__(self, key):
-        return self.has_key(key)
-    
-    def keys(self):
-        keys = {}
-        keys.update(self.common)
-        keys.update(self.other)
-        return keys.keys()
-
-    def items(self):
-        result = []
-        get=self.get
-        for k in self.keys():
-            result.append((k, get(k)))
-        return result
-
-    def values(self):
-        result = []
-        get=self.get
-        for k in self.keys():
-            result.append(get(k))
-        return result
-
-    def __str__(self):
-        L1 = self.items()
-        L1.sort()
-        return '\n'.join(map(lambda item: "%s:\t%s" % item, L1))
-
-    __repr__=__str__
-
-
-    def traverse(self, path, response=None, validated_hook=None):
-        """Traverse the object space
-
-        The REQUEST must already have a PARENTS item with at least one
-        object in it.  This is typically the root object.
-        """
-        request=self
-        request_get=request.get
-        if response is None: response=self.response
-        debug_mode=response.debug_mode
-
-        # remember path for later use
-        browser_path = path
-
-        # Cleanup the path list
-        if path[:1]=='/':  path=path[1:]
-        if path[-1:]=='/': path=path[:-1]
-        clean=[]
-        for item in path.split('/'):
-            # Make sure that certain things that dont make sense
-            # cannot be traversed.
-            if item in ('REQUEST', 'aq_self', 'aq_base'):
-                return response.notFoundError(path)
-            if not item or item=='.':
-                continue
-            elif item == '..':
-                del clean[-1]
-            else: clean.append(item)
-        path=clean
-
-        # How did this request come in? (HTTP GET, PUT, POST, etc.)
-        method=req_method=request_get('REQUEST_METHOD', 'GET').upper()
-
-        if method=='GET' or method=='POST' and not isinstance(response,
-                                                              xmlrpc.Response):
-            # Probably a browser
-            no_acquire_flag=0
-            # index_html is still the default method, only any object can
-            # override it by implementing its own __browser_default__ method
-            method = 'index_html'
-        elif self.maybe_webdav_client:
-            # Probably a WebDAV client.
-            no_acquire_flag=1
-        else:
-            no_acquire_flag=0
-
-        URL=request['URL']
-        parents=request['PARENTS']
-        object=parents[-1]
-        del parents[:]
-
-        roles = getRoles(None, None, object, UNSPECIFIED_ROLES)
-
-        # if the top object has a __bobo_traverse__ method, then use it
-        # to possibly traverse to an alternate top-level object.
-        if hasattr(object,'__bobo_traverse__'):
-            try:
-                object=object.__bobo_traverse__(request)
-                roles = getRoles(None, None, object, UNSPECIFIED_ROLES)
-            except: pass
-
-        if not path and not method:
-            return response.forbiddenError(self['URL'])
-
-        # Traverse the URL to find the object:
-        if hasattr(object, '__of__'):
-            # Try to bind the top-level object to the request
-            # This is how you get 'self.REQUEST'
-            object=object.__of__(RequestContainer(REQUEST=request))
-        parents.append(object)
-
-        steps=self.steps
-        self._steps = _steps = map(quote, steps)
-        path.reverse()
-
-        request['TraversalRequestNameStack'] = request.path = path
-        request['ACTUAL_URL'] = request['URL'] + quote(browser_path)
-
-        # Set the posttraverse for duration of the traversal here
-        self._post_traverse = post_traverse = []
-
-        entry_name = ''
-        try:
-            # We build parents in the wrong order, so we
-            # need to make sure we reverse it when we're doe.
-            while 1:
-                bpth = getattr(object, '__before_publishing_traverse__', None)
-                if bpth is not None:
-                    bpth(object, self)
-
-                path = request.path = request['TraversalRequestNameStack']
-                # Check for method:
-                if path:
-                    entry_name = path.pop()
-                elif hasattr(object, '__browser_default__'):
-                    # If we have reached the end of the path. We look to see
-                    # if the object implements __browser_default__. If so, we
-                    # call it to let the object tell us how to publish it
-                    # __browser_default__ returns the object to be published
-                    # (usually self) and a sequence of names to traverse to
-                    # find the method to be published. (Casey)
-                    request._hacked_path=1
-                    object, default_path = object.__browser_default__(request)
-                    if len(default_path) > 1:
-                        path = list(default_path)
-                        method = path.pop()
-                        request['TraversalRequestNameStack'] = path
-                        continue
-                    else:
-                        entry_name = default_path[0]
-                elif (method and hasattr(object,method)
-                      and entry_name != method
-                      and getattr(object, method) is not None):
-                    request._hacked_path=1
-                    entry_name = method
-                    method = 'index_html'
-                else:
-                    if (hasattr(object, '__call__')):
-                        roles = getRoles(object, '__call__', object.__call__,
-                                         roles)
-                    if request._hacked_path:
-                        i=URL.rfind('/')
-                        if i > 0: response.setBase(URL[:i])
-                    break
-                step = quote(entry_name)
-                _steps.append(step)
-                request['URL'] = URL = '%s/%s' % (request['URL'], step)
-                got = 0
-                if entry_name[:1]=='_':
-                    if debug_mode:
-                        return response.debugError(
-                          "Object name begins with an underscore at: %s" % URL)
-                    else: return response.forbiddenError(entry_name)
-
-                if hasattr(object,'__bobo_traverse__'):
-                    try:
-                        subobject=object.__bobo_traverse__(request,entry_name)
-                        if type(subobject) is type(()) and len(subobject) > 1:
-                            # Add additional parents into the path
-                            parents[-1:] = list(subobject[:-1])
-                            object, subobject = subobject[-2:]
-                    except (AttributeError, KeyError):
-                        if debug_mode:
-                            return response.debugError(
-                                "Cannot locate object at: %s" % URL)
-                        else:
-                            return response.notFoundError(URL)
-                else:
-                    try:
-                        # Note - no_acquire_flag is necessary to support
-                        # things like DAV.  We have to make sure
-                        # that the target object is not acquired
-                        # if the request_method is other than GET
-                        # or POST. Otherwise, you could never use
-                        # PUT to add a new object named 'test' if
-                        # an object 'test' existed above it in the
-                        # heirarchy -- you'd always get the
-                        # existing object :(
-
-                        if (no_acquire_flag and len(path) == 0 and
-                            hasattr(object, 'aq_base')):
-                            if hasattr(object.aq_base, entry_name):
-                                subobject=getattr(object, entry_name)
-                            else: raise AttributeError, entry_name
-                        else: subobject=getattr(object, entry_name)
-                    except AttributeError:
-                        got=1
-                        try: subobject=object[entry_name]
-                        except (KeyError, IndexError,
-                                TypeError, AttributeError):
-                            if debug_mode:
-                                return response.debugError(
-                                    "Cannot locate object at: %s" % URL)
-                            else:
-                                return response.notFoundError(URL)
-
-                # Ensure that the object has a docstring, or that the parent
-                # object has a pseudo-docstring for the object. Objects that
-                # have an empty or missing docstring are not published.
-                doc = getattr(subobject, '__doc__', None)
-                if doc is None:
-                    doc = getattr(object, '%s__doc__' % entry_name, None)
-                if not doc:
-                    return response.debugError(
-                        "The object at %s has an empty or missing " \
-                        "docstring. Objects must have a docstring to be " \
-                        "published." % URL
-                        )
-
-                # Hack for security: in Python 2.2.2, most built-in types
-                # gained docstrings that they didn't have before. That caused
-                # certain mutable types (dicts, lists) to become publishable
-                # when they shouldn't be. The following check makes sure that
-                # the right thing happens in both 2.2.2+ and earlier versions.
-
-                if not typeCheck(subobject):
-                    return response.debugError(
-                        "The object at %s is not publishable." % URL
-                        )
-
-                roles = getRoles(
-                    object, (not got) and entry_name or None, subobject,
-                    roles)
-
-                # Promote subobject to object
-                object=subobject
-                parents.append(object)
-
-                steps.append(entry_name)
-        finally:
-            parents.reverse()
- 
-        # After traversal post traversal hooks aren't available anymore
-        del self._post_traverse
-
-        request['PUBLISHED'] = parents.pop(0)
-
-        # Do authorization checks
-        user=groups=None
-        i=0
-
-        if 1:  # Always perform authentication.
-
-            last_parent_index=len(parents)
-            if hasattr(object, '__allow_groups__'):
-                groups=object.__allow_groups__
-                inext=0
-            else:
-                inext=None
-                for i in range(last_parent_index):
-                    if hasattr(parents[i],'__allow_groups__'):
-                        groups=parents[i].__allow_groups__
-                        inext=i+1
-                        break
-
-            if inext is not None:
-                i=inext
-
-                if hasattr(groups, 'validate'): v=groups.validate
-                else: v=old_validation
-
-                auth=request._auth
-
-                if v is old_validation and roles is UNSPECIFIED_ROLES:
-                    # No roles, so if we have a named group, get roles from
-                    # group keys
-                    if hasattr(groups,'keys'): roles=groups.keys()
-                    else:
-                        try: groups=groups()
-                        except: pass
-                        try: roles=groups.keys()
-                        except: pass
-
-                    if groups is None:
-                        # Public group, hack structures to get it to validate
-                        roles=None
-                        auth=''
-
-                if v is old_validation:
-                    user=old_validation(groups, request, auth, roles)
-                elif roles is UNSPECIFIED_ROLES: user=v(request, auth)
-                else: user=v(request, auth, roles)
-
-                while user is None and i < last_parent_index:
-                    parent=parents[i]
-                    i=i+1
-                    if hasattr(parent, '__allow_groups__'):
-                        groups=parent.__allow_groups__
-                    else: continue
-                    if hasattr(groups,'validate'): v=groups.validate
-                    else: v=old_validation
-                    if v is old_validation:
-                        user=old_validation(groups, request, auth, roles)
-                    elif roles is UNSPECIFIED_ROLES: user=v(request, auth)
-                    else: user=v(request, auth, roles)
-
-            if user is None and roles != UNSPECIFIED_ROLES:
-                response.unauthorized()
-
-        if user is not None:
-            if validated_hook is not None: validated_hook(self, user)
-            request['AUTHENTICATED_USER']=user
-            request['AUTHENTICATION_PATH']='/'.join(steps[:-i])
-
-        # Remove http request method from the URL.
-        request['URL']=URL
-
-        # Run post traversal hooks
-        if post_traverse:
-            result = exec_callables(post_traverse)
-            if result is not None:
-                object = result
-
-        return object
-
-    def post_traverse(self, f, args=()):
-        """Add a callable object and argument tuple to be post-traversed.
-        
-        If traversal and authentication succeed, each post-traversal
-        pair is processed in the order in which they were added.
-        Each argument tuple is passed to its callable.  If a callable
-        returns a value other than None, no more pairs are processed,
-        and the return value replaces the traversal result.
-        """
-        try:
-            pairs = self._post_traverse
-        except AttributeError:
-            raise RuntimeError, ('post_traverse() may only be called '
-                                 'during publishing traversal.')
-        else:
-            pairs.append((f, tuple(args)))
-
-    retry_count=0
-    def supports_retry(self): return 0
-
-    def _hold(self, object):
-        """Hold a reference to an object to delay it's destruction until mine
-        """
-        self._held=self._held+(object,)
-
-def exec_callables(callables):
-    result = None
-    for (f, args) in callables:
-        # Don't catch exceptions here. And don't hide them anyway.
-        result = f(*args)
-        if result is not None:
-            return result
-
-def old_validation(groups, request, auth,
-                   roles=UNSPECIFIED_ROLES):
-
-    if auth:
-        auth=request._authUserPW()
-        if auth: name,password = auth
-        elif roles is None: return ''
-        else: return None
-    elif request.environ.has_key('REMOTE_USER'):
-        name=request.environ['REMOTE_USER']
-        password=None
-    else:
-        if roles is None: return ''
-        return None
-
-    if roles is None: return name
-
-    keys=None
-    try:
-        keys=groups.keys
-    except:
-        try:
-            groups=groups() # Maybe it was a method defining a group
-            keys=groups.keys
-        except: pass
-
-    if keys is not None:
-        # OK, we have a named group, so apply the roles to the named
-        # group.
-        if roles is UNSPECIFIED_ROLES: roles=keys()
-        g=[]
-        for role in roles:
-            if groups.has_key(role): g.append(groups[role])
-        groups=g
-
-    for d in groups:
-        if d.has_key(name) and (d[name]==password or password is None):
-            return name
-
-    if keys is None:
-        # Not a named group, so don't go further
-        raise Forbidden, (
-            """<strong>You are not authorized to access this resource""")
-
-    return None
-
-
-
-# This mapping contains the built-in types that gained docstrings
-# between Python 2.1 and 2.2.2. By specifically checking for these
-# types during publishing, we ensure the same publishing rules in
-# both versions. The downside is that this needs to be extended as
-# new built-in types are added and future Python versions are
-# supported. That happens rarely enough that hopefully we'll be on
-# Zope 3 by then :)
-
-import types
-
-itypes = {}
-for name in ('NoneType', 'IntType', 'LongType', 'FloatType', 'StringType',
-             'BufferType', 'TupleType', 'ListType', 'DictType', 'XRangeType',
-             'SliceType', 'EllipsisType', 'UnicodeType', 'CodeType',
-             'TracebackType', 'FrameType', 'DictProxyType', 'BooleanType',
-             'ComplexType'):
-    if hasattr(types, name):
-        itypes[getattr(types, name)] = 0
-
-# Python 2.4 no longer maintains the types module.
-itypes[set] = 0
-itypes[frozenset] = 0
-
-def typeCheck(obj, deny=itypes):
-    # Return true if its ok to publish the type, false otherwise.
-    return deny.get(type(obj), 1)

Copied: Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/BaseRequest.py (from rev 67730, Zope/trunk/lib/python/ZPublisher/BaseRequest.py)

Modified: Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/Publish.py
===================================================================
--- Zope/trunk/lib/python/ZPublisher/Publish.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZPublisher/Publish.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -122,7 +122,6 @@
 
         return response
     except:
-
         # DM: provide nicer error message for FTP
         sm = None
         if response is not None:

Modified: Zope/branches/regebro-wsgi_support2/lib/python/ZServer/HTTPResponse.py
===================================================================
--- Zope/trunk/lib/python/ZServer/HTTPResponse.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZServer/HTTPResponse.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -311,6 +311,15 @@
             self._close=1
         self._request.reply_code=response.status
 
+    def start_response(self, status, headers, exc_info=None):
+        # Used for WSGI
+        status = 'HTTP/%s %s\r\n' % (self._request.version, status)
+        self.write(status)
+        headers = '\r\n'.join([': '.join(x) for x in headers])
+        self.write(headers)
+        self.write('\r\n\r\n')
+        return self.write
+        
 
 is_proxying_match = re.compile(r'[^ ]* [^ \\]*:').match
 proxying_connection_re = re.compile ('Proxy-Connection: (.*)', re.IGNORECASE)

Modified: Zope/branches/regebro-wsgi_support2/lib/python/ZServer/HTTPServer.py
===================================================================
--- Zope/trunk/lib/python/ZServer/HTTPServer.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZServer/HTTPServer.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -279,8 +279,50 @@
             </ul>""" %(self.module_name, self.hits)
             )
 
+from HTTPResponse import ChannelPipe
 
+class zwsgi_handler(zhttp_handler):
+    
+    def continue_request(self, sin, request):
+        "continue handling request now that we have the stdin"
 
+        s=get_header(CONTENT_LENGTH, request.header)
+        if s:
+            s=int(s)
+        else:
+            s=0
+        DebugLogger.log('I', id(request), s)
+
+        env=self.get_environment(request)
+        version = request.version
+        if version=='1.0' and is_proxying_match(request.request):
+            # a request that was made as if this zope was an http 1.0 proxy.
+            # that means we have to use some slightly different http
+            # headers to manage persistent connections.
+            connection_re = proxying_connection_re
+        else:
+            # a normal http request
+            connection_re = CONNECTION
+        
+        env['http_connection'] = get_header(connection_re,
+                                            request.header).lower()
+        env['server_version']=request.channel.server.SERVER_IDENT
+
+        env['wsgi.output'] = ChannelPipe(request)
+        env['wsgi.input'] = sin
+        env['wsgi.errors']       = sys.stderr
+        env['wsgi.version']      = (1,0)
+        env['wsgi.multithread']  = True
+        env['wsgi.multiprocess'] = True
+        env['wsgi.run_once']     = True
+        env['wsgi.url_scheme']   = env['SERVER_PROTOCOL'].split('/')[0]
+
+        request.channel.current_request=None
+        request.channel.queue.append(('Zope2WSGI', env, 
+                                      env['wsgi.output'].start_response))
+        request.channel.work()
+
+
 class zhttp_channel(http_channel):
     "http channel"
 

Modified: Zope/branches/regebro-wsgi_support2/lib/python/ZServer/PubCore/ZServerPublisher.py
===================================================================
--- Zope/trunk/lib/python/ZServer/PubCore/ZServerPublisher.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZServer/PubCore/ZServerPublisher.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -14,13 +14,24 @@
 class ZServerPublisher:
     def __init__(self, accept):
         from ZPublisher import publish_module
+        from ZPublisher.WSGIPublisher import publish_module as publish_wsgi
         while 1:
-            try:
-                name, request, response=accept()
-                publish_module(
-                    name,
-                    request=request,
-                    response=response)
-            finally:
-                response._finish()
-                request=response=None
+            name, a, b=accept()
+            if name == "Zope2":
+                try:
+                    publish_module(
+                        name,
+                        request=a,
+                        response=b)
+                finally:
+                    b._finish()
+                    a=b=None
+
+            elif name == "Zope2WSGI":
+                try:
+                    res = publish_wsgi(a, b)
+                    for r in res:
+                        a['wsgi.output'].write(r)
+                finally:
+                    a['wsgi.output']._close = 1
+                    a['wsgi.output'].close()

Modified: Zope/branches/regebro-wsgi_support2/lib/python/ZServer/component.xml
===================================================================
--- Zope/trunk/lib/python/ZServer/component.xml	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZServer/component.xml	2006-04-30 08:25:20 UTC (rev 67758)
@@ -19,6 +19,7 @@
          receive WebDAV source responses to GET requests.
        </description>
      </key>
+     <key name="use-wsgi" datatype="boolean" default="off" />
   </sectiontype>
 
   <sectiontype name="webdav-source-server"
@@ -26,6 +27,7 @@
                implements="ZServer.server">
      <key name="address" datatype="inet-binding-address"/>
      <key name="force-connection-close" datatype="boolean" default="off"/>
+     <key name="use-wsgi" datatype="boolean" default="off" />
   </sectiontype>
 
   <sectiontype name="persistent-cgi"

Modified: Zope/branches/regebro-wsgi_support2/lib/python/ZServer/datatypes.py
===================================================================
--- Zope/trunk/lib/python/ZServer/datatypes.py	2006-04-28 15:11:16 UTC (rev 67723)
+++ Zope/branches/regebro-wsgi_support2/lib/python/ZServer/datatypes.py	2006-04-30 08:25:20 UTC (rev 67758)
@@ -71,6 +71,7 @@
         # webdav-source-server sections won't have webdav_source_clients:
         webdav_clients = getattr(section, "webdav_source_clients", None)
         self.webdav_source_clients = webdav_clients
+        self.use_wsgi = section.use_wsgi
 
     def create(self):
         from ZServer.AccessLogger import access_logger
@@ -86,7 +87,10 @@
 
     def createHandler(self):
         from ZServer import HTTPServer
-        return HTTPServer.zhttp_handler(self.module, '', self.cgienv)
+        if self.use_wsgi:
+            return HTTPServer.zwsgi_handler(self.module, '', self.cgienv)
+        else:
+            return HTTPServer.zhttp_handler(self.module, '', self.cgienv)
 
 
 class WebDAVSourceServerFactory(HTTPServerFactory):



More information about the Checkins mailing list