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 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
, urischemes
, utils
69 from docutils
.transforms
import universal
70 from docutils
.parsers
import rst
71 from docutils
.parsers
.rst
import states
, tableparser
, roles
, languages
72 from docutils
.readers
import standalone
, pep
73 from docutils
.statemachine
import StringList
, string2lines
74 from docutils
._compat
import bytes
76 # The importing module (usually __init__.py in one of the
77 # subdirectories) may catch ImportErrors in order to detect the
78 # absence of DocutilsTestSupport in sys.path. Thus, ImportErrors
79 # resulting from problems with importing Docutils modules must
91 # Hack to make repr(StringList) look like repr(list):
92 StringList
.__repr
__ = StringList
.__str
__
99 def write(self
, string
):
106 class StandardTestCase(unittest
.TestCase
):
109 Helper class, providing the same interface as unittest.TestCase,
110 but with useful setUp and comparison methods.
116 def assertEqual(self
, first
, second
, msg
=None):
117 """Fail if the two objects are unequal as determined by the '=='
120 if not first
== second
:
121 raise self
.failureException
, \
122 (msg
or '%s != %s' % _format_str(first
, second
))
124 def assertNotEqual(self
, first
, second
, msg
=None):
125 """Fail if the two objects are equal as determined by the '=='
129 raise self
.failureException
, \
130 (msg
or '%s == %s' % _format_str(first
, second
))
132 # aliases for assertion methods, deprecated since Python 2.7
134 failUnlessEqual
= assertEquals
= assertEqual
136 assertNotEquals
= failIfEqual
= assertNotEqual
139 class CustomTestCase(StandardTestCase
):
142 Helper class, providing extended functionality over unittest.TestCase.
144 The methods assertEqual and assertNotEqual have been overwritten
145 to provide better support for multi-line strings. Furthermore,
146 see the compare_output method and the parameter list of __init__.
149 compare
= difflib
.Differ().compare
150 """Comparison method shared by all subclasses."""
152 def __init__(self
, method_name
, input, expected
, id,
153 run_in_debugger
=True, suite_settings
=None):
155 Initialise the CustomTestCase.
159 method_name -- name of test method to run.
160 input -- input to the parser.
161 expected -- expected output from the parser.
162 id -- unique test identifier, used by the test framework.
163 run_in_debugger -- if true, run this test under the pdb debugger.
164 suite_settings -- settings overrides for this test suite.
168 self
.expected
= expected
169 self
.run_in_debugger
= run_in_debugger
170 self
.suite_settings
= suite_settings
.copy() or {}
173 unittest
.TestCase
.__init
__(self
, method_name
)
177 Return string conversion. Overridden to give test id, in addition to
180 return '%s; %s' % (self
.id, unittest
.TestCase
.__str
__(self
))
183 return "<%s %s>" % (self
.id, unittest
.TestCase
.__repr
__(self
))
185 def clear_roles(self
):
186 # Language-specific roles and roles added by the
187 # "default-role" and "role" directives are currently stored
188 # globally in the roles._roles dictionary. This workaround
189 # empties that dictionary.
193 StandardTestCase
.setUp(self
)
196 def compare_output(self
, input, output
, expected
):
197 """`input`, `output`, and `expected` should all be strings."""
198 if isinstance(input, unicode):
199 input = input.encode('raw_unicode_escape')
200 if sys
.version_info
> (3,):
201 # API difference: Python 3's node.__str__ doesn't escape
202 #assert expected is None or isinstance(expected, unicode)
203 if isinstance(expected
, bytes
):
204 expected
= expected
.decode('utf-8')
205 if isinstance(output
, bytes
):
206 output
= output
.decode('utf-8')
208 if isinstance(expected
, unicode):
209 expected
= expected
.encode('raw_unicode_escape')
210 if isinstance(output
, unicode):
211 output
= output
.encode('raw_unicode_escape')
212 # Normalize line endings:
214 expected
= '\n'.join(expected
.splitlines())
216 output
= '\n'.join(output
.splitlines())
218 self
.assertEqual(output
, expected
)
219 except AssertionError, error
:
220 print >>sys
.stderr
, '\n%s\ninput:' % (self
,)
221 print >>sys
.stderr
, input
223 comparison
= ''.join(self
.compare(expected
.splitlines(1),
224 output
.splitlines(1)))
225 print >>sys
.stderr
, '-: expected\n+: output'
226 print >>sys
.stderr
, comparison
227 except AttributeError: # expected or output not a string
228 # alternative output for non-strings:
229 print >>sys
.stderr
, 'expected: %r' % expected
230 print >>sys
.stderr
, 'output: %r' % output
234 class CustomTestSuite(unittest
.TestSuite
):
237 A collection of CustomTestCases.
239 Provides test suite ID generation and a method for adding test cases.
243 """Identifier for the TestSuite. Prepended to the
244 TestCase identifiers to make identification easier."""
246 next_test_case_id
= 0
247 """The next identifier to use for non-identified test cases."""
249 def __init__(self
, tests
=(), id=None, suite_settings
=None):
251 Initialize the CustomTestSuite.
255 id -- identifier for the suite, prepended to test cases.
256 suite_settings -- settings overrides for this test suite.
258 unittest
.TestSuite
.__init
__(self
, tests
)
259 self
.suite_settings
= suite_settings
or {}
261 mypath
= os
.path
.abspath(
262 sys
.modules
[CustomTestSuite
.__module
__].__file
__)
263 outerframes
= inspect
.getouterframes(inspect
.currentframe())
264 for outerframe
in outerframes
[1:]:
265 if outerframe
[3] != '__init__':
266 callerpath
= outerframe
[1]
267 if callerpath
is None:
268 # It happens sometimes. Why is a mystery.
269 callerpath
= os
.getcwd()
270 callerpath
= os
.path
.abspath(callerpath
)
272 mydir
, myname
= os
.path
.split(mypath
)
275 if callerpath
.startswith(mydir
):
276 self
.id = callerpath
[len(mydir
) + 1:] # caller's module
282 def addTestCase(self
, test_case_class
, method_name
, input, expected
,
283 id=None, run_in_debugger
=False, **kwargs
):
285 Create a CustomTestCase in the CustomTestSuite.
286 Also return it, just in case.
290 test_case_class -- the CustomTestCase to add
291 method_name -- a string; CustomTestCase.method_name is the test
292 input -- input to the parser.
293 expected -- expected output from the parser.
294 id -- unique test identifier, used by the test framework.
295 run_in_debugger -- if true, run this test under the pdb debugger.
297 if id is None: # generate id if required
298 id = self
.next_test_case_id
299 self
.next_test_case_id
+= 1
300 # test identifier will become suiteid.testid
301 tcid
= '%s: %s' % (self
.id, id)
302 # suite_settings may be passed as a parameter;
303 # if not, set from attribute:
304 kwargs
.setdefault('suite_settings', self
.suite_settings
)
305 # generate and add test case
306 tc
= test_case_class(method_name
, input, expected
, tcid
,
307 run_in_debugger
=run_in_debugger
, **kwargs
)
311 def generate_no_tests(self
, *args
, **kwargs
):
315 class TransformTestCase(CustomTestCase
):
318 Output checker for the transform.
320 Should probably be called TransformOutputChecker, but I can deal with
321 that later when/if someone comes up with a category of transform test
322 cases that have nothing to do with the input and output of the transform.
325 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
326 settings
= option_parser
.get_default_values()
327 settings
.report_level
= 1
328 settings
.halt_level
= 5
329 settings
.debug
= package_unittest
.debug
330 settings
.warning_stream
= DevNull()
331 unknown_reference_resolvers
= ()
333 def __init__(self
, *args
, **kwargs
):
334 self
.transforms
= kwargs
['transforms']
335 """List of transforms to perform for this test case."""
337 self
.parser
= kwargs
['parser']
338 """Input parser for this test case."""
340 del kwargs
['transforms'], kwargs
['parser'] # only wanted here
341 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
343 def supports(self
, format
):
346 def test_transforms(self
):
347 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
)
353 # Don't do a ``populate_from_components()`` because that would
354 # enable the Transformer's default transforms.
355 document
.transformer
.add_transforms(self
.transforms
)
356 document
.transformer
.add_transform(universal
.TestMessages
)
357 document
.transformer
.components
['writer'] = self
358 document
.transformer
.apply_transforms()
359 output
= document
.pformat()
360 self
.compare_output(self
.input, output
, self
.expected
)
362 def test_transforms_verbosely(self
):
363 if self
.run_in_debugger
:
368 settings
= self
.settings
.copy()
369 settings
.__dict
__.update(self
.suite_settings
)
370 document
= utils
.new_document('test data', settings
)
371 self
.parser
.parse(self
.input, document
)
373 print document
.pformat()
374 for transformClass
in self
.transforms
:
375 transformClass(document
).apply()
376 output
= document
.pformat()
379 self
.compare_output(self
.input, output
, self
.expected
)
382 class TransformTestSuite(CustomTestSuite
):
385 A collection of TransformTestCases.
387 A TransformTestSuite instance manufactures TransformTestCases,
388 keeps track of them, and provides a shared test fixture (a-la
392 def __init__(self
, parser
, suite_settings
=None):
394 """Parser shared by all test cases."""
396 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
398 def generateTests(self
, dict, dictname
='totest',
399 testmethod
='test_transforms'):
401 Stock the suite with test cases generated from a test data dictionary.
403 Each dictionary key (test type's name) maps to a tuple, whose
404 first item is a list of transform classes and whose second
405 item is a list of tests. Each test is a list: input, expected
406 output, optional modifier. The optional third entry, a
407 behavior modifier, can be 0 (temporarily disable this test) or
408 1 (run this test under the pdb debugger). Tests should be
409 self-documenting and not require external comments.
411 for name
, (transforms
, cases
) in dict.items():
412 for casenum
in range(len(cases
)):
413 case
= cases
[casenum
]
414 run_in_debugger
= False
416 # TODO: (maybe) change the 3rd argument to a dict, so it
417 # can handle more cases by keyword ('disable', 'debug',
418 # 'settings'), here and in other generateTests methods.
419 # But there's also the method that
420 # HtmlPublishPartsTestSuite uses <DJG>
422 run_in_debugger
= True
426 TransformTestCase
, testmethod
,
427 transforms
=transforms
, parser
=self
.parser
,
428 input=case
[0], expected
=case
[1],
429 id='%s[%r][%s]' % (dictname
, name
, casenum
),
430 run_in_debugger
=run_in_debugger
)
433 class ParserTestCase(CustomTestCase
):
436 Output checker for the parser.
438 Should probably be called ParserOutputChecker, but I can deal with
439 that later when/if someone comes up with a category of parser test
440 cases that have nothing to do with the input and output of the parser.
443 parser
= rst
.Parser()
444 """Parser shared by all ParserTestCases."""
446 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
447 settings
= option_parser
.get_default_values()
448 settings
.report_level
= 5
449 settings
.halt_level
= 5
450 settings
.debug
= package_unittest
.debug
452 def test_parser(self
):
453 if self
.run_in_debugger
:
455 settings
= self
.settings
.copy()
456 settings
.__dict
__.update(self
.suite_settings
)
457 document
= utils
.new_document('test data', settings
)
458 self
.parser
.parse(self
.input, document
)
459 output
= document
.pformat()
460 self
.compare_output(self
.input, output
, self
.expected
)
463 class ParserTestSuite(CustomTestSuite
):
466 A collection of ParserTestCases.
468 A ParserTestSuite instance manufactures ParserTestCases,
469 keeps track of them, and provides a shared test fixture (a-la
473 test_case_class
= ParserTestCase
475 def generateTests(self
, dict, dictname
='totest'):
477 Stock the suite with test cases generated from a test data dictionary.
479 Each dictionary key (test type name) maps to a list of tests. Each
480 test is a list: input, expected output, optional modifier. The
481 optional third entry, a behavior modifier, can be 0 (temporarily
482 disable this test) or 1 (run this test under the pdb debugger). Tests
483 should be self-documenting and not require external comments.
485 for name
, cases
in dict.items():
486 for casenum
in range(len(cases
)):
487 case
= cases
[casenum
]
488 run_in_debugger
= False
491 run_in_debugger
= True
495 self
.test_case_class
, 'test_parser',
496 input=case
[0], expected
=case
[1],
497 id='%s[%r][%s]' % (dictname
, name
, casenum
),
498 run_in_debugger
=run_in_debugger
)
501 class PEPParserTestCase(ParserTestCase
):
503 """PEP-specific parser test case."""
505 parser
= rst
.Parser(rfc2822
=True, inliner
=rst
.states
.Inliner())
506 """Parser shared by all PEPParserTestCases."""
508 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
, pep
.Reader
))
509 settings
= option_parser
.get_default_values()
510 settings
.report_level
= 5
511 settings
.halt_level
= 5
512 settings
.debug
= package_unittest
.debug
515 class PEPParserTestSuite(ParserTestSuite
):
517 """A collection of PEPParserTestCases."""
519 test_case_class
= PEPParserTestCase
522 class GridTableParserTestCase(CustomTestCase
):
524 parser
= tableparser
.GridTableParser()
526 def test_parse_table(self
):
527 self
.parser
.setup(StringList(string2lines(self
.input), 'test data'))
529 self
.parser
.find_head_body_sep()
530 self
.parser
.parse_table()
531 output
= self
.parser
.cells
532 except Exception, details
:
533 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
534 self
.compare_output(self
.input, pformat(output
) + '\n',
535 pformat(self
.expected
) + '\n')
537 def test_parse(self
):
539 output
= self
.parser
.parse(StringList(string2lines(self
.input),
541 except Exception, details
:
542 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
543 self
.compare_output(self
.input, pformat(output
) + '\n',
544 pformat(self
.expected
) + '\n')
547 class GridTableParserTestSuite(CustomTestSuite
):
550 A collection of GridTableParserTestCases.
552 A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
553 keeps track of them, and provides a shared test fixture (a-la setUp and
557 test_case_class
= GridTableParserTestCase
559 def generateTests(self
, dict, dictname
='totest'):
561 Stock the suite with test cases generated from a test data dictionary.
563 Each dictionary key (test type name) maps to a list of tests. Each
564 test is a list: an input table, expected output from parse_table(),
565 expected output from parse(), optional modifier. The optional fourth
566 entry, a behavior modifier, can be 0 (temporarily disable this test)
567 or 1 (run this test under the pdb debugger). Tests should be
568 self-documenting and not require external comments.
570 for name
, cases
in dict.items():
571 for casenum
in range(len(cases
)):
572 case
= cases
[casenum
]
573 run_in_debugger
= False
576 run_in_debugger
= True
579 self
.addTestCase(self
.test_case_class
, 'test_parse_table',
580 input=case
[0], expected
=case
[1],
581 id='%s[%r][%s]' % (dictname
, name
, casenum
),
582 run_in_debugger
=run_in_debugger
)
583 self
.addTestCase(self
.test_case_class
, 'test_parse',
584 input=case
[0], expected
=case
[2],
585 id='%s[%r][%s]' % (dictname
, name
, casenum
),
586 run_in_debugger
=run_in_debugger
)
589 class SimpleTableParserTestCase(GridTableParserTestCase
):
591 parser
= tableparser
.SimpleTableParser()
594 class SimpleTableParserTestSuite(CustomTestSuite
):
597 A collection of SimpleTableParserTestCases.
600 test_case_class
= SimpleTableParserTestCase
602 def generateTests(self
, dict, dictname
='totest'):
604 Stock the suite with test cases generated from a test data dictionary.
606 Each dictionary key (test type name) maps to a list of tests. Each
607 test is a list: an input table, expected output from parse(), optional
608 modifier. The optional third entry, a behavior modifier, can be 0
609 (temporarily disable this test) or 1 (run this test under the pdb
610 debugger). Tests should be self-documenting and not require external
613 for name
, cases
in dict.items():
614 for casenum
in range(len(cases
)):
615 case
= cases
[casenum
]
616 run_in_debugger
= False
619 run_in_debugger
= True
622 self
.addTestCase(self
.test_case_class
, 'test_parse',
623 input=case
[0], expected
=case
[1],
624 id='%s[%r][%s]' % (dictname
, name
, casenum
),
625 run_in_debugger
=run_in_debugger
)
628 class PythonModuleParserTestCase(CustomTestCase
):
630 def test_parser(self
):
631 if self
.run_in_debugger
:
638 from docutils
.readers
.python
import moduleparser
639 module
= moduleparser
.parse_module(self
.input, 'test data').pformat()
641 self
.compare_output(self
.input, output
, self
.expected
)
643 def test_token_parser_rhs(self
):
644 if self
.run_in_debugger
:
651 from docutils
.readers
.python
import moduleparser
652 tr
= moduleparser
.TokenParser(self
.input)
654 self
.compare_output(self
.input, output
, self
.expected
)
657 class PythonModuleParserTestSuite(CustomTestSuite
):
660 A collection of PythonModuleParserTestCase.
663 def generateTests(self
, dict, dictname
='totest',
664 testmethod
='test_parser'):
666 Stock the suite with test cases generated from a test data dictionary.
668 Each dictionary key (test type's name) maps to a list of tests. Each
669 test is a list: input, expected output, optional modifier. The
670 optional third entry, a behavior modifier, can be 0 (temporarily
671 disable this test) or 1 (run this test under the pdb debugger). Tests
672 should be self-documenting and not require external comments.
674 for name
, cases
in dict.items():
675 for casenum
in range(len(cases
)):
676 case
= cases
[casenum
]
677 run_in_debugger
= False
680 run_in_debugger
= True
684 PythonModuleParserTestCase
, testmethod
,
685 input=case
[0], expected
=case
[1],
686 id='%s[%r][%s]' % (dictname
, name
, casenum
),
687 run_in_debugger
=run_in_debugger
)
690 class WriterPublishTestCase(CustomTestCase
, docutils
.SettingsSpec
):
693 Test case for publish.
696 settings_default_overrides
= {'_disable_config': 1,
698 writer_name
= '' # set in subclasses or constructor
700 def __init__(self
, *args
, **kwargs
):
701 if 'writer_name' in kwargs
:
702 self
.writer_name
= kwargs
['writer_name']
703 del kwargs
['writer_name']
704 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
706 def test_publish(self
):
707 if self
.run_in_debugger
:
709 output
= docutils
.core
.publish_string(
711 reader_name
='standalone',
712 parser_name
='restructuredtext',
713 writer_name
=self
.writer_name
,
715 settings_overrides
=self
.suite_settings
)
716 self
.compare_output(self
.input, output
, self
.expected
)
719 class PublishTestSuite(CustomTestSuite
):
721 def __init__(self
, writer_name
, suite_settings
=None):
723 `writer_name` is the name of the writer to use.
725 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
726 self
.test_class
= WriterPublishTestCase
727 self
.writer_name
= writer_name
729 def generateTests(self
, dict, dictname
='totest'):
730 for name
, cases
in dict.items():
731 for casenum
in range(len(cases
)):
732 case
= cases
[casenum
]
733 run_in_debugger
= False
736 run_in_debugger
= True
740 self
.test_class
, 'test_publish',
741 input=case
[0], expected
=case
[1],
742 id='%s[%r][%s]' % (dictname
, name
, casenum
),
743 run_in_debugger
=run_in_debugger
,
744 # Passed to constructor of self.test_class:
745 writer_name
=self
.writer_name
)
748 class HtmlPublishPartsTestSuite(CustomTestSuite
):
750 def generateTests(self
, dict, dictname
='totest'):
751 for name
, (settings_overrides
, cases
) in dict.items():
752 settings
= self
.suite_settings
.copy()
753 settings
.update(settings_overrides
)
754 for casenum
in range(len(cases
)):
755 case
= cases
[casenum
]
756 run_in_debugger
= False
759 run_in_debugger
= True
763 HtmlWriterPublishPartsTestCase
, 'test_publish',
764 input=case
[0], expected
=case
[1],
765 id='%s[%r][%s]' % (dictname
, name
, casenum
),
766 run_in_debugger
=run_in_debugger
,
767 suite_settings
=settings
)
770 class HtmlWriterPublishPartsTestCase(WriterPublishTestCase
):
773 Test case for HTML writer via the publish_parts interface.
778 settings_default_overrides
= \
779 WriterPublishTestCase
.settings_default_overrides
.copy()
780 settings_default_overrides
['stylesheet'] = ''
782 def test_publish(self
):
783 if self
.run_in_debugger
:
785 parts
= docutils
.core
.publish_parts(
787 reader_name
='standalone',
788 parser_name
='restructuredtext',
789 writer_name
=self
.writer_name
,
791 settings_overrides
=self
.suite_settings
)
792 output
= self
.format_output(parts
)
793 # interpolate standard variables:
794 expected
= self
.expected
% {'version': docutils
.__version
__}
795 self
.compare_output(self
.input, output
, expected
)
797 standard_content_type_template
= ('<meta http-equiv="Content-Type"'
798 ' content="text/html; charset=%s" />\n')
799 standard_generator_template
= (
800 '<meta name="generator"'
801 ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
802 standard_html_meta_value
= (
803 standard_content_type_template
804 + standard_generator_template
% docutils
.__version
__)
805 standard_meta_value
= standard_html_meta_value
% 'utf-8'
806 standard_html_prolog
= """\
807 <?xml version="1.0" encoding="%s" ?>
808 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
811 def format_output(self
, parts
):
812 """Minimize & standardize the output."""
813 # remove redundant parts & uninteresting parts:
815 assert parts
['body'] == parts
['fragment']
817 del parts
['body_pre_docinfo']
818 del parts
['body_prefix']
819 del parts
['body_suffix']
821 del parts
['head_prefix']
822 del parts
['encoding']
824 # remove standard portions:
825 parts
['meta'] = parts
['meta'].replace(self
.standard_meta_value
, '')
826 parts
['html_head'] = parts
['html_head'].replace(
827 self
.standard_html_meta_value
, '...')
828 parts
['html_prolog'] = parts
['html_prolog'].replace(
829 self
.standard_html_prolog
, '')
830 # remove empty values:
831 for key
in parts
.keys():
834 # standard output format:
839 output
.append("%r: '''%s'''"
841 if output
[-1].endswith("\n'''"):
842 output
[-1] = output
[-1][:-4] + "\\n'''"
843 return '{' + ',\n '.join(output
) + '}\n'
846 def exception_data(func
, *args
, **kwds
):
848 Execute `func(*args, **kwds)` and return the resulting exception, the
849 exception arguments, and the formatted exception string.
853 except Exception, detail
:
854 return (detail
, detail
.args
,
855 '%s: %s' % (detail
.__class
__.__name
__, detail
))
858 def _format_str(*args
):
860 Return a tuple containing representations of all args.
862 Same as map(repr, args) except that it returns multi-line
863 representations for strings containing newlines, e.g.::
875 This is a helper function for CustomTestCase.
880 if ( (isinstance(i
, bytes
) or isinstance(i
, unicode))
883 if isinstance(i
, unicode) and r
.startswith('u'):
886 elif isinstance(i
, bytes
) and r
.startswith('b'):
889 # quote_char = "'" or '"'
891 assert quote_char
in ("'", '"'), quote_char
894 r
= (stripped
+ 3 * quote_char
+ '\\\n' +
895 re
.sub(r
'(?<!\\)((\\\\)*)\\n', r
'\1\n', r
) +
897 r
= re
.sub(r
' \n', r
' \\n\\\n', r
)
898 return_tuple
.append(r
)
899 return tuple(return_tuple
)