[Zope-Checkins] SVN: Zope/branches/2.12/doc/CHANGES.rst Correct the past.

2010-07-10 Thread Martin Aspeli
Log message for revision 114489:
  Correct the past.

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2010-07-10 10:00:41 UTC (rev 114488)
+++ Zope/branches/2.12/doc/CHANGES.rst  2010-07-10 10:02:50 UTC (rev 114489)
@@ -15,9 +15,8 @@
 
 - LP #143531: Fix broken object so they give access to their state.
 
-- LP #578326: Issue a warning if someone specifies a non-public permission
-  attribute in the browser:view directive. This attribute has never been
-  supported in Zope 2.
+- LP #578326: Add support for non-public permission attributes in the
+  browser:view directive.
 
 Features Added
 ++

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/trunk/src/Products/Five/browser/ Merge r114488 from 2.12 branch

2010-07-10 Thread Martin Aspeli
Log message for revision 114490:
  Merge r114488 from 2.12 branch

Changed:
  U   Zope/trunk/src/Products/Five/browser/metaconfigure.py
  U   Zope/trunk/src/Products/Five/browser/tests/pages.txt
  U   Zope/trunk/src/Products/Five/browser/tests/pages.zcml

-=-
Modified: Zope/trunk/src/Products/Five/browser/metaconfigure.py
===
--- Zope/trunk/src/Products/Five/browser/metaconfigure.py   2010-07-10 
10:02:50 UTC (rev 114489)
+++ Zope/trunk/src/Products/Five/browser/metaconfigure.py   2010-07-10 
10:13:30 UTC (rev 114490)
@@ -201,15 +201,7 @@
  ):
 if permission is None:
 permission = 'zope.Public'
-elif permission in ('zope.Public', 'zope2.Public'):
-# No need to warn about the default case
-pass
-else:
-warnings.warn(The permission option of the browser:view / 
-  directive is not supported in Zope 2.  + \
-  Ignored for %s in %s %
-  (str(class_), _context.info), stacklevel=3)
-
+
 super(view, self).__init__(
 _context, permission, for_=for_, name=name, layer=layer,
 class_=class_, allowed_interface=allowed_interface,
@@ -314,6 +306,42 @@
 newclass, (for_, layer), self.provides, name,
 _context.info),
 )
+
+# Security
+
+_context.action(
+discriminator = ('five:protectClass', newclass),
+callable = protectClass,
+args = (newclass, permission)
+)
+
+if allowed_attributes:
+for attr in allowed_attributes:
+_context.action(
+discriminator = ('five:protectName', newclass, attr),
+callable = protectName,
+args = (newclass, attr, permission)
+)
+
+# Make everything else private
+allowed = allowed_attributes or []
+private_attrs = [name for name in dir(newclass)
+ if (not name.startswith('_')) and
+(name not in allowed) and
+ismethod(getattr(newclass, name))]
+for attr in private_attrs:
+_context.action(
+discriminator = ('five:protectName', newclass, attr),
+callable = protectName,
+args = (newclass, attr, CheckerPrivateId)
+)
+
+# Protect the class
+_context.action(
+discriminator = ('five:initialize:class', newclass),
+callable = InitializeClass,
+args = (newclass,)
+)
 
 _factory_map = {'image':{'prefix':'ImageResource',
  'count':0,

Modified: Zope/trunk/src/Products/Five/browser/tests/pages.txt
===
--- Zope/trunk/src/Products/Five/browser/tests/pages.txt2010-07-10 
10:02:50 UTC (rev 114489)
+++ Zope/trunk/src/Products/Five/browser/tests/pages.txt2010-07-10 
10:13:30 UTC (rev 114490)
@@ -253,12 +253,34 @@
aq_parent(aq_inner(context))
   Folder at /test_folder_1_ 
 
+The same applies to a view registered with browser:view / instead of
+browser:page /
+
+   request = TestRequest()
+   view = getMultiAdapter((self.folder.testoid, request), 
name=u'permission_view')
+   view.__ac_permissions__
+  (('View management screens', ('',)),)
+   aq_acquire(view, '__roles__')
+  ('Manager',)
+   context = view.context
+   from Acquisition import ImplicitAcquisitionWrapper
+   type(context) == ImplicitAcquisitionWrapper
+  True
+   view.__parent__ == view.context
+  True
+   aq_parent(view) == view.context
+  True
+   context.aq_inner.aq_parent
+  Folder at /test_folder_1_ 
+   aq_parent(aq_inner(context))
+  Folder at /test_folder_1_ 
+
 High-level security
 ---
 
protected_view_names = [
   ... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html',
-  ... 'condor.html']
+  ... 'condor.html', 'permission_view']

public_view_names = [
   ... 'public_attribute_page',

Modified: Zope/trunk/src/Products/Five/browser/tests/pages.zcml
===
--- Zope/trunk/src/Products/Five/browser/tests/pages.zcml   2010-07-10 
10:02:50 UTC (rev 114489)
+++ Zope/trunk/src/Products/Five/browser/tests/pages.zcml   2010-07-10 
10:13:30 UTC (rev 114490)
@@ -232,7 +232,15 @@
   class=.pages.SimpleView
   permission=zope2.Public
   /
-
+  
+  !-- A named view with permissions --
+  browser:view
+  name=permission_view
+  for=Products.Five.tests.testing.simplecontent.ISimpleContent
+  class=.pages.CallView
+  permission=zope2.ViewManagementScreens
+  /
+  
   !-- stuff that we'll override in overrides.zcml --
   

[Zope-Checkins] SVN: Zope/branches/2.12/ Fix processInputs() so that it no longer stomps on things like :records or :int:list

2010-05-27 Thread Martin Aspeli
Log message for revision 112780:
  Fix processInputs() so that it no longer stomps on things like :records or 
:int:list

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/Products/Five/browser/decode.py
  U   Zope/branches/2.12/src/Products/Five/browser/tests/test_decode.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2010-05-27 12:12:28 UTC (rev 112779)
+++ Zope/branches/2.12/doc/CHANGES.rst  2010-05-27 13:27:15 UTC (rev 112780)
@@ -11,6 +11,10 @@
 Bugs Fixed
 ++
 
+- Five's processInputs() would stomp on :list or :tuple values that contained
+  ints or other non-strings, would clear out :records entirely, and would not
+  do anything for :record fields.
+
 - LP #143261: The (very old-fashioned) Zope2.debug interactive request
   debugger still referred to the toplevel module ``Zope``, which was 
   renamed to ``Zope2`` a long time ago.

Modified: Zope/branches/2.12/src/Products/Five/browser/decode.py
===
--- Zope/branches/2.12/src/Products/Five/browser/decode.py  2010-05-27 
12:12:28 UTC (rev 112779)
+++ Zope/branches/2.12/src/Products/Five/browser/decode.py  2010-05-27 
13:27:15 UTC (rev 112780)
@@ -32,23 +32,40 @@
 pass
 return text
 
+def processInputValue(value, charsets):
+Recursively look for values (e.g. elements of lists, tuples or dicts)
+and attempt to decode.
+
+
+if isinstance(value, list):
+return [processInputValue(v, charsets) for v in value]
+elif isinstance(value, tuple):
+return tuple([processInputValue(v, charsets) for v in value])
+elif isinstance(value, dict):
+for k, v in value.items():
+value[k] = processInputValue(v, charsets)
+return value
+elif isinstance(value, str):
+return _decode(value, charsets)
+else:
+return value
+
 def processInputs(request, charsets=None):
+Process the values in request.form to decode strings to unicode, using
+the passed-in list of charsets. If none are passed in, look up the user's
+preferred charsets. The default is to use utf-8.
+
+
 if charsets is None:
-envadapter = IUserPreferredCharsets(request)
-charsets = envadapter.getPreferredCharsets() or ['utf-8']
-
+envadapter = IUserPreferredCharsets(request, None)
+if envadapter is None:
+charsets = ['utf-8']
+else:
+charsets = envadapter.getPreferredCharsets() or ['utf-8']
+
 for name, value in request.form.items():
 if not (isCGI_NAME(name) or name.startswith('HTTP_')):
-if isinstance(value, str):
-request.form[name] = _decode(value, charsets)
-elif isinstance(value, list):
-request.form[name] = [ _decode(val, charsets)
-   for val in value
-   if isinstance(val, str) ]
-elif isinstance(value, tuple):
-request.form[name] = tuple([ _decode(val, charsets)
- for val in value
- if isinstance(val, str) ])
+request.form[name] = processInputValue(value, charsets)
 
 def setPageEncoding(request):
 Set the encoding of the form page via the Content-Type header.

Modified: Zope/branches/2.12/src/Products/Five/browser/tests/test_decode.py
===
--- Zope/branches/2.12/src/Products/Five/browser/tests/test_decode.py   
2010-05-27 12:12:28 UTC (rev 112779)
+++ Zope/branches/2.12/src/Products/Five/browser/tests/test_decode.py   
2010-05-27 13:27:15 UTC (rev 112780)
@@ -46,6 +46,42 @@
processInputs(request, charsets)
request.form['foo'] == (u'f\xf6\xf6',)
   True
+ 
+Ints in lists are not lost::
+
+   request.form['foo'] = [1, 2, 3]
+   processInputs(request, charsets)
+   request.form['foo'] == [1, 2, 3]
+  True
+
+Ints in tuples are not lost::
+
+   request.form['foo'] = (1, 2, 3,)
+   processInputs(request, charsets)
+   request.form['foo'] == (1, 2, 3)
+  True
+
+Mixed lists work:
+
+   request.form['foo'] = [u'f\xf6\xf6'.encode('iso-8859-1'), 2, 3]
+   processInputs(request, charsets)
+   request.form['foo'] == [u'f\xf6\xf6', 2, 3]
+  True
+
+Mixed dicts work:
+
+   request.form['foo'] = {'foo': u'f\xf6\xf6'.encode('iso-8859-1'), 
'bar': 2}
+   processInputs(request, charsets)
+   request.form['foo'] == {'foo': u'f\xf6\xf6', 'bar': 2}
+  True
+
+Deep recursion works:
+
+   request.form['foo'] = [{'foo': u'f\xf6\xf6'.encode('iso-8859-1'), 
'bar': 2}, {'foo': uone, 'bar': 3}]
+   processInputs(request, charsets)
+   

[Zope-Checkins] SVN: Zope/trunk/src/Products/Five/browser/ Merge c112780 from 2.12 branch

2010-05-27 Thread Martin Aspeli
Log message for revision 112781:
  Merge c112780 from 2.12 branch

Changed:
  U   Zope/trunk/src/Products/Five/browser/decode.py
  U   Zope/trunk/src/Products/Five/browser/tests/test_decode.py

-=-
Modified: Zope/trunk/src/Products/Five/browser/decode.py
===
--- Zope/trunk/src/Products/Five/browser/decode.py  2010-05-27 13:27:15 UTC 
(rev 112780)
+++ Zope/trunk/src/Products/Five/browser/decode.py  2010-05-27 13:30:02 UTC 
(rev 112781)
@@ -32,23 +32,40 @@
 pass
 return text
 
+def processInputValue(value, charsets):
+Recursively look for values (e.g. elements of lists, tuples or dicts)
+and attempt to decode.
+
+
+if isinstance(value, list):
+return [processInputValue(v, charsets) for v in value]
+elif isinstance(value, tuple):
+return tuple([processInputValue(v, charsets) for v in value])
+elif isinstance(value, dict):
+for k, v in value.items():
+value[k] = processInputValue(v, charsets)
+return value
+elif isinstance(value, str):
+return _decode(value, charsets)
+else:
+return value
+
 def processInputs(request, charsets=None):
+Process the values in request.form to decode strings to unicode, using
+the passed-in list of charsets. If none are passed in, look up the user's
+preferred charsets. The default is to use utf-8.
+
+
 if charsets is None:
-envadapter = IUserPreferredCharsets(request)
-charsets = envadapter.getPreferredCharsets() or ['utf-8']
-
+envadapter = IUserPreferredCharsets(request, None)
+if envadapter is None:
+charsets = ['utf-8']
+else:
+charsets = envadapter.getPreferredCharsets() or ['utf-8']
+
 for name, value in request.form.items():
 if not (isCGI_NAME(name) or name.startswith('HTTP_')):
-if isinstance(value, str):
-request.form[name] = _decode(value, charsets)
-elif isinstance(value, list):
-request.form[name] = [ _decode(val, charsets)
-   for val in value
-   if isinstance(val, str) ]
-elif isinstance(value, tuple):
-request.form[name] = tuple([ _decode(val, charsets)
- for val in value
- if isinstance(val, str) ])
+request.form[name] = processInputValue(value, charsets)
 
 def setPageEncoding(request):
 Set the encoding of the form page via the Content-Type header.

Modified: Zope/trunk/src/Products/Five/browser/tests/test_decode.py
===
--- Zope/trunk/src/Products/Five/browser/tests/test_decode.py   2010-05-27 
13:27:15 UTC (rev 112780)
+++ Zope/trunk/src/Products/Five/browser/tests/test_decode.py   2010-05-27 
13:30:02 UTC (rev 112781)
@@ -46,6 +46,42 @@
processInputs(request, charsets)
request.form['foo'] == (u'f\xf6\xf6',)
   True
+ 
+Ints in lists are not lost::
+
+   request.form['foo'] = [1, 2, 3]
+   processInputs(request, charsets)
+   request.form['foo'] == [1, 2, 3]
+  True
+
+Ints in tuples are not lost::
+
+   request.form['foo'] = (1, 2, 3,)
+   processInputs(request, charsets)
+   request.form['foo'] == (1, 2, 3)
+  True
+
+Mixed lists work:
+
+   request.form['foo'] = [u'f\xf6\xf6'.encode('iso-8859-1'), 2, 3]
+   processInputs(request, charsets)
+   request.form['foo'] == [u'f\xf6\xf6', 2, 3]
+  True
+
+Mixed dicts work:
+
+   request.form['foo'] = {'foo': u'f\xf6\xf6'.encode('iso-8859-1'), 
'bar': 2}
+   processInputs(request, charsets)
+   request.form['foo'] == {'foo': u'f\xf6\xf6', 'bar': 2}
+  True
+
+Deep recursion works:
+
+   request.form['foo'] = [{'foo': u'f\xf6\xf6'.encode('iso-8859-1'), 
'bar': 2}, {'foo': uone, 'bar': 3}]
+   processInputs(request, charsets)
+   request.form['foo'] == [{'foo': u'f\xf6\xf6', 'bar': 2}, {'foo': 
uone, 'bar': 3}]
+  True
+
 
 
 def test_suite():

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/branches/2.12/src/Products/Five/browser/resource.py Apply some safety to the fix in r110185 after reports it may be causing some problems

2010-04-13 Thread Martin Aspeli
Log message for revision 110799:
  Apply some safety to the fix in r110185 after reports it may be causing some 
problems

Changed:
  U   Zope/branches/2.12/src/Products/Five/browser/resource.py

-=-
Modified: Zope/branches/2.12/src/Products/Five/browser/resource.py
===
--- Zope/branches/2.12/src/Products/Five/browser/resource.py2010-04-13 
14:27:23 UTC (rev 110798)
+++ Zope/branches/2.12/src/Products/Five/browser/resource.py2010-04-13 
14:43:07 UTC (rev 110799)
@@ -27,6 +27,7 @@
 from zope.app.publisher.fileresource import File, Image
 from zope.app.publisher.pagetemplateresource import PageTemplate
 
+from Acquisition import aq_base
 from Products.Five.browser import BrowserView
 
 
@@ -164,7 +165,8 @@
 
 # We need to propagate security so that restrictedTraverse() will
 # work
-resource.__roles__ = self.__roles__
+if hasattr(aq_base(self), '__roles__'):
+resource.__roles__ = self.__roles__
 
 return resource
 

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/trunk/src/Products/Five/browser/resource.py Merge c110799 from svn+ssh://svn.zope.org/repos/main/Zope/branches/2.12

2010-04-13 Thread Martin Aspeli
Log message for revision 110800:
  Merge c110799 from svn+ssh://svn.zope.org/repos/main/Zope/branches/2.12

Changed:
  U   Zope/trunk/src/Products/Five/browser/resource.py

-=-
Modified: Zope/trunk/src/Products/Five/browser/resource.py
===
--- Zope/trunk/src/Products/Five/browser/resource.py2010-04-13 14:43:07 UTC 
(rev 110799)
+++ Zope/trunk/src/Products/Five/browser/resource.py2010-04-13 14:47:33 UTC 
(rev 110800)
@@ -27,6 +27,7 @@
 from zope.publisher.interfaces.browser import IBrowserPublisher
 from zope.ptresource.ptresource import PageTemplate
 
+from Acquisition import aq_base
 from Products.Five.browser import BrowserView
 
 
@@ -165,7 +166,8 @@
 
 # We need to propagate security so that restrictedTraverse() will
 # work
-resource.__roles__ = self.__roles__
+if hasattr(aq_base(self), '__roles__'):
+resource.__roles__ = self.__roles__
 
 return resource
 

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/trunk/src/ZServer/PubCore/__init__.py A hint for the next person who gets very confused when importing something a second time doesn't work.

2010-04-08 Thread Martin Aspeli
Log message for revision 110660:
  A hint for the next person who gets very confused when importing something a 
second time doesn't work.

Changed:
  U   Zope/trunk/src/ZServer/PubCore/__init__.py

-=-
Modified: Zope/trunk/src/ZServer/PubCore/__init__.py
===
--- Zope/trunk/src/ZServer/PubCore/__init__.py  2010-04-08 15:54:42 UTC (rev 
110659)
+++ Zope/trunk/src/ZServer/PubCore/__init__.py  2010-04-08 15:55:42 UTC (rev 
110660)
@@ -24,6 +24,8 @@
 return apply(_handle, args, kw)
 
 def setNumberOfThreads(n):
+This function will self-destruct in 4 statements.
+
 global _n
 _n=n
 global setNumberOfThreads

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/trunk/src/Products/Five/browser/ Merge r110185 from 2.12 branch

2010-03-26 Thread Martin Aspeli
Log message for revision 110186:
  Merge r110185 from 2.12 branch

Changed:
  U   Zope/trunk/src/Products/Five/browser/resource.py
  U   Zope/trunk/src/Products/Five/browser/tests/resource.txt

-=-
Modified: Zope/trunk/src/Products/Five/browser/resource.py
===
--- Zope/trunk/src/Products/Five/browser/resource.py2010-03-26 12:39:58 UTC 
(rev 110185)
+++ Zope/trunk/src/Products/Five/browser/resource.py2010-03-26 12:48:34 UTC 
(rev 110186)
@@ -162,6 +162,11 @@
 resource = factory(name, filename)(self.request)
 resource.__name__ = name
 resource.__parent__ = self
+
+# We need to propagate security so that restrictedTraverse() will
+# work
+resource.__roles__ = self.__roles__
+
 return resource
 
 class DirectoryResourceFactory(ResourceFactory):

Modified: Zope/trunk/src/Products/Five/browser/tests/resource.txt
===
--- Zope/trunk/src/Products/Five/browser/tests/resource.txt 2010-03-26 
12:39:58 UTC (rev 110185)
+++ Zope/trunk/src/Products/Five/browser/tests/resource.txt 2010-03-26 
12:48:34 UTC (rev 110186)
@@ -69,7 +69,6 @@
   ... if not isinstance(resource, PageTemplateResource):
   ... self.assertEquals(resource(), base_url % r)
 
-
 Security
 
 
@@ -108,7 +107,15 @@
   ... path = base % resource
   ... checkRestricted(self.folder, 'context.restrictedTraverse(%s)' % 
path)
 
+Let's make sure restrictedTraverse() works directly, too. It used to get
+tripped up on subdirectories due to missing security declarations.
 
+   
self.folder.restrictedTraverse('++resource++fivetest_resources/resource.txt') 
is not None
+  True
+  
+   
self.folder.restrictedTraverse('++resource++fivetest_resources/resource_subdir/resource.txt')
 is not None
+  True
+
 Clean up
 
 

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/branches/2.12/ Hoping that silence (or apathy?) is consent here. :) Adding an event to indicate when streaming is starting in case of chunked/streamed responses using respons

2010-03-26 Thread Martin Aspeli
Log message for revision 110187:
  Hoping that silence (or apathy?) is consent here. :) Adding an event to 
