[Zope-Checkins] SVN: Zope/branches/whitmo-2.10-layers/ Merged r70147:71822 from 2.10 branch.

Stefan H. Holek stefan at epy.co.at
Mon Jan 8 13:47:09 EST 2007


Log message for revision 71823:
  Merged r70147:71822 from 2.10 branch.
  

Changed:
  U   Zope/branches/whitmo-2.10-layers/configure
  U   Zope/branches/whitmo-2.10-layers/doc/CHANGES.txt
  U   Zope/branches/whitmo-2.10-layers/doc/INSTALL.txt
  U   Zope/branches/whitmo-2.10-layers/inst/Makefile.in
  U   Zope/branches/whitmo-2.10-layers/inst/Makefile.win.in
  U   Zope/branches/whitmo-2.10-layers/inst/WinBuilders/mk/zope.mk
  U   Zope/branches/whitmo-2.10-layers/inst/versions.py
  _U  Zope/branches/whitmo-2.10-layers/lib/python/
  U   Zope/branches/whitmo-2.10-layers/lib/python/OFS/Application.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/OFS/Traversable.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/Expressions.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/PageTemplateFile.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/ZopePageTemplate.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/__init__.py
  A   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/configure.zcml
  A   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/interfaces.py
  A   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/input/BooleanAttributesAndDefault.html
  A   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/output/BooleanAttributesAndDefault.html
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/output/CheckI18nTranslateHooked.html
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testDTMLTests.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testExpressions.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testHTMLTests.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/test_ptfile.py
  A   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/unicodeconflictresolver.py
  A   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/utils.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/default.html
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/ptEdit.zpt
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/ZCatalog.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/tests/testCatalog.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Shared/DC/ZRDB/DA.py
  A   Zope/branches/whitmo-2.10-layers/lib/python/Shared/DC/ZRDB/tests/test_caching.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/Testing/ZopeTestCase/utils.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/BaseRequest.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/HTTPResponse.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/Publish.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testHTTPResponse.py
  U   Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testPublish.py
  _U  Zope/branches/whitmo-2.10-layers/lib/python/zope/
  _U  Zope/branches/whitmo-2.10-layers/lib/python/zope/app/
  U   Zope/branches/whitmo-2.10-layers/skel/bin/runzope.in
  U   Zope/branches/whitmo-2.10-layers/skel/bin/zopectl.in
  U   Zope/branches/whitmo-2.10-layers/skel/etc/site.zcml
  U   Zope/branches/whitmo-2.10-layers/test.py

-=-
Modified: Zope/branches/whitmo-2.10-layers/configure
===================================================================
--- Zope/branches/whitmo-2.10-layers/configure	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/configure	2007-01-08 18:47:06 UTC (rev 71823)
@@ -12,13 +12,13 @@
 
 # Place the optimal target version number for Zope (as returned by sys.version)
 # below
-TARGET="2.4.3"
+TARGET="2.4.4"
 
 # Order a list of "acceptable" python version numbers (as returned by
 # sys.version) below in "best" to "worst" order, not including the
 # target version.  Up to six acceptable python versions are allowed.
 # Do not include the target version number in this list!
-ACCEPTABLE="2.4.1 2.4.2"
+ACCEPTABLE="2.4.3 2.4.2"
 
 # provide the executable names for all the acceptable versions
 # (and the target version) below

Modified: Zope/branches/whitmo-2.10-layers/doc/CHANGES.txt
===================================================================
--- Zope/branches/whitmo-2.10-layers/doc/CHANGES.txt	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/doc/CHANGES.txt	2007-01-08 18:47:06 UTC (rev 71823)
@@ -3,17 +3,122 @@
   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.
+
+  Zope 2.10.2 (unreleased)
+
+    Bugs fixed
+
+      - Fixed Collector #2190: Calls to
+        zope.security.management.checkPermission aren't rerouted to
+        Zope 2's security policy.
+
+        NOTE: If you already have a Zope 2.10 instance running, you
+        will either have to recreate it or add the following lines to
+        the end of the etc/site.zcml file::
+
+          <securityPolicy
+                component="Products.Five.security.FiveSecurityPolicy" />
+
+      - Fixed Collector #2223: Evaluation of booleans in TALES and the
+        'default' variable.
+
+      - Reverted backward-incompatible fix for Collector #2191.
+
+      - Fixed the creation of lib/python/Zope2/version.txt
+
+      - added Python 2.4.4 as optimal Python version to 'configure'
+
+      - the ZopePageTemplate implementation now uses unicode
+        internally.  Non-unicode instances are migrated on-the-fly to
+        unicode. However this will work only properly for ZPT
+        instances formerly encoded as utf-8 or ISO-8859-15. For other
+        encodings you might set the environment variable
+        ZPT_REFERRED_ENCODING to insert your preferred encoding in
+        front of utf-8 and ISO-8859-15 within the encoding sniffer
+        code. In addition there is a new 'output_encodings' property
+        that controls the conversion from/to unicode for WebDAV/FTP
+        operations.
+
+      - the ZPT implementation has now a configurable option in order
+        how to deal with UnicodeDecodeErrors. A custom
+        UnicodeEncodingConflictResolver can be configured through ZCML
+        (see Products/PageTemplates/(configure.zcml,
+        unicodeconflictresolver.py, interfaces.py)
+
+      - the ZPT implementation has now a configurable option in order
+        how to deal with UnicodeDecodeErrors. A custom
+        UnicodeEncodingConflictResolver can be configured through ZCML
+        (see Products/PageTemplates/(configure.zcml,
+        unicodeconflictresolver.py, interfaces.py)
+
+  Zope 2.10.1 (2006-11-22)
+
+    Bugs fixed
+
+      - Collector #2191: extended DateTime parser for better support
+        to the ISO8601 specification.
+
+      - Reworking of _cached_result in Shared.DC.ZRDB.DA.DA:
+
+        - fixed KeyError reported in Collector #2212
+
+        - fixed two memory leaks that occurred under high load
+
+        - fixed broken cache keys for people using the obscure 
+          Shared.DC.ZRDB.DA.DA.connection_hook
+
+        - fixed incorrect cache ordering resulting in newer results
+          being dumped when the cache became too large.
+
+      - Collector #2232: Can't call DTML templates from Page Templates
+
+      - Collector #2213: Can't edit "old" ZopePageTemplate instances.
+
+      - Collector #2237: 'make' doesn't tell you to run 'make inplace'
+        before running 'make instance'.
+
+      - Collector #2235: A number of ZCatalog methods were doing boolean
+        evaluation of objects that implemented __len__ instead of checking
+        them against None. Replaced a number of "if not obj" with
+        "if obj is None".
+
+      - Collector #2208: rewriting/setting the 'charset' part of the
+        content-type HTTP header will be done only for 'text/*'
+
+      - Collector #2209: ZTUtils module could not be used inside ZPT
+
+      - Collector #2206: Set PYTHONPATH to include existing PYTHONPATH
+        in skel/bin/zopectl.in and skel/bin/runzope.in
+
+
+  Zope 2.10.0 (2006/10/04)
+
+    Bugs fixed
+
   
-  after Zope 2.10.0 beta 2 (unreleased)
+  Zope 2.10.0 RC 1 (2006/09/25)
 
     Bugs fixed
 
+      - Call setDefaultSkin on new requests created as the result of
+        ConflictError retries.
+
+      - Collector #2187: PUT_factory broken
+      
+  Zope 2.10.0 beta 2 (2006/09/17)
+
+    Bugs fixed
+
+      - Collector #2117: Don't choke in 'unrestrictedTraverse' for '+'
+        path elements.
+
       - Collector #2185: Log username for FCGI requests.
 
       - Collector #2152: Fixed MailHost documentation; simple_send does not
         process or validate its arguments in any way.
 
-      - Collector #2175: ZTUtils.make_hidden_input did not escape double-quotes.
+      - Collector #2175: ZTUtils.make_hidden_input did not escape
+        double-quotes.
 
       - Collector #2176: Fixed bad logging call.
 

Modified: Zope/branches/whitmo-2.10-layers/doc/INSTALL.txt
===================================================================
--- Zope/branches/whitmo-2.10-layers/doc/INSTALL.txt	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/doc/INSTALL.txt	2007-01-08 18:47:06 UTC (rev 71823)
@@ -12,6 +12,7 @@
    * bash or another Bourne shell variant
 
    * Python 2.4.2 or later installed somewhere in the system PATH
+     (Python 2.5 is not supported)
 
    * GNU make
 

Modified: Zope/branches/whitmo-2.10-layers/inst/Makefile.in
===================================================================
--- Zope/branches/whitmo-2.10-layers/inst/Makefile.in	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/inst/Makefile.in	2007-01-08 18:47:06 UTC (rev 71823)
@@ -38,9 +38,9 @@
 # default:     The default step (invoked when make is called without a target)
 default: build
 	@echo
-	@echo Zope built.  Next, do \'make install\' \(or \'make instance\'
-	@echo to run a Zope instance directly from the build directory\).
-	@echo
+	@echo Zope built.  Next, do \'make install\' \(or \'make inplace\',
+	@echo followed by \'make instance\' to run a Zope instance directly
+	@echo from the build directory\).
 
 # build:       Do whatever 'setup.py build' implies
 build:
@@ -81,7 +81,7 @@
 
 # instance:    Do an inplace build and create an instance home in the resulting
 #              software home.
-instance: build
+instance: build version_txt
 	${PYTHON} "${BASE_DIR}/utilities/mkzopeinstance.py" ${MKZ_FLAGS}
 
 # testinst:    Perform an inplace build and create an instance home in the
@@ -110,13 +110,15 @@
 # version_txt: create a version file in lib/python/version.txt
 version_txt:
 	printf "Zope ${MAJOR_VERSION}.${MINOR_VERSION}-${RELEASE_TAG}" >\
-          "${BASE_DIR}/lib/python/version.txt"
+          "${BASE_DIR}/lib/python/Zope2/version.txt"
 
 sdist: clobber sdist_tgz
 
 # sdist_tgz:   Create a tgz archive file as a source distribution.
 #
 sdist_tgz: version_txt
+	${FIND} . -type f -exec chmod a+r {} \; 
+	${FIND} . -type d -exec chmod a+rx {} \; 
 	${MKDIR} ${TMPDIR}
 	${CD} ${TMPDIR} && ${LN} ${BASE_DIR} ${PACKAGE_NAME} && \
           ${TAR} czfh ${BASE_DIR}/${PACKAGE_NAME}.tgz \

Modified: Zope/branches/whitmo-2.10-layers/inst/Makefile.win.in
===================================================================
--- Zope/branches/whitmo-2.10-layers/inst/Makefile.win.in	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/inst/Makefile.win.in	2007-01-08 18:47:06 UTC (rev 71823)
@@ -82,7 +82,7 @@
 
 # instance:    Do an inplace build and create an instance home in the resulting
 #              software home.
-instance: build
+instance: build version_txt
 	$(PYTHON) "$(BASE_DIR)\utilities\mkzopeinstance.py" $(MKZ_FLAGS)
 
 # testinst:    Perform an inplace build and create an instance home in the
@@ -108,10 +108,10 @@
 	-$(EXISTS) "$(BASE_DIR)\lib\python\version.txt" $(RM) "$(BASE_DIR)\lib\python\version.txt"
 	-$(EXISTS) build $(RMRF) build
 
-# version_txt: create a version file in lib/python/version.txt
+# version_txt: create a version file in lib/python/Zope2/version.txt
 version_txt:
 	echo Zope $(MAJOR_VERSION).$(MINOR_VERSION)-$(RELEASE_TAG) > \
-          "$(BASE_DIR)/lib/python/version.txt"
+          "$(BASE_DIR)/lib/python/Zope2/version.txt"
 
 # sdist:       Create a source distribution file (implies clobber).
 #

Modified: Zope/branches/whitmo-2.10-layers/inst/WinBuilders/mk/zope.mk
===================================================================
--- Zope/branches/whitmo-2.10-layers/inst/WinBuilders/mk/zope.mk	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/inst/WinBuilders/mk/zope.mk	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,4 +1,4 @@
-ZOPEVERSION = 2.10.0-b2
+ZOPEVERSION = 2.10.1-final
 ZOPEDIRNAME := Zope-$(ZOPEVERSION)
 
 ZOPE_REQUIRED_FILES=tmp/$(ZOPEDIRNAME).tgz

Modified: Zope/branches/whitmo-2.10-layers/inst/versions.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/inst/versions.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/inst/versions.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,7 +1,7 @@
 ZOPE_MAJOR_VERSION  = '2.10'
-ZOPE_MINOR_VERSION  = '0'
+ZOPE_MINOR_VERSION  = '1'
 ZOPE_BRANCH_NAME    = '$Name$'[6:] or 'no-branch'
 
 # always start prerelease branches with '0' to avoid upgrade
 # issues in RPMs
-VERSION_RELEASE_TAG = 'b2'
+VERSION_RELEASE_TAG = 'final'


Property changes on: Zope/branches/whitmo-2.10-layers/lib/python
___________________________________________________________________
Name: svn:externals
   - BTrees         svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/BTrees
ThreadedAsync  svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/ThreadedAsync
ZConfig        svn://svn.zope.org/repos/main/ZConfig/tags/ZConfig-2.3.1
ZEO            svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/ZEO
ZODB           svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/ZODB
ZopeUndo       svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/ZopeUndo
docutils       svn://svn.zope.org/repos/main/docutils/tags/0.4.0-zope
mechanize      svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/mechanize
persistent     svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/persistent
pytz           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/pytz
transaction    svn://svn.zope.org/repos/main/ZODB/tags/3.7.0b2/src/transaction
zdaemon        -r 40792 svn://svn.zope.org/repos/main/zdaemon/trunk/src/zdaemon
zodbcode       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zodbcode

   + BTrees         svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/BTrees
ThreadedAsync  svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/ThreadedAsync
ZConfig        svn://svn.zope.org/repos/main/ZConfig/tags/ZConfig-2.3.1
ZEO            svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/ZEO
ZODB           svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/ZODB
ZopeUndo       svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/ZopeUndo
docutils       svn://svn.zope.org/repos/main/docutils/tags/0.4.0-zope
mechanize      svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/mechanize
persistent     svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/persistent
pytz           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/pytz
transaction    svn://svn.zope.org/repos/main/ZODB/tags/3.7-Zope-3.3.0rc1/src/transaction
zdaemon        -r 40792 svn://svn.zope.org/repos/main/zdaemon/trunk/src/zdaemon
zodbcode       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zodbcode


Modified: Zope/branches/whitmo-2.10-layers/lib/python/OFS/Application.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/OFS/Application.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/OFS/Application.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -569,8 +569,8 @@
                 transaction.commit()
         except:
             bad_things=1
-            LOG.error('The attempt to rebuild the registry failed.',
-                error=sys.exc_info())
+            LOG.error('The attempt to rebuild the registry failed.',exc_info=True)
+               
             transaction.abort()
 
         # Now we need to see if any (disk-based) products were installed

Modified: Zope/branches/whitmo-2.10-layers/lib/python/OFS/Traversable.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/OFS/Traversable.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/OFS/Traversable.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -186,7 +186,7 @@
 
                 bobo_traverse = getattr(obj, '__bobo_traverse__', None)
                 try:
