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 # aliases for assertion methods, deprecated since Python 2.7
135 failUnlessEqual
= assertEquals
= assertEqual
137 assertNotEquals
= failIfEqual
= assertNotEqual
140 class CustomTestCase(StandardTestCase
):
143 Helper class, providing extended functionality over unittest.TestCase.
145 The methods assertEqual and assertNotEqual have been overwritten
146 to provide better support for multi-line strings. Furthermore,
147 see the compare_output method and the parameter list of __init__.
150 compare
= difflib
.Differ().compare
151 """Comparison method shared by all subclasses."""
153 def __init__(self
, method_name
, input, expected
, id,
154 run_in_debugger
=True, suite_settings
=None):
156 Initialise the CustomTestCase.
160 method_name -- name of test method to run.
161 input -- input to the parser.
162 expected -- expected output from the parser.
163 id -- unique test identifier, used by the test framework.
164 run_in_debugger -- if true, run this test under the pdb debugger.
165 suite_settings -- settings overrides for this test suite.
169 self
.expected
= expected
170 self
.run_in_debugger
= run_in_debugger
171 self
.suite_settings
= suite_settings
.copy() or {}
174 unittest
.TestCase
.__init
__(self
, method_name
)
178 Return string conversion. Overridden to give test id, in addition to
181 return '%s; %s' % (self
.id, unittest
.TestCase
.__str
__(self
))
184 return "<%s %s>" % (self
.id, unittest
.TestCase
.__repr
__(self
))
186 def clear_roles(self
):
187 # Language-specific roles and roles added by the
188 # "default-role" and "role" directives are currently stored
189 # globally in the roles._roles dictionary. This workaround
190 # empties that dictionary.
194 StandardTestCase
.setUp(self
)
197 def compare_output(self
, input, output
, expected
):
198 """`input`, `output`, and `expected` should all be strings."""
199 if isinstance(input, unicode):
200 input = input.encode('raw_unicode_escape')
201 if sys
.version_info
> (3,):
202 # API difference: Python 3's node.__str__ doesn't escape
203 #assert expected is None or isinstance(expected, unicode)
204 if isinstance(expected
, bytes
):
205 expected
= expected
.decode('utf-8')
206 if isinstance(output
, bytes
):
207 output
= output
.decode('utf-8')
209 if isinstance(expected
, unicode):
210 expected
= expected
.encode('raw_unicode_escape')
211 if isinstance(output
, unicode):
212 output
= output
.encode('raw_unicode_escape')
213 # Normalize line endings:
215 expected
= '\n'.join(expected
.splitlines())
217 output
= '\n'.join(output
.splitlines())
219 self
.assertEqual(output
, expected
)
220 except AssertionError, error
:
221 print >>sys
.stderr
, '\n%s\ninput:' % (self
,)
222 print >>sys
.stderr
, input
224 comparison
= ''.join(self
.compare(expected
.splitlines(1),
225 output
.splitlines(1)))
226 print >>sys
.stderr
, '-: expected\n+: output'
227 print >>sys
.stderr
, comparison
228 except AttributeError: # expected or output not a string
229 # alternative output for non-strings:
230 print >>sys
.stderr
, 'expected: %r' % expected
231 print >>sys
.stderr
, 'output: %r' % output
235 class CustomTestSuite(unittest
.TestSuite
):
238 A collection of CustomTestCases.
240 Provides test suite ID generation and a method for adding test cases.
244 """Identifier for the TestSuite. Prepended to the
245 TestCase identifiers to make identification easier."""
247 next_test_case_id
= 0
248 """The next identifier to use for non-identified test cases."""
250 def __init__(self
, tests
=(), id=None, suite_settings
=None):
252 Initialize the CustomTestSuite.
256 id -- identifier for the suite, prepended to test cases.
257 suite_settings -- settings overrides for this test suite.
259 unittest
.TestSuite
.__init
__(self
, tests
)
260 self
.suite_settings
= suite_settings
or {}
262 mypath
= os
.path
.abspath(
263 sys
.modules
[CustomTestSuite
.__module
__].__file
__)
264 outerframes
= inspect
.getouterframes(inspect
.currentframe())
265 for outerframe
in outerframes
[1:]:
266 if outerframe
[3] != '__init__':
267 callerpath
= outerframe
[1]
268 if callerpath
is None:
269 # It happens sometimes. Why is a mystery.
270 callerpath
= os
.getcwd()
271 callerpath
= os
.path
.abspath(callerpath
)
273 mydir
, myname
= os
.path
.split(mypath
)
276 if callerpath
.startswith(mydir
):
277 self
.id = callerpath
[len(mydir
) + 1:] # caller's module
283 def addTestCase(self
, test_case_class
, method_name
, input, expected
,
284 id=None, run_in_debugger
=False, **kwargs
):
286 Create a CustomTestCase in the CustomTestSuite.
287 Also return it, just in case.
291 test_case_class -- the CustomTestCase to add
292 method_name -- a string; CustomTestCase.method_name is the test
293 input -- input to the parser.
294 expected -- expected output from the parser.
295 id -- unique test identifier, used by the test framework.
296 run_in_debugger -- if true, run this test under the pdb debugger.
298 if id is None: # generate id if required
299 id = self
.next_test_case_id
300 self
.next_test_case_id
+= 1
301 # test identifier will become suiteid.testid
302 tcid
= '%s: %s' % (self
.id, id)
303 # suite_settings may be passed as a parameter;
304 # if not, set from attribute:
305 kwargs
.setdefault('suite_settings', self
.suite_settings
)
306 # generate and add test case
307 tc
= test_case_class(method_name
, input, expected
, tcid
,
308 run_in_debugger
=run_in_debugger
, **kwargs
)
312 def generate_no_tests(self
, *args
, **kwargs
):
316 class TransformTestCase(CustomTestCase
):
319 Output checker for the transform.
321 Should probably be called TransformOutputChecker, but I can deal with
322 that later when/if someone comes up with a category of transform test
323 cases that have nothing to do with the input and output of the transform.
326 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
327 settings
= option_parser
.get_default_values()
328 settings
.report_level
= 1
329 settings
.halt_level
= 5
330 settings
.debug
= package_unittest
.debug
331 settings
.warning_stream
= DevNull()
332 unknown_reference_resolvers
= ()
334 def __init__(self
, *args
, **kwargs
):
335 self
.transforms
= kwargs
['transforms']
336 """List of transforms to perform for this test case."""
338 self
.parser
= kwargs
['parser']
339 """Input parser for this test case."""
341 del kwargs
['transforms'], kwargs
['parser'] # only wanted here
342 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
344 def supports(self
, format
):
347 def test_transforms(self
):
348 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
)
354 # Don't do a ``populate_from_components()`` because that would
355 # enable the Transformer's default transforms.
356 document
.transformer
.add_transforms(self
.transforms
)
357 document
.transformer
.add_transform(universal
.TestMessages
)
358 document
.transformer
.components
['writer'] = self
359 document
.transformer
.apply_transforms()
360 output
= document
.pformat()
361 self
.compare_output(self
.input, output
, self
.expected
)
363 def test_transforms_verbosely(self
):
364 if self
.run_in_debugger
:
369 settings
= self
.settings
.copy()
370 settings
.__dict
__.update(self
.suite_settings
)
371 document
= utils
.new_document('test data', settings
)
372 self
.parser
.parse(self
.input, document
)
374 print document
.pformat()
375 for transformClass
in self
.transforms
:
376 transformClass(document
).apply()
377 output
= document
.pformat()
380 self
.compare_output(self
.input, output
, self
.expected
)
383 class TransformTestSuite(CustomTestSuite
):
386 A collection of TransformTestCases.
388 A TransformTestSuite instance manufactures TransformTestCases,
389 keeps track of them, and provides a shared test fixture (a-la
393 def __init__(self
, parser
, suite_settings
=None):
395 """Parser shared by all test cases."""
397 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
399 def generateTests(self
, dict, dictname
='totest',
400 testmethod
='test_transforms'):
402 Stock the suite with test cases generated from a test data dictionary.
404 Each dictionary key (test type's name) maps to a tuple, whose
405 first item is a list of transform classes and whose second
406 item is a list of tests. Each test is a list: input, expected
407 output, optional modifier. The optional third entry, a
408 behavior modifier, can be 0 (temporarily disable this test) or
409 1 (run this test under the pdb debugger). Tests should be
410 self-documenting and not require external comments.
412 for name
, (transforms
, cases
) in dict.items():
413 for casenum
in range(len(cases
)):
414 case
= cases
[casenum
]
415 run_in_debugger
= False
417 # TODO: (maybe) change the 3rd argument to a dict, so it
418 # can handle more cases by keyword ('disable', 'debug',
419 # 'settings'), here and in other generateTests methods.
420 # But there's also the method that
421 # HtmlPublishPartsTestSuite uses <DJG>
423 run_in_debugger
= True
427 TransformTestCase
, testmethod
,
428 transforms
=transforms
, parser
=self
.parser
,
429 input=case
[0], expected
=case
[1],
430 id='%s[%r][%s]' % (dictname
, name
, casenum
),
431 run_in_debugger
=run_in_debugger
)
434 class ParserTestCase(CustomTestCase
):
437 Output checker for the parser.
439 Should probably be called ParserOutputChecker, but I can deal with
440 that later when/if someone comes up with a category of parser test
441 cases that have nothing to do with the input and output of the parser.
444 parser
= rst
.Parser()
445 """Parser shared by all ParserTestCases."""
447 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
448 settings
= option_parser
.get_default_values()
449 settings
.report_level
= 5
450 settings
.halt_level
= 5
451 settings
.debug
= package_unittest
.debug
453 def test_parser(self
):
454 if self
.run_in_debugger
:
456 settings
= self
.settings
.copy()
457 settings
.__dict
__.update(self
.suite_settings
)
458 document
= utils
.new_document('test data', settings
)
459 self
.parser
.parse(self
.input, document
)
460 output
= document
.pformat()
461 self
.compare_output(self
.input, output
, self
.expected
)
464 class ParserTestSuite(CustomTestSuite
):
467 A collection of ParserTestCases.
469 A ParserTestSuite instance manufactures ParserTestCases,
470 keeps track of them, and provides a shared test fixture (a-la
474 test_case_class
= ParserTestCase
476 def generateTests(self
, dict, dictname
='totest'):
478 Stock the suite with test cases generated from a test data dictionary.
480 Each dictionary key (test type name) maps to a list of tests. Each
481 test is a list: input, expected output, optional modifier. The
482 optional third entry, a behavior modifier, can be 0 (temporarily
483 disable this test) or 1 (run this test under the pdb debugger). Tests
484 should be self-documenting and not require external comments.
486 for name
, cases
in dict.items():
487 for casenum
in range(len(cases
)):
488 case
= cases
[casenum
]
489 run_in_debugger
= False
492 run_in_debugger
= True
496 self
.test_case_class
, 'test_parser',
497 input=case
[0], expected
=case
[1],
498 id='%s[%r][%s]' % (dictname
, name
, casenum
),
499 run_in_debugger
=run_in_debugger
)
502 class PEPParserTestCase(ParserTestCase
):
504 """PEP-specific parser test case."""
506 parser
= rst
.Parser(rfc2822
=True, inliner
=rst
.states
.Inliner())
507 """Parser shared by all PEPParserTestCases."""
509 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
, pep
.Reader
))
510 settings
= option_parser
.get_default_values()
511 settings
.report_level
= 5
512 settings
.halt_level
= 5
513 settings
.debug
= package_unittest
.debug
516 class PEPParserTestSuite(ParserTestSuite
):
518 """A collection of PEPParserTestCases."""
520 test_case_class
= PEPParserTestCase
523 class GridTableParserTestCase(CustomTestCase
):
525 parser
= tableparser
.GridTableParser()
527 def test_parse_table(self
):
528 self
.parser
.setup(StringList(string2lines(self
.input), 'test data'))
530 self
.parser
.find_head_body_sep()
531 self
.parser
.parse_table()
532 output
= self
.parser
.cells
533 except Exception, details
:
534 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
535 self
.compare_output(self
.input, pformat(output
) + '\n',
536 pformat(self
.expected
) + '\n')
538 def test_parse(self
):
540 output
= self
.parser
.parse(StringList(string2lines(self
.input),
542 except Exception, details
:
543 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
544 self
.compare_output(self
.input, pformat(output
) + '\n',
545 pformat(self
.expected
) + '\n')
548 class GridTableParserTestSuite(CustomTestSuite
):
551 A collection of GridTableParserTestCases.
553 A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
554 keeps track of them, and provides a shared test fixture (a-la setUp and
558 test_case_class
= GridTableParserTestCase
560 def generateTests(self
, dict, dictname
='totest'):
562 Stock the suite with test cases generated from a test data dictionary.
564 Each dictionary key (test type name) maps to a list of tests. Each
565 test is a list: an input table, expected output from parse_table(),
566 expected output from parse(), optional modifier. The optional fourth
567 entry, a behavior modifier, can be 0 (temporarily disable this test)
568 or 1 (run this test under the pdb debugger). Tests should be
569 self-documenting and not require external comments.
571 for name
, cases
in dict.items():
572 for casenum
in range(len(cases
)):
573 case
= cases
[casenum
]
574 run_in_debugger
= False
577 run_in_debugger
= True
580 self
.addTestCase(self
.test_case_class
, 'test_parse_table',
581 input=case
[0], expected
=case
[1],
582 id='%s[%r][%s]' % (dictname
, name
, casenum
),
583 run_in_debugger
=run_in_debugger
)
584 self
.addTestCase(self
.test_case_class
, 'test_parse',
585 input=case
[0], expected
=case
[2],
586 id='%s[%r][%s]' % (dictname
, name
, casenum
),
587 run_in_debugger
=run_in_debugger
)
590 class SimpleTableParserTestCase(GridTableParserTestCase
):
592 parser
= tableparser
.SimpleTableParser()
595 class SimpleTableParserTestSuite(CustomTestSuite
):
598 A collection of SimpleTableParserTestCases.
601 test_case_class
= SimpleTableParserTestCase
603 def generateTests(self
, dict, dictname
='totest'):
605 Stock the suite with test cases generated from a test data dictionary.
607 Each dictionary key (test type name) maps to a list of tests. Each
608 test is a list: an input table, expected output from parse(), optional
609 modifier. The optional third entry, a behavior modifier, can be 0
610 (temporarily disable this test) or 1 (run this test under the pdb
611 debugger). Tests should be self-documenting and not require external
614 for name
, cases
in dict.items():
615 for casenum
in range(len(cases
)):
616 case
= cases
[casenum
]
617 run_in_debugger
= False
620 run_in_debugger
= True
623 self
.addTestCase(self
.test_case_class
, 'test_parse',
624 input=case
[0], expected
=case
[1],
625 id='%s[%r][%s]' % (dictname
, name
, casenum
),
626 run_in_debugger
=run_in_debugger
)
629 class PythonModuleParserTestCase(CustomTestCase
):
631 def test_parser(self
):
632 if self
.run_in_debugger
:
639 from docutils
.readers
.python
import moduleparser
640 module
= moduleparser
.parse_module(self
.input, 'test data').pformat()
642 self
.compare_output(self
.input, output
, self
.expected
)
644 def test_token_parser_rhs(self
):
645 if self
.run_in_debugger
:
652 from docutils
.readers
.python
import moduleparser
653 tr
= moduleparser
.TokenParser(self
.input)
655 self
.compare_output(self
.input, output
, self
.expected
)
658 class PythonModuleParserTestSuite(CustomTestSuite
):
661 A collection of PythonModuleParserTestCase.
664 def generateTests(self
, dict, dictname
='totest',
665 testmethod
='test_parser'):
667 Stock the suite with test cases generated from a test data dictionary.
669 Each dictionary key (test type's name) maps to a list of tests. Each
670 test is a list: input, expected output, optional modifier. The
671 optional third entry, a behavior modifier, can be 0 (temporarily
672 disable this test) or 1 (run this test under the pdb debugger). Tests
673 should be self-documenting and not require external comments.
675 for name
, cases
in dict.items():
676 for casenum
in range(len(cases
)):
677 case
= cases
[casenum
]
678 run_in_debugger
= False
681 run_in_debugger
= True
685 PythonModuleParserTestCase
, testmethod
,
686 input=case
[0], expected
=case
[1],
687 id='%s[%r][%s]' % (dictname
, name
, casenum
),
688 run_in_debugger
=run_in_debugger
)
691 class WriterPublishTestCase(CustomTestCase
, docutils
.SettingsSpec
):
694 Test case for publish.
697 settings_default_overrides
= {'_disable_config': 1,
699 writer_name
= '' # set in subclasses or constructor
701 def __init__(self
, *args
, **kwargs
):
702 if 'writer_name' in kwargs
:
703 self
.writer_name
= kwargs
['writer_name']
704 del kwargs
['writer_name']
705 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
707 def test_publish(self
):
708 if self
.run_in_debugger
:
710 output
= docutils
.core
.publish_string(
712 reader_name
='standalone',
713 parser_name
='restructuredtext',
714 writer_name
=self
.writer_name
,
716 settings_overrides
=self
.suite_settings
)
717 self
.compare_output(self
.input, output
, self
.expected
)
720 class PublishTestSuite(CustomTestSuite
):
722 def __init__(self
, writer_name
, suite_settings
=None):
724 `writer_name` is the name of the writer to use.
726 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
727 self
.test_class
= WriterPublishTestCase
728 self
.writer_name
= writer_name
730 def generateTests(self
, dict, dictname
='totest'):
731 for name
, cases
in dict.items():
732 for casenum
in range(len(cases
)):
733 case
= cases
[casenum
]
734 run_in_debugger
= False
737 run_in_debugger
= True
741 self
.test_class
, 'test_publish',
742 input=case
[0], expected
=case
[1],
743 id='%s[%r][%s]' % (dictname
, name
, casenum
),
744 run_in_debugger
=run_in_debugger
,
745 # Passed to constructor of self.test_class:
746 writer_name
=self
.writer_name
)
749 class HtmlPublishPartsTestSuite(CustomTestSuite
):
751 def generateTests(self
, dict, dictname
='totest'):
752 for name
, (settings_overrides
, cases
) in dict.items():
753 settings
= self
.suite_settings
.copy()
754 settings
.update(settings_overrides
)
755 for casenum
in range(len(cases
)):
756 case
= cases
[casenum
]
757 run_in_debugger
= False
760 run_in_debugger
= True
764 HtmlWriterPublishPartsTestCase
, 'test_publish',
765 input=case
[0], expected
=case
[1],
766 id='%s[%r][%s]' % (dictname
, name
, casenum
),
767 run_in_debugger
=run_in_debugger
,
768 suite_settings
=settings
)
771 class HtmlWriterPublishPartsTestCase(WriterPublishTestCase
):
774 Test case for HTML writer via the publish_parts interface.
779 settings_default_overrides
= \
780 WriterPublishTestCase
.settings_default_overrides
.copy()
781 settings_default_overrides
['stylesheet'] = ''
783 def test_publish(self
):
784 if self
.run_in_debugger
:
786 parts
= docutils
.core
.publish_parts(
788 reader_name
='standalone',
789 parser_name
='restructuredtext',
790 writer_name
=self
.writer_name
,
792 settings_overrides
=self
.suite_settings
)
793 output
= self
.format_output(parts
)
794 # interpolate standard variables:
795 expected
= self
.expected
% {'version': docutils
.__version
__}
796 self
.compare_output(self
.input, output
, expected
)
798 standard_content_type_template
= ('<meta http-equiv="Content-Type"'
799 ' content="text/html; charset=%s" />\n')
800 standard_generator_template
= (
801 '<meta name="generator"'
802 ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
803 standard_html_meta_value
= (
804 standard_content_type_template
805 + standard_generator_template
% docutils
.__version
__)
806 standard_meta_value
= standard_html_meta_value
% 'utf-8'
807 standard_html_prolog
= """\
808 <?xml version="1.0" encoding="%s" ?>
809 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
812 def format_output(self
, parts
):
813 """Minimize & standardize the output."""
814 # remove redundant parts & uninteresting parts:
816 assert parts
['body'] == parts
['fragment']
818 del parts
['body_pre_docinfo']
819 del parts
['body_prefix']
820 del parts
['body_suffix']
822 del parts
['head_prefix']
823 del parts
['encoding']
825 # remove standard portions:
826 parts
['meta'] = parts
['meta'].replace(self
.standard_meta_value
, '')
827 parts
['html_head'] = parts
['html_head'].replace(
828 self
.standard_html_meta_value
, '...')
829 parts
['html_prolog'] = parts
['html_prolog'].replace(
830 self
.standard_html_prolog
, '')
831 # remove empty values:
832 for key
in parts
.keys():
835 # standard output format:
840 output
.append("%r: '''%s'''"
842 if output
[-1].endswith("\n'''"):
843 output
[-1] = output
[-1][:-4] + "\\n'''"
844 return '{' + ',\n '.join(output
) + '}\n'
847 def exception_data(func
, *args
, **kwds
):
849 Execute `func(*args, **kwds)` and return the resulting exception, the
850 exception arguments, and the formatted exception string.
854 except Exception, detail
:
855 return (detail
, detail
.args
,
856 '%s: %s' % (detail
.__class
__.__name
__, detail
))
859 def _format_str(*args
):
861 Return a tuple containing representations of all args.
863 Same as map(repr, args) except that it returns multi-line
864 representations for strings containing newlines, e.g.::
876 This is a helper function for CustomTestCase.
881 if ( (isinstance(i
, bytes
) or isinstance(i
, unicode))
884 if isinstance(i
, unicode) and r
.startswith('u'):
887 elif isinstance(i
, bytes
) and r
.startswith('b'):
890 # quote_char = "'" or '"'
892 assert quote_char
in ("'", '"'), quote_char
895 r
= (stripped
+ 3 * quote_char
+ '\\\n' +
896 re
.sub(r
'(?<!\\)((\\\\)*)\\n', r
'\1\n', r
) +
898 r
= re
.sub(r
' \n', r
' \\n\\\n', r
)
899 return_tuple
.append(r
)
900 return tuple(return_tuple
)