indicate when streaming is starting in case of chunked/streamed responses using 
response.write()

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/ZPublisher/HTTPResponse.py
  U   Zope/branches/2.12/src/ZPublisher/interfaces.py
  U   Zope/branches/2.12/src/ZPublisher/pubevents.py
  U   Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py
  U   Zope/branches/2.12/src/ZServer/HTTPResponse.py
  U   Zope/branches/2.12/src/ZServer/tests/test_responses.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2010-03-26 12:48:34 UTC (rev 110186)
+++ Zope/branches/2.12/doc/CHANGES.rst  2010-03-26 13:14:46 UTC (rev 110187)
@@ -17,6 +17,11 @@
   - ExtensionClass = 2.13.0
   - Persistence = 2.13.0
 
+- There is now an event ZPublisher.interfaces.IPubBeforeStreaming which will
+  be fired just before the first chunk of data is written to the response
+  stream when using the write() method on the response. This is the last
+  possible point at which response headers may be set in this case.
+
 Bugs Fixed
 ++
 

Modified: Zope/branches/2.12/src/ZPublisher/HTTPResponse.py
===
--- Zope/branches/2.12/src/ZPublisher/HTTPResponse.py   2010-03-26 12:48:34 UTC 
(rev 110186)
+++ Zope/branches/2.12/src/ZPublisher/HTTPResponse.py   2010-03-26 13:14:46 UTC 
(rev 110187)
@@ -18,10 +18,12 @@
 import types, os, sys, re
 import zlib, struct
 from string import translate, maketrans
+from zope.event import notify
 from BaseResponse import BaseResponse
 from zExceptions import Unauthorized, Redirect
 from zExceptions.ExceptionFormatter import format_exception
 from ZPublisher import BadRequest, InternalError, NotFound
+from ZPublisher.pubevents import PubBeforeStreaming
 from cgi import escape
 from urllib import quote
 
@@ -921,6 +923,9 @@
 
 
 if not self._wrote:
+
+notify(PubBeforeStreaming(self))
+
 self.outputBody()
 self._wrote = 1
 self.stdout.flush()

Modified: Zope/branches/2.12/src/ZPublisher/interfaces.py
===
--- Zope/branches/2.12/src/ZPublisher/interfaces.py 2010-03-26 12:48:34 UTC 
(rev 110186)
+++ Zope/branches/2.12/src/ZPublisher/interfaces.py 2010-03-26 13:14:46 UTC 
(rev 110187)
@@ -50,3 +50,11 @@
 
 exc_info = Attribute('''The exception info as returned by 
'sys.exc_info()'.''')
 retry = Attribute('Whether the request will be retried')
+
+class IPubBeforeStreaming(Interface):
+Event fired just before a streaming response is initiated, i.e. when
+something calls response.write() for the first time. Note that this is
+carries a reference to the *response*, not the request.
+
+
+response = Attribute(uThe current HTTP response)

Modified: Zope/branches/2.12/src/ZPublisher/pubevents.py
===
--- Zope/branches/2.12/src/ZPublisher/pubevents.py  2010-03-26 12:48:34 UTC 
(rev 110186)
+++ Zope/branches/2.12/src/ZPublisher/pubevents.py  2010-03-26 13:14:46 UTC 
(rev 110187)
@@ -10,7 +10,8 @@
 from zope.interface import implements
 
 from interfaces import IPubStart, IPubSuccess, IPubFailure, \
- IPubAfterTraversal, IPubBeforeCommit, IPubBeforeAbort
+ IPubAfterTraversal, IPubBeforeCommit, IPubBeforeAbort, \
+ IPubBeforeStreaming
 
 class _Base(object):
 PubEvent base class.
@@ -49,3 +50,11 @@
 
 def __init__(self, request, exc_info, retry):
 self.request, self.exc_info, self.retry = request, exc_info, retry
+
+class PubBeforeStreaming(object):
+Notified immediately before streaming via response.write() commences
+
+implements(IPubBeforeStreaming)
+
+def __init__(self, response):
+self.response = response

Modified: Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py
===
--- Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py2010-03-26 
12:48:34 UTC (rev 110186)
+++ Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py2010-03-26 
13:14:46 UTC (rev 110187)
@@ -1,3 +1,4 @@
+from StringIO import StringIO
 from sys import modules, exc_info
 from unittest import TestCase, TestSuite, makeSuite, main
 
@@ -7,11 +8,14 @@
 
 from ZPublisher.Publish import publish, Retry
 from ZPublisher.BaseRequest import BaseRequest
+from ZPublisher.HTTPResponse import HTTPResponse
 from ZPublisher.pubevents import PubStart, PubSuccess, PubFailure, \
- PubAfterTraversal, PubBeforeCommit, PubBeforeAbort
+ PubAfterTraversal, PubBeforeCommit, PubBeforeAbort, \
+ PubBeforeStreaming
 from ZPublisher.interfaces import \
  

[Zope-Checkins] SVN: Zope/trunk/ Merge c105589 from 2.12 branch, adding IPubBeforeAbort event

2010-03-26 Thread Martin Aspeli
Log message for revision 110188:
  Merge c105589 from 2.12 branch, adding IPubBeforeAbort event