-                    if name and name[:1] in '@+':
+                    if name and name[:1] in '@+' and name != '+':
                         # Process URI segment parameters.
                         ns, nm = nsParse(name)
                         if ns:

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/Expressions.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/Expressions.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/Expressions.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -17,6 +17,11 @@
 
 $Id$
 """
+
+import logging
+
+from zope.component import getUtility
+from zope.component.interfaces import ComponentLookupError
 from zope.interface import implements
 from zope.tales.tales import Context, Iterator
 from zope.tales.expressions import PathExpr, StringExpr, NotExpr
@@ -31,13 +36,17 @@
 from MultiMapping import MultiMapping
 from Acquisition import aq_base
 from zExceptions import NotFound, Unauthorized
+
 from Products.Five.browser.providerexpression import Z2ProviderExpression
 from Products.PageTemplates import ZRPythonExpr
 from Products.PageTemplates.DeferExpr import LazyExpr
 from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService
+from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
 
 SecureModuleImporter = ZRPythonExpr._SecureModuleImporter()
 
+LOG = logging.getLogger('Expressions')
+
 # BBB 2005/05/01 -- remove after 12 months
 import zope.deprecation
 from zope.deprecation import deprecate
@@ -89,7 +98,7 @@
         if callable(base):
             try:
                 if getattr(base, 'isDocTemp', 0):
-                    ob = call_with_ns(ob, ns, 2)
+                    ob = ZRPythonExpr.call_with_ns(ob, ns, 2)
                 else:
                     ob = ob()
             except AttributeError, n:
@@ -173,6 +182,60 @@
             domain, msgid, mapping=mapping,
             context=context, default=default)
 
+    def evaluateBoolean(self, expr):
+        value = self.evaluate(expr)
+        # here we override the normal Zope 3 behaviour.  Zope 3
+        # doesn't care about the default in a boolean expression,
+        # while we do (Zope 2 legacy, see the
+        # BooleanAttributesAndDefault.html test case)
+        if value is self.getDefault():
+            return value
+        return bool(value)
+
+    def evaluateText(self, expr):
+        """ customized version in order to get rid of unicode
+            errors for all and ever
+        """
+        text = self.evaluate(expr)
+
+        if text is self.getDefault() or text is None:
+            # XXX: should be unicode???
+            return text
+
+        if isinstance(text, unicode):
+            # we love unicode, nothing to do
+            return text
+
+        elif isinstance(text, str):
+            # bahh...non-unicode string..we need to convert it to unicode
+
+            # catch ComponentLookupError in order to make tests shut-up.
+            # This should not be a problem since it won't change the old
+            # default behavior
+
+            try:
+                resolver = getUtility(IUnicodeEncodingConflictResolver)
+            except ComponentLookupError:    
+                return unicode(text)
+
+            try:
+                return resolver.resolve(self.contexts['context'], text, expr)
+            except UnicodeDecodeError,e:
+                LOG.error("""UnicodeDecodeError detected for expression "%s"\n"""
+                          """Resolver class: %s\n"""
+                          """Exception text: %s\n"""
+                          """Template: %s\n"""
+                          """Rendered text: %r"""  % \
+                          (expr, resolver.__class__, e, 
+                            self.contexts['template'].absolute_url(1), text))
+                raise 
+        else:
+
+            # This is a weird culprit ...calling unicode() on non-string
+            # objects
+            return unicode(text)
+
+
 class ZopeEngine(zope.app.pagetemplate.engine.ZopeEngine):
 
     _create_context = ZopeContext

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/PageTemplateFile.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/PageTemplateFile.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/PageTemplateFile.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -32,6 +32,14 @@
 LOG = getLogger('PageTemplateFile')
 
 def guess_type(filename, text):
+
+    # check for XML ourself since guess_content_type can't
+    # detect text/xml  if 'filename' won't end with .xml
+    # XXX: fix this in zope.contenttype
+
+    if text.startswith('<?xml'):
+        return 'text/xml'
+
     content_type, dummy = guess_content_type(filename, text)
     if content_type in ('text/html', 'text/xml'):
         return content_type

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/ZopePageTemplate.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/ZopePageTemplate.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/ZopePageTemplate.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -40,20 +40,15 @@
 from Products.PageTemplates.PageTemplateFile import guess_type
 from Products.PageTemplates.Expressions import SecureModuleImporter
 
-# regular expression to extract the encoding from the XML preamble
-encoding_reg = re.compile('<\?xml.*?encoding="(.*?)".*?\?>', re.M)
+from Products.PageTemplates.utils import encodingFromXMLPreamble, \
+         charsetFromMetaEquiv, convertToUnicode
+            
 
 preferred_encodings = ['utf-8', 'iso-8859-15']
 if os.environ.has_key('ZPT_PREFERRED_ENCODING'):
     preferred_encodings.insert(0, os.environ['ZPT_PREFERRED_ENCODING'])
+  
 
-def sniffEncoding(text, default_encoding='utf-8'):
-    """Try to determine the encoding from html or xml"""
-    if text.startswith('<?xml'):
-        mo = encoding_reg.search(text)
-        if mo:
-            return mo.group(1)
-    return default_encoding
 
 class Src(Acquisition.Explicit):
     """ I am scary code """
@@ -76,6 +71,7 @@
     __implements__ = (WriteLockInterface,)
 
     meta_type = 'Page Template'
+    output_encoding = 'iso-8859-15'  # provide default for old instances
 
     func_defaults = None
     func_code = FuncCode((), 0)
@@ -96,6 +92,7 @@
 
     _properties=({'id':'title', 'type': 'ustring', 'mode': 'w'},
                  {'id':'content_type', 'type':'string', 'mode': 'w'},
+                 {'id':'output_encoding', 'type':'string', 'mode': 'w'},
                  {'id':'expand', 'type':'boolean', 'mode': 'w'},
                  )
 
@@ -107,22 +104,65 @@
     security.declareProtected(view_management_screens,
                               'read', 'ZScriptHTML_tryForm')
 
-    def __init__(self, id, text=None, content_type=None, encoding='utf-8',
-                 strict=False):
+    def __init__(self, id, text=None, content_type='text/html', strict=True, 
+                 output_encoding='utf-8'):
         self.id = id
         self.expand = 0                                                               
-        self.strict = strict
         self.ZBindings_edit(self._default_bindings)
+        self.output_encoding = output_encoding
+        # default content
         if not text:
             text = open(self._default_content_fn).read()
-            encoding = 'utf-8'
             content_type = 'text/html'
-        self.pt_edit(text, content_type, encoding)
+        self.pt_edit(text, content_type)
 
+
     security.declareProtected(change_page_templates, 'pt_edit')
-    def pt_edit(self, text, content_type, encoding='utf-8'):
+    def pt_edit(self, text, content_type, keep_output_encoding=False):
+
         text = text.strip()
-        if self.strict and not isinstance(text, unicode):
+        
+        is_unicode = isinstance(text, unicode)
+        encoding = None
+        output_encoding = None
+
+        if content_type == 'text/xml':
+
+            if is_unicode:
+                encoding = None
+                output_encoding = 'utf-8'
+            else:
+                encoding = encodingFromXMLPreamble(text)
+                output_encoding = 'utf-8'
+            
+
+        elif content_type == 'text/html':
+
+            charset = charsetFromMetaEquiv(text)
+
+            if is_unicode:
+                if charset:
+                    encoding = None
+                    output_encoding = charset
+                else:
+                    encoding = None
+                    output_encoding = 'iso-8859-15'
+            else:
+                if charset:
+                    encoding = charset
+                    output_encoding = charset
+                else:
+                    encoding = 'iso-8859-15'
+                    output_encoding = 'iso-8859-15'
+
+        else:
+            raise ValueError('Unsupported content-type %s' % content_type)
+
+        # for content updated through WebDAV, FTP 
+        if not keep_output_encoding:
+            self.output_encoding = output_encoding
+
+        if not is_unicode:
             text = unicode(text, encoding)
 
         self.ZCacheable_invalidate()
@@ -136,16 +176,21 @@
     source_dot_xml = Src()
 
     security.declareProtected(change_page_templates, 'pt_editAction')
-    def pt_editAction(self, REQUEST, title, text, content_type, encoding, expand):
+    def pt_editAction(self, REQUEST, title, text, content_type, expand):
         """Change the title and document."""
 
         if self.wl_isLocked():
             raise ResourceLockedError("File is locked via WebDAV")
 
         self.expand = expand
-        self.pt_setTitle(title, encoding)
 
-        self.pt_edit(text, content_type, encoding)
+        # The ZMI edit view uses utf-8! So we can safely assume
+        # that 'title' and 'text' are utf-8 encoded strings - hopefully
+
+        self.pt_setTitle(title, 'utf-8') 
+        text = unicode(text, 'utf-8')
+
+        self.pt_edit(text, content_type, True)
         REQUEST.set('text', self.read()) # May not equal 'text'!
         REQUEST.set('title', self.title)
         message = "Saved changes."
@@ -154,9 +199,10 @@
                        % '<br>'.join(self._v_warnings))
         return self.pt_editForm(manage_tabs_message=message)
 
+
     security.declareProtected(change_page_templates, 'pt_setTitle')
     def pt_setTitle(self, title, encoding='utf-8'):
-        if self.strict and not isinstance(title, unicode):
+        if not isinstance(title, unicode):
             title = unicode(title, encoding)
         self._setPropValue('title', title)
 
@@ -185,8 +231,7 @@
         if not content_type in ('text/html', 'text/xml'):
             raise ValueError('Unsupported mimetype: %s' % content_type)
 
-        encoding = sniffEncoding(text, encoding)
-        self.pt_edit(text, content_type, encoding)
+        self.pt_edit(text, content_type)
         return self.pt_editForm(manage_tabs_message='Saved changes')
 
     security.declareProtected(change_page_templates, 'pt_changePrefs')
@@ -239,6 +284,13 @@
         return c
 
     def write(self, text):
+
+        if not isinstance(text, unicode):
+            text, encoding = convertToUnicode(text, 
+                                              self.content_type,
+                                              preferred_encodings)
+            self.output_encoding = encoding
+
         self.ZCacheable_invalidate()
         ZopePageTemplate.inheritedAttribute('write')(self, text)
 
@@ -288,10 +340,12 @@
     security.declareProtected(change_page_templates, 'PUT')
     def PUT(self, REQUEST, RESPONSE):
         """ Handle HTTP PUT requests """
+
         self.dav__init(REQUEST, RESPONSE)
         self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1)
-        ## XXX this should be unicode or we must pass an encoding
-        self.pt_edit(REQUEST.get('BODY', ''))
+        text = REQUEST.get('BODY', '')
+        content_type = guess_type('', text) 
+        self.pt_edit(text, content_type)
         RESPONSE.setStatus(204)
         return RESPONSE
 
@@ -302,8 +356,8 @@
     security.declareProtected(ftp_access, 'manage_FTPget')
     def manage_FTPget(self):
         "Get source for FTP download"
-        self.REQUEST.RESPONSE.setHeader('Content-Type', self.content_type)
-        return self.read()
+        result = self.pt_render()
+        return result.encode(self.output_encoding)
 
     security.declareProtected(view_management_screens, 'html')
     def html(self):
@@ -352,35 +406,29 @@
             # acquisition context, so we don't know where it is. :-(
             return None
 
+
+    def __setstate__(self, state):
+        # Perform on-the-fly migration to unicode.
+        # Perhaps it might be work with the 'generation' module here?
+        if not isinstance(state['_text'], unicode):
+            text, encoding = convertToUnicode(state['_text'], 
+                                    state.get('content_type', 'text/html'), 
+                                    preferred_encodings)
+            state['_text'] = text
+            state['output_encoding'] = encoding
+        self.__dict__.update(state) 
+
+
+    def pt_render(self, source=False, extra_context={}):
+        result = PageTemplate.pt_render(self, source, extra_context)
+        assert isinstance(result, unicode)
+        return result
+
+
     def wl_isLocked(self):
         return 0
 
-    def manage_convertUnicode(self, preferred_encodings=preferred_encodings,
-                              RESPONSE=None):
-        """Convert non-unicode templates to unicode"""
-        if not isinstance(self._text, unicode):
-            for encoding in preferred_encodings:
-                try:
-                    self._text = unicode(self._text, encoding)
-                    if RESPONSE:
-                        return RESPONSE.redirect(self.absolute_url() +
-                                                 '/pt_editForm?manage_tabs_message='
-                                                 'ZPT+successfully+converted')
-                    else:
-                        return
-                except UnicodeDecodeError:
-                    pass
 
-            raise RuntimeError('Pagetemplate could not be converted to unicode')
-
-        else:
-            if RESPONSE:
-                return RESPONSE.redirect(self.absolute_url() +
-                                         '/pt_editForm?manage_tabs_message='
-                                         'ZPT+already+converted')
-            else:
-                return
-
 InitializeClass(ZopePageTemplate)
 
 setattr(ZopePageTemplate, 'source.xml',  ZopePageTemplate.source_dot_xml)
@@ -406,8 +454,8 @@
             content_type = headers['content_type']
         else:
             content_type = guess_type(filename, text) 
-        encoding = sniffEncoding(text, encoding)
 
+
     else:
         if hasattr(text, 'read'):
             filename = getattr(text, 'filename', '')
@@ -417,9 +465,14 @@
                 content_type = headers['content_type']
             else:
                 content_type = guess_type(filename, text) 
-        encoding = sniffEncoding(text, encoding)
 
-    zpt = ZopePageTemplate(id, text, content_type, encoding)
+    # ensure that we pass unicode to the constructor to
+    # avoid further hassles with pt_edit()
+
+    if not isinstance(text, unicode):
+        text = unicode(text, encoding)
+
+    zpt = ZopePageTemplate(id, text, content_type, output_encoding=encoding)
     zpt.pt_setTitle(title, encoding)
     self._setObject(id, zpt)
     zpt = getattr(self, id)

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/__init__.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/__init__.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/__init__.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -21,6 +21,11 @@
 # Placeholder for Zope Product data
 misc_ = {}
 
+# import ZTUtils in order to make i importable through
+# ZopeGuards.load_module() where an importable modules must be
+# available in sys.modules
+import ZTUtils
+
 def initialize(context):
     # Import lazily, and defer initialization to the module
     import ZopePageTemplate

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/configure.zcml (from rev 71822, Zope/branches/2.10/lib/python/Products/PageTemplates/configure.zcml)

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/interfaces.py (from rev 71822, Zope/branches/2.10/lib/python/Products/PageTemplates/interfaces.py)

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/input/BooleanAttributesAndDefault.html (from rev 71822, Zope/branches/2.10/lib/python/Products/PageTemplates/tests/input/BooleanAttributesAndDefault.html)

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/output/BooleanAttributesAndDefault.html (from rev 71822, Zope/branches/2.10/lib/python/Products/PageTemplates/tests/output/BooleanAttributesAndDefault.html)

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/output/CheckI18nTranslateHooked.html
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/output/CheckI18nTranslateHooked.html	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/output/CheckI18nTranslateHooked.html	2007-01-08 18:47:06 UTC (rev 71823)
@@ -3,7 +3,7 @@
 <head>
    <p>[foo](bar/{})</p>
    <a href="foo" alt="[default](alttext/{})">link</a>
-   <p>[dom](${name} was born in ${country}./{'country':'Antarctica','name':'Lomax'})</p>
+   <p>[dom](${name} was born in ${country}./{'country':u'Antarctica','name':u'Lomax'})</p>
    <p>[default](hmm/{'age':u'25'})</p>
 </head>
 </body>

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testDTMLTests.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testDTMLTests.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testDTMLTests.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -14,9 +14,12 @@
 import unittest
 
 import zope.component.testing
+from zope.component import provideUtility
 from zope.traversing.adapters import DefaultTraversable
 from Products.PageTemplates.tests import util
 from Products.PageTemplates.PageTemplate import PageTemplate
+from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
+from Products.PageTemplates.unicodeconflictresolver import DefaultUnicodeEncodingConflictResolver
 from Acquisition import Implicit
 from AccessControl import SecurityManager
 from AccessControl.SecurityManagement import noSecurityManager
@@ -50,6 +53,7 @@
     def setUp(self):
         super(DTMLTests, self).setUp()
         zope.component.provideAdapter(DefaultTraversable, (None,))
+        provideUtility(DefaultUnicodeEncodingConflictResolver, IUnicodeEncodingConflictResolver)
 
         self.t = AqPageTemplate()
         self.policy = UnitTestSecurityPolicy()

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testExpressions.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testExpressions.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testExpressions.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,17 +1,33 @@
+# -*- coding: iso-8859-15 -*-
+
 import unittest
 
+import zope.component
 import zope.component.testing
 from zope.traversing.adapters import DefaultTraversable
 
 from Products.PageTemplates import Expressions
 from Products.PageTemplates.DeferExpr import LazyWrapper
 from Products.PageTemplates.DeferExpr import DeferWrapper
+from Products.PageTemplates.unicodeconflictresolver import \
+     DefaultUnicodeEncodingConflictResolver, \
+     StrictUnicodeEncodingConflictResolver, \
+     ReplacingUnicodeEncodingConflictResolver, \
+     IgnoringUnicodeEncodingConflictResolver
+from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
 
+
 class Dummy:
     __allow_access_to_unprotected_subobjects__ = 1
     def __call__(self):
         return 'dummy'
 
+class DummyDocumentTemplate:
+    __allow_access_to_unprotected_subobjects__ = 1
+    isDocTemp = True
+    def __call__(self, client=None, REQUEST={}, RESPONSE=None, **kw):
+        return 'dummy'
+
 class ExpressionTests(zope.component.testing.PlacelessSetup, unittest.TestCase):
 
     def setUp(self):
@@ -23,7 +39,8 @@
             one = 1,
             d = {'one': 1, 'b': 'b', '': 'blank', '_': 'under'},
             blank = '',
-            dummy = Dummy()
+            dummy = Dummy(),
+            dummy2 = DummyDocumentTemplate()
             )
 
     def testCompile(self):
@@ -47,8 +64,13 @@
 
     def testRenderedEval(self):
         ec = self.ec
-        assert ec.evaluate('dummy') == 'dummy'
+        self.assertEquals(ec.evaluate('dummy'), 'dummy')
 
+        # http://www.zope.org/Collectors/Zope/2232
+        # DTML templates could not be called from a Page Template
+        # due to an ImportError
+        self.assertEquals(ec.evaluate('dummy2'), 'dummy')
+
     def testEval1(self):
         '''Test advanced expression evaluation 1'''
         ec = self.ec
@@ -95,8 +117,38 @@
         self.assertEquals(ec.evaluate(''), None)
         self.assertEquals(ec.evaluate('  \n'), None)
 
+
+class UnicodeEncodingConflictResolverTests(zope.component.testing.PlacelessSetup, unittest.TestCase):
+
+    def testDefaultResolver(self):
+        zope.component.provideUtility(DefaultUnicodeEncodingConflictResolver, 
+                                      IUnicodeEncodingConflictResolver)
+        resolver = zope.component.getUtility(IUnicodeEncodingConflictResolver)
+        self.assertRaises(UnicodeDecodeError, resolver.resolve, None, 'äüö', None)
+        
+    def testStrictResolver(self):
+        zope.component.provideUtility(StrictUnicodeEncodingConflictResolver, 
+                                      IUnicodeEncodingConflictResolver)
+        resolver = zope.component.getUtility(IUnicodeEncodingConflictResolver)
+        self.assertRaises(UnicodeDecodeError, resolver.resolve, None, 'äüö', None)
+        
+    def testIgnoringResolver(self):
+        zope.component.provideUtility(IgnoringUnicodeEncodingConflictResolver, 
+                                      IUnicodeEncodingConflictResolver)
+        resolver = zope.component.getUtility(IUnicodeEncodingConflictResolver)
+        self.assertEqual(resolver.resolve(None, 'äüö', None), '')
+
+    def testReplacingResolver(self):
+        zope.component.provideUtility(ReplacingUnicodeEncodingConflictResolver, 
+                                      IUnicodeEncodingConflictResolver)
+        resolver = zope.component.getUtility(IUnicodeEncodingConflictResolver)
+        self.assertEqual(resolver.resolve(None, 'äüö', None), u'\ufffd\ufffd\ufffd')
+
 def test_suite():
-    return unittest.makeSuite(ExpressionTests)
+    return unittest.TestSuite((
+         unittest.makeSuite(ExpressionTests),
+         unittest.makeSuite(UnicodeEncodingConflictResolverTests)
+    ))
 
 if __name__=='__main__':
     main()

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testHTMLTests.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testHTMLTests.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testHTMLTests.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -14,11 +14,14 @@
 import unittest
 
 import zope.component.testing
+from zope.component import provideUtility
 from zope.traversing.adapters import DefaultTraversable
 from Products.PageTemplates.tests import util
 from Products.PageTemplates.PageTemplate import PageTemplate
 from Products.PageTemplates.GlobalTranslationService import \
      setGlobalTranslationService
+from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
+from Products.PageTemplates.unicodeconflictresolver import DefaultUnicodeEncodingConflictResolver
 from AccessControl import SecurityManager
 from AccessControl.SecurityManagement import noSecurityManager
 
@@ -67,6 +70,8 @@
         super(HTMLTests, self).setUp()
         zope.component.provideAdapter(DefaultTraversable, (None,))
 
+        provideUtility(DefaultUnicodeEncodingConflictResolver, IUnicodeEncodingConflictResolver)
+
         self.folder = f = Folder()
         f.laf = AqPageTemplate()
         f.t = AqPageTemplate()
@@ -168,6 +173,12 @@
     def checkRepeatVariable(self):
         self.assert_expected(self.folder.t, 'RepeatVariable.html')
 
+    def checkBooleanAttributesAndDefault(self):
+        # Zope 2.9 and below support the semantics that an HTML
+        # "boolean" attribute (e.g. 'selected', 'disabled', etc.) can
+        # be used together with 'default'.
+        self.assert_expected(self.folder.t, 'BooleanAttributesAndDefault.html')
+
 def test_suite():
     return unittest.makeSuite(HTMLTests, 'check')
 

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,3 +1,5 @@
+# -*- encoding: iso-8859-15 -*-
+
 """ZopePageTemplate regression tests.
 
 Ensures that adding a page template works correctly.
