Added method for settings of WebDAV resource property values in batch.

Prepared for release 0.5
This commit is contained in:
evgeny.ezhov 2017-12-03 09:42:43 +03:00
parent 354cf64d22
commit 743f8b96bb
6 changed files with 99 additions and 21 deletions

View file

@ -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.

View 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:

View file

@ -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"

View file

@ -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):

View file

@ -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)

View file

@ -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)