Changed:
  U   Zope/trunk/doc/CHANGES.rst
  U   Zope/trunk/src/ZPublisher/Publish.py
  U   Zope/trunk/src/ZPublisher/interfaces.py
  U   Zope/trunk/src/ZPublisher/pubevents.py
  U   Zope/trunk/src/ZPublisher/tests/testpubevents.py

-=-
Modified: Zope/trunk/doc/CHANGES.rst
===
--- Zope/trunk/doc/CHANGES.rst  2010-03-26 13:14:46 UTC (rev 110187)
+++ Zope/trunk/doc/CHANGES.rst  2010-03-26 13:25:09 UTC (rev 110188)
@@ -2,92 +2,115 @@
 =
 
 This file contains change information for the current Zope release.
-Change information for previous versions of Zope can be found at
-http://docs.zope.org/zope2/releases/.
+Change information for previous versions of Zope can be found in the
+file HISTORY.txt.
 
-Trunk (unreleased)
---
+Zope 2.12.2 (unreleased)
+
 
-Restructuring
-+
+Features Added
+++
 
-- Finished the move of five.formlib to an extra package and removed it from
-  Zope 2 itself. Upgrade notes have been added to the news section of the
-  release notes.
+- Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.
+  This event is fired just before IPubFailure, but, crucially, while the
+  transaction is still open.
 
-- Moved Products.Sessions APIs from ``SessionInterfaces`` to ``interfaces``,
-  leaving behind the old module / names for backward compatibility.
+- Include bytes limited cache size in the cache parameters ZMI screen.
 
-- Moved ``cmf.*`` permissions into Products.CMFCore.
+- Officially supporting Python 2.6 only (with inofficial support for
+  Python 2.5) but dropping any support and responsibility for
+  Python 2.4.
 
-- Moved general OFS related ZCML directives from Products.Five into the OFS
-  package itself.
+Bugs Fixed
+++
 
-- Ported the lazy expression into zope.tales and require a new version of it.
+- Avoid possible errors on test tear-down in Products.Five.fiveconfigure's
+  cleanUp() function if Products.meta_types has not been set
 
-- Updated Five documentation to clarify its role in regard to Zope packages.
+Zope 2.12.1 (2009/11/02)
+
 
-- Removed the deprecated ``five:containerEvents`` directive, which had been
-  a no-op for quite a while.
+Features Added
+++
 
-- Removed Products.Five.fivedirectives.IBridgeDirective - a leftover from the
-  Interface to zope.interface bridging code.
+- Updated packages:
 
-- Marked the ``five:implements /`` as officially deprecated. The standard
-  ``class /`` directive allows the same.
+  - ZODB3 = 3.9.3  (fixes bug where blob conflict errors hung commits)
+  - Acquisition = 2.12.4 (fixes problems with iteration support)
+  - setuptools = 0.6c11
 
-- Reuse IInclude from zope.configuration.xmlconfig.
+- LP #411732: Silence security declaration warnings for context and request
+  on views protected by an interface.
 
-- Reuse IMenuItemType from zope.browsermenu.
+- Assorted documentation cleanups, including a script to rebuild HTML
+  documentation on Windows.
 
-- Moved TaintedString from ZPublisher to Shared.
-  This resolves a circular import issue.
+- Refactored Windows Service support to not need or use zopeservice.py
+  in instances. This makes buildout-based instances work on Windows.
 
-- Moved zope.formlib / zope.app.form integration into a separate package
-  called five.formlib.
+Bugs Fixed
+++
 
-- We no longer depend on the ``zope-functional-testing`` extra of
-  zope.testbrowser.
+- LP #440490: zopectl fg|adduser|run|debug now work on Windows.
 
-- Removed the dependency on zope.app.publication in favor of new versions of
-  zope.publisher and zope.traversing.
+- LP #443005: zopectl stop works once more on Windows.
 
-- Requiring Python 2.6 officially
+- LP #453723: zopectl start works again on non-Windows platforms.
 
-- Changed startup server tests in Zope2 to use a randomized port number, to
-  allow the nightly buildbot to run the tests at the same time for multiple
-  configurations without the port being already in use.
+Zope 2.12.0 final  (2009/10/01)
+---
 
-- Cloned ``ZopeVocabularyRegistry`` from ``zope.app.schema``, and added
-  sane registration of it during initialization of Five.
+Features Added
+++
 
-- Removed experimental support for configuring the Twisted HTTP server
-  as an alternative to ``ZServer``.
+- Updated packages:
 
-- Moved ``Products/Five/security.py`` and security related ZCML configuration
-  into the AccessControl package.
+  - ZODB3 = 3.9.0
 
-- Moved ``Products/Five/traversing.zcml`` directly into the configure.zcml.
+- Backported clone of ``ZopeVocabularyRegistry`` from ``zope.app.schema``, and
+  sane registration of it during initialization of Five product.
 
-- Moved zope.security-style permission registrations from Products.Five into
-  the 

[Zope-Checkins] SVN: Zope/branches/2.12/ Let OFS File/Image fire lifecycle events

2010-01-11 Thread Martin Aspeli
Log message for revision 108041:
  Let OFS File/Image fire lifecycle events

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/OFS/Image.py
  U   Zope/branches/2.12/src/OFS/tests/testFileAndImage.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2010-01-11 22:46:46 UTC (rev 108040)
+++ Zope/branches/2.12/doc/CHANGES.rst  2010-01-12 00:26:43 UTC (rev 108041)
@@ -27,6 +27,10 @@
 Features Added
 ++
 
+- Made OFS.Image.File and OFS.Image.Image send IObjectModifiedEvent when
+  created through their factories and modified through the ZMI forms
+  (manage_edit() and manage_upload()).
+
 - Moved zope.formlib / zope.app.form integration into a separate package
   called five.formlib.
 

Modified: Zope/branches/2.12/src/OFS/Image.py
===
--- Zope/branches/2.12/src/OFS/Image.py 2010-01-11 22:46:46 UTC (rev 108040)
+++ Zope/branches/2.12/src/OFS/Image.py 2010-01-12 00:26:43 UTC (rev 108041)
@@ -46,6 +46,10 @@
 from OFS.PropertyManager import PropertyManager
 from OFS.SimpleItem import Item_w__name__
 
+from zope.event import notify
+from zope.lifecycleevent import ObjectModifiedEvent
+from zope.lifecycleevent import ObjectCreatedEvent
+
 manage_addFileForm = DTMLFile('dtml/imageAdd',
   globals(),
   Kind='File',
@@ -63,19 +67,23 @@
 precondition = str(precondition)
 
 id, title = cookId(id, title, file)
-
+
 self=self.this()
 
 # First, we create the file without data:
 self._setObject(id, File(id,title,'',content_type, precondition))
-
+
+newFile = self._getOb(id)
+
 # Now we upload the data.  By doing this in two steps, we
 # can use a database trick to make the upload more efficient.
 if file:
-self._getOb(id).manage_upload(file)
+newFile.manage_upload(file)
 if content_type:
-self._getOb(id).content_type=content_type
-
+newFile.content_type=content_type
+
+notify(ObjectCreatedEvent(newFile))
+
 if REQUEST is not None:
 REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main')
 
@@ -469,6 +477,9 @@
 self.update_data(filedata, content_type, len(filedata))
 else:
 self.ZCacheable_invalidate()
+
+notify(ObjectModifiedEvent(self))
+
 if REQUEST:
 message=Saved changes.
 return self.manage_main(self,REQUEST,manage_tabs_message=message)
@@ -487,7 +498,9 @@
 content_type=self._get_content_type(file, data, self.__name__,
 'application/octet-stream')
 self.update_data(data, content_type, size)
-
+
+notify(ObjectModifiedEvent(self))
+
 if REQUEST:
 message=Saved changes.
 return self.manage_main(self,REQUEST,manage_tabs_message=message)
@@ -665,14 +678,18 @@
 
 # First, we create the image without data:
 self._setObject(id, Image(id,title,'',content_type, precondition))
-
+
+newFile = self._getOb(id)
+
 # Now we upload the data.  By doing this in two steps, we
 # can use a database trick to make the upload more efficient.
 if file:
-self._getOb(id).manage_upload(file)
+newFile.manage_upload(file)
 if content_type:
-self._getOb(id).content_type=content_type
-
+newFile.content_type=content_type
+
+notify(ObjectCreatedEvent(newFile))
+
 if REQUEST is not None:
 try:url=self.DestinationURL()
 except: url=REQUEST['URL1']

Modified: Zope/branches/2.12/src/OFS/tests/testFileAndImage.py
===
--- Zope/branches/2.12/src/OFS/tests/testFileAndImage.py2010-01-11 
22:46:46 UTC (rev 108040)
+++ Zope/branches/2.12/src/OFS/tests/testFileAndImage.py2010-01-12 
00:26:43 UTC (rev 108041)
@@ -8,6 +8,8 @@
 import time
 from cStringIO import StringIO
 
+from Acquisition import aq_base
+
 from OFS.Application import Application
 from OFS.SimpleItem import SimpleItem
 from OFS.Cache import ZCM_MANAGERS
@@ -19,6 +21,12 @@
 from zExceptions import Redirect
 import transaction
 
+import OFS.Image
+
+from zope.component import adapter
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from zope.lifecycleevent.interfaces import IObjectCreatedEvent
+
 try:
 here = os.path.dirname(os.path.abspath(__file__))
 except:
@@ -57,7 +65,7 @@
mtime_func=None):
 self.get = ob
 if self.si:
-return si
+return self.si
 
 def ZCache_invalidate(self, ob):
 self.invalidated = ob
@@ -78,6 +86,38 @@
 def ZCacheManager_getCache(self):
 return ADummyCache
 
+class EventCatcher(object):
+
+def 

[Zope-Checkins] SVN: Zope/trunk/src/OFS/ Merge c108040 from 2.12 branch (OFS File/Image lifecycle events)

2010-01-11 Thread Martin Aspeli
Log message for revision 108042:
  Merge c108040 from 2.12 branch (OFS File/Image lifecycle events)

Changed:
  U   Zope/trunk/src/OFS/Image.py
  U   Zope/trunk/src/OFS/tests/testFileAndImage.py

-=-
Modified: Zope/trunk/src/OFS/Image.py
===
--- Zope/trunk/src/OFS/Image.py 2010-01-12 00:26:43 UTC (rev 108041)
+++ Zope/trunk/src/OFS/Image.py 2010-01-12 00:29:12 UTC (rev 108042)
@@ -46,6 +46,10 @@
 from OFS.PropertyManager import PropertyManager
 from OFS.SimpleItem import Item_w__name__
 
+from zope.event import notify
+from zope.lifecycleevent import ObjectModifiedEvent
+from zope.lifecycleevent import ObjectCreatedEvent
+
 manage_addFileForm = DTMLFile('dtml/imageAdd',
   globals(),
   Kind='File',
@@ -63,19 +67,23 @@
 precondition = str(precondition)
 
 id, title = cookId(id, title, file)
-
+
 self=self.this()
 
 # First, we create the file without data:
 self._setObject(id, File(id,title,'',content_type, precondition))
-
+
+newFile = self._getOb(id)
+
 # Now we upload the data.  By doing this in two steps, we
 # can use a database trick to make the upload more efficient.
 if file:
-self._getOb(id).manage_upload(file)
+newFile.manage_upload(file)
 if content_type:
-self._getOb(id).content_type=content_type
-
+newFile.content_type=content_type
+
+notify(ObjectCreatedEvent(newFile))
+
 if REQUEST is not None:
 REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main')
 
@@ -469,6 +477,9 @@
 self.update_data(filedata, content_type, len(filedata))
 else:
 self.ZCacheable_invalidate()
+
+notify(ObjectModifiedEvent(self))
+
 if REQUEST:
 message=Saved changes.
 return self.manage_main(self,REQUEST,manage_tabs_message=message)
@@ -487,7 +498,9 @@
 content_type=self._get_content_type(file, data, self.__name__,
 'application/octet-stream')
 self.update_data(data, content_type, size)
-
+
+notify(ObjectModifiedEvent(self))
+
 if REQUEST:
 message=Saved changes.
 return self.manage_main(self,REQUEST,manage_tabs_message=message)
@@ -665,14 +678,18 @@
 
 # First, we create the image without data:
 self._setObject(id, Image(id,title,'',content_type, precondition))
-
+
+newFile = self._getOb(id)
+
 # Now we upload the data.  By doing this in two steps, we
 # can use a database trick to make the upload more efficient.
 if file:
-self._getOb(id).manage_upload(file)
+newFile.manage_upload(file)
 if content_type:
-self._getOb(id).content_type=content_type
-
+newFile.content_type=content_type
+
+notify(ObjectCreatedEvent(newFile))
+
 if REQUEST is not None:
 try:url=self.DestinationURL()
 except: url=REQUEST['URL1']

Modified: Zope/trunk/src/OFS/tests/testFileAndImage.py
===
--- Zope/trunk/src/OFS/tests/testFileAndImage.py2010-01-12 00:26:43 UTC 
(rev 108041)
+++ Zope/trunk/src/OFS/tests/testFileAndImage.py2010-01-12 00:29:12 UTC 
(rev 108042)
@@ -8,6 +8,8 @@
 import time
 from cStringIO import StringIO
 
+from Acquisition import aq_base
+
 from OFS.Application import Application
 from OFS.SimpleItem import SimpleItem
 from OFS.Cache import ZCM_MANAGERS
@@ -19,6 +21,12 @@
 from zExceptions import Redirect
 import transaction
 
+import OFS.Image
+
+from zope.component import adapter
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+from zope.lifecycleevent.interfaces import IObjectCreatedEvent
+
 try:
 here = os.path.dirname(os.path.abspath(__file__))
 except:
@@ -57,7 +65,7 @@
mtime_func=None):
 self.get = ob
 if self.si:
-return si
+return self.si
 
 def ZCache_invalidate(self, ob):
 self.invalidated = ob
@@ -78,6 +86,38 @@
 def ZCacheManager_getCache(self):
 return ADummyCache
 
+class EventCatcher(object):
+
+def __init__(self):
+self.created = []
+self.modified = []
+
+self.setUp()
+
+def setUp(self):
+from zope.component import provideHandler
+provideHandler(self.handleCreated)
+provideHandler(self.handleModified)
+
+def tearDown(self):
+from zope.component import getSiteManager
+getSiteManager().unregisterHandler(self.handleCreated)
+getSiteManager().unregisterHandler(self.handleModified)
+
+def reset(self):
+self.created = []
+self.modified = []
+
+@adapter(IObjectCreatedEvent)
+def handleCreated(self, event):
+if isinstance(event.object, OFS.Image.File):
+

[Zope-Checkins] SVN: Zope/branches/2.12/ Fix regression in treatment of trusted code in view page templates.

2009-12-13 Thread Martin Aspeli
Log message for revision 106436:
  Fix regression in treatment of trusted code in view page templates.

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   
Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py
  U   Zope/branches/2.12/src/Products/PageTemplates/Expressions.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2009-12-12 10:58:43 UTC (rev 106435)
+++ Zope/branches/2.12/doc/CHANGES.rst  2009-12-13 09:28:23 UTC (rev 106436)
@@ -27,6 +27,12 @@
 Bugs Fixed
 ++
 
+- Fixed a regression in Products.PageTemplates that meant filesystem templates
+  using Products.Five.browser.pagetemplatefile would treat TALES path
+  expressions (but not python expressions) as protected code and so attempt
+  to apply security. See original issue here:
+  http://codespeak.net/pipermail/z3-five/2007q2/002185.html
+
 - LP #491249:  fix tabindex on ZRDB connection test form.
 
 - LP #490514:  preserve tainting when calling into DTML from ZPT.

Modified: 
Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py
===
--- Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py 
2009-12-12 10:58:43 UTC (rev 106435)
+++ Zope/branches/2.12/src/Products/Five/browser/tests/test_pagetemplatefile.py 
2009-12-13 09:28:23 UTC (rev 106436)
@@ -42,15 +42,15 @@
 from zope.tales.pythonexpr import PythonExpr
 from zope.contentprovider.tales import TALESProviderExpression
 from Products.PageTemplates.DeferExpr import LazyExpr
-from Products.PageTemplates.Expressions import ZopePathExpr
+from Products.PageTemplates.Expressions import TrustedZopePathExpr
 from Products.PageTemplates.Expressions import SecureModuleImporter
 
 vptf = self._makeOne('seagull.pt')
 engine = vptf.pt_getEngine()
-self.assertEqual(engine.types['standard'], ZopePathExpr)
-self.assertEqual(engine.types['path'], ZopePathExpr)
-self.assertEqual(engine.types['exists'], ZopePathExpr)
-self.assertEqual(engine.types['nocall'], ZopePathExpr)
+self.assertEqual(engine.types['standard'], TrustedZopePathExpr)
+self.assertEqual(engine.types['path'], TrustedZopePathExpr)
+self.assertEqual(engine.types['exists'], TrustedZopePathExpr)
+self.assertEqual(engine.types['nocall'], TrustedZopePathExpr)
 self.assertEqual(engine.types['string'], StringExpr)
 self.assertEqual(engine.types['python'], PythonExpr)
 self.assertEqual(engine.types['not'], NotExpr)