@@ -6,14 +8,157 @@
 
 """
 
-
 import unittest
 import Zope2
 import transaction
 import zope.component.testing
 from zope.traversing.adapters import DefaultTraversable
 from Testing.makerequest import makerequest
+from Testing.ZopeTestCase import ZopeTestCase, installProduct
+from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate, manage_addPageTemplate
+from Products.PageTemplates.utils import encodingFromXMLPreamble, charsetFromMetaEquiv
 
+
+ascii_str = '<html><body>hello world</body></html>'
+iso885915_str = '<html><body>üöäÜÖÄß</body></html>'
+utf8_str = unicode(iso885915_str, 'iso-8859-15').encode('utf-8')
+
+xml_template = '''<?xml vesion="1.0" encoding="%s"?>
+<foo>
+üöäÜÖÄß
+</foo>
+'''
+
+xml_iso_8859_15 = xml_template % 'iso-8859-15'
+xml_utf8 = unicode(xml_template, 'iso-8859-15').encode('utf-8') % 'utf-8'
+
+html_template_w_header = '''
+<html>
+    <head>
+        <META http-equiv="content-type" content="text/html; charset=%s">
+    </hed>
+    <body>
+    test üöäÜÖÄß
+    </body>
+</html>
+'''
+
+html_iso_8859_15_w_header = html_template_w_header % 'iso-8859-15'
+html_utf8_w_header = unicode(html_template_w_header, 'iso-8859-15').encode('utf-8') % 'utf-8'
+
+html_template_wo_header = '''
+<html>
+    <body>
+    test üöäÜÖÄß
+    </body>
+</html>
+'''
+
+html_iso_8859_15_wo_header = html_template_wo_header 
+html_utf8_wo_header = unicode(html_template_wo_header, 'iso-8859-15').encode('utf-8') 
+
+
+installProduct('PageTemplates')
+
+class ZPTUtilsTests(unittest.TestCase):
+
+    def testExtractEncodingFromXMLPreamble(self):
+        extract = encodingFromXMLPreamble
+        self.assertEqual(extract('<?xml version="1.0" ?>'), 'utf-8')
+        self.assertEqual(extract('<?xml encoding="utf-8" version="1.0" ?>'), 'utf-8')
+        self.assertEqual(extract('<?xml encoding="UTF-8" version="1.0" ?>'), 'utf-8')
+        self.assertEqual(extract('<?xml encoding="ISO-8859-15" version="1.0" ?>'), 'iso-8859-15')
+        self.assertEqual(extract('<?xml encoding="iso-8859-15" version="1.0" ?>'), 'iso-8859-15')
+
+    def testExtractCharsetFromMetaHTTPEquivTag(self):
+        extract = charsetFromMetaEquiv
+        self.assertEqual(extract('<html><META http-equiv="content-type" content="text/html; charset=UTF-8"></html>'), 'utf-8')
+        self.assertEqual(extract('<html><META http-equiv="content-type" content="text/html; charset=iso-8859-15"></html>'), 'iso-8859-15')
+        self.assertEqual(extract('<html><META http-equiv="content-type" content="text/html"></html>'), None)
+        self.assertEqual(extract('<html>...<html>'), None)
+        
+
+class ZopePageTemplateFileTests(ZopeTestCase):
+
+    def testPT_RenderWithAscii(self):
+        manage_addPageTemplate(self.app, 'test', text=ascii_str, encoding='ascii')
+        zpt = self.app['test']
+        result = zpt.pt_render()
+        # use startswith() because the renderer appends a trailing \n
+        self.assertEqual(result.encode('ascii').startswith(ascii_str), True)
+        self.assertEqual(zpt.output_encoding, 'iso-8859-15')
+
+    def testPT_RenderWithISO885915(self):
+        manage_addPageTemplate(self.app, 'test', text=iso885915_str, encoding='iso-8859-15')
+        zpt = self.app['test']
+        result = zpt.pt_render()
+        # use startswith() because the renderer appends a trailing \n
+        self.assertEqual(result.encode('iso-8859-15').startswith(iso885915_str), True)
+        self.assertEqual(zpt.output_encoding, 'iso-8859-15')
+
+    def testPT_RenderWithUTF8(self):
+        manage_addPageTemplate(self.app, 'test', text=utf8_str, encoding='utf-8')
+        zpt = self.app['test']
+        result = zpt.pt_render()
+        # use startswith() because the renderer appends a trailing \n
+        self.assertEqual(result.encode('utf-8').startswith(utf8_str), True)
+        self.assertEqual(zpt.output_encoding, 'iso-8859-15')
+
+    def testWriteAcceptsUnicode(self):
+        manage_addPageTemplate(self.app, 'test', '', encoding='utf-8')
+        zpt = self.app['test']
+        s = u'this is unicode'
+        zpt.write(s)
+        self.assertEqual(zpt.read(), s)
+        self.assertEqual(isinstance(zpt.read(), unicode), True)
+
+    def _createZPT(self):
+        manage_addPageTemplate(self.app, 'test', text=utf8_str, encoding='utf-8')
+        zpt = self.app['test']
+        return zpt
+
+    def _makePUTRequest(self, body):
+        return {'BODY' : body}
+
+    def _put(self, text):
+        zpt = self._createZPT()
+        REQUEST = self.app.REQUEST
+        REQUEST.set('BODY', text)
+        zpt.PUT(REQUEST, REQUEST.RESPONSE)
+        return zpt
+
+    def testPutHTMLIso8859_15WithCharsetInfo(self):
+        zpt = self._put(html_iso_8859_15_w_header)
+        self.assertEqual(zpt.output_encoding, 'iso-8859-15')
+        self.assertEqual(zpt.content_type, 'text/html')
+
+    def testPutHTMLUTF8_WithCharsetInfo(self):
+        zpt = self._put(html_utf8_w_header)
+        self.assertEqual(zpt.output_encoding, 'utf-8')
+        self.assertEqual(zpt.content_type, 'text/html')
+
+    def testPutHTMLIso8859_15WithoutCharsetInfo(self):
+        zpt = self._put(html_iso_8859_15_wo_header)
+        self.assertEqual(zpt.output_encoding, 'iso-8859-15')
+        self.assertEqual(zpt.content_type, 'text/html')
+
+    def testPutHTMLUTF8_WithoutCharsetInfo(self):
+        zpt = self._put(html_utf8_wo_header)
+        self.assertEqual(zpt.output_encoding, 'iso-8859-15')
+        self.assertEqual(zpt.content_type, 'text/html')
+
+    def testPutXMLIso8859_15(self):
+        """ XML: use always UTF-8 als output encoding """
+        zpt = self._put(xml_iso_8859_15)
+        self.assertEqual(zpt.output_encoding, 'utf-8')
+        self.assertEqual(zpt.content_type, 'text/xml')
+
+    def testPutXMLUTF8(self):
+        """ XML: use always UTF-8 als output encoding """
+        zpt = self._put(xml_utf8)
+        self.assertEqual(zpt.output_encoding, 'utf-8')
+        self.assertEqual(zpt.content_type, 'text/xml')
+
 class ZPTRegressions(unittest.TestCase):
 
     def setUp(self):
@@ -40,7 +185,7 @@
         self.assertEqual(pt.document_src().strip(), default_text.strip())
 
     def testAddWithRequest(self):
-        """Test manage_add with file"""
+        # Test manage_add with file
         request = self.app.REQUEST
         request.form['file'] = DummyFileUpload(filename='some file',
                                                data=self.text,
@@ -51,13 +196,14 @@
         self.assertEqual(pt.document_src(), self.text)
 
     def testAddWithRequestButNoFile(self):
-        """Collector #596: manage_add with text but no file"""
+        # Collector #596: manage_add with text but no file
         request = self.app.REQUEST
         self._addPT('pt1', text=self.text, REQUEST=request)
         # no object is returned when REQUEST is passed.
         pt = self.app.pt1
         self.assertEqual(pt.document_src(), self.text)
 
