##// END OF EJS Templates
support binary files in FilesWriter
MinRK -
Show More
@@ -1,115 +1,111
1 """
1 """Contains writer for writing nbconvert output to filesystem."""
2 Contains writer for writing nbconvert output to filesystem.
3 """
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
6 #
7 #Distributed under the terms of the Modified BSD License.
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
2
12 #-----------------------------------------------------------------------------
3 # Copyright (c) IPython Development Team.
13 # Imports
4 # Distributed under the terms of the Modified BSD License.
14 #-----------------------------------------------------------------------------
15
5
16 import io
6 import io
17 import os
7 import os
18 import glob
8 import glob
19
9
20 from IPython.utils.traitlets import Unicode
10 from IPython.utils.traitlets import Unicode
21 from IPython.utils.path import link_or_copy
11 from IPython.utils.path import link_or_copy
12 from IPython.utils.py3compat import unicode_type
22
13
23 from .base import WriterBase
14 from .base import WriterBase
24
15
25 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
26 # Classes
17 # Classes
27 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
28
19
29 class FilesWriter(WriterBase):
20 class FilesWriter(WriterBase):
30 """Consumes nbconvert output and produces files."""
21 """Consumes nbconvert output and produces files."""
31
22
32
23
33 build_directory = Unicode("", config=True,
24 build_directory = Unicode("", config=True,
34 help="""Directory to write output to. Leave blank
25 help="""Directory to write output to. Leave blank
35 to output to the current directory""")
26 to output to the current directory""")
36
27
37
28
38 # Make sure that the output directory exists.
29 # Make sure that the output directory exists.
39 def _build_directory_changed(self, name, old, new):
30 def _build_directory_changed(self, name, old, new):
40 if new and not os.path.isdir(new):
31 if new and not os.path.isdir(new):
41 os.makedirs(new)
32 os.makedirs(new)
42
33
43
34
44 def __init__(self, **kw):
35 def __init__(self, **kw):
45 super(FilesWriter, self).__init__(**kw)
36 super(FilesWriter, self).__init__(**kw)
46 self._build_directory_changed('build_directory', self.build_directory,
37 self._build_directory_changed('build_directory', self.build_directory,
47 self.build_directory)
38 self.build_directory)
48
39
49 def _makedir(self, path):
40 def _makedir(self, path):
50 """Make a directory if it doesn't already exist"""
41 """Make a directory if it doesn't already exist"""
51 if path and not os.path.isdir(path):
42 if path and not os.path.isdir(path):
52 self.log.info("Making directory %s", path)
43 self.log.info("Making directory %s", path)
53 os.makedirs(path)
44 os.makedirs(path)
54
45
55 def write(self, output, resources, notebook_name=None, **kw):
46 def write(self, output, resources, notebook_name=None, **kw):
56 """
47 """
57 Consume and write Jinja output to the file system. Output directory
48 Consume and write Jinja output to the file system. Output directory
58 is set via the 'build_directory' variable of this instance (a
49 is set via the 'build_directory' variable of this instance (a
59 configurable).
50 configurable).
60
51
61 See base for more...
52 See base for more...
62 """
53 """
63
54
64 # Verify that a notebook name is provided.
55 # Verify that a notebook name is provided.
65 if notebook_name is None:
56 if notebook_name is None:
66 raise TypeError('notebook_name')
57 raise TypeError('notebook_name')
67
58
68 # Pull the extension and subdir from the resources dict.
59 # Pull the extension and subdir from the resources dict.
69 output_extension = resources.get('output_extension', None)
60 output_extension = resources.get('output_extension', None)
70
61
71 # Write all of the extracted resources to the destination directory.
62 # Write all of the extracted resources to the destination directory.
72 # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG
63 # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG
73 # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS...
64 # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS...
74 for filename, data in resources.get('outputs', {}).items():
65 for filename, data in resources.get('outputs', {}).items():
75
66
76 # Determine where to write the file to
67 # Determine where to write the file to
77 dest = os.path.join(self.build_directory, filename)
68 dest = os.path.join(self.build_directory, filename)
78 path = os.path.dirname(dest)
69 path = os.path.dirname(dest)
79 self._makedir(path)
70 self._makedir(path)
80
71
81 # Write file
72 # Write file
82 self.log.debug("Writing %i bytes to support file %s", len(data), dest)
73 self.log.debug("Writing %i bytes to support file %s", len(data), dest)
83 with io.open(dest, 'wb') as f:
74 with io.open(dest, 'wb') as f:
84 f.write(data)
75 f.write(data)
85
76
86 # Copy referenced files to output directory
77 # Copy referenced files to output directory
87 if self.build_directory:
78 if self.build_directory:
88 for filename in self.files:
79 for filename in self.files:
89
80
90 # Copy files that match search pattern
81 # Copy files that match search pattern
91 for matching_filename in glob.glob(filename):
82 for matching_filename in glob.glob(filename):
92
83
93 # Make sure folder exists.
84 # Make sure folder exists.
94 dest = os.path.join(self.build_directory, filename)
85 dest = os.path.join(self.build_directory, filename)
95 path = os.path.dirname(dest)
86 path = os.path.dirname(dest)
96 self._makedir(path)
87 self._makedir(path)
97
88
98 # Copy if destination is different.
89 # Copy if destination is different.
99 if not os.path.normpath(dest) == os.path.normpath(matching_filename):
90 if not os.path.normpath(dest) == os.path.normpath(matching_filename):
100 self.log.info("Linking %s -> %s", matching_filename, dest)
91 self.log.info("Linking %s -> %s", matching_filename, dest)
101 link_or_copy(matching_filename, dest)
92 link_or_copy(matching_filename, dest)
102
93
103 # Determine where to write conversion results.
94 # Determine where to write conversion results.
104 if output_extension is not None:
95 if output_extension is not None:
105 dest = notebook_name + '.' + output_extension
96 dest = notebook_name + '.' + output_extension
106 else:
97 else:
107 dest = notebook_name
98 dest = notebook_name
108 if self.build_directory:
99 if self.build_directory:
109 dest = os.path.join(self.build_directory, dest)
100 dest = os.path.join(self.build_directory, dest)
110
101
111 # Write conversion results.
102 # Write conversion results.
112 self.log.info("Writing %i bytes to %s", len(output), dest)
103 self.log.info("Writing %i bytes to %s", len(output), dest)
104 if isinstance(output, unicode_type):
113 with io.open(dest, 'w', encoding='utf-8') as f:
105 with io.open(dest, 'w', encoding='utf-8') as f:
114 f.write(output)
106 f.write(output)
107 else:
108 with io.open(dest, 'wb') as f:
109 f.write(output)
110
115 return dest
111 return dest
General Comments 0
You need to be logged in to leave comments. Login now