changeset 7864:b080cdb8b199

fix: document/fix wrapped HtmlProperty method. The wrapped method was not documented in reference.txt. It is now documented in reference.txt. The docstring documented that it would not break up long words. Fixed by adding break_long_words=False to prevent breaking string longer than the wrap length. Wrapping was breaking the hyperlinking of long urls. Added columns argument to set the wrap length (default 80 columns).
author John Rouillard <rouilj@ieee.org>
date Sun, 07 Apr 2024 15:27:18 -0400
parents bd126f890279
children ee586ff074ed
files doc/reference.txt roundup/cgi/templating.py test/test_templating.py
diffstat 3 files changed, 46 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/doc/reference.txt	Sun Apr 07 15:21:00 2024 -0400
+++ b/doc/reference.txt	Sun Apr 07 15:27:18 2024 -0400
@@ -3316,6 +3316,12 @@
 
 		"structure msg/content/hyperlinked"
 
+  wrapped     Wraps long lines on the nearest whitespace. Like
+              plain(), it takes ``escape`` and ``hyperlink``
+              arguments. However, the defaults are to enable both
+              escape and hyperlinks. It also takes a ``columns``
+	      argument set by default to 80.
+ 
   field       render an appropriate form edit field for the property - for
 	      most types this is a text entry box, but for
 	      Booleans it is a
@@ -3337,6 +3343,7 @@
   rst         only on String properties - render the value of the property
 	      as ReStructuredText (requires the :ref:`Docutils
 	      module to be installed separately<install/docutils>`).
+
   stext       only on String properties - render the value of the property
 	      as StructuredText (requires the StructureText module to be
 	      installed separately) (depricated, to be removed
@@ -3347,25 +3354,32 @@
 
   multiline   only on String properties - render a multiline form edit
 	      field for the property
+
   email       only on String properties - render the value of the property
 	      as an obscured email address
+
   url_quote   only on String properties. It quotes any characters in the
 	      string so it is safe to use in a url. E.G. a space is
 	      replaced with %20.
+
   confirm     only on Password properties - render a second form edit field
 	      for the property, used for confirmation that the user typed
 	      the password correctly. Generates a field with name
 	      "name:confirm".
+
   now         only on Date properties - return the current date as a new
 	      property
+
   reldate     only on Date properties - render the interval between the date
 	      and now
+
   local       only on Date properties - return this date as a new property
 	      with some timezone offset, for example::
 
 		  python:context.creation.local(10)
 
 	      will render the date with a +10 hour offset.
+
   pretty      Date properties - render the date as "dd Mon YYYY" (eg. "19
 	      Mar 2004"). Takes an optional format argument, for example::
 
@@ -3382,6 +3396,7 @@
 	      (default: '%0.3f') and formats the number accordingly.
 	      If the value can't be converted, '' is returned if the
 	      value is ``None`` otherwise it is converted to a string.
+
   popcal      Generate a link to a popup calendar which may be used to
 	      edit the date field, for example::
 
@@ -3446,8 +3461,10 @@
 	      ``reverse=True`` the meaning of NoneFirst is inverted:
 	      True sorts None/unset at the end and False sorts at the
 	      beginning.
+
   reverse     only on Multilink properties - produce a list of the linked
 	      items in reverse order
+
   isset       returns True if the property has been set to a value
   =========== ================================================================
 
--- a/roundup/cgi/templating.py	Sun Apr 07 15:21:00 2024 -0400
+++ b/roundup/cgi/templating.py	Sun Apr 07 15:27:18 2024 -0400
@@ -1835,7 +1835,7 @@
             s = self.hyper_re.sub(self._hyper_repl, s)
         return s
 
-    def wrapped(self, escape=1, hyperlink=1):
+    def wrapped(self, escape=1, hyperlink=1, columns=80):
         """Render a "wrapped" representation of the property.
 
         We wrap long lines at 80 columns on the nearest whitespace. Lines
@@ -1847,13 +1847,16 @@
         - "escape" turns on/off HTML quoting
         - "hyperlink" turns on/off in-text hyperlinking of URLs, email
           addresses and designators
+        - "columns" sets the column where the wrapping will occur.
+          Default of 80.
         """
         if not self.is_view_ok():
             return self._('[hidden]')
 
         if self._value is None:
             return ''
-        s = '\n'.join(textwrap.wrap(str(self._value), 80))
+        s = '\n'.join(textwrap.wrap(str(self._value), columns,
+                                    break_long_words=False))
         if escape:
             s = html_escape(s)
         if hyperlink:
--- a/test/test_templating.py	Sun Apr 07 15:21:00 2024 -0400
+++ b/test/test_templating.py	Sun Apr 07 15:27:18 2024 -0400
@@ -450,7 +450,9 @@
                        ' Put in <html> to be escaped. Put in a'
                        ' https://example.com/link as well. Let us see if'
                        ' it will wrap properly.' )
-        test_result = ('A long string that needs to be wrapped to 80'
+
+        test_result_wrap = {}
+        test_result_wrap[80] = ('A long string that needs to be wrapped to 80'
                        ' characters and no more. Put in a\n'
                        'link <a href="issue1">issue1</a>. Put in'
                        ' &lt;html&gt; to be escaped. Put in a <a'
@@ -458,10 +460,30 @@
                        ' rel="nofollow noopener">'
                        'https://example.com/link</a> as\n'
                        'well. Let us see if it will wrap properly.')
+        test_result_wrap[20] = (
+            'A long string that\n'
+            'needs to be wrapped\n'
+            'to 80 characters and\n'
+            'no more. Put in a\nlink <a href="issue1">issue1</a>. Put in\n'
+            '&lt;html&gt; to be\n'
+            'escaped. Put in a\n'
+            '<a href="https://example.com/link" rel="nofollow '
+            'noopener">https://example.com/link</a>\n'
+            'as well. Let us see\n'
+            'if it will wrap\n'
+            'properly.')
+        test_result_wrap[100] = (
+            'A long string that needs to be wrapped to 80 characters and no more. Put in a link <a href="issue1">issue1</a>. Put in\n'
+            '&lt;html&gt; to be escaped. Put in a <a href="https://example.com/link" rel="nofollow noopener">https://example.com/link</a> as well. Let us see if it will wrap\n'
+            'properly.')
 
         p = StringHTMLProperty(self.client, 'test', '1', None, 'test',
                                test_string)
-        self.assertEqual(p.wrapped(), test_result)
+
+        for i in [80, 20, 100]:
+            wrapped = p.wrapped(columns=i)
+            print(wrapped)
+            self.assertEqual(wrapped, test_result_wrap[i])
 
     def test_string_plain_or_hyperlinked(self):
         ''' test that email obscures the email '''

Roundup Issue Tracker: http://roundup-tracker.org/