+
 class ZPTMacros(zope.component.testing.PlacelessSetup, unittest.TestCase):
 
     def setUp(self):
@@ -124,7 +270,9 @@
        
 def test_suite():
     suite = unittest.makeSuite(ZPTRegressions)
+    suite.addTests(unittest.makeSuite(ZPTUtilsTests))
     suite.addTests(unittest.makeSuite(ZPTMacros))
+    suite.addTests(unittest.makeSuite(ZopePageTemplateFileTests))
     return suite
 
 if __name__ == '__main__':

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/test_ptfile.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/test_ptfile.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/tests/test_ptfile.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -15,6 +15,12 @@
 
     TEMPFILENAME = tempfile.mktemp(".zpt")
 
+    def setUp(self):
+        from zope.component import provideUtility
+        from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver
+        from Products.PageTemplates.unicodeconflictresolver import DefaultUnicodeEncodingConflictResolver
+        provideUtility(DefaultUnicodeEncodingConflictResolver, IUnicodeEncodingConflictResolver)
+
     def tearDown(self):
         if os.path.exists(self.TEMPFILENAME):
             os.unlink(self.TEMPFILENAME)

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/unicodeconflictresolver.py (from rev 71822, Zope/branches/2.10/lib/python/Products/PageTemplates/unicodeconflictresolver.py)

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/utils.py (from rev 71822, Zope/branches/2.10/lib/python/Products/PageTemplates/utils.py)

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/default.html
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/default.html	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/default.html	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,6 +1,7 @@
 <html>
   <head>
     <title tal:content="template/title">The title</title>
+    <meta http-equiv="content-type" content="text/html;charset=utf-8">
   </head>
   <body>
     

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/ptEdit.zpt
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/ptEdit.zpt	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/PageTemplates/www/ptEdit.zpt	2007-01-08 18:47:06 UTC (rev 71823)
@@ -33,7 +33,7 @@
        tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
       </div>
     </td>
-    <td align="left" valign="top" colspan="2">
+    <td align="left" valign="top" colspan="2" rowspan="2">
       <a href="source.html" tal:condition="context/html">Browse HTML source</a>
       <a href="source.xml" tal:condition="not:context/html">Browse XML source</a>
       <br />
@@ -45,7 +45,6 @@
   </tr>
 
   <tr tal:define="errors context/pt_errors" tal:condition="errors">
-    <tal:block define="global body python:context.document_src({'raw':1})" />
     <td align="left" valign="middle" class="form-label">Errors</td>
     <td align="left" valign="middle" style="background-color: #FFDDDD"
         colspan="3">

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/ZCatalog.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/ZCatalog.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/ZCatalog.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -221,7 +221,7 @@
 
             for url in urls:
                 obj = self.resolve_path(url)
-                if not obj and hasattr(self, 'REQUEST'):
+                if obj is None and hasattr(self, 'REQUEST'):
                     obj = self.resolve_url(url, REQUEST)
                 if obj is not None:
                     self.catalog_object(obj, url)
@@ -289,7 +289,7 @@
 
             p = paths[i]
             obj = self.resolve_path(p)
-            if not obj:
+            if obj is None:
                 obj = self.resolve_url(p, self.REQUEST)
             if obj is not None:
                 try:
@@ -587,12 +587,7 @@
     def getobject(self, rid, REQUEST=None):
         """Return a cataloged object given a 'data_record_id_'
         """
-        obj = self.aq_parent.unrestrictedTraverse(self.getpath(rid))
-        if not obj:
-            if REQUEST is None:
-                REQUEST=self.REQUEST
-            obj = self.resolve_url(self.getpath(rid), REQUEST)
-        return obj
+        return self.aq_parent.unrestrictedTraverse(self.getpath(rid))
 
     def getMetadataForUID(self, uid):
         """return the correct metadata given the uid, usually the path"""

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/tests/testCatalog.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/tests/testCatalog.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Products/ZCatalog/tests/testCatalog.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -28,6 +28,7 @@
 from AccessControl.SecurityManagement import setSecurityManager
 from AccessControl.SecurityManagement import noSecurityManager
 from AccessControl import Unauthorized
+from Acquisition import Implicit
 from Products.ZCatalog import Vocabulary
 from Products.ZCatalog.Catalog import Catalog
 from Products.ZCatalog.Catalog import CatalogError
@@ -159,7 +160,40 @@
     def __nonzero__(self):
         return False
 
+# make objects with failing __len__ and __nonzero__
+class dummyLenFail(zdummy):
+    def __init__(self, num, fail):
+        zdummy.__init__(self, num)
+        self.fail = fail
 
+    def __len__(self):
+        self.fail("__len__() was called")
+
+class dummyNonzeroFail(zdummy):
+    def __init__(self, num, fail):
+        zdummy.__init__(self, num)
+        self.fail = fail
+
+    def __nonzero__(self):
+        self.fail("__nonzero__() was called")
+
+class FakeTraversalError(KeyError):
+    """fake traversal exception for testing"""
+
+class fakeparent(Implicit):
+    # fake parent mapping unrestrictedTraverse to
+    # catalog.resolve_path as simulated by TestZCatalog
+    def __init__(self, d):
+        self.d = d
+
+    marker = object()
+
+    def unrestrictedTraverse(self, path, default=marker):
+        result = self.d.get(path, default)
+        if result is self.marker:
+            raise FakeTraversalError(path)
+        return result
+
 class TestZCatalog(unittest.TestCase):
 
     def setUp(self):
@@ -246,7 +280,47 @@
         result = self._catalog(title='9999')
         self.assertEquals(1, len(result))
 
+    def testBooleanEvalOn_manage_catalogObject(self):
+        self.d['11'] = dummyLenFail(11, self.fail)
+        self.d['12'] = dummyNonzeroFail(12, self.fail)
+        # create a fake response that doesn't bomb on manage_catalogObject()
+        class myresponse:
+            def redirect(self, url):
+                pass
+        # this next call should not fail
+        self._catalog.manage_catalogObject(None, myresponse(), 'URL1', urls=('11', '12'))
 
+    def testBooleanEvalOn_refreshCatalog_getobject(self):
+        # wrap catalog under the fake parent providing unrestrictedTraverse()
+        catalog = self._catalog.__of__(fakeparent(self.d))
+        # replace entries to test refreshCatalog
+        self.d['0'] = dummyLenFail(0, self.fail)
+        self.d['1'] = dummyNonzeroFail(1, self.fail)
+        # this next call should not fail
+        catalog.refreshCatalog()
+
+        for uid in ('0', '1'):
+            rid = catalog.getrid(uid)
+            # neither should these
+            catalog.getobject(rid)
+
+    def test_getobject_doesntMaskTraversalErrorsAndDoesntDelegateTo_resolve_url(self):
+        # wrap catalog under the fake parent providing unrestrictedTraverse()
+        catalog = self._catalog.__of__(fakeparent(self.d))
+        # make resolve_url fail if ZCatalog falls back on it
+        def resolve_url(path, REQUEST):
+            self.fail(".resolve_url() should not be called by .getobject()")
+        catalog.resolve_url = resolve_url
+
+        # traversal should work at first
+        rid0 = catalog.getrid('0')
+        # lets set it up so the traversal fails
+        del self.d['0']
+        self.assertRaises(FakeTraversalError, catalog.getobject, rid0, REQUEST=object())
+        # and if there is a None at the traversal point, that's where it should return
+        self.d['0'] = None
+        self.assertEquals(catalog.getobject(rid0), None)
+
 class dummy(ExtensionClass.Base):
     att1 = 'att1'
     att2 = 'att2'

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Shared/DC/ZRDB/DA.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Shared/DC/ZRDB/DA.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Shared/DC/ZRDB/DA.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -44,8 +44,7 @@
 from webdav.Resource import Resource
 from webdav.Lockable import ResourceLockedError
 from zExceptions import BadRequest
-try: from IOBTree import Bucket
-except: Bucket=lambda:{}
+from BTrees.OOBTree import OOBucket as Bucket
 
 
 class DatabaseError(BadRequest):
@@ -357,40 +356,80 @@
 
     def _searchable_result_columns(self): return self._col
 
-    def _cached_result(self, DB__, query):
-        pure_query = query
-        # we need to munge the incoming query key in the cache
-        # so that the same request to a different db is returned
-        query = query + ('\nDBConnId: %s' % self.connection_hook, )
-        
-        # Try to fetch from cache
-        if hasattr(self,'_v_cache'): cache=self._v_cache
-        else: cache=self._v_cache={}, Bucket()
-        cache, tcache = cache
+    def _cached_result(self, DB__, query, max_rows, conn_id):
+        # Try to fetch a result from the cache.
+        # Compute and cache the result otherwise.
+        # Also maintains the cache and ensures stale entries
+        # are never returned and that the cache never gets too large.
+
+        # NB: Correct cache behavior is predicated on Bucket.keys()
+        #     returning a sequence ordered from smalled number
+        #     (ie: the oldest cache entry) to largest number
+        #     (ie: the newest cache entry). Please be careful if you
+        #     change the class instantied below!
+
+        # get hold of a cache
+        caches = getattr(self,'_v_cache',None)
+        if caches is None:
+            caches = self._v_cache = {}, Bucket()
+        cache, tcache = caches
+
+        # the key for caching
+        cache_key = query,max_rows,conn_id
+        # the maximum number of result sets to cache
         max_cache=self.max_cache_
+        # the current time
         now=time()
+        # the oldest time which is not stale
         t=now-self.cache_time_
-        if len(cache) > max_cache / 2:
+        
+        # if the cache is too big, we purge entries from it
+        if len(cache) >= max_cache:
             keys=tcache.keys()
-            keys.reverse()
-            while keys and (len(keys) > max_cache or keys[-1] < t):
-                key=keys[-1]
+            # We also hoover out any stale entries, as we're
+            # already doing cache minimisation.
+            # 'keys' is ordered, so we purge the oldest results
+            # until the cache is small enough and there are no
+            # stale entries in it
+            while keys and (len(keys) >= max_cache or keys[0] < t):
+                key=keys[0]
                 q=tcache[key]
                 del tcache[key]
-                if int(cache[q][0]) == key:
-                    del cache[q]
-                del keys[-1]
+                del cache[q]
+                del keys[0]
 
-        if cache.has_key(query):
-            k, r = cache[query]
-            if k > t: return r
+        # okay, now see if we have a cached result
+        if cache.has_key(cache_key):
+            k, r = cache[cache_key]
+            # the result may still be stale, as we only hoover out
+            # stale results above if the cache gets too large.
+            if k > t:
+                # yay! a cached result returned!
+                return r
+            else:
+                # delete stale cache entries
+                del cache[cache_key]
+                del tcache[k]
 
         # call the pure query
-        result=apply(DB__.query, pure_query)
-        if self.cache_time_ > 0:
-            tcache[int(now)]=query
-            cache[query]= now, result
+        result=DB__.query(query,max_rows)
 
+        # When a ZSQL method is handled by one ZPublisher thread twice in
+        # less time than it takes for time.time() to return a different
+        # value, the SQL generated is different, then this code will leak
+        # an entry in 'cache' for each time the ZSQL method generates
+        # different SQL until time.time() returns a different value.
+        #
+        # On Linux, you would need an extremely fast machine under extremely
+        # high load, making this extremely unlikely. On Windows, this is a
+        # little more likely, but still unlikely to be a problem.
+        #
+        # If it does become a problem, the values of the tcache mapping
+        # need to be turned into sets of cache keys rather than a single
+        # cache key.
+        tcache[now]=cache_key
+        cache[cache_key]= now, result
+
         return result
 
     security.declareProtected(use_database_methods, '__call__')
@@ -456,8 +495,9 @@
         if src__: return query
 
         if self.cache_time_ > 0 and self.max_cache_ > 0:
-            result=self._cached_result(DB__, (query, self.max_rows_))
-        else: result=DB__.query(query, self.max_rows_)
+            result=self._cached_result(DB__, query, self.max_rows_, c)
+        else:
+            result=DB__.query(query, self.max_rows_)
 
         if hasattr(self, '_v_brain'): brain=self._v_brain
         else:

Copied: Zope/branches/whitmo-2.10-layers/lib/python/Shared/DC/ZRDB/tests/test_caching.py (from rev 71822, Zope/branches/2.10/lib/python/Shared/DC/ZRDB/tests/test_caching.py)

Modified: Zope/branches/whitmo-2.10-layers/lib/python/Testing/ZopeTestCase/utils.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/Testing/ZopeTestCase/utils.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/Testing/ZopeTestCase/utils.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,4 +1,4 @@
-#############################################################################
+##############################################################################
 #
 # Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
 #

Modified: Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/BaseRequest.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/BaseRequest.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/BaseRequest.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -72,37 +72,41 @@
         if name[:1]=='_':
             raise Forbidden("Object name begins with an underscore at: %s" % URL)
 
-        try:
-            if hasattr(object,'__bobo_traverse__'):
+        
+        if hasattr(object,'__bobo_traverse__'):
+            try:
                 subobject=object.__bobo_traverse__(request, name)
                 if type(subobject) is type(()) and len(subobject) > 1:
                     # Add additional parents into the path
-                    # XXX This needs handling. Check the publish refactor branch...
-                    parents[-1:] = list(subobject[:-1])
-                    object, subobject = subobject[-2:]
+                    # XXX There are no tests for this:
+                    request['PARENTS'][-1:] = list(subobject[:-1])
+                    object, subobject = subobject[-2:]            
+            except (AttributeError, KeyError, NotFound), e:
+                # Try to find a view
+                subobject = queryMultiAdapter((object, request), Interface, name)                
+                if subobject is not None:
+                    # OFS.Application.__bobo_traverse__ calls
+                    # REQUEST.RESPONSE.notFoundError which sets the HTTP
+                    # status code to 404
+                    request.response.setStatus(200)
+                    # We don't need to do the docstring security check
+                    # for views, so lets skip it and return the object here.
+                    return subobject.__of__(object)
+                # No view found. Reraise the error raised by __bobo_traverse__
+                raise e
+        else:
+            # No __bobo_traverse__
+            # Try with an unacquired attribute:
+            if hasattr(aq_base(object), name):
+                subobject = getattr(object, name)
             else:
-                # Try getting unacquired attributes:
-                if hasattr(aq_base(object), name):
-                    subobject = getattr(object, name)
-                else:
-                    subobject=object[name]                    
-             
-        except (AttributeError, KeyError, NotFound), e:
-            # Nothing was found with __bobo_traverse__ or directly on
-            # the object. We try to fall back to a view:
-            subobject = queryMultiAdapter((object, request), Interface, name)                
-            if subobject is not None:
-                # OFS.Application.__bobo_traverse__ calls
-                # REQUEST.RESPONSE.notFoundError which sets the HTTP
-                # status code to 404
-                request.response.setStatus(200)
-                # We don't need to do the docstring security check
-                # for views, so lets skip it and return the object here.
-                return subobject.__of__(object)
+                # We try to fall back to a view:
+                subobject = queryMultiAdapter((object, request), Interface, name)                
+                if subobject is not None:
+                    return subobject.__of__(object)
             
-            # And lastly, of there is no view, try acquired attributes, but
-            # only if there is no __bobo_traverse__:
-            if not hasattr(object,'__bobo_traverse__'):
+                # And lastly, of there is no view, try acquired attributes, but
+                # only if there is no __bobo_traverse__:
                 try:
                     subobject=getattr(object, name)
                     # Again, clear any error status created by __bobo_traverse__
@@ -111,8 +115,11 @@
                     return subobject
                 except AttributeError:
                     pass
-            raise e
 
+                # Lastly we try with key access:
+                subobject = object[name]
+                
+
         # 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.

Modified: Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/HTTPResponse.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/HTTPResponse.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/HTTPResponse.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -343,7 +343,7 @@
             self.setHeader('content-type', c)
         else:
             c = self.headers['content-type']
-            if not 'charset=' in  c:
+            if c.startswith('text/') and not 'charset=' in  c:
                 c = '%s; charset=%s' % (c, default_encoding)                
                 self.setHeader('content-type', c)
 

Modified: Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/Publish.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/Publish.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/Publish.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -22,6 +22,7 @@
 from mapply import mapply
 from zExceptions import Redirect
 from zope.publisher.browser import setDefaultSkin
+from zope.security.management import newInteraction, endInteraction
 
 class Retry(Exception):
     """Raise this to retry a request
@@ -74,6 +75,9 @@
     response=None
 
     try:
+        # TODO pass request here once BaseRequest implements IParticipation
+        newInteraction()
+
         request.processInputs()
 
         request_get=request.get
@@ -119,6 +123,7 @@
 
         if transactions_manager:
             transactions_manager.commit()
+        endInteraction()
 
         return response
     except:
@@ -154,10 +159,13 @@
             finally:
                 if transactions_manager:
                     transactions_manager.abort()
+                endInteraction()
 
             # Only reachable if Retry is raised and request supports retry.
             newrequest=request.retry()
             request.close()  # Free resources held by the request.
+            # Set the default layer/skin on the newly generated request
+            setDefaultSkin(newrequest)
             try:
                 return publish(newrequest, module_name, after_list, debug)
             finally:
@@ -166,6 +174,7 @@
         else:
             if transactions_manager:
                 transactions_manager.abort()
+            endInteraction()
             raise
 
 

Modified: Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testHTTPResponse.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testHTTPResponse.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testHTTPResponse.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -94,11 +94,17 @@
         self.assertEqual(response.headers.get('content-type'),
                          'text/plain; charset=iso-8859-15')
 
-    def test_charset_application_header(self):
+    def test_charset_application_header_no_header(self):
         response = self._makeOne(body='foo',
                     headers={'content-type': 'application/foo'})
         self.assertEqual(response.headers.get('content-type'),
-                         'application/foo; charset=iso-8859-15')
+                         'application/foo')
+
+    def test_charset_application_header_with_header(self):
+        response = self._makeOne(body='foo',
+                    headers={'content-type': 'application/foo; charset: something'})
+        self.assertEqual(response.headers.get('content-type'),
+                         'application/foo; charset: something')
     
     def test_charset_application_header_unicode(self):
         response = self._makeOne(body=unicode('ärger', 'iso-8859-15'),
@@ -117,9 +123,9 @@
 
     def test_XMLEncodingRecoding(self):
         xml = u'<?xml version="1.0" encoding="iso-8859-15" ?>\n<foo><bar/></foo>'
-        response = self._makeOne(body=xml, headers={'content-type': 'application/foo; charset=utf-8'})
+        response = self._makeOne(body=xml, headers={'content-type': 'text/xml; charset=utf-8'})
         self.assertEqual(xml.replace('iso-8859-15', 'utf-8')==response.body, True)
-        response = self._makeOne(body=xml, headers={'content-type': 'application/foo; charset=iso-8859-15'})
+        response = self._makeOne(body=xml, headers={'content-type': 'text/xml; charset=iso-8859-15'})
         self.assertEqual(xml==response.body, True)
 
 

Modified: Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testPublish.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testPublish.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/lib/python/ZPublisher/tests/testPublish.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -1,3 +1,5 @@
+from zope.publisher.browser import setDefaultSkin
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
 from ZPublisher import Retry
 from ZODB.POSException import ConflictError
 
@@ -118,6 +120,14 @@
         r.retry_count = self.retry_count
         return r
 
+class RequestWithSkinCheck(Request):
+    def traverse(self, path, validated_hook):
+        if IDefaultBrowserLayer.providedBy(self):
+            return Object()
+        else:
+            tracer.exceptions['__call__'] = [ValueError]
+            return Object()
+
 module_name = __name__
 after_list = [None]
 
@@ -263,6 +273,56 @@
     raising ConflictError from zpublisher_exception_hook
     abort
 
+    The request generator applies the default skin layer to the request.
+    We have a specially crafted request that tests this.  If the
+    request does not have the required interface it raises an
+    ValueError.  Let's see that this works as expected
+
+    >>> tracer.reset()
+    >>> request = RequestWithSkinCheck()
+    >>> setDefaultSkin(request)
+    >>> response = publish(request, module_name, after_list)
+    >>> tracer.showTracedPath()
+    begin
+    __call__
+    commit
+
+    Retries generate new request objects, the publisher needs to
+    ensure that the skin layer is applied to those as well. If the
+    skin layer is not applied to subsequent requests, an ValueError
+    would be raised here.
+
+    >>> tracer.reset()
+    >>> tracer.exceptions['commit'] = [ConflictError, ConflictError,
+    ...                                  ConflictError, ConflictError]
+    >>> request = RequestWithSkinCheck()
+    >>> setDefaultSkin(request)
+    >>> response = publish(request, module_name, after_list)
+    Traceback (most recent call last):
+    ...
+    ConflictError: database conflict error
+    >>> tracer.showTracedPath()
+    begin
+    __call__
+    commit
+    raising ConflictError from commit
+    abort
+    begin
+    __call__
+    commit
+    raising ConflictError from commit
+    abort
+    begin
+    __call__
+    commit
+    raising ConflictError from commit
+    abort
+    begin
+    __call__
+    commit
+    raising ConflictError from commit
+    abort
+
     """
     pass
 


Property changes on: Zope/branches/whitmo-2.10-layers/lib/python/zope
___________________________________________________________________
Name: svn:externals
   - annotation           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/annotation
cachedescriptors     svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/cachedescriptors
component            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/component
configuration        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/configuration
contentprovider      svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/contentprovider
contenttype          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/contenttype
copypastemove        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/copypastemove
datetime             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/datetime
decorator            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/decorator
deferredimport       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/deferredimport
deprecation          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/deprecation
documenttemplate     svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/documenttemplate
dottedname           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/dottedname
dublincore           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/dublincore
event                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/event
exceptions           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/exceptions
filerepresentation   svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/filerepresentation
formlib              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/formlib
hookable             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/hookable
i18n                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/i18n
i18nmessageid        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/i18nmessageid
index                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/index
interface            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/interface
lifecycleevent       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/lifecycleevent
location             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/location
modulealias          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/modulealias
pagetemplate         svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/pagetemplate
proxy                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/proxy
publisher            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/publisher
rdb                  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/rdb
schema               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/schema
security             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/security
sendmail             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/sendmail
server               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/server
size                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/size
structuredtext       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/structuredtext
tal                  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/tal
tales                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/tales
testbrowser          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/testbrowser
testing              svn://svn.zope.org/repos/main/zope.testing/trunk/src/zope/testing
thread               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/thread
traversing           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/traversing
viewlet              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/viewlet
wfmc                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/wfmc

   + annotation           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/annotation
