diff --git a/nbconvert.py b/nbconvert.py index 8ff6fb6..67b3f8d 100755 --- a/nbconvert.py +++ b/nbconvert.py @@ -1254,6 +1254,115 @@ class ConverterNotebook(Converter): """ return [output.javascript] +class ConverterPy(Converter): + """ + A converter that takes a notebook and converts it to a .py file. + + What distinguishes this from PyWriter and PyReader in IPython.nbformat is + that subclasses can specify what to do with each type of cell. + Additionally, unlike PyWriter, this does not preserve the '# ' + opening and closing comments style comments in favor of a cleaner looking + python program. + + Note: + Even though this produces a .py file, it is not guaranteed to be valid + python file, since the notebook may be using magics and even cell + magics. + """ + extension = 'py' + + def __init__(self, infile, show_prompts=True, show_output=True): + super(ConverterPy, self).__init__(infile) + self.show_prompts = show_prompts + self.show_output = show_output + + @staticmethod + def comment(input): + "returns every line in input as commented out" + return "# "+input.replace("\n", "\n# ") + + @DocInherit + def render_heading(self, cell): + return ['#{0} {1}'.format('#'*cell.level, cell.source), ''] + + @DocInherit + def render_code(self, cell): + if not cell.input: + return [] + lines = [] + if self.show_prompts: + lines.extend(['# In[%s]:' % cell.prompt_number]) + src = cell.input + lines.extend([src, '']) + if self.show_output: + if cell.outputs : + lines.extend(['# Out[%s]:' % cell.prompt_number]) + for output in cell.outputs: + conv_fn = self.dispatch(output.output_type) + lines.extend(conv_fn(output)) + return lines + + @DocInherit + def render_markdown(self, cell): + return [self.comment(cell.source), ''] + + @DocInherit + def render_raw(self, cell): + if self.raw_as_verbatim: + return [self.comment(indent(cell.source)), ''] + else: + return [self.comment(cell.source), ''] + + @DocInherit + def render_pyout(self, output): + lines = [] + + ## if 'text' in output: + ## lines.extend(['*Out[%s]:*' % output.prompt_number, '']) + + # output is a dictionary like object with type as a key + if 'latex' in output: + pass + + if 'text' in output: + lines.extend([self.comment(indent(output.text)), '']) + + lines.append('') + return lines + + @DocInherit + def render_pyerr(self, output): + # Note: a traceback is a *list* of frames. + return [indent(remove_ansi('\n'.join(output.traceback))), ''] + + @DocInherit + def _img_lines(self, img_file): + return [ self.comment('image file: %s' % img_file), ''] + + @DocInherit + def render_display_format_text(self, output): + return [self.comment(indent(output.text))] + + @DocInherit + def _unknown_lines(self, data): + return [self.comment('Warning: Unknown cell'+ str(data))] + + @DocInherit + def render_display_format_html(self, output): + return [self.comment(output.html)] + + @DocInherit + def render_display_format_latex(self, output): + return [] + + @DocInherit + def render_display_format_json(self, output): + return [] + + @DocInherit + def render_display_format_javascript(self, output): + return [] + #----------------------------------------------------------------------------- # Standalone conversion functions #----------------------------------------------------------------------------- @@ -1396,7 +1505,7 @@ def cell_to_lines(cell): return s.split('\n') -known_formats = "rst (default), html, quick-html, latex, markdown" +known_formats = "rst (default), html, quick-html, latex, markdown, py" def main(infile, format='rst'): """Convert a notebook to html in one step""" @@ -1415,6 +1524,9 @@ def main(infile, format='rst'): elif format == 'latex': converter = ConverterLaTeX(infile) latexfname = converter.render() + elif format == 'py': + converter = ConverterPy(infile) + converter.render() else: raise SystemExit("Unknown format '%s', " % format + "known formats are: " + known_formats)