[CMF-checkins] SVN: CMF/trunk/C - CMFDefault.Document and CMFDefault.NewsItem: It is now possible to

Jens Vagelpohl jens at dataflake.org
Tue Jun 12 14:17:18 EDT 2007


Log message for revision 76644:
  - CMFDefault.Document and CMFDefault.NewsItem: It is now possible to
    register a utility (ILinebreakNormalizer) that can normalize line
    breaks upon editing or rendering out to FTP.
    (http://www.zope.org/Collectors/CMF/174)
  

Changed:
  U   CMF/trunk/CHANGES.txt
  U   CMF/trunk/CMFCore/interfaces/_tools.py
  U   CMF/trunk/CMFDefault/Document.py
  U   CMF/trunk/CMFDefault/tests/test_Document.py

-=-
Modified: CMF/trunk/CHANGES.txt
===================================================================
--- CMF/trunk/CHANGES.txt	2007-06-12 17:34:03 UTC (rev 76643)
+++ CMF/trunk/CHANGES.txt	2007-06-12 18:17:18 UTC (rev 76644)
@@ -2,6 +2,11 @@
 
   New Features
 
+    - CMFDefault.Document and CMFDefault.NewsItem: It is now possible to
+      register a utility (ILinebreakNormalizer) that can normalize line 
+      breaks upon editing or rendering out to FTP.
+      (http://www.zope.org/Collectors/CMF/174)
+
     - CMFDefault.Document and CMFDefault.NewsItem: Added a format choice for
       ReStructuredText.
       (http://www.zope.org/Collectors/CMF/485)

Modified: CMF/trunk/CMFCore/interfaces/_tools.py
===================================================================
--- CMF/trunk/CMFCore/interfaces/_tools.py	2007-06-12 17:34:03 UTC (rev 76643)
+++ CMF/trunk/CMFCore/interfaces/_tools.py	2007-06-12 18:17:18 UTC (rev 76644)
@@ -1993,3 +1993,33 @@
 
         o Permission:  Private (Python only)
         """
+
+
+class ILinebreakNormalizer(Interface):
+    
+    """ Interface for a utility to normalize line breaks in plain text
+
+    Implementations of this utility may adjust line breaks to conform to
+    any desired type, such as LF or CRLF.
+    """
+
+    def normalizeIncoming(ob, text):
+        """ Normalize line breaks in text pushed into the system
+
+        o ob is the content object receiving the text value
+
+        o text is the text value submitted by the user
+
+        o Permission:  Private (Python only)
+        """
+
+    def normalizeOutgoing(ob, text):
+        """ Normalize line breaks in text emitted by the system
+
+        o ob is the content object rendering the text value
+
+        o text is the text value to be rendered
+
+        o Permission:  Private (Python only)
+        """
+

Modified: CMF/trunk/CMFDefault/Document.py
===================================================================
--- CMF/trunk/CMFDefault/Document.py	2007-06-12 17:34:03 UTC (rev 76643)
+++ CMF/trunk/CMFDefault/Document.py	2007-06-12 18:17:18 UTC (rev 76644)
@@ -30,9 +30,11 @@
     REST_AVAILABLE = False
 from StructuredText.StructuredText import HTML
    
+from zope.component import queryUtility
 from zope.component.factory import Factory
 from zope.interface import implements
 
+from Products.CMFCore.interfaces import ILinebreakNormalizer
 from Products.CMFCore.PortalContent import PortalContent
 from Products.CMFCore.utils import contributorsplitter
 from Products.CMFCore.utils import keywordsplitter
@@ -107,12 +109,22 @@
     def _edit(self, text):
         """ Edit the Document and cook the body.
         """
-        self.text = text
         self._size = len(text)
 
         text_format = self.text_format
         if not text_format:
             text_format = self.text_format
+
+        if text_format != 'html':
+            normalizer = queryUtility(ILinebreakNormalizer)
+            
+            if normalizer is not None:
+                self.text = normalizer.normalizeIncoming(self, text)
+            else:
+                self.text = text
+        else:
+            self.text = text
+            
         if text_format == 'html':
             self.cooked_text = text
         elif text_format == 'plain':
@@ -444,7 +456,14 @@
         else:
             hdrlist = self.getMetadataHeaders()
             hdrtext = formatRFC822Headers( hdrlist )
-            bodytext = '%s\r\n\r\n%s' % ( hdrtext, self.text )
+            normalizer = queryUtility(ILinebreakNormalizer)
+            
+            if normalizer is not None:
+                text = normalizer.normalizeOutgoing(self, self.text)
+            else:
+                text = self.text
+ 
+            bodytext = '%s\r\n\r\n%s' % ( hdrtext, text )
 
         return bodytext
 

Modified: CMF/trunk/CMFDefault/tests/test_Document.py
===================================================================
--- CMF/trunk/CMFDefault/tests/test_Document.py	2007-06-12 17:34:03 UTC (rev 76643)
+++ CMF/trunk/CMFDefault/tests/test_Document.py	2007-06-12 18:17:18 UTC (rev 76644)
@@ -26,8 +26,11 @@
 
 from DocumentTemplate.DT_Util import html_quote
 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
+from zope.component import getSiteManager
+from zope.interface import implements
 from zope.interface.verify import verifyClass
 
+from Products.CMFCore.interfaces import ILinebreakNormalizer
 from Products.CMFCore.testing import ConformsToContent
 from Products.CMFCore.tests.base.content import BASIC_HTML
 from Products.CMFCore.tests.base.content import BASIC_ReST
@@ -62,7 +65,21 @@
     def _makeOne(self, *args, **kw):
         return self._getTargetClass()(*args, **kw)
 
+class DummyLinebreakNormalizer(object):
 
+    implements(ILinebreakNormalizer)
+
+    def __init__(self, before, after):
+        self.before = before
+        self.after = after
+
+    def normalizeIncoming(self, obj, text):
+        return text.replace(self.before, self.after)
+
+    def normalizeOutgoing(self, ob, text):
+        return text.replace(self.before, self.after)
+
+
 class DocumentTests(ConformsToContent, RequestTestBase):
 
     def test_interfaces(self):
@@ -474,7 +491,68 @@
         self.assertEqual( d.Format(), 'text/plain' )
         self.assertEqual( d.text_format, 'structured-text' )
 
+    def test_normalize_linebreaks_incoming(self):
+        # New feature: Line breaks can be normalized on the way in
+        # and on the way out, *if* a specific utility exists.
+        # (http://www.zope.org/Collectors/CMF/174)
+        d = self._makeOne('foo', text='')
+        LF_TEXT = 'This\nis\nsome\ntext'
+        CRLF_TEXT = 'This\r\nis\r\nsome\r\ntext'
 
+        # First case, no normalizer installed. Text will stay the same.
+        d._edit(LF_TEXT)
+        self.assertEquals(d.text, LF_TEXT)
+
+        d._edit(CRLF_TEXT)
+        self.assertEquals(d.text, CRLF_TEXT)
+        
+        # Now register a normalizer that always replaces CRLF with LF
+        # When I pass in CRLFs, the resulting text will only have LFs.
+        crlf_to_lf = DummyLinebreakNormalizer('\r\n', '\n')
+        sm = getSiteManager()
+        sm.registerUtility(crlf_to_lf, ILinebreakNormalizer)
+
+        d._edit(CRLF_TEXT)
+        self.assertEquals(d.text, LF_TEXT)
+
+        d._edit(LF_TEXT)
+        self.assertEquals(d.text, LF_TEXT)
+
+        # cleanup
+        sm.unregisterUtility(crlf_to_lf, ILinebreakNormalizer)
+
+    def test_normalize_linebreaks_outgoing(self):
+        # New feature: Line breaks can be normalized on the way in
+        # and on the way out, *if* a specific utility exists.
+        # (http://www.zope.org/Collectors/CMF/174)
+        d = self._makeOne('foo', text='')
+        LF_TEXT = 'This\nis\nsome\ntext'
+        CRLF_TEXT = 'This\r\nis\r\nsome\r\ntext'
+        HEADERS = """Title: \r\nSubject: \r\nPublisher: No publisher\r\nDescription: \r\nContributors: \r\nEffective_date: None\r\nExpiration_date: None\r\nType: Unknown\r\nFormat: text/plain\r\nLanguage: \r\nRights: \r\nSafetyBelt: \r\n\r\n"""
+
+        # First case, no normalizer installed. Text will stay the same.
+        d.text = LF_TEXT
+        self.assertEquals(d.manage_FTPget(), HEADERS + LF_TEXT)
+
+        d.text = CRLF_TEXT
+        self.assertEquals(d.manage_FTPget(), HEADERS + CRLF_TEXT)
+
+        # Now register a normalizer that always replaces CRLF with LF
+        # When I pass in CRLFs, the resulting text will only have LFs.
+        crlf_to_lf = DummyLinebreakNormalizer('\r\n', '\n')
+        sm = getSiteManager()
+        sm.registerUtility(crlf_to_lf, ILinebreakNormalizer)
+
+        d.text = (CRLF_TEXT)
+        self.assertEquals(d.manage_FTPget(), HEADERS + LF_TEXT)
+
+        d.text = LF_TEXT
+        self.assertEquals(d.manage_FTPget(), HEADERS + LF_TEXT)
+
+        # cleanup
+        sm.unregisterUtility(crlf_to_lf, ILinebreakNormalizer)
+
+
 class DocumentFTPGetTests(RequestTestBase):
 
     def setUp(self):



More information about the CMF-checkins mailing list