2 # -*- coding: iso-8859-1 -*-
4 ## Test the pylit.py literal python module
5 ## =======================================
7 ## :Date: $Date: 2007-05-17 $
8 ## :Version: SVN-Revision $Revision: 45 $
9 ## :URL: $URL: svn+ssh://svn.berlios.de/svnroot/repos/pylit/trunk/test/pylit_test.py $
10 ## :Copyright: 2006 Guenter Milde.
11 ## Released under the terms of the GNU General Public License
17 ## A catalog of errors
18 ## ----------------------
20 ## from file:///home/milde/Texte/Doc/Programmierung/Software-Carpentry/lec/unit.html
22 ## * Numbers: zero, largest, smallest magnitude, most negative
23 ## * Structures: empty, exactly one element, maximum number of elements
24 ## - Duplicate elements (e.g., letter "J" appears three times in a string)
25 ## - Aliased elements (e.g., a list contains two references to another list)
26 ## - Circular structures (e.g., a list that contains a reference to itself)
27 ## * Searching: no match found, one match found, multiple matches found,
29 ## - Code like x = find_all(structure)[0] is almost always wrong
30 ## - Should also check aliased matches (same thing found multiple times)
34 """pylit_test.py: test the "literal python" module"""
36 from pprint
import pprint
41 ## Text <-> Code conversion
42 ## ========================
47 ## Example of text, code and stripped code with typical features"::
49 text
= """.. #!/usr/bin/env python
50 # -*- coding: iso-8859-1 -*-
54 in several paragraphs followed by a literal block::
56 block1 = 'first block'
58 Some more text and the next block. ::
60 block2 = 'second block'
67 ## The converter expects the data in separate lines (iterator or list)
68 ## with trailing newlines. We use the `splitlines` string method with
71 textdata
= text
.splitlines(True)
74 ## If a "code" source is converted with the `strip` option, only text blocks
75 ## are extracted, which leads to::
77 stripped_text
= """Leading text
79 in several paragraphs followed by a literal block:
81 Some more text and the next block.
86 ## The code corresponding to the text test string.
88 ## Using a triple-quoted string for the code (and stripped_code) can create
89 ## problems with the conversion of this test by pylit (as the text parts
90 ## would be converted to text).
91 ## A workaround is using a different comment string for the text blocks and
92 ## converting with e.g. ``pylit --comment-string='## ' pylit_test.py``.
96 code
= """#!/usr/bin/env python
97 # -*- coding: iso-8859-1 -*-
101 # in several paragraphs followed by a literal block::
103 block1 = 'first block'
105 # Some more text and the next block. ::
107 block2 = 'second block'
114 codedata
= code
.splitlines(True)
116 ## Converting the text teststring with the `strip` option leads to::
118 stripped_code
= """#!/usr/bin/env python
119 # -*- coding: iso-8859-1 -*-
121 block1 = 'first block'
123 block2 = 'second block'
129 ## pprint(stripped_code.splitlines(True))
131 ## Containers for special case examples:
133 ## 1. Text2Code samples
134 ## ``textsamples["what"] = (<text data>, <output>, <output (with `strip`)``
139 ## 2. Code2Text samples
140 ## ``codesamples["what"] = (<code data>, <output>, <output (with `strip`)``
145 ## Auxiliary function to test the textsamples and codesamples::
147 def check_converter(key
, converter
, output
):
149 extract
= converter()
151 outstr
= "".join(extract
)
152 print "soll:", repr(output
)
153 print "ist: ", repr(outstr
)
154 assert output
== outstr
156 ## Test generator for textsample tests::
158 def test_Text2Code_samples():
159 for key
, sample
in textsamples
.iteritems():
160 yield (check_converter
, key
,
161 Text2Code(sample
[0].splitlines(True)), sample
[1])
163 yield (check_converter
, key
,
164 Text2Code(sample
[0].splitlines(True), strip
=True),
167 ## Test generator for codesample tests::
169 def test_Code2Text_samples():
170 for key
, sample
in codesamples
.iteritems():
171 yield (check_converter
, key
,
172 Code2Text(sample
[0].splitlines(True)), sample
[1])
174 yield (check_converter
, key
,
175 Code2Text(sample
[0].splitlines(True), strip
=True),
179 ## Pre and postprocessing filters (for testing the filter hooks)
183 def r2l_filter(data
):
184 print "applying r2l filter"
186 yield line
.replace("r", "l")
190 defaults
.preprocessors
["rl2text"] = r2l_filter
194 def l2r_filter(data
):
195 print "applying l2r filter"
197 yield line
.replace("l", "r")
201 defaults
.preprocessors
["text2rl"] = l2r_filter
205 def x2u_filter(data
):
206 print "applying x2u filter"
208 yield line
.replace("x", "u")
212 defaults
.postprocessors
["x2text"] = x2u_filter
216 def u2x_filter(data
):
217 print "applying u2x filter"
219 yield line
.replace("u", "x")
223 defaults
.postprocessors
["text2x"] = u2x_filter
227 def test_x2u_filter():
228 soll
= text
.replace("x", "u")
229 result
= "".join([line
for line
in x2u_filter(textdata
)])
230 print "soll", repr(text
)
231 print "ist", repr(result
)
232 assert soll
== result
241 class test_TextCodeConverter(object):
242 """Test the TextCodeConverter parent class"""
246 def check_marker_regexp_true(self
, sample
):
247 match
= self
.converter
.marker_regexp
.search(sample
)
248 print 'marker: %r; sample %r' %(self
.converter
.code_block_marker
, sample
)
249 print 'match %r'%match
250 assert match
is not None
254 def check_marker_regexp_false(self
, sample
):
255 assert self
.converter
.marker_regexp
.search(sample
) is None
259 def test_marker_regexp(self
):
268 ' indented text :: ',
270 'a .. directive:: somewhere::']
271 directive
= ['.. code-block:: python',
272 ' .. code-block:: python',
273 '.. code-block:: python listings',
274 ' .. code-block:: python listings']
275 misses
= ['.. comment string ::',
278 # default code_block_marker ('::')
279 self
.converter
= TextCodeConverter(textdata
)
280 for sample
in literal
:
281 yield (self
.check_marker_regexp_true
, sample
)
282 for sample
in directive
+misses
:
283 yield (self
.check_marker_regexp_false
, sample
)
284 # code-block directive as marker
285 self
.converter
= TextCodeConverter(textdata
,
286 code_block_marker
='.. code-block::')
287 for sample
in directive
:
288 yield (self
.check_marker_regexp_true
, sample
)
289 for sample
in literal
+misses
:
290 yield (self
.check_marker_regexp_false
, sample
)
294 def test_get_indent(self
):
295 converter
= TextCodeConverter(textdata
)
296 assert converter
.get_indent("foo") == 0
297 assert converter
.get_indent(" foo") == 1
298 assert converter
.get_indent(" foo") == 2
302 def test_collect_blocks(self
):
303 converter
= TextCodeConverter(textdata
)
304 textblocks
= [block
for block
in collect_blocks(textdata
)]
306 assert len(textblocks
) == 7, "text sample has 7 blocks"
307 assert reduce(operator
.__add
__, textblocks
) == textdata
314 class test_Text2Code(object):
315 """Test the Text2Code class converting rst->code"""
320 self
.converter
= Text2Code(textdata
)
322 ## test helper funs ::
324 def test_set_state_empty(self
):
326 self
.converter
.set_state([])
327 raise AssertionError, "should raise StopIteration"
328 except StopIteration:
331 def test_set_state_header(self
):
332 """test for "header" or "documentation" for first block"""
333 self
.converter
.state
= "" # normally set by the `convert` method
334 self
.converter
.set_state([".. header", " block"])
335 assert self
.converter
.state
== "header"
336 self
.converter
.state
= "" # normally set by the `convert` method
337 self
.converter
.set_state(["documentation", "block"])
338 assert self
.converter
.state
== "documentation"
340 def test_set_state_code_block(self
):
341 """test for "header" or "documentation" for "code_block" """
342 # normally set by the `convert` method
343 self
.converter
._textindent
= 0
344 self
.converter
.state
= "code_block"
345 self
.converter
.set_state(["documentation", " block"])
346 assert self
.converter
.state
== "documentation"
348 self
.converter
.state
= "code_block"
349 self
.converter
.set_state([" documentation", "block"])
350 assert self
.converter
.state
== "documentation"
352 self
.converter
.state
= "code_block"
353 self
.converter
.set_state([" code", " block"])
354 print self
.converter
.state
355 assert self
.converter
.state
== "code_block"
357 def test_header_handler(self
):
358 """should strip header-string from header"""
359 self
.converter
._codeindent
= 0
360 sample
= [".. header", " block"]
361 lines
= [line
for line
in self
.converter
.header_handler(sample
)]
363 assert lines
== ["header", "block"]
365 def test_documentation_handler(self
):
366 """should add comment string to documentation"""
367 sample
= ["doc", "block", ""]
368 lines
= [line
for line
369 in self
.converter
.documentation_handler(sample
)]
371 assert lines
== ["# doc", "# block", "# "]
373 def test_documentation_handler_set_state(self
):
374 """should add comment string to documentation"""
375 sample
= ["doc", "block::", ""]
376 lines
= [line
for line
377 in self
.converter
.documentation_handler(sample
)]
379 assert lines
== ["# doc", "# block::", ""]
380 assert self
.converter
.state
== "code_block"
382 def test_code_block_handler(self
):
383 """should un-indent code-blocks"""
384 self
.converter
._codeindent
= 0 # normally set in `convert`
385 sample
= [" code", " block", ""]
386 lines
= [line
for line
387 in self
.converter
.code_block_handler(sample
)]
389 assert lines
== ["code", "block", ""]
392 ## base tests on the "long" test data ::
395 """Calling a Text2Code instance should return the converted data as list of lines"""
396 output
= self
.converter()
399 assert codedata
== output
401 def test_call_strip(self
):
402 """strip=True should strip text parts"""
403 self
.converter
.strip
= True
404 output
= self
.converter()
405 print repr(stripped_code
.splitlines(True))
407 assert stripped_code
.splitlines(True) == output
410 outstr
= str(self
.converter
)
413 assert code
== outstr
415 def test_str_strip1(self
):
416 """strip=True should strip text parts.
418 Version 1 with `strip` given as optional argument"""
419 outstr
= str(Text2Code(textdata
, strip
=True))
420 print "ist ", repr(outstr
)
421 print "soll", repr(stripped_code
)
423 assert stripped_code
== outstr
425 def test_str_strip2(self
):
426 """strip=True should strip text parts
428 Version 2 with `strip` set after instantiation"""
429 self
.converter
.strip
= True
430 outstr
= str(self
.converter
)
431 print "ist ", repr(outstr
)
432 print "soll", repr(stripped_code
)
434 assert stripped_code
== outstr
436 def test_malindented_code_line(self
):
437 """raise error if code line is less indented than code-indent"""
438 data1
= [".. #!/usr/bin/env python\n", # indent == 4 * " "
440 " print 'hello world'"] # indent == 2 * " "
441 data2
= ["..\t#!/usr/bin/env python\n", # indent == 8 * " "
443 " print 'hello world'"] # indent == 2 * " "
444 for data
in (data1
, data2
):
446 blocks
= Text2Code(data
)()
447 assert False, "wrong indent did not raise ValueError"
451 def test_str_different_comment_string(self
):
452 """Convert only comments with the specified comment string to text
454 data
= [".. #!/usr/bin/env python\n",
456 '::\n', # leading code block as header
458 " block1 = 'first block'\n",
461 soll
= "\n".join(["#!/usr/bin/env python",
465 "block1 = 'first block'",
469 outstr
= str(Text2Code(data
, comment_string
="##"))
470 print "soll:", repr(soll
)
471 print "ist: ", repr(outstr
)
472 assert outstr
== soll
474 # Filters: test pre- and postprocessing of data
476 def test_get_filter_preprocessor(self
):
477 """should return filter from filter_set for language"""
478 preprocessor
= self
.converter
.get_filter("preprocessors", "rl")
480 assert preprocessor
== l2r_filter
482 def test_get_filter_postprocessor(self
):
483 """should return filter from filter_set for language"""
484 postprocessor
= self
.converter
.get_filter("postprocessors", "x")
486 assert postprocessor
== u2x_filter
488 def test_get_css_postprocessor(self
):
489 """should return filter from filter_set for language"""
490 postprocessor
= self
.converter
.get_filter("postprocessors", "css")
492 assert postprocessor
== dumb_c_postprocessor
494 def test_get_filter_nonexisting_language_filter(self
):
495 """should return identity_filter if language has no filter in set"""
496 preprocessor
= self
.converter
.get_filter("preprocessors", "foo")
498 assert preprocessor
== identity_filter
500 def test_get_filter_nonexisting_filter_set(self
):
501 """should return identity_filter if filter_set does not exist"""
502 processor
= self
.converter
.get_filter("foo_filters", "foo")
504 assert processor
== identity_filter
506 def test_preprocessor(self
):
507 """Preprocess data with registered preprocessor for language"""
508 output
= Text2Code(textdata
, language
="x", comment_string
="# ")()
509 soll
= [line
for line
in u2x_filter(codedata
)]
510 print "soll: ", repr(soll
)
511 print "ist: ", repr(output
)
512 assert output
== soll
514 def test_postprocessor(self
):
515 """Preprocess data with registered postprocessor for language"""
516 output
= Text2Code(textdata
, language
="x", comment_string
="# ")()
517 soll
= [line
for line
in u2x_filter(codedata
)]
518 print "soll:", repr(soll
)
519 print "ist: ", repr(output
)
520 assert output
== soll
525 ## Code follows text block without blank line
526 ## ''''''''''''''''''''''''''''''''''''''''''
528 ## End of text block detected ('::') but no paragraph separator (blank line)
531 ## It is an reStructuredText syntax error, if a "literal block
532 ## marker" is not followed by a blank line.
534 ## Assuming that no double colon at end of line occures accidentially,
535 ## pylit could fix this and issue a warning::
537 # Do we need this feature? (Complicates code a lot)
538 # textsamples["ensure blank line after text"] = (
539 # """text followed by a literal block::
540 # block1 = 'first block'
542 # """# text followed by a literal block::
544 # block1 = 'first block'
547 ## Text follows code block without blank line
548 ## ''''''''''''''''''''''''''''''''''''''''''
550 ## End of code block detected (a line not more indented than the preceding text
553 ## reStructuredText syntax demands a paragraph separator (blank line) before
556 ## Assuming that the unindent is not accidential, pylit could fix this and
557 ## issues a warning::
559 # Do we need this feature? (Complicates code)
560 # textsamples["ensure blank line after code"] = (
563 # block1 = 'first block'
568 # block1 = 'first block'
573 ## A double colon on a line on its own
574 ## '''''''''''''''''''''''''''''''''''
576 ## As a double colon is added by the Code2Text conversion after a text block
577 ## (if not already present), it could be removed by the Text2Code conversion
578 ## to keep the source small and pretty.
580 ## However, this would put the text and code source line numbers out of sync,
581 ## which is bad for error reporting, failing doctests, and the JED editor
582 ## support with the `pylit_buffer()` function in
583 ## http://jedmodes.sf.net/mode/pylit.sl .
585 ## Maybe this could be left to a post-processing filter::
587 # textsamples["remove single double colon"] = (
588 # ["text followed by a literal block\n",
592 # " foo = 'first'\n"]
593 # ["", # empty header
594 # "# text followed by a literal block\n\n",
599 ## Convert a leading reStructured text comment (variant: only if there is
600 ## content on the first line) to a leading code block. Return an empty list,
601 ## if there is no header. ::
603 textsamples
["simple header"] = (".. print 'hello world'",
604 "print 'hello world'")
606 textsamples
["no header (start with text)"] = (
607 """a classical example without header::
611 """# a classical example without header::
617 textsamples
["no header (start with blank line)"] = (
619 a classical example without header::
624 # a classical example without header::
630 textsamples
["standard header, followed by text"] = (
631 """.. #!/usr/bin/env python
632 # -*- coding: iso-8859-1 -*-
634 a classical example with header::
638 """#!/usr/bin/env python
639 # -*- coding: iso-8859-1 -*-
641 # a classical example with header::
646 textsamples
["standard header, followed by code"] = (
647 """.. #!/usr/bin/env python
651 """#!/usr/bin/env python
656 textsamples
["null string"] = ("", "", "")
663 class test_Code2Text(object):
666 self
.converter
= Code2Text(codedata
)
668 ## Code2Text.strip_literal_marker
670 ## * strip `::`-line as well as preceding blank line if on a line on its own
671 ## * strip `::` if it is preceded by whitespace.
672 ## * convert `::` to a single colon if preceded by text
675 def check_strip_code_block_marker(self
, sample
):
676 """test Code2Text.strip_code_block_marker"""
677 ist
= sample
[0].splitlines(True)
678 soll
= sample
[1].splitlines(True)
680 converter
= Code2Text(codedata
)
681 converter
.strip_code_block_marker(ist
)
682 print "soll:", repr(soll
)
683 print "ist: ", repr(ist
)
687 def test_strip_code_block_marker(self
):
688 samples
= (("text\n\n::\n\n", "text\n\n"),
689 ("text\n::\n\n", "text\n\n"),
690 ("text ::\n\n", "text\n\n"),
691 ("text::\n\n", "text:\n\n"),
692 ("text:\n\n", "text:\n\n"),
693 ("text\n\n", "text\n\n"),
696 for sample
in samples
:
697 yield (self
.check_strip_code_block_marker
, sample
)
699 ## Code2Text.set_state
702 def test_set_state(self
):
703 samples
= (("code_block", ["code_block\n"], "code_block"),
704 ("code_block", ["#code_block\n"], "code_block"),
705 ("code_block", ["## code_block\n"], "code_block"),
706 ("code_block", ["# documentation\n"], "documentation"),
707 ("code_block", ["# documentation\n"], "documentation"),
708 ("code_block", ["# \n"], "documentation"),
709 ("code_block", ["#\n"], "documentation"),
710 ("code_block", ["\n"], "documentation"),
711 ("", ["code_block\n"], "header"),
712 ("", ["# documentation\n"], "documentation"),
713 ("documentation", ["code_block\n"], "code_block"),
714 ("documentation", ["# documentation\n"], "documentation"),
716 print "comment string", repr(self
.converter
.comment_string
)
717 for (old_state
, lines
, soll
) in samples
:
718 self
.converter
.state
= old_state
719 self
.converter
.set_state(lines
)
720 print repr(lines
), "old state", old_state
721 print "soll", repr(soll
),
722 print "result", repr(self
.converter
.state
)
723 assert soll
== self
.converter
.state
725 ## base tests on the "long" test strings ::
728 output
= self
.converter()
731 assert textdata
== output
733 def test_call_strip(self
):
734 output
= Code2Text(codedata
, strip
=True)()
735 print repr(stripped_text
.splitlines(True))
737 assert stripped_text
.splitlines(True) == output
740 """Test Code2Text class converting code->text"""
741 outstr
= str(self
.converter
)
743 print "soll:", repr(text
)
744 print "ist: ", repr(outstr
)
745 assert text
== outstr
747 def test_str_strip(self
):
748 """Test Code2Text class converting code->rst with strip=True
750 Should strip code blocks
752 outstr
= str(Code2Text(codedata
, strip
=True))
753 print repr(stripped_text
)
755 assert stripped_text
== outstr
757 def test_str_different_comment_string(self
):
758 """Convert only comments with the specified comment string to text
760 outstr
= str(Code2Text(codedata
, comment_string
="##", strip
=True))
765 "block1 = 'first block'\n",
768 soll
= "\n".join(['.. # ::', # leading code block as header
770 " block1 = 'first block'",
772 ' more text'] # keep space (not part of comment string)
774 outstr
= str(Code2Text(data
, comment_string
="##"))
775 print "soll:", repr(soll
)
776 print "ist: ", repr(outstr
)
777 assert outstr
== soll
779 def test_call_different_code_block_marker(self
):
780 """recognize specified code-block marker
782 data
= ["# .. code-block:: python\n",
784 "block1 = 'first block'\n",
787 soll
= ['.. code-block:: python\n',
789 " block1 = 'first block'\n",
791 ' more text\n'] # keep space (not part of comment string)
793 converter
= Code2Text(data
, code_block_marker
='.. code-block::')
795 print "soll:", repr(soll
)
796 print "ist: ", repr(output
)
797 assert output
== soll
799 # Filters: test pre- and postprocessing of Code2Text data conversion
801 def test_get_filter_preprocessor(self
):
802 """should return Code2Text preprocessor for language"""
803 preprocessor
= self
.converter
.get_filter("preprocessors", "rl")
805 assert preprocessor
== r2l_filter
807 def test_get_css_preprocessor(self
):
808 """should return filter from filter_set for language"""
809 preprocessor
= self
.converter
.get_filter("preprocessors", "css")
811 assert preprocessor
== dumb_c_preprocessor
813 def test_get_filter_postprocessor(self
):
814 """should return Code2Text postprocessor for language"""
815 postprocessor
= self
.converter
.get_filter("postprocessors", "x")
817 assert postprocessor
== x2u_filter
819 def test_get_filter_nonexisting_language_filter(self
):
820 """should return identity_filter if language has no filter in set"""
821 preprocessor
= self
.converter
.get_filter("preprocessors", "foo")
823 assert preprocessor
== identity_filter
825 def test_get_filter_nonexisting_filter_set(self
):
826 """should return identity_filter if filter_set does not exist"""
827 processor
= self
.converter
.get_filter("foo_filters", "foo")
829 assert processor
== identity_filter
831 def test_preprocessor(self
):
832 """Preprocess data with registered preprocessor for language"""
833 converter
= Code2Text(codedata
, language
="rl", comment_string
="# ")
834 print "preprocessor", converter
.preprocessor
835 print "postprocessor", converter
.postprocessor
837 soll
= [line
.replace("r", "l") for line
in textdata
]
838 print "ist: ", repr(output
)
839 print "soll:", repr(soll
)
840 assert output
== soll
842 def test_postprocessor(self
):
843 """Postprocess data with registered postprocessor for language"""
844 output
= Code2Text(codedata
, language
="x", comment_string
="# ")()
845 soll
= [line
.replace("x", "u") for line
in textdata
]
846 print "soll:", repr(soll
)
847 print "ist: ", repr(output
)
848 assert output
== soll
854 ## blank comment line
855 ## ''''''''''''''''''''
857 ## Normally, whitespace in the comment string is significant, i.e. with
858 ## ``comment_string = "# "``, a line ``"#something\n"`` will count as code.
860 ## However, if a comment line is blank, trailing whitespace in the comment
861 ## string should be ignored, i.e. ``#\n`` is recognized as a blank text line::
863 codesamples
["ignore trailing whitespace in comment string for blank line"] = (
866 block1 = 'first block'
873 block1 = 'first block'
879 ## No blank line after text
880 ## ''''''''''''''''''''''''
882 ## If a matching comment precedes oder follows a code line (i.e. any line
883 ## without matching comment) without a blank line inbetween, it counts as code
886 ## This will keep small inline comments close to the code they comment on. It
887 ## will also keep blocks together where one commented line does not match the
888 ## comment string (the whole block will be kept as commented code)
891 codesamples
["comment before code (without blank line)"] = (
906 codesamples
["comment block before code (without blank line)"] = (
907 """# no text (watch the comment sign in the next line)::
912 """.. # no text (watch the comment sign in the next line)::
919 codesamples
["comment after code (without blank line)"] = (
922 block1 = 'first block'
929 block1 = 'first block'
938 codesamples
["comment block after code (without blank line)"] = (
941 block1 = 'first block'
948 block1 = 'first block'
956 ## missing literal block marker
957 ## ''''''''''''''''''''''''''''
959 ## If text (with matching comment string) is followed by code (line(s) without
960 ## matching comment string), but there is no double colon at the end, back
961 ## conversion would not recognize the end of text!
963 ## Therefore, pylit adds a paragraph containing only ``::`` -- the literal
964 ## block marker in expanded form. (While it would in many cases be nicer to
965 ## add the double colon to the last text line, this is not always valid rst
966 ## syntax, e.g. after a section header or a list. Therefore the automatic
967 ## insertion will use the save form, feel free to correct this by hand.)::
969 codesamples
["insert missing double colon after text block"] = (
970 """# text followed by code without double colon
974 """text followed by code without double colon
980 """text followed by code without double colon
987 ## Convert a header (leading code block) to a reStructured text comment. ::
989 codesamples
["no matching comment, just code"] = (
990 """print 'hello world'
994 """.. print 'hello world'
999 codesamples
["empty header (start with matching comment)"] = (
1000 """# a classical example without header::
1004 """a classical example without header::
1008 """a classical example without header:
1012 codesamples
["standard header, followed by text"] = (
1013 """#!/usr/bin/env python
1014 # -*- coding: iso-8859-1 -*-
1016 # a classical example with header::
1020 """.. #!/usr/bin/env python
1021 # -*- coding: iso-8859-1 -*-
1023 a classical example with header::
1027 """a classical example with header:
1031 codesamples
["standard header, followed by code"] = (
1032 """#!/usr/bin/env python
1036 """.. #!/usr/bin/env python
1048 css_code
= ['/* import the default docutils style sheet */\n',
1049 '/* --------------------------------------- */\n',
1054 '@import url("html4css1.css"); /* style */\n']
1058 css_filtered_code
= ['// import the default docutils style sheet\n',
1059 '// ---------------------------------------\n',
1064 '@import url("html4css1.css"); /* style */\n']
1068 def test_dumb_c_preprocessor():
1069 """convert `C` to `C++` comments"""
1070 output
= [line
for line
in dumb_c_preprocessor(css_code
)]
1071 print "ist: %r"%output
1072 print "soll: %r"%css_filtered
_code
1073 assert output
== css_filtered_code
1077 def test_dumb_c_postprocessor():
1078 """convert `C++` to `C` comments"""
1079 output
= [line
for line
in dumb_c_postprocessor(css_filtered_code
)]
1080 print "ist: %r"%output
1081 print "soll: %r"%css_code
1082 assert output
== css_code
1088 if __name__
== "__main__":
1089 nose
.runmodule() # requires nose 0.9.1