5

I was wondering whether there is a trick to (easily) incorporate some python code into a moinmoin page, perhaps by adding some action. The idea is that something like

<<<
for j in [1,3,5]:
   print(i)
>>>

is displayed on the page as

1
3
5

Quick and dirty is ok, safety is not a concern, I would like to have this for a stand-alone, "desktop-mode" installation.

mitchus
  • 4,677
  • 3
  • 35
  • 70

2 Answers2

7

Another approach is to add a parser.

Below is a very quick and dirty adaptation of Moinmoin's Hello World parser.

import StringIO
import sys

class Parser():        

    def __init__(self, raw, request, **kw):
        self.raw = raw
        self.request = request
        self.kw=kw

    def format(self, formatter):       
        # Execute the code
        code_out = StringIO.StringIO()
        sys.stdout = code_out
        exec self.raw
        sys.stdout = sys.__stdout__
        out_lines = code_out.getvalue().split("\n")

        # Print the output
        for out_line in out_lines:
            self.request.write(formatter.rawHTML(out_line+"<br>"))

If it is saved for example as path/to/MoinMoin/parser/interpret_python.py, then you can enter into a page

{{{#!interpret_python
for j in [1,3,5]:
   print(j)
}}}

and it will produce the text

1
3
5

when viewing the page. Can be made safe(r) by confining the execution to a sandbox.

mitchus
  • 4,677
  • 3
  • 35
  • 70
4

In your moinmoin instance go to

data/macro

Make sure that there's an __init__.py with at least the following content:

from MoinMoin.util import pysupport

modules = pysupport.getPackageModules(__file__)

Then create your macro there:

touch PyShell.py

Use this as a template:

import StringIO
import sys

def macro_PyShell(macro, code):
  code_out = StringIO.StringIO()
  sys.stdout = code_out
  exec code.strip("'").strip('"')
  sys.stdout = sys.__stdout__
  return macro.request.formatter.text(code_out.getvalue())

In your wiki-pages you should now be able to call that macro with:

<<PyShell("for i in [1,2,3]:\n  print i")>>
hoffmaje
  • 140
  • 8
  • Thanks for your answer. To clarify, what I would like to be able to do is put some arbitrary small python code _in a page in edit mode_, and have some action/macro take my code, run it through the python interpreter, and display the output _on the page in viewing mode_. Reading more into the documentation, I am thinking I should add a [parser](http://moinmo.in/HelpOnParsers). – mitchus Feb 25 '12 at 12:17
  • I modified my macro example to fit your needs. – hoffmaje Feb 25 '12 at 12:32
  • That looks pretty good! Shouldn't it be `exec` rather than `eval` though? – mitchus Feb 25 '12 at 12:40
  • Yes you are right! I edited it a second before you mentioned :D – hoffmaje Feb 25 '12 at 12:41
  • I tried it; inserting `<>` into the page indeed does call the code, however there is an error. The moinmoin log says: `return macro.request.formatter.text(exec(code)) "SyntaxError: invalid syntax"` – mitchus Feb 25 '12 at 12:53
  • It works for a single command, such as `"print(10)"`, however in the case of e.g. `"for i in [1,2,3]:\n print i"` there is an error: `execution failed [unexpected character after line continuation character]` – mitchus Feb 25 '12 at 13:27
  • Stipping ' and/or " may be needed. That's it, is it? – hoffmaje Feb 25 '12 at 13:33
  • I feel like this might be a massive security hole, if ever your wiki is exposed to the public. – lorenzog Mar 21 '14 at 14:48