nbconvertapp.py
212 lines
| 7.7 KiB
| text/x-python
|
PythonLexer
Brian E. Granger
|
r11087 | #!/usr/bin/env python | ||
"""NBConvert is a utility for conversion of IPYNB files. | ||||
Commandline interface for the NBConvert conversion utility. Read the | ||||
readme.rst for usage information | ||||
""" | ||||
#----------------------------------------------------------------------------- | ||||
#Copyright (c) 2013, the IPython Development Team. | ||||
# | ||||
#Distributed under the terms of the Modified BSD License. | ||||
# | ||||
#The full license is in the file COPYING.txt, distributed with this software. | ||||
#----------------------------------------------------------------------------- | ||||
#----------------------------------------------------------------------------- | ||||
#Imports | ||||
#----------------------------------------------------------------------------- | ||||
#Stdlib imports | ||||
from __future__ import print_function | ||||
import sys | ||||
import io | ||||
import os | ||||
#From IPython | ||||
from IPython.config.application import Application | ||||
Brian E. Granger
|
r11090 | from IPython.utils.traitlets import Bool | ||
Brian E. Granger
|
r11087 | |||
Brian E. Granger
|
r11090 | from .exporters.export import export_by_name | ||
from .exporters.exporter import Exporter | ||||
from .transformers import extractfigure | ||||
from .utils.config import GlobalConfigurable | ||||
Brian E. Granger
|
r11087 | |||
#----------------------------------------------------------------------------- | ||||
#Globals and constants | ||||
#----------------------------------------------------------------------------- | ||||
#'Keys in resources' user prompt. | ||||
KEYS_PROMPT_HEAD = "====================== Keys in Resources ==================================" | ||||
KEYS_PROMPT_BODY = """ | ||||
=========================================================================== | ||||
You are responsible for writting these files into the appropriate | ||||
directorie(s) if need be. If you do not want to see this message, enable | ||||
the 'write' (boolean) flag of the converter. | ||||
=========================================================================== | ||||
""" | ||||
#----------------------------------------------------------------------------- | ||||
#Classes and functions | ||||
#----------------------------------------------------------------------------- | ||||
class NbConvertApp(Application): | ||||
"""Application used to convert to and from notebook file type (*.ipynb)""" | ||||
stdout = Bool( | ||||
False, config=True, | ||||
help="""Whether to print the converted IPYNB file to stdout | ||||
use full do diff files without actually writing a new file""" | ||||
) | ||||
write = Bool( | ||||
True, config=True, | ||||
help="""Should the converted notebook file be written to disk | ||||
along with potential extracted resources.""" | ||||
) | ||||
aliases = { | ||||
'stdout':'NbConvertApp.stdout', | ||||
'write':'NbConvertApp.write', | ||||
} | ||||
flags = {} | ||||
flags['stdout'] = ( | ||||
{'NbConvertApp' : {'stdout' : True}}, | ||||
"""Print converted file to stdout, equivalent to --stdout=True | ||||
""" | ||||
) | ||||
flags['no-write'] = ( | ||||
{'NbConvertApp' : {'write' : True}}, | ||||
"""Do not write to disk, equivalent to --write=False | ||||
""" | ||||
) | ||||
def __init__(self, **kwargs): | ||||
"""Public constructor""" | ||||
#Call base class | ||||
super(NbConvertApp, self).__init__(**kwargs) | ||||
#Register class here to have help with help all | ||||
self.classes.insert(0, Exporter) | ||||
self.classes.insert(0, GlobalConfigurable) | ||||
def start(self, argv=None): | ||||
"""Entrypoint of NbConvert application. | ||||
Parameters | ||||
---------- | ||||
argv : list | ||||
Commandline arguments | ||||
""" | ||||
#Parse the commandline options. | ||||
self.parse_command_line(argv) | ||||
#Call base | ||||
super(NbConvertApp, self).start() | ||||
#The last arguments in list will be used by nbconvert | ||||
if len(self.extra_args) is not 3: | ||||
print( "Wrong number of arguments, use --help flag for usage", file=sys.stderr) | ||||
sys.exit(-1) | ||||
export_type = (self.extra_args)[1] | ||||
ipynb_file = (self.extra_args)[2] | ||||
#Export | ||||
return_value = export_by_name(export_type, ipynb_file) | ||||
if return_value is None: | ||||
print("Error: '%s' template not found." % export_type) | ||||
return | ||||
else: | ||||
(output, resources, exporter) = return_value | ||||
#TODO: Allow user to set output directory and file. | ||||
destination_filename = None | ||||
destination_directory = None | ||||
if self.write: | ||||
#Get the file name without the '.ipynb' (6 chars) extension and then | ||||
#remove any addition periods and spaces. The resulting name will | ||||
#be used to create the directory that the files will be exported | ||||
#into. | ||||
out_root = ipynb_file[:-6].replace('.', '_').replace(' ', '_') | ||||
destination_filename = os.path.join(out_root+'.'+exporter.file_extension) | ||||
destination_directory = out_root+'_files' | ||||
if not os.path.exists(destination_directory): | ||||
os.mkdir(destination_directory) | ||||
#Write the results | ||||
if self.stdout or not (destination_filename is None and destination_directory is None): | ||||
self._write_results(output, resources, destination_filename, destination_directory) | ||||
def _write_results(self, output, resources, destination_filename=None, destination_directory=None): | ||||
"""Output the conversion results to the console and/or filesystem | ||||
Parameters | ||||
---------- | ||||
output : str | ||||
Output of conversion | ||||
resources : dictionary | ||||
Additional input/output used by the transformers. For | ||||
example, the ExtractFigure transformer outputs the | ||||
figures it extracts into this dictionary. This method | ||||
relies on the figures being in this dictionary when | ||||
attempting to write the figures to the file system. | ||||
destination_filename : str, Optional | ||||
Filename to write output into. If None, output is not | ||||
written to a file. | ||||
destination_directory : str, Optional | ||||
Directory to write notebook data (i.e. figures) to. If | ||||
None, figures are not written to the file system. | ||||
""" | ||||
if self.stdout: | ||||
print(output.encode('utf-8')) | ||||
#Write file output from conversion. | ||||
if not destination_filename is None: | ||||
with io.open(destination_filename, 'w') as f: | ||||
f.write(output) | ||||
#Get the key names used by the extract figure transformer | ||||
figures_key = extractfigure.FIGURES_KEY | ||||
binary_key = extractfigure.BINARY_KEY | ||||
text_key = extractfigure.TEXT_KEY | ||||
#Output any associate figures into the same "root" directory. | ||||
binkeys = resources.get(figures_key, {}).get(binary_key,{}).keys() | ||||
textkeys = resources.get(figures_key, {}).get(text_key,{}).keys() | ||||
if binkeys or textkeys : | ||||
if not destination_directory is None: | ||||
for key in binkeys: | ||||
with io.open(os.path.join(destination_directory, key), 'wb') as f: | ||||
f.write(resources[figures_key][binary_key][key]) | ||||
for key in textkeys: | ||||
with io.open(os.path.join(destination_directory, key), 'w') as f: | ||||
f.write(resources[figures_key][text_key][key]) | ||||
#Figures that weren't exported which will need to be created by the | ||||
#user. Tell the user what figures these are. | ||||
if self.stdout: | ||||
print(KEYS_PROMPT_HEAD, file=sys.stderr) | ||||
print(resources[figures_key].keys(), file=sys.stderr) | ||||
print(KEYS_PROMPT_BODY , file=sys.stderr) | ||||
#----------------------------------------------------------------------------- | ||||
Brian E. Granger
|
r11092 | # Main entry point | ||
Brian E. Granger
|
r11087 | #----------------------------------------------------------------------------- | ||
Brian E. Granger
|
r11092 | def launch_new_instance(): | ||
Brian E. Granger
|
r11087 | """Application entry point""" | ||
app = NbConvertApp.instance() | ||||
app.description = __doc__ | ||||
app.start(argv=sys.argv) | ||||