files.py
135 lines
| 5.2 KiB
| text/x-python
|
PythonLexer
MinRK
|
r16264 | """Contains writer for writing nbconvert output to filesystem.""" | ||
Jonathan Frederic
|
r11369 | |||
MinRK
|
r16264 | # Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||||
Jonathan Frederic
|
r11369 | |||
import io | ||||
import os | ||||
import glob | ||||
from IPython.utils.traitlets import Unicode | ||||
MinRK
|
r16486 | from IPython.utils.path import link_or_copy, ensure_dir_exists | ||
MinRK
|
r16264 | from IPython.utils.py3compat import unicode_type | ||
Jonathan Frederic
|
r11369 | |||
from .base import WriterBase | ||||
#----------------------------------------------------------------------------- | ||||
# Classes | ||||
#----------------------------------------------------------------------------- | ||||
class FilesWriter(WriterBase): | ||||
"""Consumes nbconvert output and produces files.""" | ||||
Paul Ivanov
|
r11982 | build_directory = Unicode("", config=True, | ||
Jonathan Frederic
|
r11369 | help="""Directory to write output to. Leave blank | ||
to output to the current directory""") | ||||
Jessica B. Hamrick
|
r20590 | relpath = Unicode( | ||
"", config=True, | ||||
help="""When copying files that the notebook depends on, copy them in | ||||
relation to this path, such that the destination filename will be | ||||
Jessica B. Hamrick
|
r20619 | os.path.relpath(filename, relpath). If FilesWriter is operating on a | ||
notebook that already exists elsewhere on disk, then the default will be | ||||
the directory containing that notebook.""") | ||||
Jessica B. Hamrick
|
r20590 | |||
Jonathan Frederic
|
r11369 | |||
Jonathan Frederic
|
r11632 | # Make sure that the output directory exists. | ||
Jonathan Frederic
|
r11369 | def _build_directory_changed(self, name, old, new): | ||
MinRK
|
r16486 | if new: | ||
ensure_dir_exists(new) | ||||
Jonathan Frederic
|
r11369 | |||
def __init__(self, **kw): | ||||
super(FilesWriter, self).__init__(**kw) | ||||
self._build_directory_changed('build_directory', self.build_directory, | ||||
self.build_directory) | ||||
MinRK
|
r11842 | |||
def _makedir(self, path): | ||||
"""Make a directory if it doesn't already exist""" | ||||
MinRK
|
r16486 | if path: | ||
MinRK
|
r11842 | self.log.info("Making directory %s", path) | ||
MinRK
|
r16486 | ensure_dir_exists(path) | ||
Jonathan Frederic
|
r11369 | |||
def write(self, output, resources, notebook_name=None, **kw): | ||||
""" | ||||
Consume and write Jinja output to the file system. Output directory | ||||
is set via the 'build_directory' variable of this instance (a | ||||
configurable). | ||||
See base for more... | ||||
""" | ||||
Jonathan Frederic
|
r12005 | # Verify that a notebook name is provided. | ||
if notebook_name is None: | ||||
Jonathan Frederic
|
r12013 | raise TypeError('notebook_name') | ||
Jonathan Frederic
|
r12005 | |||
Jonathan Frederic
|
r11632 | # Pull the extension and subdir from the resources dict. | ||
Jonathan Frederic
|
r12006 | output_extension = resources.get('output_extension', None) | ||
Jonathan Frederic
|
r11369 | |||
Jessica B. Hamrick
|
r20619 | # Get the relative path for copying files | ||
if self.relpath == '': | ||||
relpath = resources.get('metadata', {}).get('path', '') | ||||
else: | ||||
relpath = self.relpath | ||||
Jonathan Frederic
|
r11632 | # Write all of the extracted resources to the destination directory. | ||
# NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG | ||||
Paul Ivanov
|
r12219 | # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS... | ||
Matthias Bussonnier
|
r20724 | |||
items = resources.get('outputs', {}).items() | ||||
if items: | ||||
Matthias Bussonnier
|
r20726 | self.log.info("Support files will be in %s", os.path.join(resources.get('output_files_dir',''), '')) | ||
Matthias Bussonnier
|
r20724 | for filename, data in items: | ||
Jonathan Frederic
|
r11369 | |||
Jonathan Frederic
|
r11632 | # Determine where to write the file to | ||
Jonathan Frederic
|
r11369 | dest = os.path.join(self.build_directory, filename) | ||
Jonathan Frederic
|
r11629 | path = os.path.dirname(dest) | ||
MinRK
|
r11842 | self._makedir(path) | ||
Jonathan Frederic
|
r11369 | |||
Jonathan Frederic
|
r11632 | # Write file | ||
MinRK
|
r11847 | self.log.debug("Writing %i bytes to support file %s", len(data), dest) | ||
Jonathan Frederic
|
r11369 | with io.open(dest, 'wb') as f: | ||
f.write(data) | ||||
Jonathan Frederic
|
r11632 | # Copy referenced files to output directory | ||
Jonathan Frederic
|
r11369 | if self.build_directory: | ||
for filename in self.files: | ||||
Jonathan Frederic
|
r11632 | # Copy files that match search pattern | ||
Jonathan Frederic
|
r11369 | for matching_filename in glob.glob(filename): | ||
Jessica B. Hamrick
|
r20590 | # compute the relative path for the filename | ||
Jessica B. Hamrick
|
r20619 | if relpath != '': | ||
dest_filename = os.path.relpath(matching_filename, relpath) | ||||
Jessica B. Hamrick
|
r20590 | else: | ||
dest_filename = matching_filename | ||||
Jonathan Frederic
|
r11632 | # Make sure folder exists. | ||
Jessica B. Hamrick
|
r20590 | dest = os.path.join(self.build_directory, dest_filename) | ||
Jonathan Frederic
|
r11369 | path = os.path.dirname(dest) | ||
MinRK
|
r11842 | self._makedir(path) | ||
Jonathan Frederic
|
r11369 | |||
Jonathan Frederic
|
r11632 | # Copy if destination is different. | ||
Jonathan Frederic
|
r11630 | if not os.path.normpath(dest) == os.path.normpath(matching_filename): | ||
MinRK
|
r11842 | self.log.info("Linking %s -> %s", matching_filename, dest) | ||
David Wolever
|
r11649 | link_or_copy(matching_filename, dest) | ||
Jonathan Frederic
|
r11369 | |||
Jonathan Frederic
|
r11632 | # Determine where to write conversion results. | ||
Jonathan Frederic
|
r12006 | if output_extension is not None: | ||
Thomas Kluyver
|
r19027 | dest = notebook_name + output_extension | ||
Jonathan Frederic
|
r12006 | else: | ||
dest = notebook_name | ||||
Jonathan Frederic
|
r11369 | if self.build_directory: | ||
dest = os.path.join(self.build_directory, dest) | ||||
Jonathan Frederic
|
r11632 | # Write conversion results. | ||
MinRK
|
r11853 | self.log.info("Writing %i bytes to %s", len(output), dest) | ||
MinRK
|
r16264 | if isinstance(output, unicode_type): | ||
with io.open(dest, 'w', encoding='utf-8') as f: | ||||
f.write(output) | ||||
else: | ||||
with io.open(dest, 'wb') as f: | ||||
f.write(output) | ||||
Paul Ivanov
|
r12219 | return dest | ||