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
))
133 if not hasattr(unittest
.TestCase
, "assertTrue"):
134 assertTrue
= unittest
.TestCase
.failUnless
136 # aliases for assertion methods, deprecated since Python 2.7
138 failUnlessEqual
= assertEquals
= assertEqual
140 assertNotEquals
= failIfEqual
= assertNotEqual
143 class CustomTestCase(StandardTestCase
):
146 Helper class, providing extended functionality over unittest.TestCase.
148 The methods assertEqual and assertNotEqual have been overwritten
149 to provide better support for multi-line strings. Furthermore,
150 see the compare_output method and the parameter list of __init__.
153 compare
= difflib
.Differ().compare
154 """Comparison method shared by all subclasses."""
156 def __init__(self
, method_name
, input, expected
, id,
157 run_in_debugger
=True, suite_settings
=None):
159 Initialise the CustomTestCase.
163 method_name -- name of test method to run.
164 input -- input to the parser.
165 expected -- expected output from the parser.
166 id -- unique test identifier, used by the test framework.
167 run_in_debugger -- if true, run this test under the pdb debugger.
168 suite_settings -- settings overrides for this test suite.
172 self
.expected
= expected
173 self
.run_in_debugger
= run_in_debugger
174 self
.suite_settings
= suite_settings
.copy() or {}
177 unittest
.TestCase
.__init
__(self
, method_name
)
181 Return string conversion. Overridden to give test id, in addition to
184 return '%s; %s' % (self
.id, unittest
.TestCase
.__str
__(self
))
187 return "<%s %s>" % (self
.id, unittest
.TestCase
.__repr
__(self
))
189 def clear_roles(self
):
190 # Language-specific roles and roles added by the
191 # "default-role" and "role" directives are currently stored
192 # globally in the roles._roles dictionary. This workaround
193 # empties that dictionary.
197 StandardTestCase
.setUp(self
)
200 def compare_output(self
, input, output
, expected
):
201 """`input`, `output`, and `expected` should all be strings."""
202 if isinstance(input, unicode):
203 input = input.encode('raw_unicode_escape')
204 if sys
.version_info
> (3,):
205 # API difference: Python 3's node.__str__ doesn't escape
206 #assert expected is None or isinstance(expected, unicode)
207 if isinstance(expected
, bytes
):
208 expected
= expected
.decode('utf-8')
209 if isinstance(output
, bytes
):
210 output
= output
.decode('utf-8')
212 if isinstance(expected
, unicode):
213 expected
= expected
.encode('raw_unicode_escape')
214 if isinstance(output
, unicode):
215 output
= output
.encode('raw_unicode_escape')
216 # Normalize line endings:
218 expected
= '\n'.join(expected
.splitlines())
220 output
= '\n'.join(output
.splitlines())
222 self
.assertEqual(output
, expected
)
223 except AssertionError, error
:
224 print >>sys
.stderr
, '\n%s\ninput:' % (self
,)
225 print >>sys
.stderr
, input
227 comparison
= ''.join(self
.compare(expected
.splitlines(1),
228 output
.splitlines(1)))
229 print >>sys
.stderr
, '-: expected\n+: output'
230 print >>sys
.stderr
, comparison
231 except AttributeError: # expected or output not a string
232 # alternative output for non-strings:
233 print >>sys
.stderr
, 'expected: %r' % expected
234 print >>sys
.stderr
, 'output: %r' % output
238 class CustomTestSuite(unittest
.TestSuite
):
241 A collection of CustomTestCases.
243 Provides test suite ID generation and a method for adding test cases.
247 """Identifier for the TestSuite. Prepended to the
248 TestCase identifiers to make identification easier."""
250 next_test_case_id
= 0
251 """The next identifier to use for non-identified test cases."""
253 def __init__(self
, tests
=(), id=None, suite_settings
=None):
255 Initialize the CustomTestSuite.
259 id -- identifier for the suite, prepended to test cases.
260 suite_settings -- settings overrides for this test suite.
262 unittest
.TestSuite
.__init
__(self
, tests
)
263 self
.suite_settings
= suite_settings
or {}
265 mypath
= os
.path
.abspath(
266 sys
.modules
[CustomTestSuite
.__module
__].__file
__)
267 outerframes
= inspect
.getouterframes(inspect
.currentframe())
268 for outerframe
in outerframes
[1:]:
269 if outerframe
[3] != '__init__':
270 callerpath
= outerframe
[1]
271 if callerpath
is None:
272 # It happens sometimes. Why is a mystery.
273 callerpath
= os
.getcwd()
274 callerpath
= os
.path
.abspath(callerpath
)
276 mydir
, myname
= os
.path
.split(mypath
)
279 if callerpath
.startswith(mydir
):
280 self
.id = callerpath
[len(mydir
) + 1:] # caller's module
286 def addTestCase(self
, test_case_class
, method_name
, input, expected
,
287 id=None, run_in_debugger
=False, **kwargs
):
289 Create a CustomTestCase in the CustomTestSuite.
290 Also return it, just in case.
294 test_case_class -- the CustomTestCase to add
295 method_name -- a string; CustomTestCase.method_name is the test
296 input -- input to the parser.
297 expected -- expected output from the parser.
298 id -- unique test identifier, used by the test framework.
299 run_in_debugger -- if true, run this test under the pdb debugger.
301 if id is None: # generate id if required
302 id = self
.next_test_case_id
303 self
.next_test_case_id
+= 1
304 # test identifier will become suiteid.testid
305 tcid
= '%s: %s' % (self
.id, id)
306 # suite_settings may be passed as a parameter;
307 # if not, set from attribute:
308 kwargs
.setdefault('suite_settings', self
.suite_settings
)
309 # generate and add test case
310 tc
= test_case_class(method_name
, input, expected
, tcid
,
311 run_in_debugger
=run_in_debugger
, **kwargs
)
315 def generate_no_tests(self
, *args
, **kwargs
):
319 class TransformTestCase(CustomTestCase
):
322 Output checker for the transform.
324 Should probably be called TransformOutputChecker, but I can deal with
325 that later when/if someone comes up with a category of transform test
326 cases that have nothing to do with the input and output of the transform.
329 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
330 settings
= option_parser
.get_default_values()
331 settings
.report_level
= 1
332 settings
.halt_level
= 5
333 settings
.debug
= package_unittest
.debug
334 settings
.warning_stream
= DevNull()
335 unknown_reference_resolvers
= ()
337 def __init__(self
, *args
, **kwargs
):
338 self
.transforms
= kwargs
['transforms']
339 """List of transforms to perform for this test case."""
341 self
.parser
= kwargs
['parser']
342 """Input parser for this test case."""
344 del kwargs
['transforms'], kwargs
['parser'] # only wanted here
345 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
347 def supports(self
, format
):
350 def test_transforms(self
):
351 if self
.run_in_debugger
:
353 settings
= self
.settings
.copy()
354 settings
.__dict
__.update(self
.suite_settings
)
355 document
= utils
.new_document('test data', settings
)
356 self
.parser
.parse(self
.input, document
)
357 # Don't do a ``populate_from_components()`` because that would
358 # enable the Transformer's default transforms.
359 document
.transformer
.add_transforms(self
.transforms
)
360 document
.transformer
.add_transform(universal
.TestMessages
)
361 document
.transformer
.components
['writer'] = self
362 document
.transformer
.apply_transforms()
363 output
= document
.pformat()
364 self
.compare_output(self
.input, output
, self
.expected
)
366 def test_transforms_verbosely(self
):
367 if self
.run_in_debugger
:
372 settings
= self
.settings
.copy()
373 settings
.__dict
__.update(self
.suite_settings
)
374 document
= utils
.new_document('test data', settings
)
375 self
.parser
.parse(self
.input, document
)
377 print document
.pformat()
378 for transformClass
in self
.transforms
:
379 transformClass(document
).apply()
380 output
= document
.pformat()
383 self
.compare_output(self
.input, output
, self
.expected
)
386 class TransformTestSuite(CustomTestSuite
):
389 A collection of TransformTestCases.
391 A TransformTestSuite instance manufactures TransformTestCases,
392 keeps track of them, and provides a shared test fixture (a-la
396 def __init__(self
, parser
, suite_settings
=None):
398 """Parser shared by all test cases."""
400 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
402 def generateTests(self
, dict, dictname
='totest',
403 testmethod
='test_transforms'):
405 Stock the suite with test cases generated from a test data dictionary.
407 Each dictionary key (test type's name) maps to a tuple, whose
408 first item is a list of transform classes and whose second
409 item is a list of tests. Each test is a list: input, expected
410 output, optional modifier. The optional third entry, a
411 behavior modifier, can be 0 (temporarily disable this test) or
412 1 (run this test under the pdb debugger). Tests should be
413 self-documenting and not require external comments.
415 for name
, (transforms
, cases
) in dict.items():
416 for casenum
in range(len(cases
)):
417 case
= cases
[casenum
]
418 run_in_debugger
= False
420 # TODO: (maybe) change the 3rd argument to a dict, so it
421 # can handle more cases by keyword ('disable', 'debug',
422 # 'settings'), here and in other generateTests methods.
423 # But there's also the method that
424 # HtmlPublishPartsTestSuite uses <DJG>
426 run_in_debugger
= True
430 TransformTestCase
, testmethod
,
431 transforms
=transforms
, parser
=self
.parser
,
432 input=case
[0], expected
=case
[1],
433 id='%s[%r][%s]' % (dictname
, name
, casenum
),
434 run_in_debugger
=run_in_debugger
)
437 class ParserTestCase(CustomTestCase
):
440 Output checker for the parser.
442 Should probably be called ParserOutputChecker, but I can deal with
443 that later when/if someone comes up with a category of parser test
444 cases that have nothing to do with the input and output of the parser.
447 parser
= rst
.Parser()
448 """Parser shared by all ParserTestCases."""
450 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
,))
451 settings
= option_parser
.get_default_values()
452 settings
.report_level
= 5
453 settings
.halt_level
= 5
454 settings
.debug
= package_unittest
.debug
456 def test_parser(self
):
457 if self
.run_in_debugger
:
459 settings
= self
.settings
.copy()
460 settings
.__dict
__.update(self
.suite_settings
)
461 document
= utils
.new_document('test data', settings
)
462 self
.parser
.parse(self
.input, document
)
463 output
= document
.pformat()
464 self
.compare_output(self
.input, output
, self
.expected
)
467 class ParserTestSuite(CustomTestSuite
):
470 A collection of ParserTestCases.
472 A ParserTestSuite instance manufactures ParserTestCases,
473 keeps track of them, and provides a shared test fixture (a-la
477 test_case_class
= ParserTestCase
479 def generateTests(self
, dict, dictname
='totest'):
481 Stock the suite with test cases generated from a test data dictionary.
483 Each dictionary key (test type name) maps to a list of tests. Each
484 test is a list: input, expected output, optional modifier. The
485 optional third entry, a behavior modifier, can be 0 (temporarily
486 disable this test) or 1 (run this test under the pdb debugger). Tests
487 should be self-documenting and not require external comments.
489 for name
, cases
in dict.items():
490 for casenum
in range(len(cases
)):
491 case
= cases
[casenum
]
492 run_in_debugger
= False
495 run_in_debugger
= True
499 self
.test_case_class
, 'test_parser',
500 input=case
[0], expected
=case
[1],
501 id='%s[%r][%s]' % (dictname
, name
, casenum
),
502 run_in_debugger
=run_in_debugger
)
505 class PEPParserTestCase(ParserTestCase
):
507 """PEP-specific parser test case."""
509 parser
= rst
.Parser(rfc2822
=True, inliner
=rst
.states
.Inliner())
510 """Parser shared by all PEPParserTestCases."""
512 option_parser
= frontend
.OptionParser(components
=(rst
.Parser
, pep
.Reader
))
513 settings
= option_parser
.get_default_values()
514 settings
.report_level
= 5
515 settings
.halt_level
= 5
516 settings
.debug
= package_unittest
.debug
519 class PEPParserTestSuite(ParserTestSuite
):
521 """A collection of PEPParserTestCases."""
523 test_case_class
= PEPParserTestCase
526 class GridTableParserTestCase(CustomTestCase
):
528 parser
= tableparser
.GridTableParser()
530 def test_parse_table(self
):
531 self
.parser
.setup(StringList(string2lines(self
.input), 'test data'))
533 self
.parser
.find_head_body_sep()
534 self
.parser
.parse_table()
535 output
= self
.parser
.cells
536 except Exception, details
:
537 output
= '%s: %s' % (details
.__class
__.__name
__, details
)
538 self
.compare_output(self
.input, pformat(output
) + '\n',
539 pformat(self
.expected
) + '\n')
541 def test_parse(self
):
543 output
= self
.parser
.parse(StringList(string2lines(self
.input),
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')
551 class GridTableParserTestSuite(CustomTestSuite
):
554 A collection of GridTableParserTestCases.
556 A GridTableParserTestSuite instance manufactures GridTableParserTestCases,
557 keeps track of them, and provides a shared test fixture (a-la setUp and
561 test_case_class
= GridTableParserTestCase
563 def generateTests(self
, dict, dictname
='totest'):
565 Stock the suite with test cases generated from a test data dictionary.
567 Each dictionary key (test type name) maps to a list of tests. Each
568 test is a list: an input table, expected output from parse_table(),
569 expected output from parse(), optional modifier. The optional fourth
570 entry, a behavior modifier, can be 0 (temporarily disable this test)
571 or 1 (run this test under the pdb debugger). Tests should be
572 self-documenting and not require external comments.
574 for name
, cases
in dict.items():
575 for casenum
in range(len(cases
)):
576 case
= cases
[casenum
]
577 run_in_debugger
= False
580 run_in_debugger
= True
583 self
.addTestCase(self
.test_case_class
, 'test_parse_table',
584 input=case
[0], expected
=case
[1],
585 id='%s[%r][%s]' % (dictname
, name
, casenum
),
586 run_in_debugger
=run_in_debugger
)
587 self
.addTestCase(self
.test_case_class
, 'test_parse',
588 input=case
[0], expected
=case
[2],
589 id='%s[%r][%s]' % (dictname
, name
, casenum
),
590 run_in_debugger
=run_in_debugger
)
593 class SimpleTableParserTestCase(GridTableParserTestCase
):
595 parser
= tableparser
.SimpleTableParser()
598 class SimpleTableParserTestSuite(CustomTestSuite
):
601 A collection of SimpleTableParserTestCases.
604 test_case_class
= SimpleTableParserTestCase
606 def generateTests(self
, dict, dictname
='totest'):
608 Stock the suite with test cases generated from a test data dictionary.
610 Each dictionary key (test type name) maps to a list of tests. Each
611 test is a list: an input table, expected output from parse(), optional
612 modifier. The optional third entry, a behavior modifier, can be 0
613 (temporarily disable this test) or 1 (run this test under the pdb
614 debugger). Tests should be self-documenting and not require external
617 for name
, cases
in dict.items():
618 for casenum
in range(len(cases
)):
619 case
= cases
[casenum
]
620 run_in_debugger
= False
623 run_in_debugger
= True
626 self
.addTestCase(self
.test_case_class
, 'test_parse',
627 input=case
[0], expected
=case
[1],
628 id='%s[%r][%s]' % (dictname
, name
, casenum
),
629 run_in_debugger
=run_in_debugger
)
632 class PythonModuleParserTestCase(CustomTestCase
):
634 def test_parser(self
):
635 if self
.run_in_debugger
:
642 from docutils
.readers
.python
import moduleparser
643 module
= moduleparser
.parse_module(self
.input, 'test data').pformat()
645 self
.compare_output(self
.input, output
, self
.expected
)
647 def test_token_parser_rhs(self
):
648 if self
.run_in_debugger
:
655 from docutils
.readers
.python
import moduleparser
656 tr
= moduleparser
.TokenParser(self
.input)
658 self
.compare_output(self
.input, output
, self
.expected
)
661 class PythonModuleParserTestSuite(CustomTestSuite
):
664 A collection of PythonModuleParserTestCase.
667 def generateTests(self
, dict, dictname
='totest',
668 testmethod
='test_parser'):
670 Stock the suite with test cases generated from a test data dictionary.
672 Each dictionary key (test type's name) maps to a list of tests. Each
673 test is a list: input, expected output, optional modifier. The
674 optional third entry, a behavior modifier, can be 0 (temporarily
675 disable this test) or 1 (run this test under the pdb debugger). Tests
676 should be self-documenting and not require external comments.
678 for name
, cases
in dict.items():
679 for casenum
in range(len(cases
)):
680 case
= cases
[casenum
]
681 run_in_debugger
= False
684 run_in_debugger
= True
688 PythonModuleParserTestCase
, testmethod
,
689 input=case
[0], expected
=case
[1],
690 id='%s[%r][%s]' % (dictname
, name
, casenum
),
691 run_in_debugger
=run_in_debugger
)
694 class WriterPublishTestCase(CustomTestCase
, docutils
.SettingsSpec
):
697 Test case for publish.
700 settings_default_overrides
= {'_disable_config': 1,
702 writer_name
= '' # set in subclasses or constructor
704 def __init__(self
, *args
, **kwargs
):
705 if 'writer_name' in kwargs
:
706 self
.writer_name
= kwargs
['writer_name']
707 del kwargs
['writer_name']
708 CustomTestCase
.__init
__(self
, *args
, **kwargs
)
710 def test_publish(self
):
711 if self
.run_in_debugger
:
713 output
= docutils
.core
.publish_string(
715 reader_name
='standalone',
716 parser_name
='restructuredtext',
717 writer_name
=self
.writer_name
,
719 settings_overrides
=self
.suite_settings
)
720 self
.compare_output(self
.input, output
, self
.expected
)
723 class PublishTestSuite(CustomTestSuite
):
725 def __init__(self
, writer_name
, suite_settings
=None):
727 `writer_name` is the name of the writer to use.
729 CustomTestSuite
.__init
__(self
, suite_settings
=suite_settings
)
730 self
.test_class
= WriterPublishTestCase
731 self
.writer_name
= writer_name
733 def generateTests(self
, dict, dictname
='totest'):
734 for name
, cases
in dict.items():
735 for casenum
in range(len(cases
)):
736 case
= cases
[casenum
]
737 run_in_debugger
= False
740 run_in_debugger
= True
744 self
.test_class
, 'test_publish',
745 input=case
[0], expected
=case
[1],
746 id='%s[%r][%s]' % (dictname
, name
, casenum
),
747 run_in_debugger
=run_in_debugger
,
748 # Passed to constructor of self.test_class:
749 writer_name
=self
.writer_name
)
752 class HtmlPublishPartsTestSuite(CustomTestSuite
):
754 def generateTests(self
, dict, dictname
='totest'):
755 for name
, (settings_overrides
, cases
) in dict.items():
756 settings
= self
.suite_settings
.copy()
757 settings
.update(settings_overrides
)
758 for casenum
in range(len(cases
)):
759 case
= cases
[casenum
]
760 run_in_debugger
= False
763 run_in_debugger
= True
767 HtmlWriterPublishPartsTestCase
, 'test_publish',
768 input=case
[0], expected
=case
[1],
769 id='%s[%r][%s]' % (dictname
, name
, casenum
),
770 run_in_debugger
=run_in_debugger
,
771 suite_settings
=settings
)
774 class HtmlWriterPublishPartsTestCase(WriterPublishTestCase
):
777 Test case for HTML writer via the publish_parts interface.
782 settings_default_overrides
= \
783 WriterPublishTestCase
.settings_default_overrides
.copy()
784 settings_default_overrides
['stylesheet'] = ''
786 def test_publish(self
):
787 if self
.run_in_debugger
:
789 parts
= docutils
.core
.publish_parts(
791 reader_name
='standalone',
792 parser_name
='restructuredtext',
793 writer_name
=self
.writer_name
,
795 settings_overrides
=self
.suite_settings
)
796 output
= self
.format_output(parts
)
797 # interpolate standard variables:
798 expected
= self
.expected
% {'version': docutils
.__version
__}
799 self
.compare_output(self
.input, output
, expected
)
801 standard_content_type_template
= ('<meta http-equiv="Content-Type"'
802 ' content="text/html; charset=%s" />\n')
803 standard_generator_template
= (
804 '<meta name="generator"'
805 ' content="Docutils %s: http://docutils.sourceforge.net/" />\n')
806 standard_html_meta_value
= (
807 standard_content_type_template
808 + standard_generator_template
% docutils
.__version
__)
809 standard_meta_value
= standard_html_meta_value
% 'utf-8'
810 standard_html_prolog
= """\
811 <?xml version="1.0" encoding="%s" ?>
812 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
815 def format_output(self
, parts
):
816 """Minimize & standardize the output."""
817 # remove redundant parts & uninteresting parts:
819 assert parts
['body'] == parts
['fragment']
821 del parts
['body_pre_docinfo']
822 del parts
['body_prefix']
823 del parts
['body_suffix']
825 del parts
['head_prefix']
826 del parts
['encoding']
828 # remove standard portions:
829 parts
['meta'] = parts
['meta'].replace(self
.standard_meta_value
, '')
830 parts
['html_head'] = parts
['html_head'].replace(
831 self
.standard_html_meta_value
, '...')
832 parts
['html_prolog'] = parts
['html_prolog'].replace(
833 self
.standard_html_prolog
, '')
834 # remove empty values:
835 for key
in parts
.keys():
838 # standard output format:
843 output
.append("%r: '''%s'''"
845 if output
[-1].endswith("\n'''"):
846 output
[-1] = output
[-1][:-4] + "\\n'''"
847 return '{' + ',\n '.join(output
) + '}\n'
850 def exception_data(func
, *args
, **kwds
):
852 Execute `func(*args, **kwds)` and return the resulting exception, the
853 exception arguments, and the formatted exception string.
857 except Exception, detail
:
858 return (detail
, detail
.args
,
859 '%s: %s' % (detail
.__class
__.__name
__, detail
))
862 def _format_str(*args
):
864 Return a tuple containing representations of all args.
866 Same as map(repr, args) except that it returns multi-line
867 representations for strings containing newlines, e.g.::
879 This is a helper function for CustomTestCase.
884 if ( (isinstance(i
, bytes
) or isinstance(i
, unicode))
887 if isinstance(i
, unicode) and r
.startswith('u'):
890 elif isinstance(i
, bytes
) and r
.startswith('b'):
893 # quote_char = "'" or '"'
895 assert quote_char
in ("'", '"'), quote_char
898 r
= (stripped
+ 3 * quote_char
+ '\\\n' +
899 re
.sub(r
'(?<!\\)((\\\\)*)\\n', r
'\1\n', r
) +
901 r
= re
.sub(r
' \n', r
' \\n\\\n', r
)
902 return_tuple
.append(r
)
903 return tuple(return_tuple
)