summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/Archiver/HyperArch.py1
-rw-r--r--src/mailman/Archiver/pipermail.py2
-rw-r--r--src/mailman/Utils.py134
-rw-r--r--src/mailman/app/moderator.py1
-rw-r--r--src/mailman/app/notifications.py2
-rw-r--r--src/mailman/bin/config_list.py10
-rw-r--r--src/mailman/bin/import.py2
-rw-r--r--src/mailman/bin/set_members.py1
-rw-r--r--src/mailman/chains/hold.py3
-rw-r--r--src/mailman/pipeline/calculate_recipients.py4
-rw-r--r--src/mailman/pipeline/replybot.py5
-rw-r--r--src/mailman/queue/archive.py2
-rw-r--r--src/mailman/queue/bounce.py2
-rw-r--r--src/mailman/queue/digest.py3
-rw-r--r--src/mailman/queue/maildir.py4
-rw-r--r--src/mailman/utilities/i18n.py6
-rw-r--r--src/mailman/utilities/string.py93
-rw-r--r--src/mailman/utilities/tests/test_templates.py10
-rw-r--r--src/mailman/utilities/tests/test_wrap.py151
19 files changed, 263 insertions, 173 deletions
diff --git a/src/mailman/Archiver/HyperArch.py b/src/mailman/Archiver/HyperArch.py
index 92b9de2f0..646608590 100644
--- a/src/mailman/Archiver/HyperArch.py
+++ b/src/mailman/Archiver/HyperArch.py
@@ -44,7 +44,6 @@ from lazr.config import as_boolean
from string import Template
from zope.component import getUtility
-from mailman import Utils
from mailman.Archiver import HyperDatabase
from mailman.Archiver import pipermail
from mailman.config import config
diff --git a/src/mailman/Archiver/pipermail.py b/src/mailman/Archiver/pipermail.py
index f47600eb1..e11cb7173 100644
--- a/src/mailman/Archiver/pipermail.py
+++ b/src/mailman/Archiver/pipermail.py
@@ -10,7 +10,7 @@ import mailbox
import cPickle as pickle
from cStringIO import StringIO
-from email.Utils import parseaddr, parsedate_tz, mktime_tz, formatdate
+from email.utils import parseaddr, parsedate_tz, mktime_tz, formatdate
from string import lowercase
__version__ = '0.11 (Mailman edition)'
diff --git a/src/mailman/Utils.py b/src/mailman/Utils.py
deleted file mode 100644
index cfd61eb7a..000000000
--- a/src/mailman/Utils.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Miscellaneous essential routines.
-
-This includes actual message transmission routines, address checking and
-message and address munging, a handy-dandy routine to map a function on all
-the mailing lists, and whatever else doesn't belong elsewhere.
-"""
-
-from __future__ import absolute_import, unicode_literals
-
-__metaclass__ = type
-__all__ = [
- ]
-
-
-import os
-import re
-import logging
-
-# pylint: disable-msg=E0611,W0403
-from string import ascii_letters, digits, whitespace
-
-import mailman.templates
-
-
-AT = '@'
-CR = '\r'
-DOT = '.'
-EMPTYSTRING = ''
-IDENTCHARS = ascii_letters + digits + '_'
-NL = '\n'
-UEMPTYSTRING = u''
-TEMPLATE_DIR = os.path.dirname(mailman.templates.__file__)
-
-# Search for $(identifier)s strings, except that the trailing s is optional,
-# since that's a common mistake
-cre = re.compile(r'%\(([_a-z]\w*?)\)s?', re.IGNORECASE)
-# Search for $$, $identifier, or ${identifier}
-dre = re.compile(r'(\${2})|\$([_a-z]\w*)|\${([_a-z]\w*)}', re.IGNORECASE)
-
-log = logging.getLogger('mailman.error')
-
-
-
-# A much more naive implementation than say, Emacs's fill-paragraph!
-# pylint: disable-msg=R0912
-def wrap(text, column=70, honor_leading_ws=True):
- """Wrap and fill the text to the specified column.
-
- Wrapping is always in effect, although if it is not possible to wrap a
- line (because some word is longer than `column' characters) the line is
- broken at the next available whitespace boundary. Paragraphs are also
- always filled, unless honor_leading_ws is true and the line begins with
- whitespace. This is the algorithm that the Python FAQ wizard uses, and
- seems like a good compromise.
-
- """
- wrapped = ''
- # first split the text into paragraphs, defined as a blank line
- paras = re.split('\n\n', text)
- for para in paras:
- # fill
- lines = []
- fillprev = False
- for line in para.split(NL):
- if not line:
- lines.append(line)
- continue
- if honor_leading_ws and line[0] in whitespace:
- fillthis = False
- else:
- fillthis = True
- if fillprev and fillthis:
- # if the previous line should be filled, then just append a
- # single space, and the rest of the current line
- lines[-1] = lines[-1].rstrip() + ' ' + line
- else:
- # no fill, i.e. retain newline
- lines.append(line)
- fillprev = fillthis
- # wrap each line
- for text in lines:
- while text:
- if len(text) <= column:
- line = text
- text = ''
- else:
- bol = column
- # find the last whitespace character
- while bol > 0 and text[bol] not in whitespace:
- bol -= 1
- # now find the last non-whitespace character
- eol = bol
- while eol > 0 and text[eol] in whitespace:
- eol -= 1
- # watch out for text that's longer than the column width
- if eol == 0:
- # break on whitespace after column
- eol = column
- while eol < len(text) and text[eol] not in whitespace:
- eol += 1
- bol = eol
- while bol < len(text) and text[bol] in whitespace:
- bol += 1
- bol -= 1
- line = text[:eol+1] + '\n'
- # find the next non-whitespace character
- bol += 1
- while bol < len(text) and text[bol] in whitespace:
- bol += 1
- text = text[bol:]
- wrapped += line
- wrapped += '\n'
- # end while text
- wrapped += '\n'
- # end for text in lines
- # the last two newlines are bogus
- return wrapped[:-2]
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py
index 50a03c833..a2f838934 100644
--- a/src/mailman/app/moderator.py
+++ b/src/mailman/app/moderator.py
@@ -35,7 +35,6 @@ from datetime import datetime
from email.utils import formataddr, formatdate, getaddresses, make_msgid
from zope.component import getUtility
-from mailman import Utils
from mailman.app.membership import add_member, delete_member
from mailman.app.notifications import (
send_admin_subscription_notice, send_welcome_message)
diff --git a/src/mailman/app/notifications.py b/src/mailman/app/notifications.py
index d7e64a020..8bfbd0934 100644
--- a/src/mailman/app/notifications.py
+++ b/src/mailman/app/notifications.py
@@ -30,12 +30,12 @@ __all__ = [
from email.utils import formataddr
from lazr.config import as_boolean
-from mailman.Utils import wrap
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import OwnerNotification, UserNotification
from mailman.interfaces.member import DeliveryMode
from mailman.utilities.i18n import make
+from mailman.utilities.string import wrap
diff --git a/src/mailman/bin/config_list.py b/src/mailman/bin/config_list.py
index 845a1371d..a40f4ee52 100644
--- a/src/mailman/bin/config_list.py
+++ b/src/mailman/bin/config_list.py
@@ -22,10 +22,10 @@ import optparse
from mailman import MailList
from mailman import errors
-from mailman.Utils import wrap
from mailman.configuration import config
from mailman.core.i18n import _
from mailman.initialize import initialize
+from mailman.utilities.string import wrap
from mailman.version import MAILMAN_VERSION
@@ -140,7 +140,7 @@ def do_list_categories(mlist, k, subcat, outfp):
# triple-quoted string nonsense in the source code.
desc = NL.join([s.lstrip() for s in info[0].splitlines()])
# Print out the category description
- desc = Utils.wrap(desc)
+ desc = wrap(desc)
for line in desc.splitlines():
print >> outfp, '#', line
print >> outfp
@@ -162,7 +162,7 @@ def do_list_categories(mlist, k, subcat, outfp):
desc = re.sub('&lt;', '<', desc)
desc = re.sub('&gt;', '>', desc)
# Print out the variable description.
- desc = Utils.wrap(desc)
+ desc = wrap(desc)
for line in desc.split('\n'):
print >> outfp, '#', line
# munge the value based on its type
@@ -246,8 +246,8 @@ def do_input(listname, infile, checkonly, verbose, parser):
# Open the specified list locked, unless checkonly is set
try:
mlist = MailList.MailList(listname, lock=not checkonly)
- except errors.MMListError, e:
- parser.error(_('No such list "$listname"\n$e'))
+ except errors.MMListError as error:
+ parser.error(_('No such list "$listname"\n$error'))
savelist = False
guibyprop = getPropertyMap(mlist)
try:
diff --git a/src/mailman/bin/import.py b/src/mailman/bin/import.py
index d4173aef2..7ed2d830e 100644
--- a/src/mailman/bin/import.py
+++ b/src/mailman/bin/import.py
@@ -18,7 +18,6 @@
"""Import the XML representation of a mailing list."""
import sys
-import codecs
import optparse
import traceback
@@ -27,7 +26,6 @@ from xml.parsers.expat import ExpatError
from mailman import Defaults
from mailman import MemberAdaptor
-from mailman import Utils
from mailman import passwords
from mailman.MailList import MailList
from mailman.core.i18n import _
diff --git a/src/mailman/bin/set_members.py b/src/mailman/bin/set_members.py
index 15ebeb29a..ef65d1b45 100644
--- a/src/mailman/bin/set_members.py
+++ b/src/mailman/bin/set_members.py
@@ -20,7 +20,6 @@ import optparse
from zope.component import getUtility
-from mailman import Message
from mailman import Utils
from mailman import passwords
from mailman.app.membership import add_member
diff --git a/src/mailman/chains/hold.py b/src/mailman/chains/hold.py
index fcd11ca72..7b78f118e 100644
--- a/src/mailman/chains/hold.py
+++ b/src/mailman/chains/hold.py
@@ -35,7 +35,6 @@ from zope.component import getUtility
from zope.event import notify
from zope.interface import implements
-from mailman.Utils import wrap
from mailman.app.moderator import hold_message
from mailman.app.replybot import can_acknowledge
from mailman.chains.base import ChainNotification, TerminalChainBase
@@ -47,7 +46,7 @@ from mailman.interfaces.languages import ILanguageManager
from mailman.interfaces.pending import IPendable, IPendings
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.i18n import make
-from mailman.utilities.string import oneline
+from mailman.utilities.string import oneline, wrap
log = logging.getLogger('mailman.vette')
diff --git a/src/mailman/pipeline/calculate_recipients.py b/src/mailman/pipeline/calculate_recipients.py
index 36f391fd0..d2527e608 100644
--- a/src/mailman/pipeline/calculate_recipients.py
+++ b/src/mailman/pipeline/calculate_recipients.py
@@ -32,12 +32,12 @@ __all__ = [
from zope.interface import implements
-from mailman import Utils
from mailman.config import config
from mailman.core import errors
from mailman.core.i18n import _
from mailman.interfaces.handler import IHandler
from mailman.interfaces.member import DeliveryStatus
+from mailman.utilities.string import wrap
@@ -89,7 +89,7 @@ class CalculateRecipients:
Your urgent message to the $realname mailing list was not authorized for
delivery. The original message as received by Mailman is attached.
""")
- raise errors.RejectMessage(Utils.wrap(text))
+ raise errors.RejectMessage(wrap(text))
# Calculate the regular recipients of the message
recipients = set(member.address.email
for member in mlist.regular_members.members
diff --git a/src/mailman/pipeline/replybot.py b/src/mailman/pipeline/replybot.py
index 5f17160c1..dffffbf47 100644
--- a/src/mailman/pipeline/replybot.py
+++ b/src/mailman/pipeline/replybot.py
@@ -30,7 +30,6 @@ import logging
from zope.component import getUtility
from zope.interface import implements
-from mailman import Utils
from mailman.core.i18n import _
from mailman.email.message import UserNotification
from mailman.interfaces.autorespond import (
@@ -38,7 +37,7 @@ from mailman.interfaces.autorespond import (
from mailman.interfaces.handler import IHandler
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.datetime import today
-from mailman.utilities.string import expand
+from mailman.utilities.string import expand, wrap
log = logging.getLogger('mailman.error')
@@ -113,7 +112,7 @@ class Replybot:
owneremail = mlist.owner_address,
)
# Interpolation and Wrap the response text.
- text = Utils.wrap(expand(response_text, d))
+ text = wrap(expand(response_text, d))
outmsg = UserNotification(msg.sender, mlist.bounces_address,
subject, text, mlist.preferred_language)
outmsg['X-Mailer'] = _('The Mailman Replybot')
diff --git a/src/mailman/queue/archive.py b/src/mailman/queue/archive.py
index 24dab34f5..99682f310 100644
--- a/src/mailman/queue/archive.py
+++ b/src/mailman/queue/archive.py
@@ -27,7 +27,7 @@ import os
import logging
from datetime import datetime
-from email.Utils import parsedate_tz, mktime_tz, formatdate
+from email.utils import parsedate_tz, mktime_tz, formatdate
from flufl.lock import Lock
from lazr.config import as_timedelta
diff --git a/src/mailman/queue/bounce.py b/src/mailman/queue/bounce.py
index a53b2d072..968659352 100644
--- a/src/mailman/queue/bounce.py
+++ b/src/mailman/queue/bounce.py
@@ -23,7 +23,7 @@ import cPickle
import logging
import datetime
-from email.Utils import parseaddr
+from email.utils import parseaddr
from lazr.config import as_timedelta
from mailman.config import config
diff --git a/src/mailman/queue/digest.py b/src/mailman/queue/digest.py
index 2541e14ed..075335158 100644
--- a/src/mailman/queue/digest.py
+++ b/src/mailman/queue/digest.py
@@ -38,7 +38,6 @@ from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formatdate, getaddresses, make_msgid
-from mailman.Utils import wrap
from mailman.config import config
from mailman.core.errors import DiscardMessage
from mailman.core.i18n import _
@@ -48,7 +47,7 @@ from mailman.pipeline.scrubber import process as scrubber
from mailman.queue import Runner
from mailman.utilities.i18n import make
from mailman.utilities.mailbox import Mailbox
-from mailman.utilities.string import oneline
+from mailman.utilities.string import oneline, wrap
diff --git a/src/mailman/queue/maildir.py b/src/mailman/queue/maildir.py
index 3d0b9497c..fe4dc9da1 100644
--- a/src/mailman/queue/maildir.py
+++ b/src/mailman/queue/maildir.py
@@ -53,8 +53,8 @@ import os
import errno
import logging
-from email.Parser import Parser
-from email.Utils import parseaddr
+from email.parser import Parser
+from email.utils import parseaddr
from mailman.config import config
from mailman.message import Message
diff --git a/src/mailman/utilities/i18n.py b/src/mailman/utilities/i18n.py
index afaf26bc0..8e769329c 100644
--- a/src/mailman/utilities/i18n.py
+++ b/src/mailman/utilities/i18n.py
@@ -31,15 +31,11 @@ import os
import errno
from itertools import product
-from zope.component import getUtility
from mailman.config import config
from mailman.core.constants import system_preferences
from mailman.core.i18n import _
-from mailman.interfaces.languages import ILanguageManager
-from mailman.utilities.string import expand
-
-from mailman.Utils import wrap as wrap_text
+from mailman.utilities.string import expand, wrap as wrap_text
diff --git a/src/mailman/utilities/string.py b/src/mailman/utilities/string.py
index 3eda0dc39..9054ed076 100644
--- a/src/mailman/utilities/string.py
+++ b/src/mailman/utilities/string.py
@@ -25,6 +25,7 @@ __all__ = [
'oneline',
'uncanonstr',
'websafe',
+ 'wrap',
]
@@ -33,14 +34,15 @@ import logging
from email.errors import HeaderParseError
from email.header import decode_header, make_header
-from string import Template
+from string import Template, whitespace
+from textwrap import TextWrapper, dedent
from zope.component import getUtility
from mailman.interfaces.languages import ILanguageManager
EMPTYSTRING = ''
-UEMPTYSTRING = u''
+NL = '\n'
log = logging.getLogger('mailman.error')
@@ -91,7 +93,7 @@ def oneline(s, cset='us-ascii', in_unicode=False):
try:
h = make_header(decode_header(s))
ustr = h.__unicode__()
- line = UEMPTYSTRING.join(ustr.splitlines())
+ line = EMPTYSTRING.join(ustr.splitlines())
if in_unicode:
return line
else:
@@ -138,3 +140,88 @@ def uncanonstr(s, lang=None):
a.append(c)
# Join characters together and coerce to byte string
return str(EMPTYSTRING.join(a))
+
+
+
+def wrap(text, column=70, honor_leading_ws=True):
+ """Wrap and fill the text to the specified column.
+
+ The input text is wrapped and filled as done by the standard library
+ textwrap module. The differences here being that this function is capable
+ of filling multiple paragraphs (as defined by text separated by blank
+ lines). Also, when `honor_leading_ws` is True (the default), paragraphs
+ that being with whitespace are not wrapped. This is the algorithm that
+ the Python FAQ wizard used.
+ """
+ # First, split the original text into paragraph, keeping all blank lines
+ # between them.
+ paragraphs = []
+ paragraph = []
+ last_indented = False
+ for line in text.splitlines(True):
+ is_indented = (len(line) > 0 and line[0] in whitespace)
+ if line == NL:
+ if len(paragraph) > 0:
+ paragraphs.append(EMPTYSTRING.join(paragraph))
+ paragraphs.append(line)
+ last_indented = False
+ paragraph = []
+ elif last_indented != is_indented:
+ # The indentation level changed. We treat this as a paragraph
+ # break but no blank line will be issued between paragraphs.
+ if len(paragraph) > 0:
+ paragraphs.append(EMPTYSTRING.join(paragraph))
+ # The next paragraph starts with this line.
+ paragraph = [line]
+ last_indented = is_indented
+ else:
+ # This line does not constitute a paragraph break.
+ paragraph.append(line)
+ # We've consumed all the lines in the original text. Transfer the last
+ # paragraph we were collecting to the full set of paragraphs.
+ paragraphs.append(EMPTYSTRING.join(paragraph))
+ # Now iterate through all paragraphs, wrapping as necessary.
+ wrapped_paragraphs = []
+ # The dedented wrapper.
+ wrapper = TextWrapper(width=column,
+ fix_sentence_endings=True)
+ # The indented wrapper. For this one, we'll clobber initial_indent and
+ # subsequent_indent as needed per indented chunk of text.
+ iwrapper = TextWrapper(width=column,
+ fix_sentence_endings=True,
+ )
+ add_paragraph_break = False
+ for paragraph in paragraphs:
+ if add_paragraph_break:
+ wrapped_paragraphs.append(NL)
+ add_paragraph_break = False
+ paragraph_text = EMPTYSTRING.join(paragraph)
+ # Just copy the blank lines to the final set of paragraphs.
+ if paragraph == NL:
+ wrapped_paragraphs.append(NL)
+ # Choose the wrapper based on whether the paragraph is indented or
+ # not. Also, do not wrap indented paragraphs if honor_leading_ws is
+ # set.
+ elif paragraph[0] in whitespace:
+ if honor_leading_ws:
+ # Leave the indented paragraph verbatim.
+ wrapped_paragraphs.append(paragraph_text)
+ else:
+ # The paragraph should be wrapped, but it must first be
+ # dedented. The leading whitespace on the first line of the
+ # original text will be used as the indentation for all lines
+ # in the wrapped text.
+ for i, ch in enumerate(paragraph_text):
+ if ch not in whitespace:
+ break
+ leading_ws = paragraph[:i]
+ iwrapper.initial_indent=leading_ws
+ iwrapper.subsequent_indent=leading_ws
+ paragraph_text = dedent(paragraph_text)
+ wrapped_paragraphs.append(iwrapper.fill(paragraph_text))
+ add_paragraph_break = True
+ else:
+ # Fill this paragraph. fill() consumes the trailing newline.
+ wrapped_paragraphs.append(wrapper.fill(paragraph_text))
+ add_paragraph_break = True
+ return EMPTYSTRING.join(wrapped_paragraphs)
diff --git a/src/mailman/utilities/tests/test_templates.py b/src/mailman/utilities/tests/test_templates.py
index 2de43ae3c..e21b44544 100644
--- a/src/mailman/utilities/tests/test_templates.py
+++ b/src/mailman/utilities/tests/test_templates.py
@@ -258,17 +258,15 @@ It will not be wrapped.
def test_no_substitutions(self):
self.assertEqual(make('nosub.txt', self.mlist), """\
-This is a global template. It has no substitutions. It will be
-wrapped.
-""")
+This is a global template. It has no substitutions. It will be
+wrapped.""")
def test_substitutions(self):
self.assertEqual(make('subs.txt', self.mlist,
kind='very nice',
howmany='a few'), """\
-This is a very nice template. It has a few substitutions. It will be
-wrapped.
-""")
+This is a very nice template. It has a few substitutions. It will be
+wrapped.""")
def test_substitutions_no_wrap(self):
self.assertEqual(make('nowrap.txt', self.mlist, wrap=False,
diff --git a/src/mailman/utilities/tests/test_wrap.py b/src/mailman/utilities/tests/test_wrap.py
new file mode 100644
index 000000000..2fc6c6ccf
--- /dev/null
+++ b/src/mailman/utilities/tests/test_wrap.py
@@ -0,0 +1,151 @@
+# Copyright (C) 2011 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""Test text wrapping."""
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'test_suite',
+ ]
+
+
+import unittest
+
+from mailman.utilities.string import wrap
+
+
+
+class TestWrap(unittest.TestCase):
+ """Test text wrapping."""
+
+ def test_simple_wrap(self):
+ text = """\
+This is a single
+paragraph. It consists
+of several sentences
+none of
+which are
+very long.
+"""
+ self.assertEqual(wrap(text), """\
+This is a single paragraph. It consists of several sentences none of
+which are very long.""")
+
+ def test_two_paragraphs(self):
+ text = """\
+This is a single
+paragraph. It consists
+of several sentences
+none of
+which are
+very long.
+
+And here is a second paragraph which
+also consists
+of several sentences. None of
+these are very long
+either.
+"""
+ self.assertEqual(wrap(text), """\
+This is a single paragraph. It consists of several sentences none of
+which are very long.
+
+And here is a second paragraph which also consists of several
+sentences. None of these are very long either.""")
+
+ def test_honor_ws(self):
+ text = """\
+This is a single
+paragraph. It consists
+of several sentences
+none of
+which are
+very long.
+
+ This paragraph is
+ indented so it
+ won't be filled.
+
+And here is a second paragraph which
+also consists
+of several sentences. None of
+these are very long
+either.
+"""
+ self.assertEqual(wrap(text), """\
+This is a single paragraph. It consists of several sentences none of
+which are very long.
+
+ This paragraph is
+ indented so it
+ won't be filled.
+
+And here is a second paragraph which also consists of several
+sentences. None of these are very long either.""")
+
+ def test_dont_honor_ws(self):
+ text = """\
+This is a single
+paragraph. It consists
+of several sentences
+none of
+which are
+very long.
+
+ This paragraph is
+ indented but we don't
+ honor whitespace so it
+ will be filled.
+
+And here is a second paragraph which
+also consists
+of several sentences. None of
+these are very long
+either.
+"""
+ self.assertEqual(wrap(text, honor_leading_ws=False), """\
+This is a single paragraph. It consists of several sentences none of
+which are very long.
+
+ This paragraph is indented but we don't honor whitespace so it
+ will be filled.
+
+And here is a second paragraph which also consists of several
+sentences. None of these are very long either.""")
+
+ def test_indentation_boundary(self):
+ text = """\
+This is a single paragraph
+that consists of one sentence.
+ And another one that breaks
+ because it is indented.
+Followed by one more paragraph.
+"""
+ self.assertEqual(wrap(text), """\
+This is a single paragraph that consists of one sentence.
+ And another one that breaks
+ because it is indented.
+Followed by one more paragraph.""")
+
+
+
+def test_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestWrap))
+ return suite