Atomic PROPPATCH
This commit is contained in:
parent
de510148a0
commit
bd7641699e
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user