Log message for revision 89904: Launchpad #254570: the PreferredCharset resolver now deals with situations where 'context' has no REQUEST attribute
Changed: U Zope/branches/2.11/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py U Zope/branches/2.11/lib/python/Products/PageTemplates/unicodeconflictresolver.py -=- Modified: Zope/branches/2.11/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py =================================================================== --- Zope/branches/2.11/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py 2008-08-16 05:50:04 UTC (rev 89903) +++ Zope/branches/2.11/lib/python/Products/PageTemplates/tests/testZopePageTemplate.py 2008-08-16 06:47:53 UTC (rev 89904) @@ -18,11 +18,14 @@ 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 +from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate +from Products.PageTemplates.ZopePageTemplate import manage_addPageTemplate +from Products.PageTemplates.utils import encodingFromXMLPreamble +from Products.PageTemplates.utils import charsetFromMetaEquiv from zope.component import provideUtility from Products.PageTemplates.interfaces import IUnicodeEncodingConflictResolver -from Products.PageTemplates.unicodeconflictresolver import PreferredCharsetResolver +from Products.PageTemplates.unicodeconflictresolver \ + import PreferredCharsetResolver ascii_str = '<html><body>hello world</body></html>' @@ -50,7 +53,8 @@ ''' 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_utf8_w_header = unicode(html_template_w_header, + 'iso-8859-15').encode('utf-8') % 'utf-8' html_template_wo_header = ''' <html> @@ -61,9 +65,23 @@ ''' 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') +html_utf8_wo_header = unicode(html_template_wo_header, + 'iso-8859-15').encode('utf-8') +xml_with_upper_attr = '''<?xml version="1.0"?> +<foo> + <bar ATTR="1" /> +</foo> +''' +html_with_upper_attr = '''<html><body> +<foo> + <bar ATTR="1" /> +</foo> +</body></html> +''' + + installProduct('PageTemplates') class ZPTUtilsTests(unittest.TestCase): @@ -71,16 +89,32 @@ 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') + 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><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) @@ -89,57 +123,73 @@ def afterSetUp(self): zope.component.provideAdapter(DefaultTraversable, (None,)) zope.component.provideAdapter(HTTPCharsets, (None,)) - provideUtility(PreferredCharsetResolver, IUnicodeEncodingConflictResolver) + provideUtility(PreferredCharsetResolver, + IUnicodeEncodingConflictResolver) def testISO_8859_15(self): manage_addPageTemplate(self.app, 'test', - text='<div tal:content="python: request.get(\'data\')" />', + text=('<div tal:content="python: ' + 'request.get(\'data\')" />'), encoding='ascii') zpt = self.app['test'] self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'ISO-8859-15,utf-8') self.app.REQUEST.set('data', 'üöä') result = zpt.pt_render() - self.assertEqual(result.startswith(unicode('<div>üöä</div>', 'iso-8859-15')), True) + self.failUnless(result.startswith(unicode('<div>üöä</div>', + 'iso-8859-15'))) def testUTF8(self): manage_addPageTemplate(self.app, 'test', - text='<div tal:content="python: request.get(\'data\')" />', + text=('<div tal:content="python: ' + 'request.get(\'data\')" />'), encoding='ascii') zpt = self.app['test'] self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'utf-8,ISO-8859-15') - self.app.REQUEST.set('data', unicode('üöä', 'iso-8859-15').encode('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) + self.failUnless(result.startswith(unicode('<div>üöä</div>', + 'iso-8859-15'))) def testUTF8WrongPreferredCharset(self): manage_addPageTemplate(self.app, 'test', - text='<div tal:content="python: request.get(\'data\')" />', + text=('<div tal:content="python: ' + 'request.get(\'data\')" />'), encoding='ascii') zpt = self.app['test'] self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'iso-8859-15') - self.app.REQUEST.set('data', unicode('üöä', 'iso-8859-15').encode('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')), False) + self.failIf(result.startswith(unicode('<div>üöä</div>', + 'iso-8859-15'))) def testStructureWithAccentedChars(self): manage_addPageTemplate(self.app, 'test', - text='<div tal:content="structure python: %s" />' % "'üöä'", + 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')) + 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) + self.failUnless(result.startswith(unicode('<div>üöä</div>', + 'iso-8859-15'))) def testBug151020(self): manage_addPageTemplate(self.app, 'test', - text='<div tal:content="structure python: %s" />' % "'üöä'", + text=('<div tal:content="structure ' + 'python: %s" />' % "'üöä'"), encoding='iso-8859-15') zpt = self.app['test'] - self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', 'x-user-defined, iso-8859-15,utf-8') - self.app.REQUEST.set('data', unicode('üöä', 'iso-8859-15').encode('utf-8')) + self.app.REQUEST.set('HTTP_ACCEPT_CHARSET', + 'x-user-defined, 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) + self.failUnless(result.startswith(unicode('<div>üöä</div>', + 'iso-8859-15'))) def test_bug_198274(self): # See https://bugs.launchpad.net/bugs/198274 @@ -168,8 +218,14 @@ class ZopePageTemplateFileTests(ZopeTestCase): + def test_class_conforms_to_IWriteLock(self): + from zope.interface.verify import verifyClass + from webdav.interfaces import IWriteLock + verifyClass(IWriteLock, ZopePageTemplate) + def testPT_RenderWithAscii(self): - manage_addPageTemplate(self.app, 'test', text=ascii_str, encoding='ascii') + 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 @@ -180,21 +236,25 @@ # Check workaround for unicode incompatibility of ZRPythonExpr. # See http://mail.zope.org/pipermail/zope/2007-February/170537.html manage_addPageTemplate(self.app, 'test', - text='<span tal:content="python: unicode(\'\xfe\', \'iso-8859-15\')" />', + text=('<span tal:content="python: ' + 'unicode(\'\xfe\', \'iso-8859-15\')" />'), encoding='iso-8859-15') zpt = self.app['test'] result = zpt.pt_render() # should not raise a UnicodeDecodeError def testPT_RenderWithISO885915(self): - manage_addPageTemplate(self.app, 'test', text=iso885915_str, encoding='iso-8859-15') + 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.failUnless(result.encode('iso-8859-15' + ).startswith(iso885915_str)) self.assertEqual(zpt.output_encoding, 'iso-8859-15') def testPT_RenderWithUTF8(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'] result = zpt.pt_render() # use startswith() because the renderer appends a trailing \n @@ -218,7 +278,8 @@ self.assertEqual(zpt.read(), xml_unicode) 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'] return zpt @@ -266,6 +327,36 @@ self.assertEqual(zpt.content_type, 'text/xml') result = zpt.pt_render() # should not raise an exception + def testXMLAttrsMustNotBeLowercased(self): + zpt = self._put(xml_with_upper_attr) + self.assertEqual(zpt.content_type, 'text/xml') + result = zpt.pt_render() + self.assertEqual('ATTR' in result, True) + + def testHTMLAttrsAreLowerCased(self): + zpt = self._put(html_with_upper_attr) + self.content_type = 'text/html' + result = zpt.pt_render() + self.assertEqual('ATTR' in result, False) + +class PreferredCharsetUnicodeResolverTests(unittest.TestCase): + + def testPreferredCharsetResolverWithoutRequestAndWithoutEncoding(self): + # This test checks the edgecase where the unicode conflict resolver + # is called with a context object having no REQUEST + context = object() + result = PreferredCharsetResolver.resolve(context, 'üöä', None) + self.assertEqual(result, 'üöä') + + def testPreferredCharsetResolverWithoutRequestAndWithEncoding(self): + # This test checks the edgecase where the unicode conflict resolver + # is called with a context object having no REQUEST + class ContextMock: + management_page_charset = 'iso-8859-15' + result = PreferredCharsetResolver.resolve(ContextMock(), 'üöä', None) + self.assertEqual(result, u'üöä') + + class ZPTRegressions(unittest.TestCase): def setUp(self): @@ -389,6 +480,7 @@ suite.addTests(unittest.makeSuite(ZPTMacros)) suite.addTests(unittest.makeSuite(ZopePageTemplateFileTests)) suite.addTests(unittest.makeSuite(ZPTUnicodeEncodingConflictResolution)) + suite.addTests(unittest.makeSuite(PreferredCharsetUnicodeResolverTests)) return suite if __name__ == '__main__': Modified: Zope/branches/2.11/lib/python/Products/PageTemplates/unicodeconflictresolver.py =================================================================== --- Zope/branches/2.11/lib/python/Products/PageTemplates/unicodeconflictresolver.py 2008-08-16 05:50:04 UTC (rev 89903) +++ Zope/branches/2.11/lib/python/Products/PageTemplates/unicodeconflictresolver.py 2008-08-16 06:47:53 UTC (rev 89904) @@ -62,25 +62,43 @@ def resolve(self, context, text, expression): - request = context.REQUEST + request = getattr(context, 'REQUEST', None) - charsets = getattr(request, '__zpt_available_charsets', None) - if charsets is None: - charsets = IUserPreferredCharsets(request).getPreferredCharsets() + # Deal with the fact that a REQUEST is not always available. + # In this case fall back to the encoding of the ZMI and the + # Python default encoding. - # add management_page_charset as one fallback + if request is None: + charsets = [default_encoding] management_charset = getattr(context, 'management_page_charset', None) if management_charset: - charsets.append(management_charset) + charsets.insert(0, management_charset) + else: + # charsets might by cached within the request + charsets = getattr(request, '__zpt_available_charsets', None) + # No uncached charsets found: investigate the HTTP_ACCEPT_CHARSET + # header. This code is only called if 'context' has a request + # object. The condition is true because otherwise 'charsets' contains + # at least the default encoding of Python. + if charsets is None: + + charsets = list() + # add Python's default encoding as last fallback charsets.append(default_encoding) + # include the charsets based on the HTTP_ACCEPT_CHARSET + # header + charsets = IUserPreferredCharsets(request).getPreferredCharsets() +\ + charsets + # cache list of charsets request.__zpt_available_charsets = charsets for enc in charsets: - if enc == '*': continue + if enc == '*': + continue try: return unicode(text, enc)
_______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins