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
50 from types
import UnicodeType
, StringType
52 testroot
= os
.path
.abspath(os
.path
.dirname(__file__
) or os
.curdir
)
54 sys
.path
.insert(0, os
.path
.normpath(os
.path
.join(testroot
, '..')))
55 sys
.path
.insert(0, testroot
)
56 sys
.path
.append(os
.path
.normpath(os
.path
.join(testroot
, '..', 'extras')))
59 import docutils_difflib
60 import package_unittest
63 from docutils
import frontend
, nodes
, statemachine
, urischemes
, utils
64 from docutils
.transforms
import universal
65 from docutils
.parsers
import rst
66 from docutils
.parsers
.rst
import states
, tableparser
, roles
, languages
67 from docutils
.readers
import standalone
, pep
68 from docutils
.readers
.python
import moduleparser
69 from docutils
.statemachine
import StringList
, string2lines
71 # The importing module (usually __init__.py in one of the
72 # subdirectories) may catch ImportErrors in order to detect the
73 # absence of DocutilsTestSupport in sys.path. Thus, ImportErrors
74 # resulting from problems with importing Docutils modules must
86 # Hack to make repr(StringList) look like repr(list):
87 StringList
.__repr
__ = StringList
.__str
__
94 def write(self
, string
):
101 class StandardTestCase(unittest
.TestCase
):
104 Helper class, providing the same interface as unittest.TestCase,
105 but with useful setUp and comparison methods.
111 def failUnlessEqual(self
, first
, second
, msg
=None):
112 """Fail if the two objects are unequal as determined by the '=='
115 if not first
== second
:
116 raise self
.failureException
, \
117 (msg
or '%s != %s' % _format_str(first
, second
))
119 def failIfEqual(self
, first
, second
, msg
=None):
120 """Fail if the two objects are equal as determined by the '=='
124 raise self
.failureException
, \
125 (msg
or '%s == %s' % _format_str(first
, second
))
127 # Synonyms for assertion methods
129 assertEqual
= assertEquals
= failUnlessEqual
131 assertNotEqual
= assertNotEquals
= failIfEqual
134 class CustomTestCase(StandardTestCase
):
137 Helper class, providing extended functionality over unittest.TestCase.
139 The methods failUnlessEqual and failIfEqual have been overwritten
140 to provide better support for multi-line strings. Furthermore,
141 see the compare_output method and the parameter list of __init__.
144 compare
= docutils_difflib
.Differ().compare
145 """Comparison method shared by all subclasses."""
147 def __init__(self
, method_name
, input, expected
, id, run_in_debugger
=0,
148 suite_settings
=None):
150 Initialise the CustomTestCase.
154 method_name -- name of test method to run.
155 input -- input to the parser.
156 expected -- expected output from the parser.
157 id -- unique test identifier, used by the test framework.
158 run_in_debugger -- if true, run this test under the pdb debugger.
159 suite_settings -- settings overrides for this test suite.
163 self
.expected
= expected
164 self
.run_in_debugger
= run_in_debugger
165 self
.suite_settings
= suite_settings
.copy() or {}
168 unittest
.TestCase
.__init
__(self
, method_name
)
172 Return string conversion. Overridden to give test id, in addition to
175 return '%s; %s' % (self
.id, unittest
.TestCase
.__str
__(self
))
178 return "<%s %s>" % (self
.id, unittest
.TestCase
.__repr
__(self
))
180 def clear_roles(self
):
181 # Language-specific roles and roles added by the
182 # "default-role" and "role" directives are currently stored
183 # globally in the roles._roles dictionary. This workaround
184 # empties that dictionary.
188 StandardTestCase
.setUp(self
)
191 def compare_output(self
, input, output
, expected
):
192 """`input`, `output`, and `expected` should all be strings."""
193 if isinstance(input, UnicodeType
):
194 input = input.encode('raw_unicode_escape')
195 if isinstance(output
, UnicodeType
):
196 output
= output
.encode('raw_unicode_escape')
197 if isinstance(expected
, UnicodeType
):
198 expected
= expected
.encode('raw_unicode_escape')
200 self
.assertEquals(output
, expected
)
201 except AssertionError, error
:
202 print >>sys
.stderr
, '\n%s\ninput:' % (self
,)
203 print >>sys
.stderr
, input
205 comparison
= ''.join(self
.compare(expected
.splitlines(1),
206 output
.splitlines(1)))
207 print >>sys
.stderr
, '-: expected\n+: output'
208 print >>sys
.stderr
, comparison
209 except AttributeError: # expected or output not a string
210 # alternative output for non-strings:
211 print >>sys
.stderr
, 'expected: %r' % expected
212 print >>sys
.stderr
, 'output: %r' % output
216 class CustomTestSuite(unittest
.TestSuite
):
219 A collection of CustomTestCases.
221 Provides test suite ID generation and a method for adding test cases.
225 """Identifier for the TestSuite. Prepended to the
226 TestCase identifiers to make identification easier."""
228 next_test_case_id
= 0
229 """The next identifier to use for non-identified test cases."""
231 def __init__(self
, tests
=(), id=None, suite_settings
=None):
233 Initialize the CustomTestSuite.
237 id -- identifier for the suite, prepended to test cases.
238 suite_settings -- settings overrides for this test suite.
240 unittest
.TestSuite
.__init
__(self
, tests
)
241 self
.suite_settings
= suite_settings
or {}
243 mypath
= os
.path
.abspath(
244 sys
.modules
[CustomTestSuite
.__module
__].__file
__)
245 outerframes
= inspect
.getouterframes(inspect
.currentframe())
246 for outerframe
in outerframes
[1:]:
247 if outerframe
[3] != '__init__':
248 callerpath
= outerframe
[1]
249 if callerpath
is None:
250 # It happens sometimes. Why is a mystery.
251 callerpath
= os
.getcwd()
252 callerpath
= os
.path
.abspath(callerpath
)
254 mydir
, myname
= os
.path
.split(mypath
)
257 if callerpath
.startswith(mydir
):
258 self
.id = callerpath
[len(mydir
) + 1:] # caller's module
264 def addTestCase(self
, test_case_class
, method_name
, input, expected
,
265 id=None, run_in_debugger
=0, **kwargs
):
267 Create a CustomTestCase in the CustomTestSuite.
268 Also return it, just in case.
272 test_case_class -- the CustomTestCase to add
273 method_name -- a string; CustomTestCase.method_name is the test
274 input -- input to the parser.
275 expected -- expected output from the parser.
276 id -- unique test identifier, used by the test framework.
277 run_in_debugger -- if true, run this test under the pdb debugger.
279 if id is None: # generate id if required
280 id = self
.next_test_case_id
281 self
.next_test_case_id
+= 1
282 # test identifier will become suiteid.testid
283 tcid
= '%s: %s' % (self
.id, id)
284 # suite_settings may be passed as a parameter;
285 # if not, set from attribute:
286 kwargs
.setdefault('suite_settings', self
.suite_settings
)
287 # generate and add test case
288 tc
= test_case_class(method_name
, input, expected
, tcid
,
289 run_in_debugger
=run_in_debugger
, **kwargs
)
293 def generate_no_tests(self
, *args
, **kwargs
):
297 class TransformTestCase(CustomTestCase
):
300 Output checker for the transform.
302 Should probably be called TransformOutputChecker, but I can deal with
303 that later when/if someone comes up with a category of transform test
304 cases that have nothing to do with the input and output of the transform.
307 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
308 settings
= option_parser
.get_default_values()
309 settings
.report_level
= 1
310 settings
.halt_level
= 5
311 settings
.debug
= package_unittest
.debug
312 settings
.warning_stream
= DevNull()
313 unknown_reference_resolvers
= ()
315 def __init__(self
, *args
, **kwargs
):
316 self
.transforms
= kwargs
['transforms']
317 """List of transforms to perform for this test case."""
319 self
.parser
= kwargs
['parser']
320 """Input parser for this test case."""
322 del kwargs
['transforms'], kwargs
['parser'] # only wanted here
323 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
325 def supports(self
, format
):
328 def test_transforms(self
):
329 if self
.run_in_debugger
:
331 settings
= self
.settings
.copy()
332 settings
.__dict
__.update(self
.suite_settings
)
333 document
= utils
.new_document('test data', settings
)
334 self
.parser
.parse(self
.input, document
)
335 # Don't do a ``populate_from_components()`` because that would
336 # enable the Transformer's default transforms.
337 document
.transformer
.add_transforms(self
.transforms
)
338 document
.transformer
.add_transform(universal
.TestMessages
)
339 document
.transformer
.components
['writer'] = self
340 document
.transformer
.apply_transforms()
341 output
= document
.pformat()
342 self
.compare_output(self
.input, output
, self
.expected
)
344 def test_transforms_verbosely(self
):
345 if self
.run_in_debugger
:
350 settings
= self
.settings
.copy()
351 settings
.__dict
__.update(self
.suite_settings
)
352 document
= utils
.new_document('test data', settings
)
353 self
.parser
.parse(self
.input, document
)
355 print document
.pformat()
356 for transformClass
in self
.transforms
:
357 transformClass(document
).apply()
358 output
= document
.pformat()
361 self
.compare_output(self
.input, output
, self
.expected
)
364 class TransformTestSuite(CustomTestSuite
):
367 A collection of TransformTestCases.
369 A TransformTestSuite instance manufactures TransformTestCases,
370 keeps track of them, and provides a shared test fixture (a-la
374 def __init__(self
, parser
, suite_settings
=None):
376 """Parser shared by all test cases."""
378 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
380 def generateTests(self
, dict, dictname
='totest',
381 testmethod
='test_transforms'):
383 Stock the suite with test cases generated from a test data dictionary.
385 Each dictionary key (test type's name) maps to a tuple, whose
386 first item is a list of transform classes and whose second
387 item is a list of tests. Each test is a list: input, expected
388 output, optional modifier. The optional third entry, a
389 behavior modifier, can be 0 (temporarily disable this test) or
390 1 (run this test under the pdb debugger). Tests should be
391 self-documenting and not require external comments.
393 for name
, (transforms
, cases
) in dict.items():
394 for casenum
in range(len(cases
)):
395 case
= cases
[casenum
]
398 # TODO: (maybe) change the 3rd argument to a dict, so it
399 # can handle more cases by keyword ('disable', 'debug',
400 # 'settings'), here and in other generateTests methods.
401 # But there's also the method that
402 # HtmlPublishPartsTestSuite uses <DJG>
408 TransformTestCase
, testmethod
,
409 transforms
=transforms
, parser
=self
.parser
,
410 input=case
[0], expected
=case
[1],
411 id='%s[%r][%s]' % (dictname
, name
, casenum
),
412 run_in_debugger
=run_in_debugger
)
415 class ParserTestCase(CustomTestCase
):
418 Output checker for the parser.
420 Should probably be called ParserOutputChecker, but I can deal with
421 that later when/if someone comes up with a category of parser test
422 cases that have nothing to do with the input and output of the parser.
425 parser
= rst
.Parser()
426 """Parser shared by all ParserTestCases."""
428 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
429 settings
= option_parser
.get_default_values()
430 settings
.report_level
= 5
431 settings
.halt_level
= 5
432 settings
.debug
= package_unittest
.debug
434 def test_parser(self
):
435 if self
.run_in_debugger
:
437 settings
= self
.settings
.copy()
438 settings
.__dict
__.update(self
.suite_settings
)
439 document
= utils
.new_document('test data', settings
)
440 self
.parser
.parse(self
.input, document
)
441 output
= document
.pformat()
442 self
.compare_output(self
.input, output
, self
.expected
)
445 class ParserTestSuite(CustomTestSuite
):
448 A collection of ParserTestCases.
450 A ParserTestSuite instance manufactures ParserTestCases,
451 keeps track of them, and provides a shared test fixture (a-la
455 test_case_class
= ParserTestCase
457 def generateTests(self
, dict, dictname
='totest'):
459 Stock the suite with test cases generated from a test data dictionary.
461 Each dictionary key (test type name) maps to a list of tests. Each
462 test is a list: input, expected output, optional modifier. The
463 optional third entry, a behavior modifier, can be 0 (temporarily
464 disable this test) or 1 (run this test under the pdb debugger). Tests
465 should be self-documenting and not require external comments.
467 for name
, cases
in dict.items():
468 for casenum
in range(len(cases
)):
469 case
= cases
[casenum
]
477 self
.test_case_class
, 'test_parser',
478 input=case
[0], expected
=case
[1],
479 id='%s[%r][%s]' % (dictname
, name
, casenum
),
480 run_in_debugger
=run_in_debugger
)
483 class PEPParserTestCase(ParserTestCase
):
485 """PEP-specific parser test case."""
487 parser
= rst
.Parser(rfc2822
=1, inliner
=rst
.states
.Inliner())
488 """Parser shared by all PEPParserTestCases."""
490 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
, pep
.Reader
))
491 settings
= option_parser
.get_default_values()
492 settings
.report_level
= 5
493 settings
.halt_level
= 5
494 settings
.debug
= package_unittest
.debug
497 class PEPParserTestSuite(ParserTestSuite
):
499 """A collection of PEPParserTestCases."""
501 test_case_class
= PEPParserTestCase
504 class GridTableParserTestCase(CustomTestCase
):
506 parser
= tableparser
.GridTableParser()
508 def test_parse_table(self
):
509 self
.parser
.setup(StringList(string2lines(self
.input), 'test data'))
511 self
.parser
.find_head_body_sep()
512 self
.parser
.parse_table()
513 output
= self
.parser
.cells
514 except Exception, details
:
515 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
516 self
.compare_output(self
.input, pformat(output
) + '\n',
517 pformat(self
.expected
) + '\n')
519 def test_parse(self
):
521 output
= self
.parser
.parse(StringList(string2lines(self
.input),
523 except Exception, details
:
524 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
525 self
.compare_output(self
.input, pformat(output
) + '\n',
526 pformat(self
.expected
) + '\n')
529 class GridTableParserTestSuite(CustomTestSuite
):
532 A collection of GridTableParserTestCases.
534 A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
535 keeps track of them, and provides a shared test fixture (a-la setUp and
539 test_case_class
= GridTableParserTestCase
541 def generateTests(self
, dict, dictname
='totest'):
543 Stock the suite with test cases generated from a test data dictionary.
545 Each dictionary key (test type name) maps to a list of tests. Each
546 test is a list: an input table, expected output from parse_table(),
547 expected output from parse(), optional modifier. The optional fourth
548 entry, a behavior modifier, can be 0 (temporarily disable this test)
549 or 1 (run this test under the pdb debugger). Tests should be
550 self-documenting and not require external comments.
552 for name
, cases
in dict.items():
553 for casenum
in range(len(cases
)):
554 case
= cases
[casenum
]
561 self
.addTestCase(self
.test_case_class
, 'test_parse_table',
562 input=case
[0], expected
=case
[1],
563 id='%s[%r][%s]' % (dictname
, name
, casenum
),
564 run_in_debugger
=run_in_debugger
)
565 self
.addTestCase(self
.test_case_class
, 'test_parse',
566 input=case
[0], expected
=case
[2],
567 id='%s[%r][%s]' % (dictname
, name
, casenum
),
568 run_in_debugger
=run_in_debugger
)
571 class SimpleTableParserTestCase(GridTableParserTestCase
):
573 parser
= tableparser
.SimpleTableParser()
576 class SimpleTableParserTestSuite(CustomTestSuite
):
579 A collection of SimpleTableParserTestCases.
582 test_case_class
= SimpleTableParserTestCase
584 def generateTests(self
, dict, dictname
='totest'):
586 Stock the suite with test cases generated from a test data dictionary.
588 Each dictionary key (test type name) maps to a list of tests. Each
589 test is a list: an input table, expected output from parse(), optional
590 modifier. The optional third entry, a behavior modifier, can be 0
591 (temporarily disable this test) or 1 (run this test under the pdb
592 debugger). Tests should be self-documenting and not require external
595 for name
, cases
in dict.items():
596 for casenum
in range(len(cases
)):
597 case
= cases
[casenum
]
604 self
.addTestCase(self
.test_case_class
, 'test_parse',
605 input=case
[0], expected
=case
[1],
606 id='%s[%r][%s]' % (dictname
, name
, casenum
),
607 run_in_debugger
=run_in_debugger
)
610 class PythonModuleParserTestCase(CustomTestCase
):
612 def test_parser(self
):
613 if self
.run_in_debugger
:
615 module
= moduleparser
.parse_module(self
.input, 'test data').pformat()
617 self
.compare_output(self
.input, output
, self
.expected
)
619 def test_token_parser_rhs(self
):
620 if self
.run_in_debugger
:
622 tr
= moduleparser
.TokenParser(self
.input)
624 self
.compare_output(self
.input, output
, self
.expected
)
627 class PythonModuleParserTestSuite(CustomTestSuite
):
630 A collection of PythonModuleParserTestCase.
633 def generateTests(self
, dict, dictname
='totest',
634 testmethod
='test_parser'):
636 Stock the suite with test cases generated from a test data dictionary.
638 Each dictionary key (test type's name) maps to a list of tests. Each
639 test is a list: input, expected output, optional modifier. The
640 optional third entry, a behavior modifier, can be 0 (temporarily
641 disable this test) or 1 (run this test under the pdb debugger). Tests
642 should be self-documenting and not require external comments.
644 for name
, cases
in dict.items():
645 for casenum
in range(len(cases
)):
646 case
= cases
[casenum
]
654 PythonModuleParserTestCase
, testmethod
,
655 input=case
[0], expected
=case
[1],
656 id='%s[%r][%s]' % (dictname
, name
, casenum
),
657 run_in_debugger
=run_in_debugger
)
660 class WriterPublishTestCase(CustomTestCase
, docutils
.SettingsSpec
):
663 Test case for publish.
666 settings_default_overrides
= {'_disable_config': 1,
668 writer_name
= '' # set in subclasses or constructor
670 def __init__(self
, *args
, **kwargs
):
671 if 'writer_name' in kwargs
:
672 self
.writer_name
= kwargs
['writer_name']
673 del kwargs
['writer_name']
674 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
676 def test_publish(self
):
677 if self
.run_in_debugger
:
679 output
= docutils
.core
.publish_string(
681 reader_name
='standalone',
682 parser_name
='restructuredtext',
683 writer_name
=self
.writer_name
,
685 settings_overrides
=self
.suite_settings
)
686 self
.compare_output(self
.input, output
, self
.expected
)
689 class PublishTestSuite(CustomTestSuite
):
691 def __init__(self
, writer_name
, suite_settings
=None):
693 `writer_name` is the name of the writer to use.
695 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
696 self
.test_class
= WriterPublishTestCase
697 self
.writer_name
= writer_name
699 def generateTests(self
, dict, dictname
='totest'):
700 for name
, cases
in dict.items():
701 for casenum
in range(len(cases
)):
702 case
= cases
[casenum
]
710 self
.test_class
, 'test_publish',
711 input=case
[0], expected
=case
[1],
712 id='%s[%r][%s]' % (dictname
, name
, casenum
),
713 run_in_debugger
=run_in_debugger
,
714 # Passed to constructor of self.test_class:
715 writer_name
=self
.writer_name
)
718 class HtmlPublishPartsTestSuite(CustomTestSuite
):
720 def generateTests(self
, dict, dictname
='totest'):
721 for name
, (settings_overrides
, cases
) in dict.items():
722 settings
= self
.suite_settings
.copy()
723 settings
.update(settings_overrides
)
724 for casenum
in range(len(cases
)):
725 case
= cases
[casenum
]
733 HtmlWriterPublishPartsTestCase
, 'test_publish',
734 input=case
[0], expected
=case
[1],
735 id='%s[%r][%s]' % (dictname
, name
, casenum
),
736 run_in_debugger
=run_in_debugger
,
737 suite_settings
=settings
)
740 class HtmlWriterPublishPartsTestCase(WriterPublishTestCase
):
743 Test case for HTML writer via the publish_parts interface.
748 settings_default_overrides
= \
749 WriterPublishTestCase
.settings_default_overrides
.copy()
750 settings_default_overrides
['stylesheet'] = ''
752 def test_publish(self
):
753 if self
.run_in_debugger
:
755 parts
= docutils
.core
.publish_parts(
757 reader_name
='standalone',
758 parser_name
='restructuredtext',
759 writer_name
=self
.writer_name
,
761 settings_overrides
=self
.suite_settings
)
762 output
= self
.format_output(parts
)
763 # interpolate standard variables:
764 expected
= self
.expected
% {'version': docutils
.__version
__}
765 self
.compare_output(self
.input, output
, expected
)
767 standard_content_type_template
= ('<meta http-equiv="Content-Type"'
768 ' content="text/html; charset=%s" />\n')
769 standard_generator_template
= (
770 '<meta name="generator"'
771 ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
772 standard_html_meta_value
= (
773 standard_content_type_template
774 + standard_generator_template
% docutils
.__version
__)
775 standard_meta_value
= standard_html_meta_value
% 'utf-8'
776 standard_html_prolog
= """\
777 <?xml version="1.0" encoding="%s" ?>
778 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
781 def format_output(self
, parts
):
782 """Minimize & standardize the output."""
783 # remove redundant parts & uninteresting parts:
785 assert parts
['body'] == parts
['fragment']
787 del parts
['body_pre_docinfo']
788 del parts
['body_prefix']
789 del parts
['body_suffix']
791 del parts
['head_prefix']
792 del parts
['encoding']
794 # remove standard portions:
795 parts
['meta'] = parts
['meta'].replace(self
.standard_meta_value
, '')
796 parts
['html_head'] = parts
['html_head'].replace(
797 self
.standard_html_meta_value
, '...')
798 parts
['html_prolog'] = parts
['html_prolog'].replace(
799 self
.standard_html_prolog
, '')
800 # remove empty values:
801 for key
in parts
.keys():
804 # standard output format:
809 output
.append("%r: '''%s'''"
810 % (key
, parts
[key
].encode('raw_unicode_escape')))
811 if output
[-1].endswith("\n'''"):
812 output
[-1] = output
[-1][:-4] + "\\n'''"
813 return '{' + ',\n '.join(output
) + '}\n'
816 def exception_data(code
):
818 Execute `code` and return the resulting exception, the exception arguments,
819 and the formatted exception string.
823 except Exception, detail
:
824 return (detail
, detail
.args
,
825 '%s: %s' % (detail
.__class
__.__name
__, detail
))
828 def _format_str(*args
):
830 Return a tuple containing representations of all args.
832 Same as map(repr, args) except that it returns multi-line
833 representations for strings containing newlines, e.g.::
845 This is a helper function for CustomTestCase.
850 if ( (isinstance(i
, StringType
) or isinstance(i
, UnicodeType
))
853 if isinstance(i
, UnicodeType
):
854 # stripped = 'u' or 'U'
857 # quote_char = "'" or '"'
859 assert quote_char
in ("'", '"')
862 r
= (stripped
+ 3 * quote_char
+ '\\\n' +
863 re
.sub(r
'(?<!\\)((\\\\)*)\\n', r
'\1\n', r
) +
865 r
= re
.sub(r
' \n', r
' \\n\\\n', r
)
866 return_tuple
.append(r
)
867 return tuple(return_tuple
)