Atomic writes (fix #440)
This commit is contained in:
parent
5e5427f987
commit
4c91ee8906
@ -38,6 +38,7 @@ from importlib import import_module
|
||||
from itertools import groupby
|
||||
from random import getrandbits
|
||||
|
||||
from atomicwrites import AtomicWriter
|
||||
import vobject
|
||||
|
||||
if os.name == "nt":
|
||||
@ -151,6 +152,15 @@ def path_to_filesystem(root, *paths):
|
||||
return safe_path
|
||||
|
||||
|
||||
class _EncodedAtomicWriter(AtomicWriter):
|
||||
def __init__(self, path, encoding, mode="w", overwrite=True):
|
||||
self._encoding = encoding
|
||||
return super().__init__(path, mode, overwrite=True)
|
||||
|
||||
def get_fileobject(self, **kwargs):
|
||||
return super().get_fileobject(encoding=self._encoding, **kwargs)
|
||||
|
||||
|
||||
class Item:
|
||||
def __init__(self, collection, item, href, last_modified=None):
|
||||
self.collection = collection
|
||||
@ -319,6 +329,12 @@ class Collection(BaseCollection):
|
||||
self.owner = None
|
||||
self.is_principal = principal
|
||||
|
||||
@contextmanager
|
||||
def _atomic_write(self, path, mode="w"):
|
||||
with _EncodedAtomicWriter(
|
||||
path, self.storage_encoding, mode).open() as fd:
|
||||
yield fd
|
||||
|
||||
@classmethod
|
||||
def discover(cls, path, depth="1"):
|
||||
# path == None means wrong URL
|
||||
@ -447,7 +463,7 @@ class Collection(BaseCollection):
|
||||
path = path_to_filesystem(self._filesystem_path, href)
|
||||
if not os.path.exists(path):
|
||||
item = Item(self, vobject_item, href)
|
||||
with open(path, "w", encoding=self.storage_encoding) as fd:
|
||||
with self._atomic_write(path) as fd:
|
||||
fd.write(item.serialize())
|
||||
return item
|
||||
else:
|
||||
@ -465,7 +481,7 @@ class Collection(BaseCollection):
|
||||
text = fd.read()
|
||||
if not etag or etag == get_etag(text):
|
||||
item = Item(self, vobject_item, href)
|
||||
with open(path, "w", encoding=self.storage_encoding) as fd:
|
||||
with self._atomic_write(path) as fd:
|
||||
fd.write(item.serialize())
|
||||
return item
|
||||
else:
|
||||
@ -516,7 +532,7 @@ class Collection(BaseCollection):
|
||||
else:
|
||||
properties.pop(key, None)
|
||||
|
||||
with open(props_path, "w+", encoding=self.storage_encoding) as prop:
|
||||
with self._atomic_write(props_path, "w+") as prop:
|
||||
json.dump(properties, prop)
|
||||
|
||||
@property
|
||||
|
2
setup.py
2
setup.py
@ -62,7 +62,7 @@ setup(
|
||||
packages=["radicale"],
|
||||
provides=["radicale"],
|
||||
scripts=["bin/radicale"],
|
||||
install_requires=["vobject"],
|
||||
install_requires=["vobject", "atomicwrites"],
|
||||
setup_requires=["pytest-runner"],
|
||||
tests_require=["pytest-cov", "pytest-flake8", "pytest-isort", "pytest"],
|
||||
extras_require={
|
||||
|
Loading…
Reference in New Issue
Block a user