##// END OF EJS Templates
Make the directory name be the default relpath
Jessica B. Hamrick -
Show More
@@ -1,279 +1,280 b''
1 1 """This module defines a base Exporter class. For Jinja template-based export,
2 2 see templateexporter.py.
3 3 """
4 4
5 5
6 6 from __future__ import print_function, absolute_import
7 7
8 8 import io
9 9 import os
10 10 import copy
11 11 import collections
12 12 import datetime
13 13
14 14 from IPython.config.configurable import LoggingConfigurable
15 15 from IPython.config import Config
16 16 from IPython import nbformat
17 17 from IPython.utils.traitlets import MetaHasTraits, Unicode, List, TraitError
18 18 from IPython.utils.importstring import import_item
19 19 from IPython.utils import text, py3compat
20 20
21 21
22 22 class ResourcesDict(collections.defaultdict):
23 23 def __missing__(self, key):
24 24 return ''
25 25
26 26
27 27 class FilenameExtension(Unicode):
28 28 """A trait for filename extensions."""
29 29
30 30 default_value = u''
31 31 info_text = 'a filename extension, beginning with a dot'
32 32
33 33 def validate(self, obj, value):
34 34 # cast to proper unicode
35 35 value = super(FilenameExtension, self).validate(obj, value)
36 36
37 37 # check that it starts with a dot
38 38 if value and not value.startswith('.'):
39 39 msg = "FileExtension trait '{}' does not begin with a dot: {!r}"
40 40 raise TraitError(msg.format(self.name, value))
41 41
42 42 return value
43 43
44 44
45 45 class Exporter(LoggingConfigurable):
46 46 """
47 47 Class containing methods that sequentially run a list of preprocessors on a
48 48 NotebookNode object and then return the modified NotebookNode object and
49 49 accompanying resources dict.
50 50 """
51 51
52 52 file_extension = FilenameExtension(
53 53 '.txt', config=True,
54 54 help="Extension of the file that should be written to disk"
55 55 )
56 56
57 57 # MIME type of the result file, for HTTP response headers.
58 58 # This is *not* a traitlet, because we want to be able to access it from
59 59 # the class, not just on instances.
60 60 output_mimetype = ''
61 61
62 62 #Configurability, allows the user to easily add filters and preprocessors.
63 63 preprocessors = List(config=True,
64 64 help="""List of preprocessors, by name or namespace, to enable.""")
65 65
66 66 _preprocessors = List()
67 67
68 68 default_preprocessors = List(['IPython.nbconvert.preprocessors.coalesce_streams',
69 69 'IPython.nbconvert.preprocessors.SVG2PDFPreprocessor',
70 70 'IPython.nbconvert.preprocessors.ExtractOutputPreprocessor',
71 71 'IPython.nbconvert.preprocessors.CSSHTMLHeaderPreprocessor',
72 72 'IPython.nbconvert.preprocessors.RevealHelpPreprocessor',
73 73 'IPython.nbconvert.preprocessors.LatexPreprocessor',
74 74 'IPython.nbconvert.preprocessors.ClearOutputPreprocessor',
75 75 'IPython.nbconvert.preprocessors.ExecutePreprocessor',
76 76 'IPython.nbconvert.preprocessors.HighlightMagicsPreprocessor'],
77 77 config=True,
78 78 help="""List of preprocessors available by default, by name, namespace,
79 79 instance, or type.""")
80 80
81 81
82 82 def __init__(self, config=None, **kw):
83 83 """
84 84 Public constructor
85 85
86 86 Parameters
87 87 ----------
88 88 config : config
89 89 User configuration instance.
90 90 """
91 91 with_default_config = self.default_config
92 92 if config:
93 93 with_default_config.merge(config)
94 94
95 95 super(Exporter, self).__init__(config=with_default_config, **kw)
96 96
97 97 self._init_preprocessors()
98 98
99 99
100 100 @property
101 101 def default_config(self):
102 102 return Config()
103 103
104 104 def from_notebook_node(self, nb, resources=None, **kw):
105 105 """
106 106 Convert a notebook from a notebook node instance.
107 107
108 108 Parameters
109 109 ----------
110 110 nb : :class:`~IPython.nbformat.NotebookNode`
111 111 Notebook node (dict-like with attr-access)
112 112 resources : dict
113 113 Additional resources that can be accessed read/write by
114 114 preprocessors and filters.
115 115 **kw
116 116 Ignored (?)
117 117 """
118 118 nb_copy = copy.deepcopy(nb)
119 119 resources = self._init_resources(resources)
120 120
121 121 if 'language' in nb['metadata']:
122 122 resources['language'] = nb['metadata']['language'].lower()
123 123
124 124 # Preprocess
125 125 nb_copy, resources = self._preprocess(nb_copy, resources)
126 126
127 127 return nb_copy, resources
128 128
129 129
130 130 def from_filename(self, filename, resources=None, **kw):
131 131 """
132 132 Convert a notebook from a notebook file.
133 133
134 134 Parameters
135 135 ----------
136 136 filename : str
137 137 Full filename of the notebook file to open and convert.
138 138 """
139 139
140 140 # Pull the metadata from the filesystem.
141 141 if resources is None:
142 142 resources = ResourcesDict()
143 143 if not 'metadata' in resources or resources['metadata'] == '':
144 144 resources['metadata'] = ResourcesDict()
145 basename = os.path.basename(filename)
145 path, basename = os.path.split(filename)
146 146 notebook_name = basename[:basename.rfind('.')]
147 147 resources['metadata']['name'] = notebook_name
148 resources['metadata']['path'] = path
148 149
149 150 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
150 151 resources['metadata']['modified_date'] = modified_date.strftime(text.date_format)
151 152
152 153 with io.open(filename, encoding='utf-8') as f:
153 154 return self.from_notebook_node(nbformat.read(f, as_version=4), resources=resources, **kw)
154 155
155 156
156 157 def from_file(self, file_stream, resources=None, **kw):
157 158 """
158 159 Convert a notebook from a notebook file.
159 160
160 161 Parameters
161 162 ----------
162 163 file_stream : file-like object
163 164 Notebook file-like object to convert.
164 165 """
165 166 return self.from_notebook_node(nbformat.read(file_stream, as_version=4), resources=resources, **kw)
166 167
167 168
168 169 def register_preprocessor(self, preprocessor, enabled=False):
169 170 """
170 171 Register a preprocessor.
171 172 Preprocessors are classes that act upon the notebook before it is
172 173 passed into the Jinja templating engine. preprocessors are also
173 174 capable of passing additional information to the Jinja
174 175 templating engine.
175 176
176 177 Parameters
177 178 ----------
178 179 preprocessor : preprocessor
179 180 """
180 181 if preprocessor is None:
181 182 raise TypeError('preprocessor')
182 183 isclass = isinstance(preprocessor, type)
183 184 constructed = not isclass
184 185
185 186 # Handle preprocessor's registration based on it's type
186 187 if constructed and isinstance(preprocessor, py3compat.string_types):
187 188 # Preprocessor is a string, import the namespace and recursively call
188 189 # this register_preprocessor method
189 190 preprocessor_cls = import_item(preprocessor)
190 191 return self.register_preprocessor(preprocessor_cls, enabled)
191 192
192 193 if constructed and hasattr(preprocessor, '__call__'):
193 194 # Preprocessor is a function, no need to construct it.
194 195 # Register and return the preprocessor.
195 196 if enabled:
196 197 preprocessor.enabled = True
197 198 self._preprocessors.append(preprocessor)
198 199 return preprocessor
199 200
200 201 elif isclass and isinstance(preprocessor, MetaHasTraits):
201 202 # Preprocessor is configurable. Make sure to pass in new default for
202 203 # the enabled flag if one was specified.
203 204 self.register_preprocessor(preprocessor(parent=self), enabled)
204 205
205 206 elif isclass:
206 207 # Preprocessor is not configurable, construct it
207 208 self.register_preprocessor(preprocessor(), enabled)
208 209
209 210 else:
210 211 # Preprocessor is an instance of something without a __call__
211 212 # attribute.
212 213 raise TypeError('preprocessor')
213 214
214 215
215 216 def _init_preprocessors(self):
216 217 """
217 218 Register all of the preprocessors needed for this exporter, disabled
218 219 unless specified explicitly.
219 220 """
220 221 self._preprocessors = []
221 222
222 223 # Load default preprocessors (not necessarly enabled by default).
223 224 for preprocessor in self.default_preprocessors:
224 225 self.register_preprocessor(preprocessor)
225 226
226 227 # Load user-specified preprocessors. Enable by default.
227 228 for preprocessor in self.preprocessors:
228 229 self.register_preprocessor(preprocessor, enabled=True)
229 230
230 231
231 232 def _init_resources(self, resources):
232 233
233 234 #Make sure the resources dict is of ResourcesDict type.
234 235 if resources is None:
235 236 resources = ResourcesDict()
236 237 if not isinstance(resources, ResourcesDict):
237 238 new_resources = ResourcesDict()
238 239 new_resources.update(resources)
239 240 resources = new_resources
240 241
241 242 #Make sure the metadata extension exists in resources
242 243 if 'metadata' in resources:
243 244 if not isinstance(resources['metadata'], ResourcesDict):
244 245 new_metadata = ResourcesDict()
245 246 new_metadata.update(resources['metadata'])
246 247 resources['metadata'] = new_metadata
247 248 else:
248 249 resources['metadata'] = ResourcesDict()
249 250 if not resources['metadata']['name']:
250 251 resources['metadata']['name'] = 'Notebook'
251 252
252 253 #Set the output extension
253 254 resources['output_extension'] = self.file_extension
254 255 return resources
255 256
256 257
257 258 def _preprocess(self, nb, resources):
258 259 """
259 260 Preprocess the notebook before passing it into the Jinja engine.
260 261 To preprocess the notebook is to apply all of the
261 262
262 263 Parameters
263 264 ----------
264 265 nb : notebook node
265 266 notebook that is being exported.
266 267 resources : a dict of additional resources that
267 268 can be accessed read/write by preprocessors
268 269 """
269 270
270 271 # Do a copy.deepcopy first,
271 272 # we are never safe enough with what the preprocessors could do.
272 273 nbc = copy.deepcopy(nb)
273 274 resc = copy.deepcopy(resources)
274 275
275 276 #Run each preprocessor on the notebook. Carry the output along
276 277 #to each preprocessor
277 278 for preprocessor in self._preprocessors:
278 279 nbc, resc = preprocessor(nbc, resc)
279 280 return nbc, resc
@@ -1,123 +1,131 b''
1 1 """Contains writer for writing nbconvert output to filesystem."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 import io
7 7 import os
8 8 import glob
9 9
10 10 from IPython.utils.traitlets import Unicode
11 11 from IPython.utils.path import link_or_copy, ensure_dir_exists
12 12 from IPython.utils.py3compat import unicode_type
13 13
14 14 from .base import WriterBase
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Classes
18 18 #-----------------------------------------------------------------------------
19 19
20 20 class FilesWriter(WriterBase):
21 21 """Consumes nbconvert output and produces files."""
22 22
23 23
24 24 build_directory = Unicode("", config=True,
25 25 help="""Directory to write output to. Leave blank
26 26 to output to the current directory""")
27 27
28 28 relpath = Unicode(
29 29 "", config=True,
30 30 help="""When copying files that the notebook depends on, copy them in
31 31 relation to this path, such that the destination filename will be
32 os.path.relpath(filename, relpath).""")
32 os.path.relpath(filename, relpath). If FilesWriter is operating on a
33 notebook that already exists elsewhere on disk, then the default will be
34 the directory containing that notebook.""")
33 35
34 36
35 37 # Make sure that the output directory exists.
36 38 def _build_directory_changed(self, name, old, new):
37 39 if new:
38 40 ensure_dir_exists(new)
39 41
40 42
41 43 def __init__(self, **kw):
42 44 super(FilesWriter, self).__init__(**kw)
43 45 self._build_directory_changed('build_directory', self.build_directory,
44 46 self.build_directory)
45 47
46 48 def _makedir(self, path):
47 49 """Make a directory if it doesn't already exist"""
48 50 if path:
49 51 self.log.info("Making directory %s", path)
50 52 ensure_dir_exists(path)
51 53
52 54 def write(self, output, resources, notebook_name=None, **kw):
53 55 """
54 56 Consume and write Jinja output to the file system. Output directory
55 57 is set via the 'build_directory' variable of this instance (a
56 58 configurable).
57 59
58 60 See base for more...
59 61 """
60 62
61 63 # Verify that a notebook name is provided.
62 64 if notebook_name is None:
63 65 raise TypeError('notebook_name')
64 66
65 67 # Pull the extension and subdir from the resources dict.
66 68 output_extension = resources.get('output_extension', None)
67 69
70 # Get the relative path for copying files
71 if self.relpath == '':
72 relpath = resources.get('metadata', {}).get('path', '')
73 else:
74 relpath = self.relpath
75
68 76 # Write all of the extracted resources to the destination directory.
69 77 # NOTE: WE WRITE EVERYTHING AS-IF IT'S BINARY. THE EXTRACT FIG
70 78 # PREPROCESSOR SHOULD HANDLE UNIX/WINDOWS LINE ENDINGS...
71 79 for filename, data in resources.get('outputs', {}).items():
72 80
73 81 # Determine where to write the file to
74 82 dest = os.path.join(self.build_directory, filename)
75 83 path = os.path.dirname(dest)
76 84 self._makedir(path)
77 85
78 86 # Write file
79 87 self.log.debug("Writing %i bytes to support file %s", len(data), dest)
80 88 with io.open(dest, 'wb') as f:
81 89 f.write(data)
82 90
83 91 # Copy referenced files to output directory
84 92 if self.build_directory:
85 93 for filename in self.files:
86 94
87 95 # Copy files that match search pattern
88 96 for matching_filename in glob.glob(filename):
89 97
90 98 # compute the relative path for the filename
91 if self.relpath:
92 dest_filename = os.path.relpath(matching_filename, self.relpath)
99 if relpath != '':
100 dest_filename = os.path.relpath(matching_filename, relpath)
93 101 else:
94 102 dest_filename = matching_filename
95 103
96 104 # Make sure folder exists.
97 105 dest = os.path.join(self.build_directory, dest_filename)
98 106 path = os.path.dirname(dest)
99 107 self._makedir(path)
100 108
101 109 # Copy if destination is different.
102 110 if not os.path.normpath(dest) == os.path.normpath(matching_filename):
103 111 self.log.info("Linking %s -> %s", matching_filename, dest)
104 112 link_or_copy(matching_filename, dest)
105 113
106 114 # Determine where to write conversion results.
107 115 if output_extension is not None:
108 116 dest = notebook_name + output_extension
109 117 else:
110 118 dest = notebook_name
111 119 if self.build_directory:
112 120 dest = os.path.join(self.build_directory, dest)
113 121
114 122 # Write conversion results.
115 123 self.log.info("Writing %i bytes to %s", len(output), dest)
116 124 if isinstance(output, unicode_type):
117 125 with io.open(dest, 'w', encoding='utf-8') as f:
118 126 f.write(output)
119 127 else:
120 128 with io.open(dest, 'wb') as f:
121 129 f.write(output)
122 130
123 131 return dest
@@ -1,238 +1,307 b''
1 1 """
2 2 Module with tests for files
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (c) 2013, the IPython Development Team.
7 7 #
8 8 # Distributed under the terms of the Modified BSD License.
9 9 #
10 10 # The full license is in the file COPYING.txt, distributed with this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import sys
18 18 import os
19 19
20 20 from ...tests.base import TestsBase
21 21 from ..files import FilesWriter
22 22 from IPython.utils.py3compat import PY3
23 23
24 24 if PY3:
25 25 from io import StringIO
26 26 else:
27 27 from StringIO import StringIO
28 28
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Class
32 32 #-----------------------------------------------------------------------------
33 33
34 34 class Testfiles(TestsBase):
35 35 """Contains test functions for files.py"""
36 36
37 37 def test_basic_output(self):
38 38 """Is FilesWriter basic output correct?"""
39 39
40 40 # Work in a temporary directory.
41 41 with self.create_temp_cwd():
42 42
43 43 # Create the resoruces dictionary
44 44 res = {}
45 45
46 46 # Create files writer, test output
47 47 writer = FilesWriter()
48 48 writer.write(u'y', res, notebook_name="z")
49 49
50 50 # Check the output of the file
51 51 with open('z', 'r') as f:
52 52 output = f.read()
53 53 self.assertEqual(output, u'y')
54 54
55 55 def test_ext(self):
56 56 """Does the FilesWriter add the correct extension to the output?"""
57 57
58 58 # Work in a temporary directory.
59 59 with self.create_temp_cwd():
60 60
61 61 # Create the resoruces dictionary
62 62 res = {'output_extension': '.txt'}
63 63
64 64 # Create files writer, test output
65 65 writer = FilesWriter()
66 66 writer.write(u'y', res, notebook_name="z")
67 67
68 68 # Check the output of the file
69 69 assert os.path.isfile('z.txt')
70 70 with open('z.txt', 'r') as f:
71 71 output = f.read()
72 72 self.assertEqual(output, u'y')
73 73
74 74
75 75 def test_extract(self):
76 76 """Can FilesWriter write extracted figures correctly?"""
77 77
78 78 # Work in a temporary directory.
79 79 with self.create_temp_cwd():
80 80
81 81 # Create the resoruces dictionary
82 82 res = {'outputs': {os.path.join('z_files', 'a'): b'b'}}
83 83
84 84 # Create files writer, test output
85 85 writer = FilesWriter()
86 86 writer.write(u'y', res, notebook_name="z")
87 87
88 88 # Check the output of the file
89 89 with open('z', 'r') as f:
90 90 output = f.read()
91 91 self.assertEqual(output, u'y')
92 92
93 93 # Check the output of the extracted file
94 94 extracted_file_dest = os.path.join('z_files', 'a')
95 95 assert os.path.isfile(extracted_file_dest)
96 96 with open(extracted_file_dest, 'r') as f:
97 97 output = f.read()
98 98 self.assertEqual(output, 'b')
99 99
100 100
101 101 def test_builddir(self):
102 102 """Can FilesWriter write to a build dir correctly?"""
103 103
104 104 # Work in a temporary directory.
105 105 with self.create_temp_cwd():
106 106
107 107 # Create the resoruces dictionary
108 108 res = {'outputs': {os.path.join('z_files', 'a'): b'b'}}
109 109
110 110 # Create files writer, test output
111 111 writer = FilesWriter()
112 112 writer.build_directory = u'build'
113 113 writer.write(u'y', res, notebook_name="z")
114 114
115 115 # Check the output of the file
116 116 assert os.path.isdir(writer.build_directory)
117 117 dest = os.path.join(writer.build_directory, 'z')
118 118 with open(dest, 'r') as f:
119 119 output = f.read()
120 120 self.assertEqual(output, u'y')
121 121
122 122 # Check the output of the extracted file
123 123 extracted_file_dest = os.path.join(writer.build_directory, 'z_files', 'a')
124 124 assert os.path.isfile(extracted_file_dest)
125 125 with open(extracted_file_dest, 'r') as f:
126 126 output = f.read()
127 127 self.assertEqual(output, 'b')
128 128
129 129
130 130 def test_links(self):
131 131 """Can the FilesWriter handle linked files correctly?"""
132 132
133 133 # Work in a temporary directory.
134 134 with self.create_temp_cwd():
135 135
136 136 # Create test file
137 137 os.mkdir('sub')
138 138 with open(os.path.join('sub', 'c'), 'w') as f:
139 139 f.write('d')
140 140
141 141 # Create the resoruces dictionary
142 142 res = {}
143 143
144 144 # Create files writer, test output
145 145 writer = FilesWriter()
146 146 writer.files = [os.path.join('sub', 'c')]
147 147 writer.build_directory = u'build'
148 148 writer.write(u'y', res, notebook_name="z")
149 149
150 150 # Check the output of the file
151 151 assert os.path.isdir(writer.build_directory)
152 152 dest = os.path.join(writer.build_directory, 'z')
153 153 with open(dest, 'r') as f:
154 154 output = f.read()
155 155 self.assertEqual(output, u'y')
156 156
157 157 # Check to make sure the linked file was copied
158 158 path = os.path.join(writer.build_directory, 'sub')
159 159 assert os.path.isdir(path)
160 160 dest = os.path.join(path, 'c')
161 161 assert os.path.isfile(dest)
162 162 with open(dest, 'r') as f:
163 163 output = f.read()
164 164 self.assertEqual(output, 'd')
165 165
166 166 def test_glob(self):
167 167 """Can the FilesWriter handle globbed files correctly?"""
168 168
169 169 # Work in a temporary directory.
170 170 with self.create_temp_cwd():
171 171
172 172 # Create test files
173 173 os.mkdir('sub')
174 174 with open(os.path.join('sub', 'c'), 'w') as f:
175 175 f.write('e')
176 176 with open(os.path.join('sub', 'd'), 'w') as f:
177 177 f.write('e')
178 178
179 179 # Create the resoruces dictionary
180 180 res = {}
181 181
182 182 # Create files writer, test output
183 183 writer = FilesWriter()
184 184 writer.files = ['sub/*']
185 185 writer.build_directory = u'build'
186 186 writer.write(u'y', res, notebook_name="z")
187 187
188 188 # Check the output of the file
189 189 assert os.path.isdir(writer.build_directory)
190 190 dest = os.path.join(writer.build_directory, 'z')
191 191 with open(dest, 'r') as f:
192 192 output = f.read()
193 193 self.assertEqual(output, u'y')
194 194
195 195 # Check to make sure the globbed files were copied
196 196 path = os.path.join(writer.build_directory, 'sub')
197 197 assert os.path.isdir(path)
198 198 for filename in ['c', 'd']:
199 199 dest = os.path.join(path, filename)
200 200 assert os.path.isfile(dest)
201 201 with open(dest, 'r') as f:
202 202 output = f.read()
203 203 self.assertEqual(output, 'e')
204 204
205 205 def test_relpath(self):
206 206 """Can the FilesWriter handle relative paths for linked files correctly?"""
207 207
208 208 # Work in a temporary directory.
209 209 with self.create_temp_cwd():
210 210
211 211 # Create test file
212 212 os.mkdir('sub')
213 213 with open(os.path.join('sub', 'c'), 'w') as f:
214 214 f.write('d')
215 215
216 216 # Create the resoruces dictionary
217 217 res = {}
218 218
219 219 # Create files writer, test output
220 220 writer = FilesWriter()
221 221 writer.files = [os.path.join('sub', 'c')]
222 222 writer.build_directory = u'build'
223 223 writer.relpath = 'sub'
224 224 writer.write(u'y', res, notebook_name="z")
225 225
226 226 # Check the output of the file
227 227 assert os.path.isdir(writer.build_directory)
228 228 dest = os.path.join(writer.build_directory, 'z')
229 229 with open(dest, 'r') as f:
230 230 output = f.read()
231 231 self.assertEqual(output, u'y')
232 232
233 233 # Check to make sure the linked file was copied
234 234 dest = os.path.join(writer.build_directory, 'c')
235 235 assert os.path.isfile(dest)
236 236 with open(dest, 'r') as f:
237 237 output = f.read()
238 238 self.assertEqual(output, 'd')
239
240 def test_relpath_default(self):
241 """Is the FilesWriter default relative path correct?"""
242
243 # Work in a temporary directory.
244 with self.create_temp_cwd():
245
246 # Create test file
247 os.mkdir('sub')
248 with open(os.path.join('sub', 'c'), 'w') as f:
249 f.write('d')
250
251 # Create the resoruces dictionary
252 res = dict(metadata=dict(path="sub"))
253
254 # Create files writer, test output
255 writer = FilesWriter()
256 writer.files = [os.path.join('sub', 'c')]
257 writer.build_directory = u'build'
258 writer.write(u'y', res, notebook_name="z")
259
260 # Check the output of the file
261 assert os.path.isdir(writer.build_directory)
262 dest = os.path.join(writer.build_directory, 'z')
263 with open(dest, 'r') as f:
264 output = f.read()
265 self.assertEqual(output, u'y')
266
267 # Check to make sure the linked file was copied
268 dest = os.path.join(writer.build_directory, 'c')
269 assert os.path.isfile(dest)
270 with open(dest, 'r') as f:
271 output = f.read()
272 self.assertEqual(output, 'd')
273
274 def test_relpath_default(self):
275 """Does the FilesWriter relpath option take precedence over the path?"""
276
277 # Work in a temporary directory.
278 with self.create_temp_cwd():
279
280 # Create test file
281 os.mkdir('sub')
282 with open(os.path.join('sub', 'c'), 'w') as f:
283 f.write('d')
284
285 # Create the resoruces dictionary
286 res = dict(metadata=dict(path="other_sub"))
287
288 # Create files writer, test output
289 writer = FilesWriter()
290 writer.files = [os.path.join('sub', 'c')]
291 writer.build_directory = u'build'
292 writer.relpath = 'sub'
293 writer.write(u'y', res, notebook_name="z")
294
295 # Check the output of the file
296 assert os.path.isdir(writer.build_directory)
297 dest = os.path.join(writer.build_directory, 'z')
298 with open(dest, 'r') as f:
299 output = f.read()
300 self.assertEqual(output, u'y')
301
302 # Check to make sure the linked file was copied
303 dest = os.path.join(writer.build_directory, 'c')
304 assert os.path.isfile(dest)
305 with open(dest, 'r') as f:
306 output = f.read()
307 self.assertEqual(output, 'd')
General Comments 0
You need to be logged in to leave comments. Login now