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.utils.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 if sys
.version_info
>= (3,0):
54 sys
.path
.insert(0, os
.path
.normpath(os
.path
.join(testroot
,
55 '..', 'build', 'lib')))
56 sys
.path
.append(os
.path
.normpath(os
.path
.join(testroot
, '..',
57 'build', 'lib', 'extras')))
59 sys
.path
.insert(0, os
.path
.normpath(os
.path
.join(testroot
, '..')))
60 sys
.path
.append(os
.path
.normpath(os
.path
.join(testroot
, '..', 'extras')))
61 sys
.path
.insert(0, testroot
)
65 import package_unittest
68 from docutils
import frontend
, nodes
, statemachine
, utils
69 from docutils
.utils
import urischemes
70 from docutils
.transforms
import universal
71 from docutils
.parsers
import rst
72 from docutils
.parsers
.rst
import states
, tableparser
, roles
, languages
73 from docutils
.readers
import standalone
, pep
74 from docutils
.statemachine
import StringList
, string2lines
75 from docutils
._compat
import bytes
77 # The importing module (usually __init__.py in one of the
78 # subdirectories) may catch ImportErrors in order to detect the
79 # absence of DocutilsTestSupport in sys.path. Thus, ImportErrors
80 # resulting from problems with importing Docutils modules must
92 # Hack to make repr(StringList) look like repr(list):
93 StringList
.__repr
__ = StringList
.__str
__
100 def write(self
, string
):
107 class StandardTestCase(unittest
.TestCase
):
110 Helper class, providing the same interface as unittest.TestCase,
111 but with useful setUp and comparison methods.
117 def assertEqual(self
, first
, second
, msg
=None):
118 """Fail if the two objects are unequal as determined by the '=='
121 if not first
== second
:
122 raise self
.failureException
, (
123 msg
or '%s != %s' % _format_str(first
, second
))
125 def assertNotEqual(self
, first
, second
, msg
=None):
126 """Fail if the two objects are equal as determined by the '=='
130 raise self
.failureException
, (
131 msg
or '%s == %s' % _format_str(first
, second
))
133 # assertIn and assertNotIn: new in Python 2.7:
135 def assertIn(self
, a
, b
, msg
=None):
137 raise self
.failureException
, (
138 msg
or '%s not in %s' % _format_str(a
, b
))
140 def assertNotIn(self
, a
, b
, msg
=None):
142 raise self
.failureException
, (
143 msg
or '%s in %s' % _format_str(a
, b
))
145 # aliases for assertion methods, deprecated since Python 2.7
147 failUnlessEqual
= assertEquals
= assertEqual
149 assertNotEquals
= failIfEqual
= assertNotEqual
152 class CustomTestCase(StandardTestCase
):
155 Helper class, providing extended functionality over unittest.TestCase.
157 The methods assertEqual and assertNotEqual have been overwritten
158 to provide better support for multi-line strings. Furthermore,
159 see the compare_output method and the parameter list of __init__.
162 compare
= difflib
.Differ().compare
163 """Comparison method shared by all subclasses."""
165 def __init__(self
, method_name
, input, expected
, id,
166 run_in_debugger
=True, suite_settings
=None):
168 Initialise the CustomTestCase.
172 method_name -- name of test method to run.
173 input -- input to the parser.
174 expected -- expected output from the parser.
175 id -- unique test identifier, used by the test framework.
176 run_in_debugger -- if true, run this test under the pdb debugger.
177 suite_settings -- settings overrides for this test suite.
181 self
.expected
= expected
182 self
.run_in_debugger
= run_in_debugger
183 self
.suite_settings
= suite_settings
.copy() or {}
186 unittest
.TestCase
.__init
__(self
, method_name
)
190 Return string conversion. Overridden to give test id, in addition to
193 return '%s; %s' % (self
.id, unittest
.TestCase
.__str
__(self
))
196 return "<%s %s>" % (self
.id, unittest
.TestCase
.__repr
__(self
))
198 def clear_roles(self
):
199 # Language-specific roles and roles added by the
200 # "default-role" and "role" directives are currently stored
201 # globally in the roles._roles dictionary. This workaround
202 # empties that dictionary.
206 StandardTestCase
.setUp(self
)
209 def compare_output(self
, input, output
, expected
):
210 """`input`, `output`, and `expected` should all be strings."""
211 if isinstance(input, unicode):
212 input = input.encode('raw_unicode_escape')
213 if sys
.version_info
> (3,):
214 # API difference: Python 3's node.__str__ doesn't escape
215 #assert expected is None or isinstance(expected, unicode)
216 if isinstance(expected
, bytes
):
217 expected
= expected
.decode('utf-8')
218 if isinstance(output
, bytes
):
219 output
= output
.decode('utf-8')
221 if isinstance(expected
, unicode):
222 expected
= expected
.encode('raw_unicode_escape')
223 if isinstance(output
, unicode):
224 output
= output
.encode('raw_unicode_escape')
225 # Normalize line endings:
227 expected
= '\n'.join(expected
.splitlines())
229 output
= '\n'.join(output
.splitlines())
231 self
.assertEqual(output
, expected
)
232 except AssertionError, error
:
233 print >>sys
.stderr
, '\n%s\ninput:' % (self
,)
234 print >>sys
.stderr
, input
236 comparison
= ''.join(self
.compare(expected
.splitlines(1),
237 output
.splitlines(1)))
238 print >>sys
.stderr
, '-: expected\n+: output'
239 print >>sys
.stderr
, comparison
240 except AttributeError: # expected or output not a string
241 # alternative output for non-strings:
242 print >>sys
.stderr
, 'expected: %r' % expected
243 print >>sys
.stderr
, 'output: %r' % output
247 class CustomTestSuite(unittest
.TestSuite
):
250 A collection of CustomTestCases.
252 Provides test suite ID generation and a method for adding test cases.
256 """Identifier for the TestSuite. Prepended to the
257 TestCase identifiers to make identification easier."""
259 next_test_case_id
= 0
260 """The next identifier to use for non-identified test cases."""
262 def __init__(self
, tests
=(), id=None, suite_settings
=None):
264 Initialize the CustomTestSuite.
268 id -- identifier for the suite, prepended to test cases.
269 suite_settings -- settings overrides for this test suite.
271 unittest
.TestSuite
.__init
__(self
, tests
)
272 self
.suite_settings
= suite_settings
or {}
274 mypath
= os
.path
.abspath(
275 sys
.modules
[CustomTestSuite
.__module
__].__file
__)
276 outerframes
= inspect
.getouterframes(inspect
.currentframe())
277 for outerframe
in outerframes
[1:]:
278 if outerframe
[3] != '__init__':
279 callerpath
= outerframe
[1]
280 if callerpath
is None:
281 # It happens sometimes. Why is a mystery.
282 callerpath
= os
.getcwd()
283 callerpath
= os
.path
.abspath(callerpath
)
285 mydir
, myname
= os
.path
.split(mypath
)
288 if callerpath
.startswith(mydir
):
289 self
.id = callerpath
[len(mydir
) + 1:] # caller's module
295 def addTestCase(self
, test_case_class
, method_name
, input, expected
,
296 id=None, run_in_debugger
=False, **kwargs
):
298 Create a CustomTestCase in the CustomTestSuite.
299 Also return it, just in case.
303 test_case_class -- the CustomTestCase to add
304 method_name -- a string; CustomTestCase.method_name is the test
305 input -- input to the parser.
306 expected -- expected output from the parser.
307 id -- unique test identifier, used by the test framework.
308 run_in_debugger -- if true, run this test under the pdb debugger.
310 if id is None: # generate id if required
311 id = self
.next_test_case_id
312 self
.next_test_case_id
+= 1
313 # test identifier will become suiteid.testid
314 tcid
= '%s: %s' % (self
.id, id)
315 # suite_settings may be passed as a parameter;
316 # if not, set from attribute:
317 kwargs
.setdefault('suite_settings', self
.suite_settings
)
318 # generate and add test case
319 tc
= test_case_class(method_name
, input, expected
, tcid
,
320 run_in_debugger
=run_in_debugger
, **kwargs
)
324 def generate_no_tests(self
, *args
, **kwargs
):
328 class TransformTestCase(CustomTestCase
):
331 Output checker for the transform.
333 Should probably be called TransformOutputChecker, but I can deal with
334 that later when/if someone comes up with a category of transform test
335 cases that have nothing to do with the input and output of the transform.
338 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
339 settings
= option_parser
.get_default_values()
340 settings
.report_level
= 1
341 settings
.halt_level
= 5
342 settings
.debug
= package_unittest
.debug
343 settings
.warning_stream
= DevNull()
344 unknown_reference_resolvers
= ()
346 def __init__(self
, *args
, **kwargs
):
347 self
.transforms
= kwargs
['transforms']
348 """List of transforms to perform for this test case."""
350 self
.parser
= kwargs
['parser']
351 """Input parser for this test case."""
353 del kwargs
['transforms'], kwargs
['parser'] # only wanted here
354 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
356 def supports(self
, format
):
359 def test_transforms(self
):
360 if self
.run_in_debugger
:
362 settings
= self
.settings
.copy()
363 settings
.__dict
__.update(self
.suite_settings
)
364 document
= utils
.new_document('test data', settings
)
365 self
.parser
.parse(self
.input, document
)
366 # Don't do a ``populate_from_components()`` because that would
367 # enable the Transformer's default transforms.
368 document
.transformer
.add_transforms(self
.transforms
)
369 document
.transformer
.add_transform(universal
.TestMessages
)
370 document
.transformer
.components
['writer'] = self
371 document
.transformer
.apply_transforms()
372 output
= document
.pformat()
373 self
.compare_output(self
.input, output
, self
.expected
)
375 def test_transforms_verbosely(self
):
376 if self
.run_in_debugger
:
381 settings
= self
.settings
.copy()
382 settings
.__dict
__.update(self
.suite_settings
)
383 document
= utils
.new_document('test data', settings
)
384 self
.parser
.parse(self
.input, document
)
386 print document
.pformat()
387 for transformClass
in self
.transforms
:
388 transformClass(document
).apply()
389 output
= document
.pformat()
392 self
.compare_output(self
.input, output
, self
.expected
)
395 class TransformTestSuite(CustomTestSuite
):
398 A collection of TransformTestCases.
400 A TransformTestSuite instance manufactures TransformTestCases,
401 keeps track of them, and provides a shared test fixture (a-la
405 def __init__(self
, parser
, suite_settings
=None):
407 """Parser shared by all test cases."""
409 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
411 def generateTests(self
, dict, dictname
='totest',
412 testmethod
='test_transforms'):
414 Stock the suite with test cases generated from a test data dictionary.
416 Each dictionary key (test type's name) maps to a tuple, whose
417 first item is a list of transform classes and whose second
418 item is a list of tests. Each test is a list: input, expected
419 output, optional modifier. The optional third entry, a
420 behavior modifier, can be 0 (temporarily disable this test) or
421 1 (run this test under the pdb debugger). Tests should be
422 self-documenting and not require external comments.
424 for name
, (transforms
, cases
) in dict.items():
425 for casenum
in range(len(cases
)):
426 case
= cases
[casenum
]
427 run_in_debugger
= False
429 # TODO: (maybe) change the 3rd argument to a dict, so it
430 # can handle more cases by keyword ('disable', 'debug',
431 # 'settings'), here and in other generateTests methods.
432 # But there's also the method that
433 # HtmlPublishPartsTestSuite uses <DJG>
435 run_in_debugger
= True
439 TransformTestCase
, testmethod
,
440 transforms
=transforms
, parser
=self
.parser
,
441 input=case
[0], expected
=case
[1],
442 id='%s[%r][%s]' % (dictname
, name
, casenum
),
443 run_in_debugger
=run_in_debugger
)
446 class ParserTestCase(CustomTestCase
):
449 Output checker for the parser.
451 Should probably be called ParserOutputChecker, but I can deal with
452 that later when/if someone comes up with a category of parser test
453 cases that have nothing to do with the input and output of the parser.
456 parser
= rst
.Parser()
457 """Parser shared by all ParserTestCases."""
459 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
460 settings
= option_parser
.get_default_values()
461 settings
.report_level
= 5
462 settings
.halt_level
= 5
463 settings
.debug
= package_unittest
.debug
465 def test_parser(self
):
466 if self
.run_in_debugger
:
468 settings
= self
.settings
.copy()
469 settings
.__dict
__.update(self
.suite_settings
)
470 document
= utils
.new_document('test data', settings
)
471 self
.parser
.parse(self
.input, document
)
472 output
= document
.pformat()
473 self
.compare_output(self
.input, output
, self
.expected
)
476 class ParserTestSuite(CustomTestSuite
):
479 A collection of ParserTestCases.
481 A ParserTestSuite instance manufactures ParserTestCases,
482 keeps track of them, and provides a shared test fixture (a-la
486 test_case_class
= ParserTestCase
488 def generateTests(self
, dict, dictname
='totest'):
490 Stock the suite with test cases generated from a test data dictionary.
492 Each dictionary key (test type name) maps to a list of tests. Each
493 test is a list: input, expected output, optional modifier. The
494 optional third entry, a behavior modifier, can be 0 (temporarily
495 disable this test) or 1 (run this test under the pdb debugger). Tests
496 should be self-documenting and not require external comments.
498 for name
, cases
in dict.items():
499 for casenum
in range(len(cases
)):
500 case
= cases
[casenum
]
501 run_in_debugger
= False
504 run_in_debugger
= True
508 self
.test_case_class
, 'test_parser',
509 input=case
[0], expected
=case
[1],
510 id='%s[%r][%s]' % (dictname
, name
, casenum
),
511 run_in_debugger
=run_in_debugger
)
514 class PEPParserTestCase(ParserTestCase
):
516 """PEP-specific parser test case."""
518 parser
= rst
.Parser(rfc2822
=True, inliner
=rst
.states
.Inliner())
519 """Parser shared by all PEPParserTestCases."""
521 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
, pep
.Reader
))
522 settings
= option_parser
.get_default_values()
523 settings
.report_level
= 5
524 settings
.halt_level
= 5
525 settings
.debug
= package_unittest
.debug
528 class PEPParserTestSuite(ParserTestSuite
):
530 """A collection of PEPParserTestCases."""
532 test_case_class
= PEPParserTestCase
535 class GridTableParserTestCase(CustomTestCase
):
537 parser
= tableparser
.GridTableParser()
539 def test_parse_table(self
):
540 self
.parser
.setup(StringList(string2lines(self
.input), 'test data'))
542 self
.parser
.find_head_body_sep()
543 self
.parser
.parse_table()
544 output
= self
.parser
.cells
545 except Exception, details
:
546 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
547 self
.compare_output(self
.input, pformat(output
) + '\n',
548 pformat(self
.expected
) + '\n')
550 def test_parse(self
):
552 output
= self
.parser
.parse(StringList(string2lines(self
.input),
554 except Exception, details
:
555 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
556 self
.compare_output(self
.input, pformat(output
) + '\n',
557 pformat(self
.expected
) + '\n')
560 class GridTableParserTestSuite(CustomTestSuite
):
563 A collection of GridTableParserTestCases.
565 A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
566 keeps track of them, and provides a shared test fixture (a-la setUp and
570 test_case_class
= GridTableParserTestCase
572 def generateTests(self
, dict, dictname
='totest'):
574 Stock the suite with test cases generated from a test data dictionary.
576 Each dictionary key (test type name) maps to a list of tests. Each
577 test is a list: an input table, expected output from parse_table(),
578 expected output from parse(), optional modifier. The optional fourth
579 entry, a behavior modifier, can be 0 (temporarily disable this test)
580 or 1 (run this test under the pdb debugger). Tests should be
581 self-documenting and not require external comments.
583 for name
, cases
in dict.items():
584 for casenum
in range(len(cases
)):
585 case
= cases
[casenum
]
586 run_in_debugger
= False
589 run_in_debugger
= True
592 self
.addTestCase(self
.test_case_class
, 'test_parse_table',
593 input=case
[0], expected
=case
[1],
594 id='%s[%r][%s]' % (dictname
, name
, casenum
),
595 run_in_debugger
=run_in_debugger
)
596 self
.addTestCase(self
.test_case_class
, 'test_parse',
597 input=case
[0], expected
=case
[2],
598 id='%s[%r][%s]' % (dictname
, name
, casenum
),
599 run_in_debugger
=run_in_debugger
)
602 class SimpleTableParserTestCase(GridTableParserTestCase
):
604 parser
= tableparser
.SimpleTableParser()
607 class SimpleTableParserTestSuite(CustomTestSuite
):
610 A collection of SimpleTableParserTestCases.
613 test_case_class
= SimpleTableParserTestCase
615 def generateTests(self
, dict, dictname
='totest'):
617 Stock the suite with test cases generated from a test data dictionary.
619 Each dictionary key (test type name) maps to a list of tests. Each
620 test is a list: an input table, expected output from parse(), optional
621 modifier. The optional third entry, a behavior modifier, can be 0
622 (temporarily disable this test) or 1 (run this test under the pdb
623 debugger). Tests should be self-documenting and not require external
626 for name
, cases
in dict.items():
627 for casenum
in range(len(cases
)):
628 case
= cases
[casenum
]
629 run_in_debugger
= False
632 run_in_debugger
= True
635 self
.addTestCase(self
.test_case_class
, 'test_parse',
636 input=case
[0], expected
=case
[1],
637 id='%s[%r][%s]' % (dictname
, name
, casenum
),
638 run_in_debugger
=run_in_debugger
)
641 class PythonModuleParserTestCase(CustomTestCase
):
643 def test_parser(self
):
644 if self
.run_in_debugger
:
651 from docutils
.readers
.python
import moduleparser
652 module
= moduleparser
.parse_module(self
.input, 'test data').pformat()
654 self
.compare_output(self
.input, output
, self
.expected
)
656 def test_token_parser_rhs(self
):
657 if self
.run_in_debugger
:
664 from docutils
.readers
.python
import moduleparser
665 tr
= moduleparser
.TokenParser(self
.input)
667 self
.compare_output(self
.input, output
, self
.expected
)
670 class PythonModuleParserTestSuite(CustomTestSuite
):
673 A collection of PythonModuleParserTestCase.
676 def generateTests(self
, dict, dictname
='totest',
677 testmethod
='test_parser'):
679 Stock the suite with test cases generated from a test data dictionary.
681 Each dictionary key (test type's name) maps to a list of tests. Each
682 test is a list: input, expected output, optional modifier. The
683 optional third entry, a behavior modifier, can be 0 (temporarily
684 disable this test) or 1 (run this test under the pdb debugger). Tests
685 should be self-documenting and not require external comments.
687 for name
, cases
in dict.items():
688 for casenum
in range(len(cases
)):
689 case
= cases
[casenum
]
690 run_in_debugger
= False
693 run_in_debugger
= True
697 PythonModuleParserTestCase
, testmethod
,
698 input=case
[0], expected
=case
[1],
699 id='%s[%r][%s]' % (dictname
, name
, casenum
),
700 run_in_debugger
=run_in_debugger
)
703 class WriterPublishTestCase(CustomTestCase
, docutils
.SettingsSpec
):
706 Test case for publish.
709 settings_default_overrides
= {'_disable_config': True,
710 'strict_visitor': True}
711 writer_name
= '' # set in subclasses or constructor
713 def __init__(self
, *args
, **kwargs
):
714 if 'writer_name' in kwargs
:
715 self
.writer_name
= kwargs
['writer_name']
716 del kwargs
['writer_name']
717 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
719 def test_publish(self
):
720 if self
.run_in_debugger
:
722 output
= docutils
.core
.publish_string(
724 reader_name
='standalone',
725 parser_name
='restructuredtext',
726 writer_name
=self
.writer_name
,
728 settings_overrides
=self
.suite_settings
)
729 self
.compare_output(self
.input, output
, self
.expected
)
732 class PublishTestSuite(CustomTestSuite
):
734 def __init__(self
, writer_name
, suite_settings
=None):
736 `writer_name` is the name of the writer to use.
738 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
739 self
.test_class
= WriterPublishTestCase
740 self
.writer_name
= writer_name
742 def generateTests(self
, dict, dictname
='totest'):
743 for name
, cases
in dict.items():
744 for casenum
in range(len(cases
)):
745 case
= cases
[casenum
]
746 run_in_debugger
= False
749 run_in_debugger
= True
753 self
.test_class
, 'test_publish',
754 input=case
[0], expected
=case
[1],
755 id='%s[%r][%s]' % (dictname
, name
, casenum
),
756 run_in_debugger
=run_in_debugger
,
757 # Passed to constructor of self.test_class:
758 writer_name
=self
.writer_name
)
761 class HtmlPublishPartsTestSuite(CustomTestSuite
):
763 def generateTests(self
, dict, dictname
='totest'):
764 for name
, (settings_overrides
, cases
) in dict.items():
765 settings
= self
.suite_settings
.copy()
766 settings
.update(settings_overrides
)
767 for casenum
in range(len(cases
)):
768 case
= cases
[casenum
]
769 run_in_debugger
= False
772 run_in_debugger
= True
776 HtmlWriterPublishPartsTestCase
, 'test_publish',
777 input=case
[0], expected
=case
[1],
778 id='%s[%r][%s]' % (dictname
, name
, casenum
),
779 run_in_debugger
=run_in_debugger
,
780 suite_settings
=settings
)
783 class HtmlWriterPublishPartsTestCase(WriterPublishTestCase
):
786 Test case for HTML writer via the publish_parts interface.
791 settings_default_overrides
= \
792 WriterPublishTestCase
.settings_default_overrides
.copy()
793 settings_default_overrides
['stylesheet'] = ''
795 def test_publish(self
):
796 if self
.run_in_debugger
:
798 parts
= docutils
.core
.publish_parts(
800 reader_name
='standalone',
801 parser_name
='restructuredtext',
802 writer_name
=self
.writer_name
,
804 settings_overrides
=self
.suite_settings
)
805 output
= self
.format_output(parts
)
806 # interpolate standard variables:
807 expected
= self
.expected
% {'version': docutils
.__version
__}
808 self
.compare_output(self
.input, output
, expected
)
810 standard_content_type_template
= ('<meta http-equiv="Content-Type"'
811 ' content="text/html; charset=%s" />\n')
812 standard_generator_template
= (
813 '<meta name="generator"'
814 ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
815 standard_html_meta_value
= (
816 standard_content_type_template
817 + standard_generator_template
% docutils
.__version
__)
818 standard_meta_value
= standard_html_meta_value
% 'utf-8'
819 standard_html_prolog
= """\
820 <?xml version="1.0" encoding="%s" ?>
821 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
824 def format_output(self
, parts
):
825 """Minimize & standardize the output."""
826 # remove redundant parts & uninteresting parts:
828 assert parts
['body'] == parts
['fragment']
830 del parts
['body_pre_docinfo']
831 del parts
['body_prefix']
832 del parts
['body_suffix']
834 del parts
['head_prefix']
835 del parts
['encoding']
837 # remove standard portions:
838 parts
['meta'] = parts
['meta'].replace(self
.standard_meta_value
, '')
839 parts
['html_head'] = parts
['html_head'].replace(
840 self
.standard_html_meta_value
, '...')
841 parts
['html_prolog'] = parts
['html_prolog'].replace(
842 self
.standard_html_prolog
, '')
843 # remove empty values:
844 for key
in parts
.keys():
847 # standard output format:
852 output
.append("%r: '''%s'''"
854 if output
[-1].endswith("\n'''"):
855 output
[-1] = output
[-1][:-4] + "\\n'''"
856 return '{' + ',\n '.join(output
) + '}\n'
859 def exception_data(func
, *args
, **kwds
):
861 Execute `func(*args, **kwds)` and return the resulting exception, the
862 exception arguments, and the formatted exception string.
866 except Exception, detail
:
867 return (detail
, detail
.args
,
868 '%s: %s' % (detail
.__class
__.__name
__, detail
))
871 def _format_str(*args
):
873 Return a tuple containing representations of all args.
875 Same as map(repr, args) except that it returns multi-line
876 representations for strings containing newlines, e.g.::
888 This is a helper function for CustomTestCase.
893 if ( (isinstance(i
, bytes
) or isinstance(i
, unicode))
896 if isinstance(i
, unicode) and r
.startswith('u'):
899 elif isinstance(i
, bytes
) and r
.startswith('b'):
902 # quote_char = "'" or '"'
904 assert quote_char
in ("'", '"'), quote_char
907 r
= (stripped
+ 3 * quote_char
+ '\\\n' +
908 re
.sub(r
'(?<!\\)((\\\\)*)\\n', r
'\1\n', r
) +
910 r
= re
.sub(r
' \n', r
' \\n\\\n', r
)
911 return_tuple
.append(r
)
912 return tuple(return_tuple
)