Modified: Zope/branches/2.12/src/Products/PageTemplates/Expressions.py
===
--- Zope/branches/2.12/src/Products/PageTemplates/Expressions.py
2009-12-12 10:58:43 UTC (rev 106435)
+++ Zope/branches/2.12/src/Products/PageTemplates/Expressions.py
2009-12-13 09:28:23 UTC (rev 106436)
@@ -79,6 +79,26 @@
  request=request)
 return object
 
+def trustedBoboAwareZopeTraverse(object, path_items, econtext):
+Traverses a sequence of names, first trying attributes then items.
+
+This uses Zope 3 path traversal where possible and interacts
+correctly with objects providing OFS.interface.ITraversable when
+necessary (bobo-awareness).
+
+request = getattr(econtext, 'request', None)
+path_items = list(path_items)
+path_items.reverse()
+
+while path_items:
+name = path_items.pop()
+if OFS.interfaces.ITraversable.providedBy(object):
+object = object.unrestrictedTraverse(name)
+else:
+object = traversePathElement(object, name, path_items,
+ request=request)
+return object
+
 def render(ob, ns):
 Calls the object, possibly a document template, or just returns
 it if not callable.  (From DT_Util.py)
@@ -104,11 +124,13 @@
 
 class ZopePathExpr(PathExpr):
 
+_TRAVERSER = staticmethod(boboAwareZopeTraverse)
+
 def __init__(self, name, expr, engine):
 if not expr.strip():
 expr = 'nothing'
 super(ZopePathExpr, self).__init__(name, expr, engine,
-   boboAwareZopeTraverse)
+   self._TRAVERSER)
 
 # override this to support different call metrics (see bottom of
 # method) and Zope 2's traversal exceptions (ZopeUndefs instead of
@@ -146,6 +168,9 @@
 return 1
 return 0
 
+class TrustedZopePathExpr(ZopePathExpr):
+_TRAVERSER = staticmethod(trustedBoboAwareZopeTraverse)
+
 class SafeMapping(MultiMapping):
 Mapping with security declarations and limited method exposure.
 
@@ -347,11 +372,11 @@
 return False
 return ob1 == ob2
 
-def 

[Zope-Checkins] SVN: Zope/trunk/src/Products/ Merge r106436 from 2.12 branch, fixing a regression in the ZPT engine for trusted code

2009-12-13 Thread Martin Aspeli
Log message for revision 106437:
  Merge r106436 from 2.12 branch, fixing a regression in the ZPT engine for 
trusted code

Changed:
  U   Zope/trunk/src/Products/Five/browser/tests/test_pagetemplatefile.py
  U   Zope/trunk/src/Products/PageTemplates/Expressions.py

-=-
Modified: Zope/trunk/src/Products/Five/browser/tests/test_pagetemplatefile.py
===
--- Zope/trunk/src/Products/Five/browser/tests/test_pagetemplatefile.py 
2009-12-13 09:28:23 UTC (rev 106436)
+++ Zope/trunk/src/Products/Five/browser/tests/test_pagetemplatefile.py 
2009-12-13 09:44:17 UTC (rev 106437)
@@ -42,15 +42,15 @@
 from zope.tales.pythonexpr import PythonExpr
 from zope.contentprovider.tales import TALESProviderExpression
 from Products.PageTemplates.DeferExpr import LazyExpr
-from Products.PageTemplates.Expressions import ZopePathExpr
+from Products.PageTemplates.Expressions import TrustedZopePathExpr
 from Products.PageTemplates.Expressions import SecureModuleImporter
 
 vptf = self._makeOne('seagull.pt')
 engine = vptf.pt_getEngine()
-self.assertEqual(engine.types['standard'], ZopePathExpr)
-self.assertEqual(engine.types['path'], ZopePathExpr)
-self.assertEqual(engine.types['exists'], ZopePathExpr)
-self.assertEqual(engine.types['nocall'], ZopePathExpr)
+self.assertEqual(engine.types['standard'], TrustedZopePathExpr)
+self.assertEqual(engine.types['path'], TrustedZopePathExpr)
+self.assertEqual(engine.types['exists'], TrustedZopePathExpr)
+self.assertEqual(engine.types['nocall'], TrustedZopePathExpr)
 self.assertEqual(engine.types['string'], StringExpr)
 self.assertEqual(engine.types['python'], PythonExpr)
 self.assertEqual(engine.types['not'], NotExpr)

Modified: Zope/trunk/src/Products/PageTemplates/Expressions.py
===
--- Zope/trunk/src/Products/PageTemplates/Expressions.py2009-12-13 
09:28:23 UTC (rev 106436)
+++ Zope/trunk/src/Products/PageTemplates/Expressions.py2009-12-13 
09:44:17 UTC (rev 106437)
@@ -79,6 +79,26 @@
  request=request)
 return object
 
+def trustedBoboAwareZopeTraverse(object, path_items, econtext):
+Traverses a sequence of names, first trying attributes then items.
+
+This uses Zope 3 path traversal where possible and interacts
+correctly with objects providing OFS.interface.ITraversable when
+necessary (bobo-awareness).
+
+request = getattr(econtext, 'request', None)
+path_items = list(path_items)
+path_items.reverse()
+
+while path_items:
+name = path_items.pop()
+if OFS.interfaces.ITraversable.providedBy(object):
+object = object.unrestrictedTraverse(name)
+else:
+object = traversePathElement(object, name, path_items,
+ request=request)
+return object
+
 def render(ob, ns):
 Calls the object, possibly a document template, or just returns
 it if not callable.  (From DT_Util.py)
@@ -104,11 +124,13 @@
 
 class ZopePathExpr(PathExpr):
 
+_TRAVERSER = staticmethod(boboAwareZopeTraverse)
+
 def __init__(self, name, expr, engine):
 if not expr.strip():
 expr = 'nothing'
 super(ZopePathExpr, self).__init__(name, expr, engine,
-   boboAwareZopeTraverse)
+   self._TRAVERSER)
 
 # override this to support different call metrics (see bottom of
 # method) and Zope 2's traversal exceptions (ZopeUndefs instead of
@@ -146,6 +168,9 @@
 return 1
 return 0
 
+class TrustedZopePathExpr(ZopePathExpr):
+_TRAVERSER = staticmethod(trustedBoboAwareZopeTraverse)
+
 class SafeMapping(MultiMapping):
 Mapping with security declarations and limited method exposure.
 
@@ -347,11 +372,11 @@
 return False
 return ob1 == ob2
 
-def createZopeEngine():
+def createZopeEngine(zpe=ZopePathExpr):
 e = ZopeEngine()
 e.iteratorFactory = PathIterator
-for pt in ZopePathExpr._default_type_names:
-e.registerType(pt, ZopePathExpr)
+for pt in zpe._default_type_names:
+e.registerType(pt, zpe)
 e.registerType('string', StringExpr)
 e.registerType('python', ZRPythonExpr.PythonExpr)
 e.registerType('not', NotExpr)
@@ -364,7 +389,7 @@
 def createTrustedZopeEngine():
 # same as createZopeEngine, but use non-restricted Python
 # expression evaluator
-e = createZopeEngine()
+e = createZopeEngine(TrustedZopePathExpr)
 e.types['python'] = PythonExpr
 return e
 

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/branches/2.12/ Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.

2009-11-12 Thread Martin Aspeli
Log message for revision 105589:
  Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.
  This event is fired just before IPubFailure, but, crucially, while the 
transaction is still open.

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/ZPublisher/Publish.py
  U   Zope/branches/2.12/src/ZPublisher/interfaces.py
  U   Zope/branches/2.12/src/ZPublisher/pubevents.py
  U   Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2009-11-12 21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/doc/CHANGES.rst  2009-11-13 05:59:41 UTC (rev 105589)
@@ -11,6 +11,10 @@
 Features Added
 ++
 
