|
from docutils import nodes |
|
from docutils.parsers.rst.directives.tables import RSTTable |
|
|
|
|
|
def parse_equations(argument): |
|
defdict = {} |
|
for eqstr in argument.split('\n'): |
|
(dest, defun) = [s.strip() for s in eqstr.split('=', 1)] |
|
defdict[int(dest.strip('{}'))] = defun |
|
return defdict |
|
|
|
|
|
def parse_setup(argument): |
|
scope = {} |
|
exec argument in scope |
|
return scope |
|
|
|
|
|
def new_paragraph(rawtext): |
|
paragraph = nodes.paragraph() |
|
paragraph += nodes.Text(rawtext) |
|
return paragraph |
|
|
|
|
|
class SpreadSheet(RSTTable): |
|
|
|
option_spec = {'eq': parse_equations, |
|
'setup': parse_setup,} |
|
|
|
def run(self): |
|
table_node_list = RSTTable.run(self) |
|
table_node = table_node_list[0] |
|
message = table_node_list[1:] |
|
|
|
scope = self.options['setup'] |
|
defdict = self.options['eq'] |
|
for tbody in table_node.traverse(nodes.tbody): |
|
for row in tbody.traverse(nodes.row): |
|
coldata = [ |
|
None if len(entry) == 0 else str(entry[0][0]) |
|
for entry in row.traverse(nodes.entry)] |
|
for (i, eq) in defdict.iteritems(): |
|
result = eval(eq.format(*coldata), scope) |
|
coldata[i] = str(result) |
|
for (entry, coldata) in zip(row.traverse(nodes.entry), |
|
coldata): |
|
# entry.clear() |
|
if len(entry) == 0 and coldata is not None: |
|
entry += new_paragraph(coldata) |
|
return [table_node] + message |
|
|
|
|
|
SAMPLE_TEXT = """ |
|
.. spreadsheet:: This is my spread sheet |
|
:eq: {2} = {0} and {1} |
|
{3} = not {2} |
|
{5} = {4} |
|
{7} = '{6}({5}) = %.2f' % {6}({5}) |
|
:setup: from numpy import sin, cos, exp, log |
|
def f(n): |
|
return f(n-1) * n if n > 1 else 1 |
|
|
|
=== === ========= ============= ==== ==== ==== =========== |
|
p q p and q not (p and q) fac. func func(fac.) |
|
=== === ========= ============= ==== ==== ==== =========== |
|
0 0 f(1) sin |
|
1 0 f(2) cos |
|
0 1 f(3) exp |
|
1 1 f(4) log |
|
=== === ========= ============= ==== ==== ==== =========== |
|
""" |
|
|
|
|
|
def register_my_directive(): |
|
from docutils.parsers.rst import directives |
|
directives.register_directive("spreadsheet", SpreadSheet) |
|
|
|
|
|
def sample(writer_name="html"): |
|
register_my_directive() |
|
from docutils.core import publish_parts |
|
return publish_parts(SAMPLE_TEXT, writer_name=writer_name) |
|
|
|
|
|
if __name__ == '__main__': |
|
print sample()["whole"] |