[Zope-Checkins] SVN: Zope/branches/2.11/lib/python/Products/PageTemplates/ Launchpad #254570:

Andreas Jung andreas at andreas-jung.com
Sat Aug 16 02:47:53 EDT 2008


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)



More information about the Zope-Checkins mailing list