[sagenb] 08/179: Tools for sws2rst
felix salfelder
felix-guest at moszumanska.debian.org
Tue May 6 12:05:04 UTC 2014
This is an automated email from the git hooks/post-receive script.
felix-guest pushed a commit to branch master
in repository sagenb.
commit 94f0b0c5bc86bb0983ee53742139a31fb843945d
Author: Pablo Angulo <pablo.angulo at uam.es>
Date: Wed Jan 19 10:58:48 2011 +0100
Tools for sws2rst
---
sagenb/misc/comments2rst.py | 370 +++++++++++++++++++++++++++++++++++++++++++
sagenb/misc/results2rst.py | 168 ++++++++++++++++++++
sagenb/misc/worksheet2rst.py | 196 +++++++++++++++++++++++
3 files changed, 734 insertions(+)
diff --git a/sagenb/misc/comments2rst.py b/sagenb/misc/comments2rst.py
new file mode 100644
index 0000000..ebbb809
--- /dev/null
+++ b/sagenb/misc/comments2rst.py
@@ -0,0 +1,370 @@
+# -*- coding: utf-8 -*-
+r"""
+Convert html from text cells in the notebook into ReStructuredText
+
+This is called by sws2rst
+
+- Pablo Angulo Ardoy (2011-02-25): initial version
+"""
+#**************************************************
+# Copyright (C) 2011 Pablo Angulo
+#
+# Distributed under the terms of the GPL License
+#**************************************************
+
+
+import re
+import os
+try:
+ from BeautifulSoup import (ICantBelieveItsBeautifulSoup, Tag,
+ CData, Comment, Declaration, ProcessingInstruction)
+except ImportError:
+ raise ImportError, """BeautifulSoup must be installed.
+
+You might download a spkg from:
+
+http://trac.sagemath.org/sage_trac/raw-attachment/ticket/10637/beautifulsoup-3.2.0.p0.spkg
+"""
+
+def preprocess_display_latex(text):
+ r"""replace $$some display latex$$ with <display>some display latex</display>
+ before the soup is built.
+
+ Deals with the situation where <p></p> tags are mixed
+ with $$, like $$<p>display_latex$$</p>, unless the mess is huge
+
+ EXAMPLES::
+
+ sage: from sagenb.misc.comments2rst import preprocess_display_latex
+ sage: s="$$a=2$$"
+ sage: preprocess_display_latex(s)
+ '<display>a=2</display>'
+ sage: s="<p>$$a=2$$</p>"
+ sage: preprocess_display_latex(s)
+ '<p><display>a=2</display></p>'
+ sage: s="<p>$$a=2</p>$$"
+ sage: preprocess_display_latex(s)
+ '<p><display>a=2</display></p>'
+ sage: s="$$<p>a=2</p>$$"
+ sage: preprocess_display_latex(s)
+ '<display>a=2</display>'
+ """
+ ls = []
+ start_tag = True
+ partes = text.split('$$')
+ for c in partes[:-1]:
+ if start_tag:
+ ls.append(c)
+ ls.append('<display>')
+ else:
+ c0, count = prune_tags(c)
+ ls.append(c0)
+ ls.append('</display>')
+ if count == 1:
+ ls.append('<p>')
+ elif count == -1:
+ ls.append('</p>')
+ elif abs(count)>1:
+ raise Exception, 'display latex was messed up with html code'
+ start_tag = not start_tag
+ ls.append(partes[-1])
+ return ''.join(ls)
+
+def prune_tags(text):
+ count = text.count('<p>') - text.count('</p>')
+ return text.replace('<br/>','').replace('<br />','').replace('<p>','').replace('</p>',''), count
+
+escapable_chars = { '+' :r'\+',
+ '*' :r'\*',
+ '|' :r'\|',
+ '-' :r'\-'}
+def escape_chars(text):
+ for c,r in escapable_chars.iteritems():
+ text = text.replace(c,r)
+ return text
+
+def replace_courier(soup):
+ """Lacking a better option, I use courier font to mark <code>
+ within tinyMCE. And I want to turn that into real code tags.
+
+ Most users won't be needing this(?)
+ """
+ for t in soup.findAll(lambda s:s.has_key('style') and 'courier' in s['style']):
+ tag = Tag(soup, 'code')
+ while t.contents:
+ tag.append(t.contents[0])
+ t.replaceWith(tag)
+
+#inline_latex is careful not to confuse escaped dollars
+inline_latex = re.compile(r'([^\\])\$(.*?)([^\\])\$')
+latex_beginning = re.compile(r'\$(.*?)([^\\])\$')
+def replace_latex(soup):
+ r"""Replaces inline latex by :math:`code` and escapes
+ some rst special chars like +, -, * and | outside of inline latex
+
+ does not escape chars inside display or pre tags
+
+ EXAMPLES::
+
+ sage: from sagenb.misc.comments2rst import replace_latex
+ sage: from BeautifulSoup import ICantBelieveItsBeautifulSoup
+ sage: s = ICantBelieveItsBeautifulSoup("<p>Some <strong>latex: $e^\pi i=-1$</strong></p>")
+ sage: replace_latex(s)
+ sage: s
+ <p>Some <strong>latex: :math:`e^\pi i=-1`</strong></p>
+ sage: s = ICantBelieveItsBeautifulSoup("<p><strong>2+2 | 1+3</strong></p>")
+ sage: replace_latex(s)
+ sage: s
+ <p><strong>2\+2 \| 1\+3</strong></p>
+ """
+ for t in soup.findAll(text=re.compile('.+')):
+ if latex_beginning.match(t):
+ t.replaceWith(inline_latex.sub('\\1:math:`\\2\\3`',
+ latex_beginning.sub(':math:`\\1\\2`',
+ unicode(t),
+ 1)))
+ elif inline_latex.search(t):
+ t.replaceWith(inline_latex.sub('\\1:math:`\\2\\3`',
+ unicode(t)))
+ elif not (t.fetchParents(name = 'display')
+ or t.fetchParents(name = 'pre')):
+ t.replaceWith(escape_chars(t))
+
+class Soup2Rst(object):
+ """builds the rst text from the Soup Tree
+ """
+ tags = {'h1':'header',
+ 'h2':'header',
+ 'h3':'header',
+ 'h4':'header',
+ 'p': 'inline_no_tag',
+ '[document]': 'document',
+ 'br': 'br',
+ 'b':'strong',
+ 'strong':'strong',
+ 'em':'em',
+ 'pre':'pre',
+ 'code':'code',
+ 'display':'display',
+ 'span':'inline_no_tag',
+ 'ul':'ul',
+ 'ol':'ol',
+ 'li':'li',
+ 'a':'a',
+ 'table':'table',
+# 'tr':'tr',
+ 'td':'inline_no_tag',
+ 'th':'inline_no_tag',
+ 'tt':'inline_no_tag',
+ 'div':'block_no_tag',
+ 'img':'img',
+# '':'',
+ }
+
+ headers = {'h1':u'=',
+ 'h2':u'-',
+ 'h3':u'~',
+ 'h4':u'"',
+ }
+
+ def __init__(self, images_dir):
+ self.images_dir = images_dir
+ self._nested_list = 0
+ self._inside_ol = False
+ self._inside_code_tag = False
+
+ def visit(self, node):
+ if isinstance(node, (CData, Comment, Declaration, ProcessingInstruction)):
+ return ''
+ elif hasattr(node, 'name'):
+ try:
+ visitor = getattr(self, 'visit_' + self.tags[node.name])
+ return visitor(node)
+ except (KeyError, AttributeError):
+ print 'Warning: node not supported (or something else?) ' + node.name
+ return unicode(node)
+ else:
+ #Assume plain string
+ return unicode(node).replace('\n','')
+
+ def visit_document(self, node):
+ return '\n'.join(self.visit(tag) for tag in node.contents)
+
+ def get_plain_text(self, node):
+ """Gets all text, removing all tags"""
+ if hasattr(node, 'contents'):
+ t = ' '.join(self.get_plain_text(tag) for tag in node.contents)
+ else:
+ t = unicode(node)
+ return t.replace('\n','')
+
+ def visit_header(self, node):
+ s = ' '.join(self.visit(tag) for tag in node.contents)
+ spacer = self.headers[node.name]*len(s)
+ return s.replace( '\n', '') + '\n' + spacer
+
+ def visit_pre(self, node):
+ return '::\n\n '+unicode(node)[5:-6].replace('<br />','\n').replace('<br></br>','\n').replace('\n','\n ')
+
+ def visit_ul(self, node):
+ self._nested_list += 1
+ result = '\n'.join(self.visit(tag) for tag in node.contents)
+ self._nested_list -= 1
+ return result
+
+ def visit_ol(self, node):
+ self._nested_list += 1
+ self._inside_ol = True
+ result = '\n'.join(self.visit(tag) for tag in node.contents)
+ self._nested_list -= 1
+ self._inside_ol = False
+ return result
+
+ def visit_li(self, node):
+ return (' '*self._nested_list
+ + ('#. ' if self._inside_ol else '- ')
+ +' '.join(self.visit(tag) for tag in node.contents))
+
+ def visit_display(self, node):
+ return ('\n.. MATH::\n\n ' +
+ unicode(node)[9:-10].replace('<br></br>','\n').replace('\n','\n ') +
+ '\n\n')
+
+ def visit_img(self, node):
+ return '.. image:: ' + os.path.join(self.images_dir, node['src'].replace(' ','_')) + '\n :align: center\n'
+
+ def visit_table(self,node):
+ rows = []
+ for elt in node.contents:
+ if not hasattr(elt,'name'):
+ pass
+ elif elt.name == 'thead':
+ rows.extend(self.prepare_tr(row)
+ for row in elt
+ if hasattr(row,'name') and
+ row.name=='tr')
+ rows.append([]) #this row represents a separator
+ elif elt.name == 'tbody':
+ rows.extend(self.prepare_tr(row)
+ for row in elt
+ if hasattr(row,'name') and
+ row.name=='tr')
+ elif elt.name == 'tr':
+ rows.append(self.prepare_tr(elt))
+
+ ncols = max(len(row) for row in rows)
+ for row in rows:
+ if len(row) < ncols:
+ row.extend( ['']*(ncols - len(row)))
+ cols_sizes = [max(len(td) for td in tds_in_col)
+ for tds_in_col in zip(*rows)]
+ result = [' '.join('='*c for c in cols_sizes)]
+
+ for row in rows:
+ if any(td for td in row):
+ result.append(' '.join(td+' '*(l - len(td))
+ for l,td in zip(cols_sizes,row)))
+ else:
+ result.append(' '.join('-'*c for c in cols_sizes))
+ result.append(' '.join('='*c for c in cols_sizes))
+ return '\n'.join(result)
+
+ def prepare_tr(self, node):
+ return [self.visit(tag) for tag in node.contents if tag!='\n']
+
+ def visit_br(self, node):
+ return '\n'
+
+ def visit_strong(self, node):
+ if node.contents:
+ content = ' '.join(self.visit(tag) for tag in node.contents).strip()
+ if '``' in content or self._inside_code_tag:
+ return content
+ else:
+ return '**' + content + '**'
+ else:
+ return ''
+
+ def visit_em(self,node):
+ if node.contents:
+ return '*' + ' '.join(self.visit(tag) for tag in node.contents).strip() + '*'
+ else:
+ return ''
+
+ def visit_code(self, node):
+ if node.contents:
+ self._inside_code_tag = True
+ content = self.get_plain_text(node).strip()
+ self._inside_code_tag = False
+ return '``' + content + '``'
+ else:
+ return ''
+
+ def visit_inline_no_tag(self, node):
+ return (' '.join(self.visit(tag)
+ for tag in node.contents)).strip() + '\n'
+
+ def visit_block_no_tag(self, node):
+ return '\n'.join(self.visit(tag) for tag in node.contents)
+
+ def visit_a(self, node):
+ return ('`' + ' '.join(self.visit(tag) for tag in node.contents) +
+ ' <' + node['href'] + '>`_'
+ )
+
+def html2rst(text, images_dir):
+ """Converts html, tipically generated by tinyMCE, into rst
+ compatible with Sage documentation.
+
+ The main job is done by BeautifulSoup, which is much more
+ robust than conventional parsers like HTMLParser, but also
+ several details specific of this context are taken into
+ account, so this code differs from generic approaches like
+ those found on the web.
+
+ INPUT:
+
+ - ``text`` -- string -- a chunk of HTML text
+
+ - ``images_dir`` -- string -- folder where images are stored
+
+ OUTPUT:
+
+ - string -- rst text
+
+ EXAMPLES::
+
+ sage: from sagenb.misc.comments2rst import html2rst
+ sage: html2rst('<p>Some text with <em>math</em>: $e^{\pi i}=-1$</p>', '')
+ u'Some text with *math* : :math:`e^{\\pi i}=-1`\n'
+ sage: html2rst('<p>Text with <em>incorrect</p> nesting</em>.', '')
+ u'Text with *incorrect*\n\n nesting\n.'
+ sage: html2rst('<pre>Preformatted: \n a+2\n</pre><p> Not preformatted: \n a+2\n</p>', '')
+ u'::\n\n Preformatted: \n a+2\n \nNot preformatted: a\\+2\n'
+ sage: html2rst('áñ ñá','')
+ u'\xe1\xf1 \xf1\xe1'
+ sage: html2rst('<p>some text</p><p>$$</p><p>3.183098861 \cdot 10^{-1}</p><p>$$</p>','')
+ u'some text\n\n.. MATH::\n\n 3.183098861 \\cdot 10^{-1}\n'
+ """
+
+ #replace $$some display latex$$ with
+ #<display>some display latex</display>
+ text = preprocess_display_latex(text)
+
+ #eliminate nasty
+ text = text.replace(' ',' ')
+
+ #ICantBelieveItsBeautifulSoup is better than BeautifulSoup
+ #for html that wasn't generated by humans (like tinyMCE)
+ soup = ICantBelieveItsBeautifulSoup(text,
+ convertEntities=ICantBelieveItsBeautifulSoup.HTML_ENTITIES)
+
+ #remove all comments
+ comments = soup.findAll(text=lambda text:isinstance(text, Comment))
+ for comment in comments:
+ comment.extract()
+
+ replace_courier(soup)
+ replace_latex(soup)
+ v = Soup2Rst(images_dir)
+ return v.visit(soup)
diff --git a/sagenb/misc/results2rst.py b/sagenb/misc/results2rst.py
new file mode 100644
index 0000000..23b87fd
--- /dev/null
+++ b/sagenb/misc/results2rst.py
@@ -0,0 +1,168 @@
+# -*- coding: utf-8 -*-
+r"""
+Convert output from code cells in the notebook into ReStructuredText
+
+This is called by sws2rst
+
+- Pablo Angulo Ardoy (2011-02-25): initial version
+"""
+#**************************************************
+# Copyright (C) 2011 Pablo Angulo
+#
+# Distributed under the terms of the GPL License
+#**************************************************
+
+
+import re
+IMAGES_DIR = 'images/'
+
+#We parse lines one by one but keep track of current scope
+#similarly to worksheet2rst.py
+#Results are split into different types. Some are discarded
+class States(object):
+ NORMAL = 0
+ HTML = 1
+ MATH = 2
+ TRACEBACK = 3
+
+class LineTypes(object):
+ PLAIN = 0
+ IMAGE = 1
+ LATEX = 2
+ HTML = 3
+ TRACE = 4
+
+class ResultsParser(object):
+ """Auxiliary class for results2rst
+ """
+ def __init__(self, images_dir):
+ ##Order matters, place more restrictive regex's before more general ones
+ ##If no regex matches, line will be discarded
+ ##a self transition is needes to produce any output
+ self.transitions = {
+ States.NORMAL:[
+ #IMAGE
+ (re.compile(r"^\<html\>\<font color='black'\>"
+ r"\<img src='cell\://(.*?)'\>"
+ r"\</font\>\</html\>"),
+ "\n.. image:: " + images_dir + "\\1\n :align: center\n",
+ LineTypes.IMAGE,
+ States.NORMAL),
+ #SELF-CONTAINED MATH
+ (re.compile(r"^\<html\>\<div class=\"math\"\>"
+ r"\\newcommand\{\\Bold\}\[1\]\{\\mathbf\{\#1\}\}"
+ r"(.*?)\</div\>\</html\>$"),
+ "\n.. MATH::\n\n \\1\n",
+ LineTypes.LATEX,
+ States.NORMAL),
+ #SELF-CONTAINED MATH - BIS
+ (re.compile(r"^\<html\>\<div class=\"math\"\>"
+ r"(.*?)\</div\>\</html\>$"),
+ "\n.. MATH::\n\n \\1",
+ LineTypes.LATEX,
+ States.NORMAL),
+ #START Traceback
+ (re.compile(r"^(Traceback.*)"),
+ " Traceback (most recent call last):",
+ LineTypes.TRACE,
+ States.TRACEBACK),
+ #START MATH
+ (re.compile(r"^\<html\>\<div class=\"math\"\>"
+ r"\\newcommand\{\\Bold\}\[1\]\{\\mathbf\{\#1\}\}(.*?)"),
+ "\n.. MATH::\n\n \\1",
+ LineTypes.LATEX,
+ States.MATH),
+ #SELF-CONTAINED HTML
+ (re.compile(r"^\<html\>.*</html\>$"),
+ " <html>...</html>",
+ LineTypes.HTML,
+ States.NORMAL),
+ #START HTML
+ (re.compile(r"^\<html\>.*"),
+ " <html>...</html>",
+ LineTypes.HTML,
+ States.HTML),
+ #CONTINUE NORMAL
+ (re.compile("(.*)"),
+ " \\1",
+ LineTypes.PLAIN,
+ States.NORMAL),
+ ],
+ States.MATH:[
+ #END MATH
+ (re.compile(r"(.*?)\</div\>\</html\>$"),
+ " \\1",
+ LineTypes.LATEX,
+ States.NORMAL),
+ #CONTINUE MATH
+ (re.compile("(.*)"),
+ " \\1",
+ LineTypes.LATEX,
+ States.MATH),
+ ],
+ States.TRACEBACK:[
+ #END Traceback
+ (re.compile(r"^(\S.*)"),
+ " ...\n \\1",
+ LineTypes.TRACE,
+ States.NORMAL),
+ ],
+ States.HTML:[
+ #END HTML
+ (re.compile(r".*</html\>$"),
+ "",
+ LineTypes.HTML,
+ States.NORMAL),
+ ],
+ }
+
+ def parse(self, text):
+ result_plain = []
+ result_show = []
+ state = States.NORMAL
+ for line in text.splitlines():
+ for regex, replacement, line_type, new_state in self.transitions[state]:
+ if regex.match(line):
+ result = result_plain if line_type in (LineTypes.PLAIN, LineTypes.HTML)\
+ else result_show
+ result.append( regex.sub(replacement, line))
+ state = new_state
+ break
+ result_plain.extend(result_show)
+ return '\n'.join(result_plain)
+
+def results2rst(text, images_dir):
+ r"""Converts the result of evaluation of notebook cells
+ into rst compatible with Sage documentation.
+
+ Several common patterns are identified, and treated
+ accordingly. Some patterns are dropped, while others
+ are not recognized.
+
+ Currently, latex and images are recognized and converted.
+
+ INPUT:
+
+ - ``text`` -- string -- a chunk of HTML text
+
+ - ``images_dir`` -- string -- folder where images are stored
+
+ OUTPUT:
+
+ - string -- rst text
+
+ EXAMPLES::
+
+ sage: from sagenb.misc.results2rst import results2rst
+ sage: s="<html><font color='black'><img src='cell://sage0.png'></font></html>"
+ sage: results2rst(s,'')
+ '\n.. image:: sage0.png\n :align: center\n'
+ sage: results2rst("4",'')
+ ' 4'
+ sage: s=r'<html><div class="math">\newcommand{\Bold}[1]{\mathbf{#1}}\frac{3}{2}</div></html>'
+ sage: results2rst(s,'')
+ '\n.. MATH::\n\n \\frac{3}{2}\n'
+ """
+ Parser = ResultsParser(images_dir)
+ return Parser.parse(text)
+
diff --git a/sagenb/misc/worksheet2rst.py b/sagenb/misc/worksheet2rst.py
new file mode 100644
index 0000000..f12fe3e
--- /dev/null
+++ b/sagenb/misc/worksheet2rst.py
@@ -0,0 +1,196 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+r"""
+Convert worksheet.html files into ReStructuredText documents
+
+This is called by 'sage -sws2rst'. Can also be used as a commandline script
+(if BeautifulSoup is installed):
+
+``python worksheet2rst.py worksheet.html``
+
+or
+
+``cat worksheet.html | python worksheet2rst.py``
+
+AUTHOR:
+
+- Pablo Angulo Ardoy (2011-02-25): initial version
+
+
+The content of worksheet.html is split into comments, code, and output
+(the result of evaluating the code), as follows:
+
+comments
+{{{id=..|
+code
+///
+results
+}}}
+
+Each kind of text is dealt with separately.
+
+"""
+#**************************************************
+# Copyright (C) 2011 Pablo Angulo
+#
+# Distributed under the terms of the GPL License
+#**************************************************
+
+
+import sys
+import os
+import re
+from comments2rst import html2rst
+from results2rst import results2rst
+import codecs
+
+#We parse lines one by one but keep track of current scope
+#comments
+#{{{id=..|
+#code
+#///
+#results
+#}}}
+#RESULT_TO_BE_DROPPED corresponds to a results section whose
+#code was empty, and will be discarded, whether it's empty or not
+class States(object):
+ COMMENT = 0
+ CODE = 1
+ RESULT = 2
+ RESULT_TO_BE_DROPPED = 3
+
+# REs for splitting comments, code and results
+START_CELL_RE = re.compile('^\{\{\{id=(\d*)\|')
+END_CODE_RE = re.compile('^\/\/\/')
+END_CELL_RE = re.compile('^\}\}\}')
+
+#When to switch State, and which State to
+transitions = {
+ States.COMMENT:(
+ START_CELL_RE,
+ States.CODE
+ ),
+ States.CODE:(
+ END_CODE_RE,
+ States.RESULT),
+ States.RESULT:(
+ END_CELL_RE,
+ States.COMMENT),
+ States.RESULT_TO_BE_DROPPED:(
+ END_CELL_RE,
+ States.COMMENT)
+ }
+
+def code_parser(text):
+ """
+
+ Arguments:
+
+ INPUT:
+
+ - ``s``:sage code, may or may not start with "sage:"
+
+ OUTPUT:
+
+ - string -- rst text
+
+ EXAMPLES (not used for unit test, see
+ http://groups.google.com/group/sage-devel/browse_thread/thread/d82cb049ac102f3a)
+
+ : from sagenb.misc.worksheet2rst import code_parser
+ : s="a=2"
+ : code_parser(s)
+ '::\n\n sage: a=2'
+ : s="def f(n):\n return n+1\n"
+ : code_parser(s)
+ '::\n\n sage: def f(n):\n ... return n+1'
+ : s="sage: def f(n):\nsage: return n+1\n"
+ : code_parser(s)
+ '::\n\n sage: def f(n):\n ... return n+1'
+ """
+ lines = ['::', '']
+ for s in text.splitlines():
+ l = s[6:] if s.startswith('sage: ') else s
+ if not l: continue
+ prefix = ' ... ' if l[0] == ' ' else ' sage: '
+ lines.append(prefix + l)
+ return '\n'.join(lines)
+
+def worksheet2rst(s, images_dir=''):
+ """Parses a string, tipically the content of the file
+ worksheet.html inside a sws file, and converts it into
+ rst compatible with Sage documentation.
+
+ INPUT:
+
+ - ``s`` -- string -- text, tipically the content of
+ worksheet.html
+
+ - ``images_dir`` -- string -- folder where images are stored
+
+ OUTPUT:
+
+ - string -- rst text
+
+ EXAMPLES (not used for unit test, see
+ http://groups.google.com/group/sage-devel/browse_thread/thread/d82cb049ac102f3a)
+
+ : from sagenb.misc.worksheet2rst import worksheet2rst
+ : worksheet2rst('<p>some text</p>\n{{{id=1|\nprint 2+2\n///\n4\n}}}')
+ u'.. -*- coding: utf-8 -*-\n\nsome text\n\n::\n\n sage: print 2+2\n 4\n\n.. end of output\n'
+ : s = '{{{id=2|\nshow(f)\n///\n<html><div class="math">\\sqrt{x}</div></html>\n}}}\n'
+ : worksheet2rst(s)
+ u'.. -*- coding: utf-8 -*-\n\n\n::\n\n sage: show(f)\n\n.. MATH::\n\n \\sqrt{x}\n\n.. end of output\n'
+ """
+ result_parser = results2rst
+ state = States.COMMENT
+ result = ['.. -*- coding: utf-8 -*-\n']
+ ls = []
+ last = 0
+ for line in s.splitlines():
+ regex, next_state= transitions[state]
+ m = regex.match(line)
+ if m:
+ if state == States.COMMENT:
+ last_cell_id = m.group(1)
+ img_path = images_dir + os.path.sep
+ result.append(html2rst(u'\n'.join(ls), img_path))
+ elif state == States.RESULT:
+ img_path = os.path.join(images_dir, 'cell_%s_'%last_cell_id)
+ result.append(result_parser(u'\n'.join(ls),
+ img_path))
+ result.append('')
+ result.append('.. end of output')
+ elif state == States.CODE:
+ if ls and any(ls):
+ result.append(code_parser(u'\n'.join(ls)))
+ else:
+ next_state = States.RESULT_TO_BE_DROPPED
+ ls = []
+ state = next_state
+ else:
+ ls.append(line)
+ if state == States.COMMENT:
+ img_path = images_dir + os.path.sep
+ result.append(html2rst(u'\n'.join(ls), img_path))
+ elif state == States.RESULT:
+ img_path = os.path.join(images_dir, 'cell_%s_'%last_cell_id)
+ result.append(result_parser(u'\n'.join(ls),
+ img_path))
+ result.append('')
+ result.append('.. end of output')
+ elif state == States.CODE:
+ result.append(code_parser(u'\n'.join(ls)))
+
+ return u'\n'.join(result)
+
+if __name__=='__main__':
+ if len(sys.argv)>1:
+ fichero = codecs.open(sys.argv[1], mode='r', encoding='utf-8')
+ text = fichero.read()
+ fichero.close()
+ else:
+ text = sys.stdin.read()
+
+ print worksheet2rst(text).encode('utf-8')
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sagenb.git
More information about the debian-science-commits
mailing list