Sphinx execute code
| from docutils.parsers.rst import Directive, directives | |
| from docutils import nodes | |
| import sys | |
| import StringIO | |
| import os | |
| # execute_code function thanks to Stackoverflow code post from hekevintran | |
| # https://stackoverflow.com/questions/701802/how-do-i-execute-a-string-containing-python-code-in-python | |
| __author__ = 'jp.senior@gmail.com' | |
| __docformat__ = 'restructuredtext' | |
| __version__ = '0.2' | |
| __doc__ = """ | |
| ==================== | |
| Execute_code example | |
| ==================== | |
| Options right now (as of version 0.2) are: | |
| linenos | |
| If specified, will show line numbers | |
| output_language | |
| Customizes pygments lexxer for specified language (Eg, Javascript, bash) | |
| hide_code | |
| If specified, will hide the code block and only show results | |
| hide_headers | |
| If specified, hides the 'Code' and 'Results' caption headers around the literal blocks | |
| filename | |
| If specified, will load code from a file (relative to sphinx doc root) and ignore content. | |
| Usage | |
| _____ | |
| .. execute_code:: | |
| :linenos: | |
| print 'python highlight code' | |
| class Foo(object): | |
| def __init__(self): | |
| self.bar = 'baz' | |
| def out(self): | |
| print self.bar | |
| f = Foo() | |
| f.out() | |
| Loading from a filename | |
| _______________________ | |
| .. execute_code:: | |
| :filename: sources/api_samples/hello_world.py | |
| """ | |
| class ExecuteCode(Directive): | |
| has_content = True | |
| required_arguments = 0 | |
| optional_arguments = 1 | |
| option_spec = { | |
| 'linenos': directives.flag, | |
| 'output_language': directives.unchanged, # Runs specified pygments lexer on output data | |
| 'hide_code': directives.flag, | |
| 'hide_headers': directives.flag, | |
| 'filename': directives.path, | |
| } | |
| def run(self): | |
| language = self.options.get('language') or 'python' | |
| linenos = 'linenos' in self.options | |
| output_language = self.options.get('output_language') or 'none' | |
| hide_code = 'hide_code' in self.options | |
| hide_headers = 'hide_headers' in self.options | |
| filename = self.options.get('filename') | |
| code = '' | |
| if not filename: | |
| code = '\n'.join(self.content) | |
| if filename: | |
| try: | |
| with open(filename, 'r') as f: | |
| code = f.read() | |
| self.warning('code is %s' % code) | |
| except (IOError, OSError) as e: | |
| # Raise warning instead of a code block | |
| error = 'Error opening file: %s, working folder: %s' % (e, os.getcwd()) | |
| self.warning(error) | |
| return [nodes.warning(error, error)] | |
| output = [] | |
| # Show the example code | |
| if not hide_code: | |
| input_code = nodes.literal_block(code, code) | |
| input_code['language'] = language | |
| input_code['linenos'] = linenos | |
| if not hide_headers: | |
| output.append(nodes.caption(text='Code %s' % filename or '') ) | |
| output.append(input_code) | |
| # Show the code results | |
| if not hide_headers: | |
| output.append(nodes.caption(text='Results')) | |
| code_results = self.execute_code(code) | |
| code_results = nodes.literal_block(code_results, code_results) | |
| code_results['linenos'] = linenos | |
| code_results['language'] = output_language | |
| output.append(code_results) | |
| return output | |
| def execute_code(self, code): | |
| """ Executes supplied code as pure python and returns a list of stdout, stderr | |
| Args: | |
| code (string): Python code to execute | |
| Results: | |
| (list): stdout, stderr of executed python code | |
| Raises: | |
| ExecutionError when supplied python is incorrect | |
| Examples: | |
| >>> execute_code('print foobar') | |
| ... foobar | |
| """ | |
| output = StringIO.StringIO() | |
| err = StringIO.StringIO() | |
| sys.stdout = output | |
| sys.stderr = err | |
| try: | |
| exec code | |
| except (TypeError): | |
| pass | |
| sys.stdout = sys.__stdout__ | |
| sys.stderr = sys.__stderr__ | |
| results = list() | |
| results.append(output.getvalue()) | |
| results.append(err.getvalue()) | |
| results = ''.join(results) | |
| return results | |
| def setup(app): | |
| app.add_directive('execute_code', ExecuteCode) | |
| return {'version': __version__} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment