Atomic PROPPATCH

This commit is contained in:
Unrud 2016-08-03 14:45:52 +02:00
parent de510148a0
commit bd7641699e
3 changed files with 21 additions and 24 deletions

View File

@ -484,8 +484,7 @@ class Application:
# timezone = props.get("C:calendar-timezone") # timezone = props.get("C:calendar-timezone")
collection = self.Collection.create_collection( collection = self.Collection.create_collection(
environ["PATH_INFO"], tag="VCALENDAR") environ["PATH_INFO"], tag="VCALENDAR")
for key, value in props.items(): collection.set_meta(props)
collection.set_meta(key, value)
return client.CREATED, {}, None return client.CREATED, {}, None
def do_MKCOL(self, environ, read_collections, write_collections, content, def do_MKCOL(self, environ, read_collections, write_collections, content,
@ -498,8 +497,7 @@ class Application:
props = xmlutils.props_from_request(content) props = xmlutils.props_from_request(content)
collection = self.Collection.create_collection(environ["PATH_INFO"]) collection = self.Collection.create_collection(environ["PATH_INFO"])
for key, value in props.items(): collection.set_meta(props)
collection.set_meta(key, value)
return client.CREATED, {}, None return client.CREATED, {}, None
def do_MOVE(self, environ, read_collections, write_collections, content, def do_MOVE(self, environ, read_collections, write_collections, content,
@ -582,7 +580,7 @@ class Application:
tags = {value: key for key, value in storage.MIMETYPES.items()} tags = {value: key for key, value in storage.MIMETYPES.items()}
tag = tags.get(content_type.split(";")[0]) tag = tags.get(content_type.split(";")[0])
if tag: if tag:
collection.set_meta("tag", tag) collection.set_meta({"tag": tag})
headers = {} headers = {}
item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection) item_name = xmlutils.name_from_path(environ["PATH_INFO"], collection)
item = collection.get(item_name) item = collection.get(item_name)

View File

@ -298,8 +298,8 @@ class BaseCollection:
"""Get metadata value for collection.""" """Get metadata value for collection."""
raise NotImplementedError raise NotImplementedError
def set_meta(self, key, value): def set_meta(self, props):
"""Set metadata value for collection.""" """Set metadata values for collection."""
raise NotImplementedError raise NotImplementedError
@property @property
@ -419,7 +419,7 @@ class Collection(BaseCollection):
tag = collection[0].name tag = collection[0].name
if tag == "VCALENDAR": if tag == "VCALENDAR":
self.set_meta("tag", "VCALENDAR") self.set_meta({"tag": "VCALENDAR"})
if collection: if collection:
collection, = collection collection, = collection
items = [] items = []
@ -440,7 +440,7 @@ class Collection(BaseCollection):
self._find_available_file_name(), new_collection) self._find_available_file_name(), new_collection)
elif tag == "VCARD": elif tag == "VCARD":
self.set_meta("tag", "VADDRESSBOOK") self.set_meta({"tag": "VADDRESSBOOK"})
if collection: if collection:
for card in collection: for card in collection:
self.upload(self._find_available_file_name(), card) self.upload(self._find_available_file_name(), card)
@ -542,19 +542,16 @@ class Collection(BaseCollection):
with open(self._props_path, encoding=self.storage_encoding) as prop: with open(self._props_path, encoding=self.storage_encoding) as prop:
return json.load(prop).get(key) return json.load(prop).get(key)
def set_meta(self, key, value): def set_meta(self, props):
properties = {}
if os.path.exists(self._props_path): if os.path.exists(self._props_path):
with open(self._props_path, encoding=self.storage_encoding) as prop: with open(self._props_path, encoding=self.storage_encoding) as prop:
properties.update(json.load(prop)) old_props = json.load(prop)
old_props.update(props)
if value: props = old_props
properties[key] = value # filter empty entries
else: props = {k:v for k,v in props.items() if v}
properties.pop(key, None)
with self._atomic_write(self._props_path, "w+") as prop: with self._atomic_write(self._props_path, "w+") as prop:
json.dump(properties, prop) json.dump(props, prop)
@property @property
def last_modified(self): def last_modified(self):

View File

@ -757,12 +757,14 @@ def proppatch(path, xml_request, collection):
href.text = _href(collection, path) href.text = _href(collection, path)
response.append(href) response.append(href)
for short_name, value in props_to_set.items(): # Merge props_to_set and props_to_remove
collection.set_meta(short_name, value)
_add_propstat_to(response, short_name, 200)
for short_name in props_to_remove: for short_name in props_to_remove:
collection.set_meta(short_name, "") props_to_set[short_name] = ""
# Set/Delete props in one atomic operation
collection.set_meta(props_to_set)
for short_name in props_to_set:
_add_propstat_to(response, short_name, 200) _add_propstat_to(response, short_name, 200)
return _pretty_xml(multistatus) return _pretty_xml(multistatus)