[Zope-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 " and '
-
- - 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 Zope-Checkins
mailing list