##// END OF EJS Templates
Implement atomic save...
Thomas Kluyver -
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 io.open(os_path, 'w', encoding='utf-8') as f:
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 io.open(os_path, 'wb') as f:
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