cachedescriptors     svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/cachedescriptors
component            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/component
configuration        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/configuration
contentprovider      svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/contentprovider
contenttype          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/contenttype
copypastemove        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/copypastemove
datetime             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/datetime
decorator            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/decorator
deferredimport       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/deferredimport
deprecation          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/deprecation
documenttemplate     svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/documenttemplate
dottedname           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/dottedname
dublincore           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/dublincore
event                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/event
exceptions           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/exceptions
filerepresentation   svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/filerepresentation
formlib              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/formlib
hookable             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/hookable
i18n                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/i18n
i18nmessageid        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/i18nmessageid
index                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/index
interface            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/interface
lifecycleevent       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/lifecycleevent
location             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/location
modulealias          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/modulealias
pagetemplate         svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/pagetemplate
proxy                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/proxy
publisher            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/publisher
rdb                  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/rdb
schema               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/schema
security             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/security
sendmail             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/sendmail
server               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/server
size                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/size
structuredtext       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/structuredtext
tal                  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/tal
tales                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/tales
testbrowser          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/testbrowser
testing              svn://svn.zope.org/repos/main/zope.testing/tags/3.0/src/zope/testing
thread               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/thread
traversing           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/traversing
viewlet              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/viewlet
wfmc                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/wfmc




Property changes on: Zope/branches/whitmo-2.10-layers/lib/python/zope/app
___________________________________________________________________
Name: svn:externals
   - annotation          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/annotation
apidoc              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/apidoc
applicationcontrol  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/applicationcontrol
appsetup            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/appsetup
authentication      svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/authentication
basicskin           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/basicskin
broken              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/broken
cache               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/cache
component           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/component
container           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/container
content             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/content
content_types       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/content_types
copypastemove       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/copypastemove
datetimeutils       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/datetimeutils
debug               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/debug
decorator           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/decorator
dependable          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/dependable
dtmlpage            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/dtmlpage
dublincore          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/dublincore
error               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/error
event               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/event
exception           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/exception
file                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/file
filerepresentation  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/filerepresentation
folder              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/folder
form                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/form
ftests              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/ftests
generations         svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/generations
http                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/http
i18n                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/i18n
interface           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/interface
intid               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/intid
introspector        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/introspector
keyreference        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/keyreference
layers              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/layers
locales             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/locales
location            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/location
mail                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/mail
onlinehelp          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/onlinehelp
pagetemplate        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/pagetemplate
preference          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/preference
preview             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/preview
principalannotation svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/principalannotation
publication         svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/publication
publisher           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/publisher
rdb                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/rdb
renderer            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/renderer
rotterdam           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/rotterdam
schema              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/schema
security            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/security
servicenames        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/servicenames
session             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/session
site                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/site
size                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/size
skins               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/skins
sqlscript           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/sqlscript
testing             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/testing
tests               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/tests
timezones           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/timezones
traversing          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/traversing
tree                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/tree
undo                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/undo
wfmc                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/wfmc
wsgi                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/wsgi
zapi                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/zapi
zopeappgenerations  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/zopeappgenerations
zptpage             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0b2/src/zope/app/zptpage

   + annotation          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/annotation
apidoc              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/apidoc
applicationcontrol  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/applicationcontrol
appsetup            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/appsetup
authentication      svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/authentication
basicskin           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/basicskin
broken              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/broken
cache               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/cache
component           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/component
container           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/container
content             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/content
content_types       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/content_types
copypastemove       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/copypastemove
datetimeutils       svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/datetimeutils
debug               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/debug
decorator           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/decorator
dependable          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/dependable
dtmlpage            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/dtmlpage
dublincore          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/dublincore
error               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/error
event               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/event
exception           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/exception
file                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/file
filerepresentation  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/filerepresentation
folder              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/folder
form                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/form
ftests              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/ftests
generations         svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/generations
http                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/http
i18n                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/i18n
interface           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/interface
intid               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/intid
introspector        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/introspector
keyreference        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/keyreference
layers              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/layers
locales             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/locales
location            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/location
mail                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/mail
onlinehelp          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/onlinehelp
pagetemplate        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/pagetemplate
preference          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/preference
preview             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/preview
principalannotation svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/principalannotation
publication         svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/publication
publisher           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/publisher
rdb                 svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/rdb
renderer            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/renderer
rotterdam           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/rotterdam
schema              svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/schema
security            svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/security
servicenames        svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/servicenames
session             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/session
site                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/site
size                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/size
skins               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/skins
sqlscript           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/sqlscript
testing             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/testing
tests               svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/tests
timezones           svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/timezones
traversing          svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/traversing
tree                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/tree
undo                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/undo
wfmc                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/wfmc
wsgi                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/wsgi
zapi                svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/zapi
zopeappgenerations  svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/zopeappgenerations
zptpage             svn://svn.zope.org/repos/main/Zope3/tags/3.3.0/src/zope/app/zptpage


Modified: Zope/branches/whitmo-2.10-layers/skel/bin/runzope.in
===================================================================
--- Zope/branches/whitmo-2.10-layers/skel/bin/runzope.in	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/skel/bin/runzope.in	2007-01-08 18:47:06 UTC (rev 71823)
@@ -5,7 +5,7 @@
 INSTANCE_HOME="<<INSTANCE_HOME>>"
 CONFIG_FILE="<<INSTANCE_HOME>>/etc/zope.conf"
 SOFTWARE_HOME="<<SOFTWARE_HOME>>"
-PYTHONPATH="$SOFTWARE_HOME"
+PYTHONPATH="$SOFTWARE_HOME:$PYTHONPATH"
 export PYTHONPATH INSTANCE_HOME SOFTWARE_HOME
 
 ZOPE_RUN="$SOFTWARE_HOME/Zope2/Startup/run.py"

Modified: Zope/branches/whitmo-2.10-layers/skel/bin/zopectl.in
===================================================================
--- Zope/branches/whitmo-2.10-layers/skel/bin/zopectl.in	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/skel/bin/zopectl.in	2007-01-08 18:47:06 UTC (rev 71823)
@@ -5,7 +5,7 @@
 INSTANCE_HOME="<<INSTANCE_HOME>>"
 CONFIG_FILE="<<INSTANCE_HOME>>/etc/zope.conf"
 SOFTWARE_HOME="<<SOFTWARE_HOME>>"
-PYTHONPATH="$SOFTWARE_HOME"
+PYTHONPATH="$SOFTWARE_HOME:$PYTHONPATH"
 export PYTHONPATH INSTANCE_HOME SOFTWARE_HOME
 
 ZDCTL="$SOFTWARE_HOME/Zope2/Startup/zopectl.py"

Modified: Zope/branches/whitmo-2.10-layers/skel/etc/site.zcml
===================================================================
--- Zope/branches/whitmo-2.10-layers/skel/etc/site.zcml	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/skel/etc/site.zcml	2007-01-08 18:47:06 UTC (rev 71823)
@@ -2,25 +2,25 @@
 	       xmlns:meta="http://namespaces.zope.org/meta"
            xmlns:five="http://namespaces.zope.org/five">
 
+  <meta:provides feature="devmode" />
+
   <include package="Products.Five" />
   <meta:redefinePermission from="zope2.Public" to="zope.Public" />
 
 
   <!-- Load the meta -->
-
   <include files="package-includes/*-meta.zcml" />
   <five:loadProducts file="meta.zcml"/>
 
-
   <!-- Load the configuration -->
-
   <include files="package-includes/*-configure.zcml" />
   <five:loadProducts />
 
-
   <!-- Load the configuration overrides-->
-
-  <includeOverrides files="package-includes/*-overrides.zcml" />
   <five:loadProductsOverrides />
 
+
+  <securityPolicy
+      component="Products.Five.security.FiveSecurityPolicy" />
+
 </configure>

Modified: Zope/branches/whitmo-2.10-layers/test.py
===================================================================
--- Zope/branches/whitmo-2.10-layers/test.py	2007-01-08 17:49:28 UTC (rev 71822)
+++ Zope/branches/whitmo-2.10-layers/test.py	2007-01-08 18:47:06 UTC (rev 71823)
@@ -21,22 +21,22 @@
 
 import os.path, sys
 
-# Remove this directory from path:
-here = os.path.abspath(os.path.dirname(sys.argv[0]))
-sys.path[:] = [p for p in sys.path if os.path.abspath(p) != here]
+# Remove script directory from path:
+scriptdir = os.path.realpath(os.path.dirname(sys.argv[0]))
+sys.path[:] = [p for p in sys.path if os.path.realpath(p) != scriptdir]
 
 shome = os.environ.get('SOFTWARE_HOME')
 zhome = os.environ.get('ZOPE_HOME')
 ihome = os.environ.get('INSTANCE_HOME')
 
 if zhome:
-    zhome = os.path.abspath(zhome)
+    zhome = os.path.realpath(zhome)
     if shome:
-        shome = os.path.abspath(shome)
+        shome = os.path.realpath(shome)
     else:
         shome = os.path.join(zhome, 'lib', 'python')
 elif shome:
-    shome = os.path.abspath(shome)
+    shome = os.path.realpath(shome)
     zhome = os.path.dirname(os.path.dirname(shome))
 elif ihome:
     print >> sys.stderr, '''
@@ -44,8 +44,13 @@
     must be set
     '''
 else:
-    # No zope home, assume that it is the script directory
-    zhome = os.path.abspath(os.path.dirname(sys.argv[0]))
+    # No zope home, derive it from script directory:
+    # (test.py lives in either ZOPE_HOME or ZOPE_HOME/bin)
+    parentdir, lastpart = os.path.split(scriptdir)
+    if lastpart == 'bin':
+        zhome = parentdir
+    else:
+        zhome = scriptdir
     shome = os.path.join(zhome, 'lib', 'python')
 
 sys.path.insert(0, shome)



More information about the Zope-Checkins mailing list