+- Added IPubBeforeAbort event to mirror IPubBeforeCommit in failure scenarios.
+  This event is fired just before IPubFailure, but, crucially, while the
+  transaction is still open.
+
 - Include bytes limited cache size in the cache parameters ZMI screen.
 
 - Officially supporting Python 2.6 only (with inofficial support for

Modified: Zope/branches/2.12/src/ZPublisher/Publish.py
===
--- Zope/branches/2.12/src/ZPublisher/Publish.py2009-11-12 21:21:32 UTC 
(rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/Publish.py2009-11-13 05:59:41 UTC 
(rev 105589)
@@ -27,7 +27,7 @@
 from zope.event import notify
 
 from pubevents import PubStart, PubSuccess, PubFailure, \
- PubBeforeCommit, PubAfterTraversal
+ PubBeforeCommit, PubAfterTraversal, PubBeforeAbort
 
 class Retry(Exception):
 Raise this to retry a request
@@ -173,8 +173,12 @@
 )
 retry = True
 finally:
+
 # Note: 'abort's can fail. Nevertheless, we want end request 
handling
 try: 
+
+notify(PubBeforeAbort(request, exc_info, retry))
+
 if transactions_manager:
 transactions_manager.abort()
 finally:
@@ -196,6 +200,9 @@
 else:
 # Note: 'abort's can fail. Nevertheless, we want end request 
handling
 try:
+
+notify(PubBeforeAbort(request, exc_info, False))
+
 if transactions_manager:
 transactions_manager.abort()
 finally:

Modified: Zope/branches/2.12/src/ZPublisher/interfaces.py
===
--- Zope/branches/2.12/src/ZPublisher/interfaces.py 2009-11-12 21:21:32 UTC 
(rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/interfaces.py 2009-11-13 05:59:41 UTC 
(rev 105589)
@@ -41,5 +41,12 @@
 
 class IPubBeforeCommit(IPubEvent):
 notified immediately before the transaction commit (i.e. after the main
-request processing is finished.
+request processing is finished).
 
+
+class IPubBeforeAbort(IPubEvent):
+notified immediately before the transaction abort (i.e. after the main
+request processing is finished, and there was an error).
+
+exc_info = Attribute('''The exception info as returned by 
'sys.exc_info()'.''')
+retry = Attribute('Whether the request will be retried')

Modified: Zope/branches/2.12/src/ZPublisher/pubevents.py
===
--- Zope/branches/2.12/src/ZPublisher/pubevents.py  2009-11-12 21:21:32 UTC 
(rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/pubevents.py  2009-11-13 05:59:41 UTC 
(rev 105589)
@@ -10,7 +10,7 @@
 from zope.interface import implements
 
 from interfaces import IPubStart, IPubSuccess, IPubFailure, \
- IPubAfterTraversal, IPubBeforeCommit
+ IPubAfterTraversal, IPubBeforeCommit, IPubBeforeAbort
 
 class _Base(object):
 PubEvent base class.
@@ -42,3 +42,10 @@
 class PubBeforeCommit(_Base):
 notified immediately before the commit.
 implements(IPubBeforeCommit)
+
+class PubBeforeAbort(_Base):
+notified immediately before an abort.
+implements(IPubBeforeAbort)
+
+def __init__(self, request, exc_info, retry):
+self.request, self.exc_info, self.retry = request, exc_info, retry

Modified: Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py
===
--- Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py2009-11-12 
21:21:32 UTC (rev 105588)
+++ Zope/branches/2.12/src/ZPublisher/tests/testpubevents.py2009-11-13 
05:59:41 UTC (rev 105589)
@@ -8,7 +8,7 @@
 from ZPublisher.Publish import publish, Retry
 from ZPublisher.BaseRequest import BaseRequest
 from ZPublisher.pubevents import PubStart, PubSuccess, PubFailure, \
- PubAfterTraversal, PubBeforeCommit
+ PubAfterTraversal, PubBeforeCommit, 

[Zope-Checkins] SVN: Zope/branches/2.12/src/ZPublisher/Publish.py Be a bit more forceful about aborting the transaction

2009-11-12 Thread Martin Aspeli
Log message for revision 105590:
  Be a bit more forceful about aborting the transaction

Changed:
  U   Zope/branches/2.12/src/ZPublisher/Publish.py

-=-
Modified: Zope/branches/2.12/src/ZPublisher/Publish.py
===
--- Zope/branches/2.12/src/ZPublisher/Publish.py2009-11-13 05:59:41 UTC 
(rev 105589)
+++ Zope/branches/2.12/src/ZPublisher/Publish.py2009-11-13 06:42:23 UTC 
(rev 105590)
@@ -175,12 +175,12 @@
 finally:
 
 # Note: 'abort's can fail. Nevertheless, we want end request 
handling
-try: 
-
-notify(PubBeforeAbort(request, exc_info, retry))
-
-if transactions_manager:
-transactions_manager.abort()
+try: 
+try:
+notify(PubBeforeAbort(request, exc_info, retry))
+finally:
+if transactions_manager:
+transactions_manager.abort()
 finally:
 endInteraction()
 notify(PubFailure(request, exc_info, retry))
@@ -198,19 +198,19 @@
 newrequest.close()
 
 else:
+
 # Note: 'abort's can fail. Nevertheless, we want end request 
handling
-try:
-
-notify(PubBeforeAbort(request, exc_info, False))
-
-if transactions_manager:
-transactions_manager.abort()
+try: 
+try:
+notify(PubBeforeAbort(request, exc_info, False))
+finally:
+if transactions_manager:
+transactions_manager.abort()
 finally:
 endInteraction()
-notify(PubFailure(request, exc_info, False))
+notify(PubFailure(request, exc_info, retry))
 raise
 
-
 def publish_module_standard(module_name,
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,
environ=os.environ, debug=0, request=None, response=None):

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/branches/2.12/ Avoid possible errors on test tear-down in Products.Five.fiveconfigure's cleanUp() function if Products.meta_types has not been set

2009-11-06 Thread Martin Aspeli
Log message for revision 105503:
  Avoid possible errors on test tear-down in Products.Five.fiveconfigure's 
cleanUp() function if Products.meta_types has not been set

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/Products/Five/fiveconfigure.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===
--- Zope/branches/2.12/doc/CHANGES.rst  2009-11-06 06:23:44 UTC (rev 105502)
+++ Zope/branches/2.12/doc/CHANGES.rst  2009-11-06 08:21:09 UTC (rev 105503)
@@ -11,8 +11,9 @@
 Bugs Fixed
 ++
 
+- Avoid possible errors on test tear-down in Products.Five.fiveconfigure's
+  cleanUp() function if Products.meta_types has not been set
 
-
 Zope 2.12.1 (2009/11/02)
 
 

Modified: Zope/branches/2.12/src/Products/Five/fiveconfigure.py
===
--- Zope/branches/2.12/src/Products/Five/fiveconfigure.py   2009-11-06 
06:23:44 UTC (rev 105502)
+++ Zope/branches/2.12/src/Products/Five/fiveconfigure.py   2009-11-06 
08:21:09 UTC (rev 105503)
@@ -225,7 +225,7 @@
 _register_monkies = []
 
 global _meta_type_regs
-Products.meta_types = tuple([ info for info in Products.meta_types
+Products.meta_types = tuple([ info for info in getattr(Products, 
'meta_types', [])
   if info['name'] not in _meta_type_regs ])
 _meta_type_regs = []
 

___
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins


[Zope-Checkins] SVN: Zope/trunk/ Make the set_attributes and set_schema options to class ...require ... //class issue a warning rather than throw an exception. Whilst the concept doesn't make mu

2009-04-13 Thread Martin Aspeli
Log message for revision 99145:
  Make the set_attributes and set_schema options to class ...require ... 
//class issue a warning rather than throw an exception. Whilst the concept 
doesn't make much sense in Zope 2, it's desirable to be able to re-use existing 
packages that do declare such protection

Changed:
  U   Zope/trunk/doc/CHANGES.rst
  U   Zope/trunk/src/Products/Five/metaconfigure.py
  U   Zope/trunk/src/Products/Five/tests/test_security.py

-=-
Modified: Zope/trunk/doc/CHANGES.rst
===
--- Zope/trunk/doc/CHANGES.rst  2009-04-13 02:25:29 UTC (rev 99144)
+++ Zope/trunk/doc/CHANGES.rst  2009-04-13 10:15:12 UTC (rev 99145)
@@ -23,6 +23,11 @@
 Restructuring
 +
 
+- Using require set_schema=... / or require set_attributes=... / in
+  the class / directive now emits a warning rather than an error. The
+  concept of protecting attribute 'set' does not exist in Zope 2, but it
+  should be possible to re-use packages that do declare such protection.
+
 - Updated to DateTime 2.12.0.
 
 - Updated to ZODB 3.9.0a12.

Modified: Zope/trunk/src/Products/Five/metaconfigure.py
===
--- Zope/trunk/src/Products/Five/metaconfigure.py   2009-04-13 02:25:29 UTC 
(rev 99144)
+++ Zope/trunk/src/Products/Five/metaconfigure.py   2009-04-13 10:15:12 UTC 
(rev 99145)
@@ -16,12 +16,11 @@
 $Id$
 
 import warnings
-from zope.configuration.exceptions import ConfigurationError
-from zope.app.component import contentdirective
+from zope.security import metaconfigure
 from App.class_init import InitializeClass
 from Products.Five.security import protectName
 
-class ClassDirective(contentdirective.ClassDirective):
+class ClassDirective(metaconfigure.ClassDirective):
 
 def __protectName(self, name, permission_id):
 self.__context.action(
@@ -30,14 +29,17 @@
 args = (self.__class, name, permission_id)
 )
 
-def __protectSetAttributes(self, attributes, permissions):
-raise ConfigurationError('set_attributes parameter not supported.')
+def __protectSetAttributes(self, names, permission_id):
+warnings.warn(The set_attribute option of the require / directive 
is not supported in Zope 2.  + \
+  Ignored for %s % str(self.__class), stacklevel=3)
 
-def __proctectSetSchema(self, schema, permission):
-raise ConfigurationError('set_schema parameter not supported.')
+def __protectSetSchema(self, schema, permission):
+warnings.warn(The set_schema option of the require / directive is 
not supported in Zope 2.  + \
+  Ignored for %s % str(self.__class), stacklevel=3)
 
 def __mimic(self, _context, class_):
-raise ConfigurationError('like_class parameter not supported.')
+warnings.warn(The like_class option of the require / directive is 
not supported in Zope 2.  + \
+  Ignored for %s % str(self.__class), stacklevel=3)
 
 def __call__(self):
 return self.__context.action(

Modified: Zope/trunk/src/Products/Five/tests/test_security.py
===
--- Zope/trunk/src/Products/Five/tests/test_security.py 2009-04-13 02:25:29 UTC 
(rev 99144)
+++ Zope/trunk/src/Products/Five/tests/test_security.py 2009-04-13 10:15:12 UTC 
(rev 99145)
@@ -18,6 +18,7 @@
 
 from zope.interface import implements
 from zope.interface import Interface
+from zope.schema import TextLine
 from AccessControl.SecurityInfo import ClassSecurityInfo
 
 class ISuperDummy(Interface):
@@ -51,6 +52,16 @@
 security.declarePrivate('baz')
 security.declareProtected('View management screens', 'keg')
 
+class IDummy3(Interface):
+attr = TextLine(title=uAttribute)
+
+class Dummy3:
+implements(IDummy3)
+attr = None
+
+class Dummy4:
+foo = None
+
 def test_security_equivalence():
 This test demonstrates that the traditional declarative security of
 Zope 2 can be replaced by ZCML statements without any loss of
@@ -219,6 +230,56 @@
tearDown()
 
 
+def test_set_warnings():
+This test demonstrates that set_attributes and set_schema will result
+in warnings, not errors. This type of protection doesn't make sense in
+Zope 2, but we want to be able to re-use pure Zope 3 packages that use
+them without error.
+
+   from zope.app.testing.placelesssetup import setUp, tearDown
+   setUp()
+
+Before we can make security declarations through ZCML, we need to
+register the directive and the permission:
+
+   import Products.Five
+   from Products.Five import zcml
+   zcml.load_config('meta.zcml', Products.Five)
+   zcml.load_config('permissions.zcml', Products.Five)
+
+Now we provide some ZCML declarations for ``Dummy1``:
+
+   configure_zcml = '''
+  ... configure xmlns=http://namespaces.zope.org/zope;
+  ...
+  ...   class 

[Zope-Checkins] SVN: Zope/trunk/ Let the permission / directive auto-register permissions that don't exist already

2009-04-13 Thread Martin Aspeli
Log message for revision 99146:
  Let the permission / directive auto-register permissions that don't exist 
already

Changed:
  U   Zope/trunk/doc/CHANGES.rst
  U   Zope/trunk/src/Products/Five/permissions.zcml
  U   Zope/trunk/src/Products/Five/security.py
  U   Zope/trunk/src/Products/Five/tests/test_security.py

-=-
Modified: Zope/trunk/doc/CHANGES.rst
===
--- Zope/trunk/doc/CHANGES.rst  2009-04-13 10:15:12 UTC (rev 99145)
+++ Zope/trunk/doc/CHANGES.rst  2009-04-13 10:46:06 UTC (rev 99146)
@@ -23,6 +23,12 @@
 Restructuring
 +
 
+- If the permission / ZCML directive is used to declare a permission that
+  does not exist, the permission will now be created automatically, defaulting
+  to being granted to the Manager role only. This means it is possible to
+  create new permissions using ZCML only. The permission will Permissions that
+  already exist will not be changed.
+
 - Using require set_schema=... / or require set_attributes=... / in
   the class / directive now emits a warning rather than an error. The
   concept of protecting attribute 'set' does not exist in Zope 2, but it

Modified: Zope/trunk/src/Products/Five/permissions.zcml
===
--- Zope/trunk/src/Products/Five/permissions.zcml   2009-04-13 10:15:12 UTC 
(rev 99145)
+++ Zope/trunk/src/Products/Five/permissions.zcml   2009-04-13 10:46:06 UTC 
(rev 99146)
@@ -1,6 +1,13 @@
 configure xmlns=http://namespaces.zope.org/zope;
i18n_domain=Five
 
+  !-- Create permissions declared in ZCML if they don't exist already --
+  subscriber
+for=zope.security.interfaces.IPermission
+ zope.component.interfaces.IRegistered
+handler=.security.create_permission_from_permission_directive
+/
+
   permission
   id=five.ManageSite
   title=Manage Five local sites

Modified: Zope/trunk/src/Products/Five/security.py
===
--- Zope/trunk/src/Products/Five/security.py2009-04-13 10:15:12 UTC (rev 
99145)
+++ Zope/trunk/src/Products/Five/security.py2009-04-13 10:46:06 UTC (rev 
99146)
@@ -34,7 +34,13 @@
 
 from AccessControl.SecurityInfo import ClassSecurityInfo
 from AccessControl.SecurityManagement import getSecurityManager
+from AccessControl.Permission import _registeredPermissions
+from AccessControl.Permission import pname
 
+import Products
+
+from Globals import ApplicationDefaultPermissions
+
 CheckerPublicId = 'zope.Public'
 CheckerPrivateId = 'zope2.Private'
 
@@ -155,3 +161,21 @@
 # Zope 2 uses string, not unicode yet
 perm = str(permission.title)
 security.declareObjectProtected(perm)
+
+def create_permission_from_permission_directive(permission, event):
+When a new IPermission utility is registered (via the permission /
+directive), create the equivalent Zope2 style permission.
+
+
+global _registeredPermissions
+
+zope2_permission = permission.title
+roles = ('Manager',)
+
+if not _registeredPermissions.has_key(zope2_permission):
+_registeredPermissions[zope2_permission] = 1
+
+Products.__ac_permissions__ += ((zope2_permission, (), roles,),)
+
+mangled = pname(zope2_permission)
+setattr(ApplicationDefaultPermissions, mangled, roles)

Modified: Zope/trunk/src/Products/Five/tests/test_security.py
===
--- Zope/trunk/src/Products/Five/tests/test_security.py 2009-04-13 10:15:12 UTC 
(rev 99145)
+++ Zope/trunk/src/Products/Five/tests/test_security.py 2009-04-13 10:46:06 UTC 
(rev 99146)
@@ -374,6 +374,76 @@
tearDown()
 
 
+def test_register_permission():
+This test demonstrates that if the permission / directive is used
+to create a permission that does not already exist, it is created on 
+startup, with roles defaulting to Manager.
+
+   from zope.app.testing.placelesssetup import setUp, tearDown
+   setUp()
+
+First, we need to configure the relevant parts of Five.
+
+   import Products.Five
+   from Products.Five import zcml
+   zcml.load_config('meta.zcml', Products.Five)
+   zcml.load_config('permissions.zcml', Products.Five)
+
+We can now register a permission in ZCML:
+
+   configure_zcml = '''
+  ... configure xmlns=http://namespaces.zope.org/zope;
+  ...
+  ...   permission
+  ...   id=Products.Five.tests.DummyPermission
+  ...   title=Five: Dummy permission
+  ...   /
+  ...
+  ... /configure
+  ... '''
+   zcml.load_string(configure_zcml)
+  
+The permission will be made available globally, with default role set
+of ('Manager',).
+  
+   from pprint import pprint
+   pprint(self.app.rolesOfPermission('Five: Dummy permission'))
+  [{'name': 'Anonymous', 'selected': ''},
+