PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/trac2rst.py

https://github.com/fperez/nitime
Python | 127 lines | 115 code | 6 blank | 6 comment | 0 complexity | 8c93c9d5ba9572fa57d6b398ac7a9eaf MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #!/usr/bin/env python
  2. ''' Script to do very basic conversion of TRAC to reST format '''
  3. import sys
  4. import re
  5. rst_section_levels = ['*', '=', '-', '~', '^']
  6. heading_re = re.compile('^(=+) +([^=]+) +(=+)')
  7. enumerate_re = re.compile(r'^ +(\d+\)) +(.*)')
  8. link_re = re.compile(r'\[+ *(http://[\w.\-~/]+) +(.+?) *\]+')
  9. italic_re = re.compile(r"'''(.+?)'''")
  10. bold_re = re.compile(r"''(.+?)''")
  11. inpre_re = re.compile(r"{{{(.+?)}}}")
  12. outprestart_re = re.compile(r"^ *{{{ *$")
  13. outprestop_re = re.compile(r"^ *}}} *$")
  14. define_re = re.compile("^([^ ])(.*?)::")
  15. class state_object(object):
  16. def __init__(self, lines, indent=''):
  17. self.lines = lines
  18. self.indent = indent
  19. def add_line(self, line):
  20. self.lines.append(self.indent+line)
  21. def __call__(self, line):
  22. raise NotImplementedError
  23. def __iter__(self):
  24. for line in self.lines:
  25. yield line
  26. class preformatted_state(state_object):
  27. ''' State function for within preformatted blocks '''
  28. def __call__(self, line):
  29. if outprestop_re.match(line):
  30. self.add_line('')
  31. return standard_state(self.lines)
  32. self.add_line(' ' + line)
  33. return self
  34. def std_subs(line):
  35. ''' standard in-line substitutions '''
  36. line = link_re.sub(r'`\2 <\1>`_', line)
  37. line = italic_re.sub(r'*\1*', line)
  38. line = bold_re.sub(r'**\1**', line)
  39. line = inpre_re.sub(r'``\1``', line)
  40. return line
  41. class standard_state(state_object):
  42. def __call__(self, line):
  43. ''' State function for within normal text '''
  44. # beginning preformat block?
  45. if outprestart_re.match(line):
  46. self.add_line('::')
  47. self.add_line('')
  48. return preformatted_state(self.lines)
  49. # Heading
  50. hmatch = heading_re.match(line)
  51. if hmatch:
  52. eq1, heading, eq2 = hmatch.groups()
  53. if len(eq1) == len(eq2):
  54. self.add_line(heading)
  55. self.add_line(rst_section_levels[len(eq1)] * len(heading))
  56. return self
  57. if line.startswith(' *'):
  58. line = line[1:]
  59. line = enumerate_re.sub(r'#. \2', line)
  60. line = define_re.sub(r'\1\2', line)
  61. line = std_subs(line)
  62. self.add_line(line)
  63. return self
  64. def trac2rst(linesource):
  65. ''' Process trac line source
  66. A simple finite state machine
  67. >>> lines = ['Hello', '= Heading1 =', '=Heading2=', '== Heading 3 ==']
  68. >>> trac2rst(lines)
  69. ['Hello', 'Heading1', '========', '=Heading2=', 'Heading 3', '---------']
  70. >>> trac2rst([' * bullet point'])
  71. ['* bullet point']
  72. >>> trac2rst([' 33 not numbered'])
  73. [' 33 not numbered']
  74. >>> trac2rst([' 33) numbered'])
  75. ['#. numbered']
  76. >>> trac2rst(['some text then [http://www.python.org/doc a link], then text'])
  77. ['some text then `a link <http://www.python.org/doc>`_, then text']
  78. >>> line = 'text [http://www.python.org python] ' + \
  79. 'text [http://www.scipy.org scipy] '
  80. >>> trac2rst([line])
  81. ['text `python <http://www.python.org>`_ text `scipy <http://www.scipy.org>`_']
  82. >>> # The next line conceals the triple quotes from the docstring parser
  83. >>> trac2rst([r"Some %sitalic%s text, then %smore%s" % (("'"*3,) * 4)])
  84. ['Some *italic* text, then *more*']
  85. >>> trac2rst([r"Some ''bold'' text, then ''more''"])
  86. ['Some **bold** text, then **more**']
  87. >>> # inline preformatted text
  88. >>> trac2rst(['here is some {{{preformatted text}}} (end)'])
  89. ['here is some ``preformatted text`` (end)']
  90. >>> # multiline preformatted
  91. >>> trac2rst(['','{{{','= preformatted =', ' * text', '}}}'])
  92. ['', '::', '', ' = preformatted =', ' * text', '']
  93. >>> # define
  94. >>> trac2rst(['a definition::', ' some explanation'])
  95. ['a definition', ' some explanation']
  96. '''
  97. processor = standard_state([])
  98. for line in linesource:
  99. line = line.rstrip()
  100. processor = processor(line)
  101. return processor.lines
  102. if __name__ == '__main__':
  103. try:
  104. infile = sys.argv[1]
  105. except IndexError:
  106. raise OSError('Need input file')
  107. lines = trac2rst(file(infile))
  108. print '\n'.join(lines)