Added method for settings of WebDAV resource property values in batch.
Prepared for release 0.5
This commit is contained in:
parent
354cf64d22
commit
743f8b96bb
6 changed files with 99 additions and 21 deletions
|
@ -1,4 +1,4 @@
|
||||||
python setup.py register -r pypitestCOPYRIGHT AND PERMISSION NOTICE
|
COPYRIGHT AND PERMISSION NOTICE
|
||||||
|
|
||||||
Copyright (c) 2016, The WDC Project, and many
|
Copyright (c) 2016, The WDC Project, and many
|
||||||
contributors, see the THANKS file.
|
contributors, see the THANKS file.
|
||||||
|
|
|
@ -7,10 +7,14 @@ But uses `requests` instead of `PyCURL`
|
||||||
|
|
||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
Version 0.5 – 03.12.2017
|
||||||
|
* Added method for setting of WebDAV resource property values in batch
|
||||||
|
|
||||||
Version 0.4 - 27.11.2017
|
Version 0.4 - 27.11.2017
|
||||||
* Refactoring of WebDAV client and making it works in following methods:
|
* Refactoring of WebDAV client and making it works in following methods:
|
||||||
- Checking is remote resource directory
|
- Checking is remote resource directory
|
||||||
- Fixed problem when connection lost during request executing and nothing was happened, now it raises an exception.
|
- Fixed problem when connection lost during request executing and nothing was happened, now it raises an exception
|
||||||
|
|
||||||
Version 0.3 - 18.10.2017
|
Version 0.3 - 18.10.2017
|
||||||
* Refactoring of WebDAV client and making it works in following methods:
|
* Refactoring of WebDAV client and making it works in following methods:
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -6,7 +6,7 @@ from setuptools import setup, find_packages
|
||||||
from setuptools.command.install import install as InstallCommand
|
from setuptools.command.install import install as InstallCommand
|
||||||
from setuptools.command.test import test as TestCommand
|
from setuptools.command.test import test as TestCommand
|
||||||
|
|
||||||
version = "0.4"
|
version = "0.5"
|
||||||
requirements = "libxml2-dev libxslt-dev python-dev"
|
requirements = "libxml2-dev libxslt-dev python-dev"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -160,10 +160,18 @@ class ClientTestCase(TestCase):
|
||||||
self.assertTrue('created' in result)
|
self.assertTrue('created' in result)
|
||||||
self.assertTrue('modified' in result)
|
self.assertTrue('modified' in result)
|
||||||
|
|
||||||
def test_get_property(self):
|
def test_directory_is_dir(self):
|
||||||
|
self._prepare_for_downloading()
|
||||||
|
self.assertTrue(self.client.is_dir(self.remote_path_dir), 'Should return True for directory')
|
||||||
|
|
||||||
|
def test_file_is_not_dir(self):
|
||||||
|
self._prepare_for_downloading()
|
||||||
|
self.assertFalse(self.client.is_dir(self.remote_path_file), 'Should return False for file')
|
||||||
|
|
||||||
|
def test_get_property_of_non_exist(self):
|
||||||
self._prepare_for_downloading()
|
self._prepare_for_downloading()
|
||||||
result = self.client.get_property(remote_path=self.remote_path_file, option={'name': 'aProperty'})
|
result = self.client.get_property(remote_path=self.remote_path_file, option={'name': 'aProperty'})
|
||||||
self.assertEquals(result, None)
|
self.assertEquals(result, None, 'For not found property should return value as None')
|
||||||
|
|
||||||
def test_set_property(self):
|
def test_set_property(self):
|
||||||
self._prepare_for_downloading()
|
self._prepare_for_downloading()
|
||||||
|
@ -174,7 +182,28 @@ class ClientTestCase(TestCase):
|
||||||
})
|
})
|
||||||
result = self.client.get_property(remote_path=self.remote_path_file,
|
result = self.client.get_property(remote_path=self.remote_path_file,
|
||||||
option={'namespace': 'test', 'name': 'aProperty'})
|
option={'namespace': 'test', 'name': 'aProperty'})
|
||||||
self.assertEquals(result, "aValue")
|
self.assertEquals(result, 'aValue', 'Property value should be set')
|
||||||
|
|
||||||
|
def test_set_property_batch(self):
|
||||||
|
self._prepare_for_downloading()
|
||||||
|
self.client.set_property_batch(remote_path=self.remote_path_file, option=[
|
||||||
|
{
|
||||||
|
'namespace': 'test',
|
||||||
|
'name': 'aProperty',
|
||||||
|
'value': 'aValue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'namespace': 'test',
|
||||||
|
'name': 'aProperty2',
|
||||||
|
'value': 'aValue2'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
result = self.client.get_property(remote_path=self.remote_path_file,
|
||||||
|
option={'namespace': 'test', 'name': 'aProperty'})
|
||||||
|
self.assertEquals(result, 'aValue', 'First property value should be set')
|
||||||
|
result = self.client.get_property(remote_path=self.remote_path_file,
|
||||||
|
option={'namespace': 'test', 'name': 'aProperty2'})
|
||||||
|
self.assertEquals(result, 'aValue2', 'Second property value should be set')
|
||||||
|
|
||||||
def _prepare_for_downloading(self):
|
def _prepare_for_downloading(self):
|
||||||
if not self.client.check(remote_path=self.remote_path_dir):
|
if not self.client.check(remote_path=self.remote_path_dir):
|
||||||
|
|
|
@ -72,24 +72,56 @@ class ClientTestCase(TestCase):
|
||||||
result = utils.parse_get_property_response(content=content, name='aProperty')
|
result = utils.parse_get_property_response(content=content, name='aProperty')
|
||||||
self.assertEquals(result, 'aValue')
|
self.assertEquals(result, 'aValue')
|
||||||
|
|
||||||
def test_create_set_property_request_content(self):
|
def test_create_set_one_property_request_content(self):
|
||||||
option = {
|
option = {
|
||||||
'namespace': 'test',
|
'namespace': 'test',
|
||||||
'name': 'aProperty',
|
'name': 'aProperty',
|
||||||
'value': 'aValue'
|
'value': 'aValue'
|
||||||
}
|
}
|
||||||
result = utils.create_set_property_request_content(option=option)
|
result = utils.create_set_property_batch_request_content(options=[option])
|
||||||
self.assertEquals(result, '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<propertyupdate xmlns="DAV:"><set><prop>'
|
self.assertEquals(result, '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<propertyupdate xmlns="DAV:"><set><prop>'
|
||||||
'<aProperty xmlns="test">aValue</aProperty></prop></set></propertyupdate>')
|
'<aProperty xmlns="test">aValue</aProperty></prop></set></propertyupdate>')
|
||||||
|
|
||||||
def test_create_set_property_request_content_name_only(self):
|
def test_create_set_one_property_request_content_name_only(self):
|
||||||
option = {
|
option = {
|
||||||
'name': 'aProperty'
|
'name': 'aProperty'
|
||||||
}
|
}
|
||||||
result = utils.create_set_property_request_content(option=option)
|
result = utils.create_set_property_batch_request_content(options=[option])
|
||||||
self.assertEquals(result, '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<propertyupdate xmlns="DAV:"><set><prop>'
|
self.assertEquals(result, '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<propertyupdate xmlns="DAV:"><set><prop>'
|
||||||
'<aProperty xmlns=""></aProperty></prop></set></propertyupdate>')
|
'<aProperty xmlns=""></aProperty></prop></set></propertyupdate>')
|
||||||
|
|
||||||
|
def test_create_set_property_batch_request_content(self):
|
||||||
|
options = [
|
||||||
|
{
|
||||||
|
'namespace': 'test',
|
||||||
|
'name': 'aProperty',
|
||||||
|
'value': 'aValue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'namespace': 'test2',
|
||||||
|
'name': 'aProperty2',
|
||||||
|
'value': 'aValue2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
result = utils.create_set_property_batch_request_content(options=options)
|
||||||
|
self.assertEquals(result, '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<propertyupdate xmlns="DAV:"><set><prop>'
|
||||||
|
'<aProperty xmlns="test">aValue</aProperty><aProperty2 xmlns="test2">aValue2'
|
||||||
|
'</aProperty2></prop></set></propertyupdate>')
|
||||||
|
|
||||||
|
def test_create_set_property_batch_request_content_name_only(self):
|
||||||
|
options = [
|
||||||
|
{
|
||||||
|
'name': 'aProperty'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'aProperty2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
result = utils.create_set_property_batch_request_content(options=options)
|
||||||
|
self.assertEquals(result, '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<propertyupdate xmlns="DAV:"><set><prop>'
|
||||||
|
'<aProperty xmlns=""></aProperty><aProperty2 xmlns=""></aProperty2></prop></set>'
|
||||||
|
'</propertyupdate>')
|
||||||
|
|
||||||
def test_etree_to_string(self):
|
def test_etree_to_string(self):
|
||||||
tree = ElementTree(Element('test'))
|
tree = ElementTree(Element('test'))
|
||||||
result = utils.etree_to_string(tree)
|
result = utils.etree_to_string(tree)
|
||||||
|
|
|
@ -575,7 +575,6 @@ class Client(object):
|
||||||
path = self.get_full_path(urn)
|
path = self.get_full_path(urn)
|
||||||
return WebDavXmlUtils.parse_info_response(content=response.content, path=path, hostname=self.webdav.hostname)
|
return WebDavXmlUtils.parse_info_response(content=response.content, path=path, hostname=self.webdav.hostname)
|
||||||
|
|
||||||
# TODO refactor code below and write tests for it.
|
|
||||||
@wrap_connection_error
|
@wrap_connection_error
|
||||||
def is_dir(self, remote_path):
|
def is_dir(self, remote_path):
|
||||||
"""Checks is the remote resource directory.
|
"""Checks is the remote resource directory.
|
||||||
|
@ -623,11 +622,24 @@ class Client(object):
|
||||||
`name`: the name of property which will be set,
|
`name`: the name of property which will be set,
|
||||||
`value`: (optional) the value of property which will be set. Defaults is empty string.
|
`value`: (optional) the value of property which will be set. Defaults is empty string.
|
||||||
"""
|
"""
|
||||||
|
self.set_property_batch(remote_path=remote_path, option=[option])
|
||||||
|
|
||||||
|
@wrap_connection_error
|
||||||
|
def set_property_batch(self, remote_path, option):
|
||||||
|
"""Sets batch metadata properties of remote resource on WebDAV server in batch.
|
||||||
|
More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPPATCH
|
||||||
|
|
||||||
|
:param remote_path: the path to remote resource.
|
||||||
|
:param option: the property attributes as list of dictionaries with following keys:
|
||||||
|
`namespace`: (optional) the namespace for XML property which will be set,
|
||||||
|
`name`: the name of property which will be set,
|
||||||
|
`value`: (optional) the value of property which will be set. Defaults is empty string.
|
||||||
|
"""
|
||||||
urn = Urn(remote_path)
|
urn = Urn(remote_path)
|
||||||
if not self.check(urn.path()):
|
if not self.check(urn.path()):
|
||||||
raise RemoteResourceNotFound(urn.path())
|
raise RemoteResourceNotFound(urn.path())
|
||||||
|
|
||||||
data = WebDavXmlUtils.create_set_property_request_content(option)
|
data = WebDavXmlUtils.create_set_property_batch_request_content(option)
|
||||||
self.execute_request(action='set_property', path=urn.quote(), data=data)
|
self.execute_request(action='set_property', path=urn.quote(), data=data)
|
||||||
|
|
||||||
def resource(self, remote_path):
|
def resource(self, remote_path):
|
||||||
|
@ -874,10 +886,10 @@ class WebDavXmlUtils:
|
||||||
:return: True in case the remote resource is directory and False otherwise.
|
:return: True in case the remote resource is directory and False otherwise.
|
||||||
"""
|
"""
|
||||||
response = WebDavXmlUtils.extract_response_for_path(content=content, path=path, hostname=hostname)
|
response = WebDavXmlUtils.extract_response_for_path(content=content, path=path, hostname=hostname)
|
||||||
type = response.find(".//{DAV:}resourcetype")
|
resource_type = response.find(".//{DAV:}resourcetype")
|
||||||
if type is None:
|
if resource_type is None:
|
||||||
raise MethodNotSupported(name="is_dir", server=self.webdav.hostname)
|
raise MethodNotSupported(name="is_dir", server=hostname)
|
||||||
dir_type = type.find("{DAV:}collection")
|
dir_type = resource_type.find("{DAV:}collection")
|
||||||
|
|
||||||
return True if dir_type is not None else False
|
return True if dir_type is not None else False
|
||||||
|
|
||||||
|
@ -908,10 +920,10 @@ class WebDavXmlUtils:
|
||||||
return tree.xpath('//*[local-name() = $name]', name=name)[0].text
|
return tree.xpath('//*[local-name() = $name]', name=name)[0].text
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_set_property_request_content(option):
|
def create_set_property_batch_request_content(options):
|
||||||
"""Creates an XML for requesting of setting a property value for remote WebDAV resource.
|
"""Creates an XML for requesting of setting a property values for remote WebDAV resource in batch.
|
||||||
|
|
||||||
:param option: the property attributes as dictionary with following keys:
|
:param options: the property attributes as list of dictionaries with following keys:
|
||||||
`namespace`: (optional) the namespace for XML property which will be set,
|
`namespace`: (optional) the namespace for XML property which will be set,
|
||||||
`name`: the name of property which will be set,
|
`name`: the name of property which will be set,
|
||||||
`value`: (optional) the value of property which will be set. Defaults is empty string.
|
`value`: (optional) the value of property which will be set. Defaults is empty string.
|
||||||
|
@ -920,6 +932,7 @@ class WebDavXmlUtils:
|
||||||
root_node = etree.Element('propertyupdate', xmlns='DAV:')
|
root_node = etree.Element('propertyupdate', xmlns='DAV:')
|
||||||
set_node = etree.SubElement(root_node, 'set')
|
set_node = etree.SubElement(root_node, 'set')
|
||||||
prop_node = etree.SubElement(set_node, 'prop')
|
prop_node = etree.SubElement(set_node, 'prop')
|
||||||
|
for option in options:
|
||||||
opt_node = etree.SubElement(prop_node, option['name'], xmlns=option.get('namespace', ''))
|
opt_node = etree.SubElement(prop_node, option['name'], xmlns=option.get('namespace', ''))
|
||||||
opt_node.text = option.get('value', '')
|
opt_node.text = option.get('value', '')
|
||||||
tree = etree.ElementTree(root_node)
|
tree = etree.ElementTree(root_node)
|
||||||
|
|
Loading…
Add table
Reference in a new issue