Show More
@@ -13,6 +13,7 b' from tornado import web' | |||||
13 |
|
13 | |||
14 | from .manager import ContentsManager |
|
14 | from .manager import ContentsManager | |
15 | from IPython.nbformat import current |
|
15 | from IPython.nbformat import current | |
|
16 | from IPython.utils.io import atomic_writing | |||
16 | from IPython.utils.path import ensure_dir_exists |
|
17 | from IPython.utils.path import ensure_dir_exists | |
17 | from IPython.utils.traitlets import Unicode, Bool, TraitError |
|
18 | from IPython.utils.traitlets import Unicode, Bool, TraitError | |
18 | from IPython.utils.py3compat import getcwd |
|
19 | from IPython.utils.py3compat import getcwd | |
@@ -295,7 +296,7 b' class FileContentsManager(ContentsManager):' | |||||
295 | if 'name' in nb['metadata']: |
|
296 | if 'name' in nb['metadata']: | |
296 | nb['metadata']['name'] = u'' |
|
297 | nb['metadata']['name'] = u'' | |
297 |
|
298 | |||
298 |
with |
|
299 | with atomic_writing(os_path, encoding='utf-8') as f: | |
299 | current.write(nb, f, u'json') |
|
300 | current.write(nb, f, u'json') | |
300 |
|
301 | |||
301 | def _save_file(self, os_path, model, name='', path=''): |
|
302 | def _save_file(self, os_path, model, name='', path=''): | |
@@ -312,7 +313,7 b' class FileContentsManager(ContentsManager):' | |||||
312 | bcontent = base64.decodestring(b64_bytes) |
|
313 | bcontent = base64.decodestring(b64_bytes) | |
313 | except Exception as e: |
|
314 | except Exception as e: | |
314 | raise web.HTTPError(400, u'Encoding error saving %s: %s' % (os_path, e)) |
|
315 | raise web.HTTPError(400, u'Encoding error saving %s: %s' % (os_path, e)) | |
315 |
with |
|
316 | with atomic_writing(os_path, 'wb') as f: | |
316 | f.write(bcontent) |
|
317 | f.write(bcontent) | |
317 |
|
318 | |||
318 | def _save_directory(self, os_path, model, name='', path=''): |
|
319 | def _save_directory(self, os_path, model, name='', path=''): |
@@ -16,6 +16,7 b' from __future__ import absolute_import' | |||||
16 | # Imports |
|
16 | # Imports | |
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 | import codecs |
|
18 | import codecs | |
|
19 | from contextlib import contextmanager | |||
19 | import os |
|
20 | import os | |
20 | import sys |
|
21 | import sys | |
21 | import tempfile |
|
22 | import tempfile | |
@@ -217,6 +218,23 b" def temp_pyfile(src, ext='.py'):" | |||||
217 | f.flush() |
|
218 | f.flush() | |
218 | return fname, f |
|
219 | return fname, f | |
219 |
|
220 | |||
|
221 | @contextmanager | |||
|
222 | def atomic_writing(path, mode='w', encoding='utf-8', **kwargs): | |||
|
223 | tmp_file = path + '.tmp-write' | |||
|
224 | if 'b' in mode: | |||
|
225 | encoding = None | |||
|
226 | ||||
|
227 | with open(tmp_file, mode, encoding=encoding, **kwargs) as f: | |||
|
228 | yield f | |||
|
229 | ||||
|
230 | # Written successfully, now rename it | |||
|
231 | ||||
|
232 | if os.name == 'nt' and os.path.exists(path): | |||
|
233 | # Rename over existing file doesn't work on Windows | |||
|
234 | os.remove(path) | |||
|
235 | ||||
|
236 | os.rename(tmp_file, path) | |||
|
237 | ||||
220 |
|
238 | |||
221 | def raw_print(*args, **kw): |
|
239 | def raw_print(*args, **kw): | |
222 | """Raw print to sys.__stdout__, otherwise identical interface to print().""" |
|
240 | """Raw print to sys.__stdout__, otherwise identical interface to print().""" |
General Comments 0
You need to be logged in to leave comments.
Login now