5 ## Test pylit.py Python Module
6 ## +++++++++++++++++++++++++++
8 ## :Copyright: 2006 Guenter Milde.
9 ## Released under the terms of the GNU General Public License
14 ## A catalogue of errors
15 ## =====================
17 ## from file:///home/milde/Texte/Doc/Programmierung/Software-Carpentry/lec/unit.html
19 ## * Numbers: zero, largest, smallest magnitude, most negative
20 ## * Structures: empty, exactly one element, maximum number of elements
21 ## - Duplicate elements (e.g., letter "J" appears three times in a string)
22 ## - Aliased elements (e.g., a list contains two references to another list)
23 ## - Circular structures (e.g., a list that contains a reference to itself)
24 ## * Searching: no match found, one match found, multiple matches found,
26 ## - Code like x = find_all(structure)[0] is almost always wrong
27 ## - Should also check aliased matches (same thing found multiple times)
31 """pylit_test.py: test the "literal python" module"""
33 from pprint
import pprint
39 ## Text <-> Code conversion
40 ## ========================
45 ## Example of text, code and stripped code with typical features"::
47 text
= """.. #!/usr/bin/env python
48 # -*- coding: iso-8859-1 -*-
52 in several paragraphs followed by a literal block::
54 block1 = 'first block'
56 Some more text and the next block. ::
58 block2 = 'second block'
64 ## The converter expects the data in separate lines (iterator or list)
65 ## with trailing newlines. We use the `splitlines` string method with
68 textdata
= text
.splitlines(True)
70 ## If a "code" source is converted with the `strip` option, only text blocks
71 ## are extracted, which leads to::
73 stripped_text
= """Leading text
75 in several paragraphs followed by a literal block:
77 Some more text and the next block.
82 ## The code corresponding to the text test string.
84 ## Using a triple-quoted string for the code (and stripped_code) can create
85 ## problems with the conversion of this test by pylit (as the text parts
86 ## would be converted to text).
87 ## A workaround is using a different comment string for the text blocks and
88 ## converting with e.g. ``pylit --comment-string='## ' pylit_test.py``.
92 code
= """#!/usr/bin/env python
93 # -*- coding: iso-8859-1 -*-
97 # in several paragraphs followed by a literal block::
99 block1 = 'first block'
101 # Some more text and the next block. ::
103 block2 = 'second block'
104 print(block1, block2)
109 codedata
= code
.splitlines(True)
111 ## Converting the text teststring with the `strip` option leads to::
113 stripped_code
= """#!/usr/bin/env python
114 # -*- coding: iso-8859-1 -*-
116 block1 = 'first block'
118 block2 = 'second block'
119 print(block1, block2)
124 ## pprint(stripped_code.splitlines(True))
126 ## Containers for special case examples:
128 ## 1. Text2Code samples
129 ## ``textsamples["what"] = (<text data>, <output>, <output (with `strip`)``
134 ## 2. Code2Text samples
135 ## ``codesamples["what"] = (<code data>, <output>, <output (with `strip`)``
140 ## Auxiliary function to test the textsamples and codesamples::
142 def check_converter(key
, converter
, output
):
144 extract
= converter()
146 outstr
= "".join(extract
)
147 print("soll:", repr(output
))
148 print("ist: ", repr(outstr
))
149 assert output
== outstr
151 ## Test generator for textsample tests::
153 def test_Text2Code_samples():
154 for key
, sample
in textsamples
.items():
155 yield (check_converter
, key
,
156 Text2Code(sample
[0].splitlines(True)), sample
[1])
158 yield (check_converter
, key
,
159 Text2Code(sample
[0].splitlines(True), strip
=True),
162 ## Test generator for codesample tests::
164 def test_Code2Text_samples():
165 for key
, sample
in codesamples
.items():
166 yield (check_converter
, key
,
167 Code2Text(sample
[0].splitlines(True)), sample
[1])
169 yield (check_converter
, key
,
170 Code2Text(sample
[0].splitlines(True), strip
=True),
173 ## Pre and postprocessing filters (for testing the filter hooks)
177 def r2l_filter(data
):
178 print("applying r2l filter")
180 yield line
.replace("r", "l")
184 defaults
.preprocessors
["rl2text"] = r2l_filter
188 def l2r_filter(data
):
189 print("applying l2r filter")
191 yield line
.replace("l", "r")
195 defaults
.preprocessors
["text2rl"] = l2r_filter
199 def x2u_filter(data
):
200 print("applying x2u filter")
202 yield line
.replace("x", "u")
206 defaults
.postprocessors
["x2text"] = x2u_filter
210 def u2x_filter(data
):
211 print("applying u2x filter")
213 yield line
.replace("u", "x")
217 defaults
.postprocessors
["text2x"] = u2x_filter
221 def test_x2u_filter():
222 soll
= text
.replace("x", "u")
223 result
= "".join([line
for line
in x2u_filter(textdata
)])
224 print("soll", repr(text
))
225 print("ist", repr(result
))
226 assert soll
== result
235 class test_TextCodeConverter(object):
236 """Test the TextCodeConverter parent class
241 def check_marker_regexp_true(self
, sample
, converter
):
242 match
= converter
.marker_regexp
.search(sample
)
243 print('marker: %r; sample %r' %(converter
.code_block_marker
, sample
))
244 print('match %r'%match
)
245 assert match
is not None
249 def check_marker_regexp_false(self
, sample
, converter
):
250 print('marker: %r; sample %r' %(converter
.code_block_marker
, sample
))
251 assert converter
.marker_regexp
.search(sample
) is None
255 def test_marker_regexp(self
):
264 ' indented text :: ',
266 'a .. directive:: somewhere::']
267 directives
= ['.. code-block:: python',
268 ' .. code-block:: python',
269 '.. code-block:: python listings',
270 ' .. code-block:: python listings']
271 misses
= ['.. comment string ::',
274 # default code_block_marker ('::')
275 self
.converter
= TextCodeConverter(textdata
)
276 assert self
.converter
.code_block_marker
== '::'
277 # self.converter is not seen by the check_marker_regexp_true() method
278 for sample
in literal
:
279 yield (self
.check_marker_regexp_true
, sample
, self
.converter
)
280 for sample
in directives
+misses
:
281 yield (self
.check_marker_regexp_false
, sample
, self
.converter
)
282 # code-block directive as marker
283 self
.converter
= TextCodeConverter(textdata
,
284 code_block_marker
='.. code-block::')
285 assert self
.converter
.code_block_marker
== '.. code-block::'
286 for sample
in directives
:
287 yield (self
.check_marker_regexp_true
, sample
, self
.converter
)
288 for sample
in literal
+misses
:
289 yield (self
.check_marker_regexp_false
, sample
, self
.converter
)
293 def test_get_indent(self
):
294 converter
= TextCodeConverter(textdata
)
295 assert converter
.get_indent("foo") == 0
296 assert converter
.get_indent(" foo") == 1
297 assert converter
.get_indent(" foo") == 2
301 def test_collect_blocks(self
):
302 converter
= TextCodeConverter(textdata
)
303 textblocks
= [block
for block
in collect_blocks(textdata
)]
305 assert len(textblocks
) == 7, "text sample has 7 blocks"
306 # assert reduce(operator.__add__, textblocks) == textdata
307 assert [line
for textblock
in textblocks
308 for line
in textblock
] == textdata
315 class test_Text2Code(object):
316 """Test the Text2Code class converting rst->code"""
321 self
.converter
= Text2Code(textdata
)
323 ## test helper funs ::
325 def test_set_state_empty(self
):
327 self
.converter
.set_state([])
328 raise AssertionError("should raise StopIteration")
329 except StopIteration:
332 def test_set_state_header(self
):
333 """test for "header" or "documentation" for first block"""
334 self
.converter
.state
= "" # normally set by the `convert` method
335 self
.converter
.set_state([".. header", " block"])
336 assert self
.converter
.state
== "header"
337 self
.converter
.state
= "" # normally set by the `convert` method
338 self
.converter
.set_state(["documentation", "block"])
339 assert self
.converter
.state
== "documentation"
341 def test_set_state_code_block(self
):
342 """test for "header" or "documentation" for "code_block" """
343 # normally set by the `convert` method
344 self
.converter
._textindent
= 0
345 self
.converter
.state
= "code_block"
346 self
.converter
.set_state(["documentation", " block"])
347 assert self
.converter
.state
== "documentation"
349 self
.converter
.state
= "code_block"
350 self
.converter
.set_state([" documentation", "block"])
351 assert self
.converter
.state
== "documentation"
353 self
.converter
.state
= "code_block"
354 self
.converter
.set_state([" code", " block"])
355 print(self
.converter
.state
)
356 assert self
.converter
.state
== "code_block"
358 def test_header_handler(self
):
359 """should strip header-string from header"""
360 self
.converter
._codeindent
= 0
361 sample
= [".. header", " block"]
362 lines
= [line
for line
in self
.converter
.header_handler(sample
)]
364 assert lines
== ["header", "block"]
366 def test_documentation_handler(self
):
367 """should add comment string to documentation"""
368 sample
= ["doc", "block", ""]
369 lines
= [line
for line
370 in self
.converter
.documentation_handler(sample
)]
372 assert lines
== ["# doc", "# block", "#"]
374 def test_documentation_handler_set_state(self
):
375 """should add comment string to documentation"""
376 sample
= ["doc", "block::", ""]
377 lines
= [line
for line
378 in self
.converter
.documentation_handler(sample
)]
380 assert lines
== ["# doc", "# block::", ""]
381 assert self
.converter
.state
== "code_block"
383 def test_code_block_handler(self
):
384 """should un-indent code-blocks"""
385 self
.converter
._codeindent
= 0 # normally set in `convert`
386 sample
= [" code", " block", ""]
387 lines
= [line
for line
388 in self
.converter
.code_block_handler(sample
)]
390 assert lines
== ["code", "block", ""]
393 ## base tests on the "long" test data ::
396 """Calling a Text2Code instance should return the converted data as list of lines"""
397 output
= self
.converter()
398 print(repr(codedata
))
400 assert codedata
== output
402 def test_call_strip(self
):
403 """strip=True should strip text parts"""
404 self
.converter
.strip
= True
405 output
= self
.converter()
406 print(repr(stripped_code
.splitlines(True)))
408 assert stripped_code
.splitlines(True) == output
411 outstr
= str(self
.converter
)
414 assert code
== outstr
416 def test_str_strip1(self
):
417 """strip=True should strip text parts.
419 Version 1 with `strip` given as optional argument"""
420 outstr
= str(Text2Code(textdata
, strip
=True))
421 print("ist ", repr(outstr
))
422 print("soll", repr(stripped_code
))
424 assert stripped_code
== outstr
426 def test_str_strip2(self
):
427 """strip=True should strip text parts
429 Version 2 with `strip` set after instantiation"""
430 self
.converter
.strip
= True
431 outstr
= str(self
.converter
)
432 print("ist ", repr(outstr
))
433 print("soll", repr(stripped_code
))
435 assert stripped_code
== outstr
437 def test_malindented_code_line(self
):
438 """raise error if code line is less indented than code-indent"""
439 data1
= [".. #!/usr/bin/env python\n", # indent == 4 * " "
441 " print('hello world'"] # indent == 2 * " ")
442 data2
= ["..\t#!/usr/bin/env python\n", # indent == 8 * " "
444 " print('hello world'"] # indent == 2 * " ")
445 for data
in (data1
, data2
):
447 blocks
= Text2Code(data
)()
448 assert False, "wrong indent did not raise ValueError"
452 def test_str_different_comment_string(self
):
453 """Convert only comments with the specified comment string to text
455 data
= [".. #!/usr/bin/env python\n",
457 '::\n', # leading code block as header
459 " block1 = 'first block'\n",
462 soll
= "\n".join(["#!/usr/bin/env python",
466 "block1 = 'first block'",
470 outstr
= str(Text2Code(data
, comment_string
="##"))
471 print("soll:", repr(soll
))
472 print("ist: ", repr(outstr
))
473 assert outstr
== soll
475 # Filters: test pre- and postprocessing of data
477 def test_get_filter_preprocessor(self
):
478 """should return filter from filter_set for language"""
479 preprocessor
= self
.converter
.get_filter("preprocessors", "rl")
481 assert preprocessor
== l2r_filter
483 def test_get_filter_postprocessor(self
):
484 """should return filter from filter_set for language"""
485 postprocessor
= self
.converter
.get_filter("postprocessors", "x")
487 assert postprocessor
== u2x_filter
489 def test_get_css_postprocessor(self
):
490 """should return filter from filter_set for language"""
491 postprocessor
= self
.converter
.get_filter("postprocessors", "css")
493 assert postprocessor
== dumb_c_postprocessor
495 def test_get_filter_nonexisting_language_filter(self
):
496 """should return identity_filter if language has no filter in set"""
497 preprocessor
= self
.converter
.get_filter("preprocessors", "foo")
499 assert preprocessor
== identity_filter
501 def test_get_filter_nonexisting_filter_set(self
):
502 """should return identity_filter if filter_set does not exist"""
503 processor
= self
.converter
.get_filter("foo_filters", "foo")
505 assert processor
== identity_filter
507 def test_preprocessor(self
):
508 """Preprocess data with registered preprocessor for language"""
509 output
= Text2Code(textdata
, language
="x", comment_string
="# ")()
510 soll
= [line
for line
in u2x_filter(codedata
)]
511 print("soll: ", repr(soll
))
512 print("ist: ", repr(output
))
513 assert output
== soll
515 def test_postprocessor(self
):
516 """Preprocess data with registered postprocessor for language"""
517 output
= Text2Code(textdata
, language
="x", comment_string
="# ")()
518 soll
= [line
for line
in u2x_filter(codedata
)]
519 print("soll:", repr(soll
))
520 print("ist: ", repr(output
))
521 assert output
== soll
526 ## Code follows text block without blank line
527 ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
529 ## End of text block detected ('::') but no paragraph separator (blank line)
532 ## It is an reStructuredText syntax error, if a "literal block
533 ## marker" is not followed by a blank line.
535 ## Assuming that no double colon at end of line occurs accidentally,
536 ## pylit could fix this and issue a warning::
538 # Do we need this feature? (Complicates code a lot)
539 # textsamples["ensure blank line after text"] = (
540 # """text followed by a literal block::
541 # block1 = 'first block'
543 # """# text followed by a literal block::
545 # block1 = 'first block'
548 ## Text follows code block without blank line
549 ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
551 ## End of code block detected (a line not more indented than the preceding text
554 ## reStructuredText syntax demands a paragraph separator (blank line) before
557 ## Assuming that the unindent is not accidental, pylit could fix this and
558 ## issues a warning::
560 # Do we need this feature? (Complicates code)
561 # textsamples["ensure blank line after code"] = (
564 # block1 = 'first block'
569 # block1 = 'first block'
574 ## Options follow code-block directive
575 ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
577 textsamples
["code-block directive options"] = (
591 textsamples
["no code-block directive options"] = (
594 text following ``::`` without blank line
600 # text following ``::`` without blank line
605 ## A double colon on a line on its own
606 ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
608 ## As a double colon is added by the Code2Text conversion after a text block
609 ## (if not already present), it could be removed by the Text2Code conversion
610 ## to keep the source small and pretty.
612 ## However, this would put the text and code source line numbers out of sync,
613 ## which is bad for error reporting, failing doctests, and the JED editor
614 ## support with the `pylit_buffer()` function in
615 ## https://jedmodes.sourceforge.io/mode/pylit/.
617 ## Maybe this could be left to a post-processing filter::
619 # textsamples["remove single double colon"] = (
620 # ["text followed by a literal block\n",
624 # " foo = 'first'\n"]
625 # ["", # empty header
626 # "# text followed by a literal block\n\n",
631 ## Convert a leading reStructured text comment (variant: only if there is
632 ## content on the first line) to a leading code block. Return an empty list,
633 ## if there is no header. ::
635 textsamples
["simple header"] = (".. print('hello world')",
636 "print('hello world')")
638 textsamples
["no header (start with text)"] = (
639 """a classical example without header::
643 """# a classical example without header::
649 textsamples
["no header (start with blank line)"] = (
651 a classical example without header::
656 # a classical example without header::
662 textsamples
["standard header, followed by text"] = (
663 """.. #!/usr/bin/env python
664 # -*- coding: iso-8859-1 -*-
666 a classical example with header::
670 """#!/usr/bin/env python
671 # -*- coding: iso-8859-1 -*-
673 # a classical example with header::
678 textsamples
["standard header, followed by code"] = (
679 """.. #!/usr/bin/env python
683 """#!/usr/bin/env python
688 textsamples
["null string"] = ("", "", "")
695 class test_Code2Text(object):
698 self
.converter
= Code2Text(codedata
)
700 ## Code2Text.strip_literal_marker
702 ## * strip `::`-line as well as preceding blank line if on a line on its own
703 ## * strip `::` if it is preceded by whitespace.
704 ## * convert `::` to a single colon if preceded by text
707 def check_strip_code_block_marker(self
, sample
):
708 """test Code2Text.strip_code_block_marker"""
709 ist
= sample
[0].splitlines(True)
710 soll
= sample
[1].splitlines(True)
712 converter
= Code2Text(codedata
)
713 converter
.strip_code_block_marker(ist
)
714 print("soll:", repr(soll
))
715 print("ist: ", repr(ist
))
719 def test_strip_code_block_marker(self
):
720 samples
= (("text\n\n::\n\n", "text\n\n"),
721 ("text\n::\n\n", "text\n\n"),
722 ("text ::\n\n", "text\n\n"),
723 ("text::\n\n", "text:\n\n"),
724 ("text:\n\n", "text:\n\n"),
725 ("text\n\n", "text\n\n"),
728 for sample
in samples
:
729 yield (self
.check_strip_code_block_marker
, sample
)
731 ## Code2Text.set_state
734 def test_set_state(self
):
735 samples
= (("code_block", ["code_block\n"], "code_block"),
736 ("code_block", ["#code_block\n"], "code_block"),
737 ("code_block", ["## code_block\n"], "code_block"),
738 ("code_block", ["# documentation\n"], "documentation"),
739 ("code_block", ["# documentation\n"], "documentation"),
740 ("code_block", ["# \n"], "documentation"),
741 ("code_block", ["#\n"], "documentation"),
742 ("code_block", ["\n"], "documentation"),
743 ("", ["code_block\n"], "header"),
744 ("", ["# documentation\n"], "documentation"),
745 ("documentation", ["code_block\n"], "code_block"),
746 ("documentation", ["# documentation\n"], "documentation"),
748 print("comment string", repr(self
.converter
.comment_string
))
749 for (old_state
, lines
, soll
) in samples
:
750 self
.converter
.state
= old_state
751 self
.converter
.set_state(lines
)
752 print(repr(lines
), "old state", old_state
)
753 print("soll", repr(soll
),)
754 print("result", repr(self
.converter
.state
))
755 assert soll
== self
.converter
.state
757 ## base tests on the "long" test strings ::
760 output
= self
.converter()
761 print(repr(textdata
))
763 assert textdata
== output
765 def test_call_strip(self
):
766 output
= Code2Text(codedata
, strip
=True)()
767 print(repr(stripped_text
.splitlines(True)))
769 assert stripped_text
.splitlines(True) == output
772 """Test Code2Text class converting code->text"""
773 outstr
= str(self
.converter
)
775 print("soll:", repr(text
))
776 print("ist: ", repr(outstr
))
777 assert text
== outstr
779 def test_str_strip(self
):
780 """Test Code2Text class converting code->rst with strip=True
782 Should strip code blocks
784 outstr
= str(Code2Text(codedata
, strip
=True))
785 print(repr(stripped_text
))
787 assert stripped_text
== outstr
789 def test_str_different_comment_string(self
):
790 """Convert only comments with the specified comment string to text
792 outstr
= str(Code2Text(codedata
, comment_string
="##", strip
=True))
797 'block1 = "first block"\n',
800 soll
= ('.. # ::\n' # leading code block as header
802 ' block1 = "first block"\n'
804 ' more text' # keep space (not part of comment string)
806 outstr
= str(Code2Text(data
, comment_string
="##"))
807 print("soll:", repr(soll
))
808 print("ist: ", repr(outstr
))
809 assert outstr
== soll
811 def test_call_different_code_block_marker(self
):
812 """recognize specified code-block marker
814 data
= ["# .. code-block:: python\n",
816 "block1 = 'first block'\n",
819 soll
= ['.. code-block:: python\n',
821 " block1 = 'first block'\n",
823 ' more text\n'] # keep space (not part of comment string)
825 converter
= Code2Text(data
, code_block_marker
='.. code-block::')
827 print("soll:", repr(soll
))
828 print("ist: ", repr(output
))
829 assert output
== soll
831 # Filters: test pre- and postprocessing of Code2Text data conversion
833 def test_get_filter_preprocessor(self
):
834 """should return Code2Text preprocessor for language"""
835 preprocessor
= self
.converter
.get_filter("preprocessors", "rl")
837 assert preprocessor
== r2l_filter
839 def test_get_css_preprocessor(self
):
840 """should return filter from filter_set for language"""
841 preprocessor
= self
.converter
.get_filter("preprocessors", "css")
843 assert preprocessor
== dumb_c_preprocessor
845 def test_get_filter_postprocessor(self
):
846 """should return Code2Text postprocessor for language"""
847 postprocessor
= self
.converter
.get_filter("postprocessors", "x")
849 assert postprocessor
== x2u_filter
851 def test_get_filter_nonexisting_language_filter(self
):
852 """should return identity_filter if language has no filter in set"""
853 preprocessor
= self
.converter
.get_filter("preprocessors", "foo")
855 assert preprocessor
== identity_filter
857 def test_get_filter_nonexisting_filter_set(self
):
858 """should return identity_filter if filter_set does not exist"""
859 processor
= self
.converter
.get_filter("foo_filters", "foo")
861 assert processor
== identity_filter
863 def test_preprocessor(self
):
864 """Preprocess data with registered preprocessor for language"""
865 converter
= Code2Text(codedata
, language
="rl", comment_string
="# ")
866 print("preprocessor", converter
.preprocessor
)
867 print("postprocessor", converter
.postprocessor
)
869 soll
= [line
.replace("r", "l") for line
in textdata
]
870 print("ist: ", repr(output
))
871 print("soll:", repr(soll
))
872 assert output
== soll
874 def test_postprocessor(self
):
875 """Postprocess data with registered postprocessor for language"""
876 output
= Code2Text(codedata
, language
="x", comment_string
="# ")()
877 soll
= [line
.replace("x", "u") for line
in textdata
]
878 print("soll:", repr(soll
))
879 print("ist: ", repr(output
))
880 assert output
== soll
886 ## blank comment line
887 ## ~~~~~~~~~~~~~~~~~~
889 ## Normally, whitespace in the comment string is significant, i.e. with
890 ## ``comment_string = "# "``, a line ``"#something\n"`` will count as code.
892 ## However, if a comment line is blank, trailing whitespace in the comment
893 ## string should be ignored, i.e. ``#\n`` is recognised as a blank text line::
895 codesamples
["ignore trailing whitespace in comment string for blank line"] = (
898 block1 = 'first block'
905 block1 = 'first block'
911 ## No blank line after text
912 ## ~~~~~~~~~~~~~~~~~~~~~~~~
914 ## If a matching comment precedes or follows a code line (i.e. any line
915 ## without matching comment) without a blank line in between, it counts as code
918 ## This will keep small inline comments close to the code they comment on. It
919 ## will also keep blocks together where one commented line does not match the
920 ## comment string (the whole block will be kept as commented code)
923 codesamples
["comment before code (without blank line)"] = (
941 codesamples
["comment block before code (without blank line)"] = (
943 # no text (watch the comment sign in the next line)::
949 .. # no text (watch the comment sign in the next line)::
956 codesamples
["comment after code (without blank line)"] = (
960 block1 = 'first block'
968 block1 = 'first block'
977 codesamples
["comment block after code (without blank line)"] = (
981 block1 = 'first block'
988 block1 = 'first block'
996 ## missing literal block marker
997 ## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
999 ## If text (with matching comment string) is followed by code (line(s) without
1000 ## matching comment string), but there is no double colon at the end, back
1001 ## conversion would not recognise the end of text!
1003 ## Therefore, pylit adds a paragraph containing only ``::`` -- the literal
1004 ## block marker in expanded form. (While it would in many cases be nicer to
1005 ## add the double colon to the last text line, this is not always valid rst
1006 ## syntax, e.g. after a section header or a list. Therefore the automatic
1007 ## insertion will use the save form, feel free to correct this by hand.)::
1009 codesamples
["insert missing double colon after text block"] = (
1010 """# text followed by code without double colon
1014 """text followed by code without double colon
1020 """text followed by code without double colon
1024 codesamples
["ignore directive options when looking for code-block marker"] = (
1028 # :option2: argument
1040 codesamples
["code-block marker followed by text not a directive option"] = (
1043 # text following ``::`` without blank line
1049 text following ``::`` without blank line
1060 ## Convert a header (leading code block) to a reStructured text comment. ::
1062 codesamples
["no matching comment, just code"] = (
1063 """print('hello world')
1067 """.. print('hello world')
1072 codesamples
["empty header (start with matching comment)"] = (
1073 """# a classical example without header::
1075 print('hello world')
1077 """a classical example without header::
1079 print('hello world')
1081 """a classical example without header:
1085 codesamples
["standard header, followed by text"] = (
1086 """#!/usr/bin/env python
1087 # -*- coding: iso-8859-1 -*-
1089 # a classical example with header::
1091 print('hello world')
1093 """.. #!/usr/bin/env python
1094 # -*- coding: iso-8859-1 -*-
1096 a classical example with header::
1098 print('hello world')
1100 """a classical example with header:
1104 codesamples
["standard header, followed by code"] = (
1105 """#!/usr/bin/env python
1107 print('hello world')
1109 """.. #!/usr/bin/env python
1111 print('hello world')
1120 css_code
= ['/* import the default Docutils style sheet */\n',
1121 '/* --------------------------------------- */\n',
1126 '@import url("html4css1.css"); /* style */\n']
1130 css_filtered_code
= ['// import the default Docutils style sheet\n',
1131 '// ---------------------------------------\n',
1136 '@import url("html4css1.css"); /* style */\n']
1140 def test_dumb_c_preprocessor():
1141 """convert `C` to `C++` comments"""
1142 output
= [line
for line
in dumb_c_preprocessor(css_code
)]
1143 print("ist: %r"%output
)
1144 print("soll: %r"%css_filtered
_code
)
1145 assert output
== css_filtered_code
1149 def test_dumb_c_postprocessor():
1150 """convert `C++` to `C` comments"""
1151 output
= [line
for line
in dumb_c_postprocessor(css_filtered_code
)]
1152 print("ist: %r"%output
)
1153 print("soll: %r"%css_code
)
1154 assert output
== css_code
1160 if __name__
== "__main__":
1161 nose
.runmodule() # requires nose 0.9.1