Commit 76338da2 authored by Andreas Zeidler's avatar Andreas Zeidler

merged r78106:80849 from the zope 2.10 branch

parent ee997b7d
...@@ -8,7 +8,32 @@ Zope Changes ...@@ -8,7 +8,32 @@ Zope Changes
- Backported feature from Zope 2.11 to support named temporary files. - Backported feature from Zope 2.11 to support named temporary files.
Zope 2.10.4 (23.06.2007) Zope 2.10.5 (unreleased)
Bugs fixed
- Launchpad #147201: treat container-class in zope.conf as a string,
making it possible to use types from extra products directories.
- Collector #2358: backported fix making 'Products' package a real
"namespace package" from the trunk.
- Collector #2287: form ':record' objects did not implement enough of
the mapping interface.
- Collector #2352: fix in OFS.Traversable
- Collector #2346: username logging in FCGI crashed the server
- ZopePageTemplate's pt_edit did not recognize content type arguments
which had a charset information included.
- Collector #2332: SessionDataManger: don't swallow ConflictErrors
- Collector #2339: ZPT: fixed unicode issue when using the 'structure'
directive
Zope 2.10.4 (2007/06/23)
Other changes Other changes
...@@ -16,6 +41,8 @@ Zope Changes ...@@ -16,6 +41,8 @@ Zope Changes
- updated to Zope 3.3.2 - updated to Zope 3.3.2
- updated to Five 1.5.5
Bugs fixed Bugs fixed
- Collector #1306: Missing acquisition context on local roles screen. - Collector #1306: Missing acquisition context on local roles screen.
......
...@@ -44,6 +44,10 @@ a.strong-link { ...@@ -44,6 +44,10 @@ a.strong-link {
color: #000099; color: #000099;
} }
a img {
border: 0;
}
p { p {
font-family: Verdana, Helvetica, sans-serif; font-family: Verdana, Helvetica, sans-serif;
font-size: 10pt; font-size: 10pt;
......
...@@ -634,9 +634,10 @@ def install_products(app): ...@@ -634,9 +634,10 @@ def install_products(app):
folder_permissions, raise_exc=debug_mode) folder_permissions, raise_exc=debug_mode)
# Delayed install of packages-as-products # Delayed install of packages-as-products
for module, init_func in Products._packages_to_initialize: for module, init_func in getattr(Products, '_packages_to_initialize', []):
install_package(app, module, init_func, raise_exc=debug_mode) install_package(app, module, init_func, raise_exc=debug_mode)
Products._packages_to_initialize = [] if hasattr(Products, '_packages_to_initialize'):
del Products._packages_to_initialize
Products.meta_types=Products.meta_types+tuple(meta_types) Products.meta_types=Products.meta_types+tuple(meta_types)
InitializeClass(Folder.Folder) InitializeClass(Folder.Folder)
......
...@@ -186,10 +186,9 @@ class Traversable: ...@@ -186,10 +186,9 @@ class Traversable:
bobo_traverse = getattr(obj, '__bobo_traverse__', None) bobo_traverse = getattr(obj, '__bobo_traverse__', None)
try: try:
if name and name[:1] in '@+' and name != '+': if name and name[:1] in '@+' and name != '+' and nsParse(name)[1]:
# Process URI segment parameters. # Process URI segment parameters.
ns, nm = nsParse(name) ns, nm = nsParse(name)
if ns:
try: try:
next = namespaceLookup( next = namespaceLookup(
ns, nm, obj, self.REQUEST).__of__(obj) ns, nm, obj, self.REQUEST).__of__(obj)
...@@ -198,6 +197,7 @@ class Traversable: ...@@ -198,6 +197,7 @@ class Traversable:
raise Unauthorized(name) raise Unauthorized(name)
except TraversalError: except TraversalError:
raise AttributeError(name) raise AttributeError(name)
elif bobo_traverse is not None: elif bobo_traverse is not None:
next = bobo_traverse(REQUEST, name) next = bobo_traverse(REQUEST, name)
if restricted: if restricted:
......
import unittest import unittest
class TestApplication(unittest.TestCase): class ApplicationTests(unittest.TestCase):
def test_z3interfaces(self): def _getTargetClass(self):
from OFS.interfaces import IApplication
from OFS.Application import Application from OFS.Application import Application
return Application
def _makeOne(self):
return self._getTargetClass()()
def test_class_provides_IApplication(self):
from OFS.interfaces import IApplication
from zope.interface.verify import verifyClass from zope.interface.verify import verifyClass
verifyClass(IApplication, Application) verifyClass(IApplication, self._getTargetClass())
def test_instance_conforms_to_IApplication(self):
from OFS.interfaces import IApplication
from zope.interface.verify import verifyObject
verifyObject(IApplication, self._makeOne())
def test_instance_attributes(self):
app = self._makeOne()
self.failUnless(app.isTopLevelPrincipiaApplicationObject)
self.assertEqual(app.title, 'Zope')
def test_id_no_request(self):
app = self._makeOne()
self.assertEqual(app.id(), 'Zope')
def test_id_w_request_no_SCRIPT_NAME(self):
app = self._makeOne()
app.REQUEST = {}
self.assertEqual(app.id(), 'Zope')
def test_id_w_request_w_SCRIPT_NAME(self):
app = self._makeOne()
app.REQUEST = {'SCRIPT_NAME': '/Dummy'}
self.assertEqual(app.id(), 'Dummy')
def test_title_and_id_plus_title_or_id(self):
app = self._makeOne()
app.title = 'Other'
self.assertEqual(app.title_and_id(), 'Other')
self.assertEqual(app.title_or_id(), 'Other')
def test___bobo_traverse__attribute_hit(self):
app = self._makeOne()
app.NAME = 'attribute'
app._getOb = lambda x, y: x
request = {}
self.assertEqual(app.__bobo_traverse__(request, 'NAME'), 'attribute')
def test___bobo_traverse__attribute_miss_key_hit(self):
app = self._makeOne()
app._getOb = lambda x, y: x
request = {}
self.assertEqual(app.__bobo_traverse__(request, 'OTHER'), 'OTHER')
def test___bobo_traverse__attribute_key_miss_R_M_default_real_request(self):
from UserDict import UserDict
request = UserDict()
class _Response:
def notFoundError(self, msg):
1/0
request.RESPONSE = _Response()
app = self._makeOne()
app._getOb = _noWay
self.assertRaises(ZeroDivisionError,
app.__bobo_traverse__, request, 'NONESUCH')
def test___bobo_traverse__attribute_key_miss_R_M_default_fake_request(self):
app = self._makeOne()
app._getOb = _noWay
request = {}
self.assertRaises(KeyError, app.__bobo_traverse__, request, 'NONESUCH')
def test___bobo_traverse__attribute_key_miss_R_M_is_GET(self):
app = self._makeOne()
app._getOb = _noWay
request = {'REQUEST_METHOD': 'GET'}
self.assertRaises(KeyError, app.__bobo_traverse__, request, 'NONESUCH')
def test___bobo_traverse__attribute_key_miss_R_M_not_GET_POST(self):
from Acquisition import aq_inner, aq_parent
from webdav.NullResource import NullResource
app = self._makeOne()
app._getOb = _noWay
request = {'REQUEST_METHOD': 'GOOFY'}
result = app.__bobo_traverse__(request, 'OTHER')
self.failUnless(isinstance(result, NullResource))
self.failUnless(aq_parent(aq_inner(result)) is app)
def _noWay(self, key, default=None):
raise KeyError(key)
def test_suite(): def test_suite():
return unittest.TestSuite(( return unittest.TestSuite((
unittest.makeSuite(TestApplication), unittest.makeSuite(ApplicationTests),
)) ))
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -169,6 +169,7 @@ class TestTraverse( unittest.TestCase ): ...@@ -169,6 +169,7 @@ class TestTraverse( unittest.TestCase ):
self.app = makerequest( self.root, stdout=responseOut ) self.app = makerequest( self.root, stdout=responseOut )
manage_addFolder( self.app, 'folder1' ) manage_addFolder( self.app, 'folder1' )
folder1 = getattr( self.app, 'folder1' ) folder1 = getattr( self.app, 'folder1' )
setattr(folder1, '+something', 'plus')
folder1.all_meta_types = \ folder1.all_meta_types = \
( { 'name' : 'File' ( { 'name' : 'File'
...@@ -379,6 +380,10 @@ class TestTraverse( unittest.TestCase ): ...@@ -379,6 +380,10 @@ class TestTraverse( unittest.TestCase ):
aq_base(self.root.folder1.file.restrictedTraverse('../..')) is aq_base(self.root.folder1.file.restrictedTraverse('../..')) is
aq_base(self.root)) aq_base(self.root))
def testTraverseToNameStartingWithPlus(self):
# Verify it's possible to traverse to a name such as +something
self.failUnless(
self.folder1.unrestrictedTraverse('+something') is 'plus')
import os, sys import os, sys
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -217,11 +217,19 @@ class ZopeContext(Context): ...@@ -217,11 +217,19 @@ class ZopeContext(Context):
return value return value
return bool(value) return bool(value)
def evaluateStructure(self, expr):
text = super(ZopeContext, self).evaluateStructure(expr)
return self._handleText(text, expr)
def evaluateText(self, expr): def evaluateText(self, expr):
""" customized version in order to get rid of unicode """ customized version in order to get rid of unicode
errors for all and ever errors for all and ever
""" """
text = self.evaluate(expr) text = self.evaluate(expr)
return self._handleText(text, expr)
def _handleText(self, text, expr):
if text is self.getDefault() or text is None: if text is self.getDefault() or text is None:
# XXX: should be unicode??? # XXX: should be unicode???
......
...@@ -126,7 +126,7 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable, ...@@ -126,7 +126,7 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
encoding = None encoding = None
output_encoding = None output_encoding = None
if content_type in ('text/xml',): if content_type.startswith('text/xml'):
if is_unicode: if is_unicode:
encoding = None encoding = None
...@@ -135,8 +135,7 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable, ...@@ -135,8 +135,7 @@ class ZopePageTemplate(Script, PageTemplate, Historical, Cacheable,
encoding = encodingFromXMLPreamble(text) encoding = encodingFromXMLPreamble(text)
output_encoding = 'utf-8' output_encoding = 'utf-8'
elif content_type.startswith('text/html'):
elif content_type in ('text/html',) :
charset = charsetFromMetaEquiv(text) charset = charsetFromMetaEquiv(text)
......
...@@ -121,6 +121,16 @@ class ZPTUnicodeEncodingConflictResolution(ZopeTestCase): ...@@ -121,6 +121,16 @@ class ZPTUnicodeEncodingConflictResolution(ZopeTestCase):
result = zpt.pt_render() result = zpt.pt_render()
self.assertEqual(result.startswith(unicode('<div></div>', 'iso-8859-15')), False) self.assertEqual(result.startswith(unicode('<div></div>', 'iso-8859-15')), False)
def testStructureWithAccentedChars(self):
manage_addPageTemplate(self.app, 'test',
text='<div tal:content="structure python: %s" />' % "''",
encoding='iso-8859-15')
zpt = self.app['test']
self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'iso-8859-15,utf-8')
self.app.REQUEST.set('data', unicode('', 'iso-8859-15').encode('utf-8'))
result = zpt.pt_render()
self.assertEqual(result.startswith(unicode('<div></div>', 'iso-8859-15')), True)
class ZopePageTemplateFileTests(ZopeTestCase): class ZopePageTemplateFileTests(ZopeTestCase):
...@@ -165,6 +175,14 @@ class ZopePageTemplateFileTests(ZopeTestCase): ...@@ -165,6 +175,14 @@ class ZopePageTemplateFileTests(ZopeTestCase):
self.assertEqual(zpt.read(), s) self.assertEqual(zpt.read(), s)
self.assertEqual(isinstance(zpt.read(), unicode), True) self.assertEqual(isinstance(zpt.read(), unicode), True)
def testEditWithContentTypeCharset(self):
manage_addPageTemplate(self.app, 'test', xml_utf8, encoding='utf-8')
zpt = self.app['test']
xml_unicode = unicode(xml_utf8, 'utf-8').strip()
zpt.pt_edit(xml_unicode, 'text/xml')
zpt.pt_edit(xml_unicode, 'text/xml; charset=utf-8')
self.assertEqual(zpt.read(), xml_unicode)
def _createZPT(self): def _createZPT(self):
manage_addPageTemplate(self.app, 'test', text=utf8_str, encoding='utf-8') manage_addPageTemplate(self.app, 'test', text=utf8_str, encoding='utf-8')
zpt = self.app['test'] zpt = self.app['test']
......
...@@ -15,6 +15,7 @@ import re, time, sys ...@@ -15,6 +15,7 @@ import re, time, sys
from logging import getLogger from logging import getLogger
import Globals import Globals
from OFS.SimpleItem import Item from OFS.SimpleItem import Item
from ZODB.POSException import ConflictError
from Acquisition import Implicit, Explicit, aq_base from Acquisition import Implicit, Explicit, aq_base
from Persistence import Persistent from Persistence import Persistent
from AccessControl.Owned import Owned from AccessControl.Owned import Owned
...@@ -219,6 +220,8 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs): ...@@ -219,6 +220,8 @@ class SessionDataManager(Item, Implicit, Persistent, RoleManager, Owned, Tabs):
LOG.debug('External data container at %s in use' % args) LOG.debug('External data container at %s in use' % args)
self._v_wrote_dc_type = 1 self._v_wrote_dc_type = 1
return self.unrestrictedTraverse(self.obpath) return self.unrestrictedTraverse(self.obpath)
except ConflictError:
raise
except: except:
raise SessionDataManagerErr, ( raise SessionDataManagerErr, (
"External session data container '%s' not found." % "External session data container '%s' not found." %
......
...@@ -12,7 +12,9 @@ ...@@ -12,7 +12,9 @@
############################################################################## ##############################################################################
__ac_permissions__=() __ac_permissions__=()
# This is used to keep track of packages which need to be initialized as # See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
# products. These will be processed during the usual product installation try:
# in OFS.Application __import__('pkg_resources').declare_namespace(__name__)
_packages_to_initialize = [] except ImportError:
\ No newline at end of file from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
...@@ -174,7 +174,7 @@ def installPackage(name, quiet=0): ...@@ -174,7 +174,7 @@ def installPackage(name, quiet=0):
'''Installs a registered Python package like a Zope product.''' '''Installs a registered Python package like a Zope product.'''
start = time.time() start = time.time()
if _patched and not _installedPackages.has_key(name): if _patched and not _installedPackages.has_key(name):
for module, init_func in Products._packages_to_initialize: for module, init_func in getattr(Products, '_packages_to_initialize', []):
if module.__name__ == name: if module.__name__ == name:
if not quiet: _print('Installing %s ... ' % module.__name__) if not quiet: _print('Installing %s ... ' % module.__name__)
# We want to fail immediately if a package throws an exception # We want to fail immediately if a package throws an exception
......
...@@ -405,6 +405,7 @@ class TestRequestGarbage1(base.TestCase): ...@@ -405,6 +405,7 @@ class TestRequestGarbage1(base.TestCase):
_sentinel1.append('__del__') _sentinel1.append('__del__')
def afterSetUp(self): def afterSetUp(self):
_sentinel1[:] = []
self.anApp = base.app() self.anApp = base.app()
self.anApp.REQUEST._hold(self.Held()) self.anApp.REQUEST._hold(self.Held())
...@@ -422,6 +423,7 @@ class TestRequestGarbage2(base.TestCase): ...@@ -422,6 +423,7 @@ class TestRequestGarbage2(base.TestCase):
_sentinel2.append('__del__') _sentinel2.append('__del__')
def afterSetUp(self): def afterSetUp(self):
_sentinel2[:] = []
self.app.REQUEST._hold(self.Held()) self.app.REQUEST._hold(self.Held())
def testClearClosesRequest(self): def testClearClosesRequest(self):
...@@ -438,6 +440,7 @@ class TestRequestGarbage3(sandbox.Sandboxed, base.TestCase): ...@@ -438,6 +440,7 @@ class TestRequestGarbage3(sandbox.Sandboxed, base.TestCase):
_sentinel3.append('__del__') _sentinel3.append('__del__')
def afterSetUp(self): def afterSetUp(self):
_sentinel3[:] = []
self.app.REQUEST._hold(self.Held()) self.app.REQUEST._hold(self.Held())
def testClearClosesRequest(self): def testClearClosesRequest(self):
......
...@@ -1533,7 +1533,7 @@ class record: ...@@ -1533,7 +1533,7 @@ class record:
_guarded_writes = 1 _guarded_writes = 1
def __getattr__(self, key, default=None): def __getattr__(self, key, default=None):
if key in ('get', 'keys', 'items', 'values', 'copy', 'has_key'): if key in ('get', 'keys', 'items', 'values', 'copy', 'has_key', '__contains__', '__iter__', '__len__'):
return getattr(self.__dict__, key) return getattr(self.__dict__, key)
raise AttributeError, key raise AttributeError, key
......
...@@ -86,6 +86,28 @@ class RecordTests( unittest.TestCase ): ...@@ -86,6 +86,28 @@ class RecordTests( unittest.TestCase ):
d = eval( r ) d = eval( r )
self.assertEqual( d, record.__dict__ ) self.assertEqual( d, record.__dict__ )
def test_contains(self):
from ZPublisher.HTTPRequest import record
record = record()
record.a = 1
self.assertTrue('a' in record)
def test_iter(self):
from ZPublisher.HTTPRequest import record
record = record()
record.a = 1
record.b = 2
record.c = 3
for k in record:
self.assertTrue(k in ('a','b','c'))
def test_len(self):
from ZPublisher.HTTPRequest import record
record = record()
record.a = 1
record.b = 2
record.c = 3
self.assertEqual(len(record), 3)
class ProcessInputsTests(unittest.TestCase): class ProcessInputsTests(unittest.TestCase):
def _getHTTPRequest(self, env): def _getHTTPRequest(self, env):
......
...@@ -456,18 +456,15 @@ class FCGIChannel(asynchat.async_chat): ...@@ -456,18 +456,15 @@ class FCGIChannel(asynchat.async_chat):
method=self.env['REQUEST_METHOD'] method=self.env['REQUEST_METHOD']
else: else:
method="GET" method="GET"
user_name = '-'
if self.env.has_key('HTTP_AUTHORIZATION'): if self.env.has_key('HTTP_AUTHORIZATION'):
http_authorization=self.env['HTTP_AUTHORIZATION'] http_authorization=self.env['HTTP_AUTHORIZATION']
if string.lower(http_authorization[:6]) == 'basic ': if string.lower(http_authorization[:6]) == 'basic ':
try: decoded=base64.decodestring(http_authorization[6:]) try: decoded=base64.decodestring(http_authorization[6:])
except base64.binascii.Error: decoded='' except base64.binascii.Error: decoded=''
t = string.split(decoded, ':', 1) t = string.split(decoded, ':', 1)
if len(t) < 2: if len(t) >= 2:
user_name = '-'
else:
user_name = t[0] user_name = t[0]
else:
user_name='-'
if self.addr: if self.addr:
self.server.logger.log ( self.server.logger.log (
self.addr[0], self.addr[0],
......
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
</description> </description>
</key> </key>
<key name="container-class" datatype=".python_dotted_path"> <key name="container-class" datatype="string">
<description> <description>
Change the contiainer class a (mounted) database uses on a Change the contiainer class a (mounted) database uses on a
per-database basis to support a different container than a plain per-database basis to support a different container than a plain
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment