mirror of
https://github.com/jupyter/notebook.git
synced 2024-12-27 04:20:22 +08:00
Merge pull request #6269 from takluyver/atomic-save
Implement atomic save
This commit is contained in:
commit
fbae96f9cb
@ -13,6 +13,7 @@ from tornado import web
|
||||
|
||||
from .manager import ContentsManager
|
||||
from IPython.nbformat import current
|
||||
from IPython.utils.io import atomic_writing
|
||||
from IPython.utils.path import ensure_dir_exists
|
||||
from IPython.utils.traitlets import Unicode, Bool, TraitError
|
||||
from IPython.utils.py3compat import getcwd
|
||||
@ -295,7 +296,7 @@ class FileContentsManager(ContentsManager):
|
||||
if 'name' in nb['metadata']:
|
||||
nb['metadata']['name'] = u''
|
||||
|
||||
with io.open(os_path, 'w', encoding='utf-8') as f:
|
||||
with atomic_writing(os_path, encoding='utf-8') as f:
|
||||
current.write(nb, f, u'json')
|
||||
|
||||
def _save_file(self, os_path, model, name='', path=''):
|
||||
@ -312,7 +313,7 @@ class FileContentsManager(ContentsManager):
|
||||
bcontent = base64.decodestring(b64_bytes)
|
||||
except Exception as e:
|
||||
raise web.HTTPError(400, u'Encoding error saving %s: %s' % (os_path, e))
|
||||
with io.open(os_path, 'wb') as f:
|
||||
with atomic_writing(os_path, text=False) as f:
|
||||
f.write(bcontent)
|
||||
|
||||
def _save_directory(self, os_path, model, name='', path=''):
|
||||
|
@ -15,6 +15,7 @@ from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
|
||||
import io as stdlib_io
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
@ -23,8 +24,11 @@ import unittest
|
||||
import nose.tools as nt
|
||||
|
||||
from IPython.testing.decorators import skipif
|
||||
from IPython.utils.io import Tee, capture_output, unicode_std_stream
|
||||
from IPython.utils.io import (Tee, capture_output, unicode_std_stream,
|
||||
atomic_writing,
|
||||
)
|
||||
from IPython.utils.py3compat import doctest_refactor_print, PY3
|
||||
from IPython.utils.tempdir import TemporaryDirectory
|
||||
|
||||
if PY3:
|
||||
from io import StringIO
|
||||
@ -121,4 +125,27 @@ def test_UnicodeStdStream_nowrap():
|
||||
nt.assert_is(unicode_std_stream(), sys.stdout)
|
||||
assert not sys.stdout.closed
|
||||
finally:
|
||||
sys.stdout = orig_stdout
|
||||
sys.stdout = orig_stdout
|
||||
|
||||
def test_atomic_writing():
|
||||
class CustomExc(Exception): pass
|
||||
|
||||
with TemporaryDirectory() as td:
|
||||
f1 = os.path.join(td, 'penguin')
|
||||
with stdlib_io.open(f1, 'w') as f:
|
||||
f.write(u'Before')
|
||||
|
||||
with nt.assert_raises(CustomExc):
|
||||
with atomic_writing(f1) as f:
|
||||
f.write(u'Failing write')
|
||||
raise CustomExc
|
||||
|
||||
# Because of the exception, the file should not have been modified
|
||||
with stdlib_io.open(f1, 'r') as f:
|
||||
nt.assert_equal(f.read(), u'Before')
|
||||
|
||||
with atomic_writing(f1) as f:
|
||||
f.write(u'Overwritten')
|
||||
|
||||
with stdlib_io.open(f1, 'r') as f:
|
||||
nt.assert_equal(f.read(), u'Overwritten')
|
||||
|
Loading…
Reference in New Issue
Block a user