2 # Authors: David Goodger <goodger@python.org>;
3 # Garth Kidd <garth@deadlybloodyserious.com>
4 # Copyright: This module has been placed in the public domain.
10 - `statemachine` is 'docutils.statemachine'
11 - `nodes` is 'docutils.nodes'
12 - `urischemes` is 'docutils.urischemes'
13 - `utils` is 'docutils.utils'
14 - `transforms` is 'docutils.transforms'
15 - `states` is 'docutils.parsers.rst.states'
16 - `tableparser` is 'docutils.parsers.rst.tableparser'
23 - `TransformTestSuite`
26 - `ParserTransformTestCase`
28 - `PEPParserTestSuite`
29 - `GridTableParserTestCase`
30 - `GridTableParserTestSuite`
31 - `SimpleTableParserTestCase`
32 - `SimpleTableParserTestSuite`
33 - `WriterPublishTestCase`
34 - `LatexWriterPublishTestCase`
35 - `PseudoXMLWriterPublishTestCase`
36 - `HtmlWriterPublishTestCase`
38 - `HtmlFragmentTestSuite`
39 - `DevNull` (output sink)
41 __docformat__
= 'reStructuredText'
49 from pprint
import pformat
51 testroot
= os
.path
.abspath(os
.path
.dirname(__file__
) or os
.curdir
)
53 sys
.path
.insert(0, os
.path
.normpath(os
.path
.join(testroot
, '..')))
54 sys
.path
.insert(0, testroot
)
55 sys
.path
.append(os
.path
.normpath(os
.path
.join(testroot
, '..', 'extras')))
58 import docutils_difflib
59 import package_unittest
62 from docutils
import frontend
, nodes
, statemachine
, urischemes
, utils
63 from docutils
.transforms
import universal
64 from docutils
.parsers
import rst
65 from docutils
.parsers
.rst
import states
, tableparser
, roles
, languages
66 from docutils
.readers
import standalone
, pep
67 from docutils
.readers
.python
import moduleparser
68 from docutils
.statemachine
import StringList
, string2lines
70 # The importing module (usually __init__.py in one of the
71 # subdirectories) may catch ImportErrors in order to detect the
72 # absence of DocutilsTestSupport in sys.path. Thus, ImportErrors
73 # resulting from problems with importing Docutils modules must
85 # Hack to make repr(StringList) look like repr(list):
86 StringList
.__repr
__ = StringList
.__str
__
93 def write(self
, string
):
100 class StandardTestCase(unittest
.TestCase
):
103 Helper class, providing the same interface as unittest.TestCase,
104 but with useful setUp and comparison methods.
110 def failUnlessEqual(self
, first
, second
, msg
=None):
111 """Fail if the two objects are unequal as determined by the '=='
114 if not first
== second
:
115 raise self
.failureException
, \
116 (msg
or '%s != %s' % _format_str(first
, second
))
118 def failIfEqual(self
, first
, second
, msg
=None):
119 """Fail if the two objects are equal as determined by the '=='
123 raise self
.failureException
, \
124 (msg
or '%s == %s' % _format_str(first
, second
))
126 # Synonyms for assertion methods
128 assertEqual
= assertEquals
= failUnlessEqual
130 assertNotEqual
= assertNotEquals
= failIfEqual
133 class CustomTestCase(StandardTestCase
):
136 Helper class, providing extended functionality over unittest.TestCase.
138 The methods failUnlessEqual and failIfEqual have been overwritten
139 to provide better support for multi-line strings. Furthermore,
140 see the compare_output method and the parameter list of __init__.
143 compare
= docutils_difflib
.Differ().compare
144 """Comparison method shared by all subclasses."""
146 def __init__(self
, method_name
, input, expected
, id, run_in_debugger
=0,
147 suite_settings
=None):
149 Initialise the CustomTestCase.
153 method_name -- name of test method to run.
154 input -- input to the parser.
155 expected -- expected output from the parser.
156 id -- unique test identifier, used by the test framework.
157 run_in_debugger -- if true, run this test under the pdb debugger.
158 suite_settings -- settings overrides for this test suite.
162 self
.expected
= expected
163 self
.run_in_debugger
= run_in_debugger
164 self
.suite_settings
= suite_settings
.copy() or {}
167 unittest
.TestCase
.__init
__(self
, method_name
)
171 Return string conversion. Overridden to give test id, in addition to
174 return '%s; %s' % (self
.id, unittest
.TestCase
.__str
__(self
))
177 return "<%s %s>" % (self
.id, unittest
.TestCase
.__repr
__(self
))
179 def clear_roles(self
):
180 # Language-specific roles and roles added by the
181 # "default-role" and "role" directives are currently stored
182 # globally in the roles._roles dictionary. This workaround
183 # empties that dictionary.
187 StandardTestCase
.setUp(self
)
190 def compare_output(self
, input, output
, expected
):
191 """`input`, `output`, and `expected` should all be strings."""
192 if isinstance(input, unicode):
193 input = input.encode('raw_unicode_escape')
194 if isinstance(output
, unicode):
195 output
= output
.encode('raw_unicode_escape')
196 if isinstance(expected
, unicode):
197 expected
= expected
.encode('raw_unicode_escape')
199 self
.assertEquals(output
, expected
)
200 except AssertionError, error
:
201 print >>sys
.stderr
, '\n%s\ninput:' % (self
,)
202 print >>sys
.stderr
, input
204 comparison
= ''.join(self
.compare(expected
.splitlines(1),
205 output
.splitlines(1)))
206 print >>sys
.stderr
, '-: expected\n+: output'
207 print >>sys
.stderr
, comparison
208 except AttributeError: # expected or output not a string
209 # alternative output for non-strings:
210 print >>sys
.stderr
, 'expected: %r' % expected
211 print >>sys
.stderr
, 'output: %r' % output
215 class CustomTestSuite(unittest
.TestSuite
):
218 A collection of CustomTestCases.
220 Provides test suite ID generation and a method for adding test cases.
224 """Identifier for the TestSuite. Prepended to the
225 TestCase identifiers to make identification easier."""
227 next_test_case_id
= 0
228 """The next identifier to use for non-identified test cases."""
230 def __init__(self
, tests
=(), id=None, suite_settings
=None):
232 Initialize the CustomTestSuite.
236 id -- identifier for the suite, prepended to test cases.
237 suite_settings -- settings overrides for this test suite.
239 unittest
.TestSuite
.__init
__(self
, tests
)
240 self
.suite_settings
= suite_settings
or {}
242 mypath
= os
.path
.abspath(
243 sys
.modules
[CustomTestSuite
.__module
__].__file
__)
244 outerframes
= inspect
.getouterframes(inspect
.currentframe())
245 for outerframe
in outerframes
[1:]:
246 if outerframe
[3] != '__init__':
247 callerpath
= outerframe
[1]
248 if callerpath
is None:
249 # It happens sometimes. Why is a mystery.
250 callerpath
= os
.getcwd()
251 callerpath
= os
.path
.abspath(callerpath
)
253 mydir
, myname
= os
.path
.split(mypath
)
256 if callerpath
.startswith(mydir
):
257 self
.id = callerpath
[len(mydir
) + 1:] # caller's module
263 def addTestCase(self
, test_case_class
, method_name
, input, expected
,
264 id=None, run_in_debugger
=0, **kwargs
):
266 Create a CustomTestCase in the CustomTestSuite.
267 Also return it, just in case.
271 test_case_class -- the CustomTestCase to add
272 method_name -- a string; CustomTestCase.method_name is the test
273 input -- input to the parser.
274 expected -- expected output from the parser.
275 id -- unique test identifier, used by the test framework.
276 run_in_debugger -- if true, run this test under the pdb debugger.
278 if id is None: # generate id if required
279 id = self
.next_test_case_id
280 self
.next_test_case_id
+= 1
281 # test identifier will become suiteid.testid
282 tcid
= '%s: %s' % (self
.id, id)
283 # suite_settings may be passed as a parameter;
284 # if not, set from attribute:
285 kwargs
.setdefault('suite_settings', self
.suite_settings
)
286 # generate and add test case
287 tc
= test_case_class(method_name
, input, expected
, tcid
,
288 run_in_debugger
=run_in_debugger
, **kwargs
)
292 def generate_no_tests(self
, *args
, **kwargs
):
296 class TransformTestCase(CustomTestCase
):
299 Output checker for the transform.
301 Should probably be called TransformOutputChecker, but I can deal with
302 that later when/if someone comes up with a category of transform test
303 cases that have nothing to do with the input and output of the transform.
306 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
307 settings
= option_parser
.get_default_values()
308 settings
.report_level
= 1
309 settings
.halt_level
= 5
310 settings
.debug
= package_unittest
.debug
311 settings
.warning_stream
= DevNull()
312 unknown_reference_resolvers
= ()
314 def __init__(self
, *args
, **kwargs
):
315 self
.transforms
= kwargs
['transforms']
316 """List of transforms to perform for this test case."""
318 self
.parser
= kwargs
['parser']
319 """Input parser for this test case."""
321 del kwargs
['transforms'], kwargs
['parser'] # only wanted here
322 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
324 def supports(self
, format
):
327 def test_transforms(self
):
328 if self
.run_in_debugger
:
330 settings
= self
.settings
.copy()
331 settings
.__dict
__.update(self
.suite_settings
)
332 document
= utils
.new_document('test data', settings
)
333 self
.parser
.parse(self
.input, document
)
334 # Don't do a ``populate_from_components()`` because that would
335 # enable the Transformer's default transforms.
336 document
.transformer
.add_transforms(self
.transforms
)
337 document
.transformer
.add_transform(universal
.TestMessages
)
338 document
.transformer
.components
['writer'] = self
339 document
.transformer
.apply_transforms()
340 output
= document
.pformat()
341 self
.compare_output(self
.input, output
, self
.expected
)
343 def test_transforms_verbosely(self
):
344 if self
.run_in_debugger
:
349 settings
= self
.settings
.copy()
350 settings
.__dict
__.update(self
.suite_settings
)
351 document
= utils
.new_document('test data', settings
)
352 self
.parser
.parse(self
.input, document
)
354 print document
.pformat()
355 for transformClass
in self
.transforms
:
356 transformClass(document
).apply()
357 output
= document
.pformat()
360 self
.compare_output(self
.input, output
, self
.expected
)
363 class TransformTestSuite(CustomTestSuite
):
366 A collection of TransformTestCases.
368 A TransformTestSuite instance manufactures TransformTestCases,
369 keeps track of them, and provides a shared test fixture (a-la
373 def __init__(self
, parser
, suite_settings
=None):
375 """Parser shared by all test cases."""
377 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
379 def generateTests(self
, dict, dictname
='totest',
380 testmethod
='test_transforms'):
382 Stock the suite with test cases generated from a test data dictionary.
384 Each dictionary key (test type's name) maps to a tuple, whose
385 first item is a list of transform classes and whose second
386 item is a list of tests. Each test is a list: input, expected
387 output, optional modifier. The optional third entry, a
388 behavior modifier, can be 0 (temporarily disable this test) or
389 1 (run this test under the pdb debugger). Tests should be
390 self-documenting and not require external comments.
392 for name
, (transforms
, cases
) in dict.items():
393 for casenum
in range(len(cases
)):
394 case
= cases
[casenum
]
397 # TODO: (maybe) change the 3rd argument to a dict, so it
398 # can handle more cases by keyword ('disable', 'debug',
399 # 'settings'), here and in other generateTests methods.
400 # But there's also the method that
401 # HtmlPublishPartsTestSuite uses <DJG>
407 TransformTestCase
, testmethod
,
408 transforms
=transforms
, parser
=self
.parser
,
409 input=case
[0], expected
=case
[1],
410 id='%s[%r][%s]' % (dictname
, name
, casenum
),
411 run_in_debugger
=run_in_debugger
)
414 class ParserTestCase(CustomTestCase
):
417 Output checker for the parser.
419 Should probably be called ParserOutputChecker, but I can deal with
420 that later when/if someone comes up with a category of parser test
421 cases that have nothing to do with the input and output of the parser.
424 parser
= rst
.Parser()
425 """Parser shared by all ParserTestCases."""
427 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
428 settings
= option_parser
.get_default_values()
429 settings
.report_level
= 5
430 settings
.halt_level
= 5
431 settings
.debug
= package_unittest
.debug
433 def test_parser(self
):
434 if self
.run_in_debugger
:
436 settings
= self
.settings
.copy()
437 settings
.__dict
__.update(self
.suite_settings
)
438 document
= utils
.new_document('test data', settings
)
439 self
.parser
.parse(self
.input, document
)
440 output
= document
.pformat()
441 self
.compare_output(self
.input, output
, self
.expected
)
444 class ParserTestSuite(CustomTestSuite
):
447 A collection of ParserTestCases.
449 A ParserTestSuite instance manufactures ParserTestCases,
450 keeps track of them, and provides a shared test fixture (a-la
454 test_case_class
= ParserTestCase
456 def generateTests(self
, dict, dictname
='totest'):
458 Stock the suite with test cases generated from a test data dictionary.
460 Each dictionary key (test type name) maps to a list of tests. Each
461 test is a list: input, expected output, optional modifier. The
462 optional third entry, a behavior modifier, can be 0 (temporarily
463 disable this test) or 1 (run this test under the pdb debugger). Tests
464 should be self-documenting and not require external comments.
466 for name
, cases
in dict.items():
467 for casenum
in range(len(cases
)):
468 case
= cases
[casenum
]
476 self
.test_case_class
, 'test_parser',
477 input=case
[0], expected
=case
[1],
478 id='%s[%r][%s]' % (dictname
, name
, casenum
),
479 run_in_debugger
=run_in_debugger
)
482 class PEPParserTestCase(ParserTestCase
):
484 """PEP-specific parser test case."""
486 parser
= rst
.Parser(rfc2822
=1, inliner
=rst
.states
.Inliner())
487 """Parser shared by all PEPParserTestCases."""
489 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
, pep
.Reader
))
490 settings
= option_parser
.get_default_values()
491 settings
.report_level
= 5
492 settings
.halt_level
= 5
493 settings
.debug
= package_unittest
.debug
496 class PEPParserTestSuite(ParserTestSuite
):
498 """A collection of PEPParserTestCases."""
500 test_case_class
= PEPParserTestCase
503 class GridTableParserTestCase(CustomTestCase
):
505 parser
= tableparser
.GridTableParser()
507 def test_parse_table(self
):
508 self
.parser
.setup(StringList(string2lines(self
.input), 'test data'))
510 self
.parser
.find_head_body_sep()
511 self
.parser
.parse_table()
512 output
= self
.parser
.cells
513 except Exception, details
:
514 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
515 self
.compare_output(self
.input, pformat(output
) + '\n',
516 pformat(self
.expected
) + '\n')
518 def test_parse(self
):
520 output
= self
.parser
.parse(StringList(string2lines(self
.input),
522 except Exception, details
:
523 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
524 self
.compare_output(self
.input, pformat(output
) + '\n',
525 pformat(self
.expected
) + '\n')
528 class GridTableParserTestSuite(CustomTestSuite
):
531 A collection of GridTableParserTestCases.
533 A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
534 keeps track of them, and provides a shared test fixture (a-la setUp and
538 test_case_class
= GridTableParserTestCase
540 def generateTests(self
, dict, dictname
='totest'):
542 Stock the suite with test cases generated from a test data dictionary.
544 Each dictionary key (test type name) maps to a list of tests. Each
545 test is a list: an input table, expected output from parse_table(),
546 expected output from parse(), optional modifier. The optional fourth
547 entry, a behavior modifier, can be 0 (temporarily disable this test)
548 or 1 (run this test under the pdb debugger). Tests should be
549 self-documenting and not require external comments.
551 for name
, cases
in dict.items():
552 for casenum
in range(len(cases
)):
553 case
= cases
[casenum
]
560 self
.addTestCase(self
.test_case_class
, 'test_parse_table',
561 input=case
[0], expected
=case
[1],
562 id='%s[%r][%s]' % (dictname
, name
, casenum
),
563 run_in_debugger
=run_in_debugger
)
564 self
.addTestCase(self
.test_case_class
, 'test_parse',
565 input=case
[0], expected
=case
[2],
566 id='%s[%r][%s]' % (dictname
, name
, casenum
),
567 run_in_debugger
=run_in_debugger
)
570 class SimpleTableParserTestCase(GridTableParserTestCase
):
572 parser
= tableparser
.SimpleTableParser()
575 class SimpleTableParserTestSuite(CustomTestSuite
):
578 A collection of SimpleTableParserTestCases.
581 test_case_class
= SimpleTableParserTestCase
583 def generateTests(self
, dict, dictname
='totest'):
585 Stock the suite with test cases generated from a test data dictionary.
587 Each dictionary key (test type name) maps to a list of tests. Each
588 test is a list: an input table, expected output from parse(), optional
589 modifier. The optional third entry, a behavior modifier, can be 0
590 (temporarily disable this test) or 1 (run this test under the pdb
591 debugger). Tests should be self-documenting and not require external
594 for name
, cases
in dict.items():
595 for casenum
in range(len(cases
)):
596 case
= cases
[casenum
]
603 self
.addTestCase(self
.test_case_class
, 'test_parse',
604 input=case
[0], expected
=case
[1],
605 id='%s[%r][%s]' % (dictname
, name
, casenum
),
606 run_in_debugger
=run_in_debugger
)
609 class PythonModuleParserTestCase(CustomTestCase
):
611 def test_parser(self
):
612 if self
.run_in_debugger
:
614 module
= moduleparser
.parse_module(self
.input, 'test data').pformat()
616 self
.compare_output(self
.input, output
, self
.expected
)
618 def test_token_parser_rhs(self
):
619 if self
.run_in_debugger
:
621 tr
= moduleparser
.TokenParser(self
.input)
623 self
.compare_output(self
.input, output
, self
.expected
)
626 class PythonModuleParserTestSuite(CustomTestSuite
):
629 A collection of PythonModuleParserTestCase.
632 def generateTests(self
, dict, dictname
='totest',
633 testmethod
='test_parser'):
635 Stock the suite with test cases generated from a test data dictionary.
637 Each dictionary key (test type's name) maps to a list of tests. Each
638 test is a list: input, expected output, optional modifier. The
639 optional third entry, a behavior modifier, can be 0 (temporarily
640 disable this test) or 1 (run this test under the pdb debugger). Tests
641 should be self-documenting and not require external comments.
643 for name
, cases
in dict.items():
644 for casenum
in range(len(cases
)):
645 case
= cases
[casenum
]
653 PythonModuleParserTestCase
, testmethod
,
654 input=case
[0], expected
=case
[1],
655 id='%s[%r][%s]' % (dictname
, name
, casenum
),
656 run_in_debugger
=run_in_debugger
)
659 class WriterPublishTestCase(CustomTestCase
, docutils
.SettingsSpec
):
662 Test case for publish.
665 settings_default_overrides
= {'_disable_config': 1,
667 writer_name
= '' # set in subclasses or constructor
669 def __init__(self
, *args
, **kwargs
):
670 if 'writer_name' in kwargs
:
671 self
.writer_name
= kwargs
['writer_name']
672 del kwargs
['writer_name']
673 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
675 def test_publish(self
):
676 if self
.run_in_debugger
:
678 output
= docutils
.core
.publish_string(
680 reader_name
='standalone',
681 parser_name
='restructuredtext',
682 writer_name
=self
.writer_name
,
684 settings_overrides
=self
.suite_settings
)
685 self
.compare_output(self
.input, output
, self
.expected
)
688 class PublishTestSuite(CustomTestSuite
):
690 def __init__(self
, writer_name
, suite_settings
=None):
692 `writer_name` is the name of the writer to use.
694 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
695 self
.test_class
= WriterPublishTestCase
696 self
.writer_name
= writer_name
698 def generateTests(self
, dict, dictname
='totest'):
699 for name
, cases
in dict.items():
700 for casenum
in range(len(cases
)):
701 case
= cases
[casenum
]
709 self
.test_class
, 'test_publish',
710 input=case
[0], expected
=case
[1],
711 id='%s[%r][%s]' % (dictname
, name
, casenum
),
712 run_in_debugger
=run_in_debugger
,
713 # Passed to constructor of self.test_class:
714 writer_name
=self
.writer_name
)
717 class HtmlPublishPartsTestSuite(CustomTestSuite
):
719 def generateTests(self
, dict, dictname
='totest'):
720 for name
, (settings_overrides
, cases
) in dict.items():
721 settings
= self
.suite_settings
.copy()
722 settings
.update(settings_overrides
)
723 for casenum
in range(len(cases
)):
724 case
= cases
[casenum
]
732 HtmlWriterPublishPartsTestCase
, 'test_publish',
733 input=case
[0], expected
=case
[1],
734 id='%s[%r][%s]' % (dictname
, name
, casenum
),
735 run_in_debugger
=run_in_debugger
,
736 suite_settings
=settings
)
739 class HtmlWriterPublishPartsTestCase(WriterPublishTestCase
):
742 Test case for HTML writer via the publish_parts interface.
747 settings_default_overrides
= \
748 WriterPublishTestCase
.settings_default_overrides
.copy()
749 settings_default_overrides
['stylesheet'] = ''
751 def test_publish(self
):
752 if self
.run_in_debugger
:
754 parts
= docutils
.core
.publish_parts(
756 reader_name
='standalone',
757 parser_name
='restructuredtext',
758 writer_name
=self
.writer_name
,
760 settings_overrides
=self
.suite_settings
)
761 output
= self
.format_output(parts
)
762 # interpolate standard variables:
763 expected
= self
.expected
% {'version': docutils
.__version
__}
764 self
.compare_output(self
.input, output
, expected
)
766 standard_content_type_template
= ('<meta http-equiv="Content-Type"'
767 ' content="text/html; charset=%s" />\n')
768 standard_generator_template
= (
769 '<meta name="generator"'
770 ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
771 standard_html_meta_value
= (
772 standard_content_type_template
773 + standard_generator_template
% docutils
.__version
__)
774 standard_meta_value
= standard_html_meta_value
% 'utf-8'
775 standard_html_prolog
= """\
776 <?xml version="1.0" encoding="%s" ?>
777 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
780 def format_output(self
, parts
):
781 """Minimize & standardize the output."""
782 # remove redundant parts & uninteresting parts:
784 assert parts
['body'] == parts
['fragment']
786 del parts
['body_pre_docinfo']
787 del parts
['body_prefix']
788 del parts
['body_suffix']
790 del parts
['head_prefix']
791 del parts
['encoding']
793 # remove standard portions:
794 parts
['meta'] = parts
['meta'].replace(self
.standard_meta_value
, '')
795 parts
['html_head'] = parts
['html_head'].replace(
796 self
.standard_html_meta_value
, '...')
797 parts
['html_prolog'] = parts
['html_prolog'].replace(
798 self
.standard_html_prolog
, '')
799 # remove empty values:
800 for key
in parts
.keys():
803 # standard output format:
808 output
.append("%r: '''%s'''"
809 % (key
, parts
[key
].encode('raw_unicode_escape')))
810 if output
[-1].endswith("\n'''"):
811 output
[-1] = output
[-1][:-4] + "\\n'''"
812 return '{' + ',\n '.join(output
) + '}\n'
815 def exception_data(code
):
817 Execute `code` and return the resulting exception, the exception arguments,
818 and the formatted exception string.
822 except Exception, detail
:
823 return (detail
, detail
.args
,
824 '%s: %s' % (detail
.__class
__.__name
__, detail
))
827 def _format_str(*args
):
829 Return a tuple containing representations of all args.
831 Same as map(repr, args) except that it returns multi-line
832 representations for strings containing newlines, e.g.::
844 This is a helper function for CustomTestCase.
849 if ( (isinstance(i
, str) or isinstance(i
, unicode))
852 if isinstance(i
, unicode):
853 # stripped = 'u' or 'U'
856 # quote_char = "'" or '"'
858 assert quote_char
in ("'", '"')
861 r
= (stripped
+ 3 * quote_char
+ '\\\n' +
862 re
.sub(r
'(?<!\\)((\\\\)*)\\n', r
'\1\n', r
) +
864 r
= re
.sub(r
' \n', r
' \\n\\\n', r
)
865 return_tuple
.append(r
)
866 return tuple(return_tuple
)