Fix issues and tests
This commit is contained in:
parent
85b10d53c9
commit
8c7ee2e372
3 changed files with 111 additions and 56 deletions
|
@ -35,29 +35,39 @@ class BaseClientTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client = Client(self.options)
|
self.client = Client(self.options)
|
||||||
if path.exists(path=self.local_path_dir):
|
self.clean_local_dir(self.local_path_dir)
|
||||||
shutil.rmtree(path=self.local_path_dir)
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if path.exists(path=self.local_path_dir):
|
self.clean_local_dir(self.local_path_dir)
|
||||||
shutil.rmtree(path=self.local_path_dir)
|
self.clean_remote_dir(self.remote_path_dir)
|
||||||
if self.client.check(remote_path=self.remote_path_dir):
|
self.clean_remote_dir(self.remote_path_dir2)
|
||||||
self.client.clean(remote_path=self.remote_path_dir)
|
|
||||||
if self.client.check(remote_path=self.remote_path_dir2):
|
|
||||||
self.client.clean(remote_path=self.remote_path_dir2)
|
|
||||||
|
|
||||||
def _prepare_for_downloading(self, inner_dir=False):
|
def clean_remote_dir(self, remote_path_dir):
|
||||||
if not self.client.check(remote_path=self.remote_path_dir):
|
if self.client.check(remote_path=remote_path_dir):
|
||||||
self.client.mkdir(remote_path=self.remote_path_dir)
|
self.client.clean(remote_path=remote_path_dir)
|
||||||
if not self.client.check(remote_path=self.remote_path_file):
|
|
||||||
self.client.upload_file(remote_path=self.remote_path_file, local_path=self.local_file_path)
|
@staticmethod
|
||||||
|
def clean_local_dir(local_path_dir):
|
||||||
|
if path.exists(path=local_path_dir):
|
||||||
|
shutil.rmtree(path=local_path_dir)
|
||||||
|
|
||||||
|
def _prepare_for_downloading(self, inner_dir=False, base_path=''):
|
||||||
|
if base_path:
|
||||||
|
self._create_remote_dir_if_needed(base_path)
|
||||||
|
self._prepare_dir_for_downloading(base_path + self.remote_path_dir, base_path + self.remote_path_file, self.local_file_path)
|
||||||
if not path.exists(self.local_path_dir):
|
if not path.exists(self.local_path_dir):
|
||||||
os.makedirs(self.local_path_dir)
|
os.makedirs(self.local_path_dir)
|
||||||
if inner_dir:
|
if inner_dir:
|
||||||
if not self.client.check(remote_path=self.remote_inner_path_dir):
|
self._prepare_dir_for_downloading(base_path + self.remote_inner_path_dir, base_path + self.remote_inner_path_file, self.local_file_path)
|
||||||
self.client.mkdir(remote_path=self.remote_inner_path_dir)
|
|
||||||
if not self.client.check(remote_path=self.remote_inner_path_file):
|
def _prepare_dir_for_downloading(self, remote_path_dir, remote_path_file, local_file_path):
|
||||||
self.client.upload_file(remote_path=self.remote_inner_path_file, local_path=self.local_file_path)
|
self._create_remote_dir_if_needed(remote_path_dir)
|
||||||
|
if not self.client.check(remote_path=remote_path_file):
|
||||||
|
self.client.upload_file(remote_path=remote_path_file, local_path=local_file_path)
|
||||||
|
|
||||||
|
def _create_remote_dir_if_needed(self, remote_dir):
|
||||||
|
if not self.client.check(remote_path=remote_dir):
|
||||||
|
self.client.mkdir(remote_path=remote_dir)
|
||||||
|
|
||||||
def _prepare_for_uploading(self):
|
def _prepare_for_uploading(self):
|
||||||
if not self.client.check(remote_path=self.remote_path_dir):
|
if not self.client.check(remote_path=self.remote_path_dir):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import os.path
|
import os.path
|
||||||
|
import shutil
|
||||||
import unittest
|
import unittest
|
||||||
from io import BytesIO, StringIO
|
from io import BytesIO, StringIO
|
||||||
from os import path
|
from os import path
|
||||||
|
@ -9,6 +10,7 @@ from webdav3.exceptions import MethodNotSupported, OptionNotValid, RemoteResourc
|
||||||
|
|
||||||
|
|
||||||
class ClientTestCase(BaseClientTestCase):
|
class ClientTestCase(BaseClientTestCase):
|
||||||
|
pulled_file = BaseClientTestCase.local_path_dir + os.sep + BaseClientTestCase.local_file
|
||||||
|
|
||||||
def test_list(self):
|
def test_list(self):
|
||||||
self._prepare_for_downloading()
|
self._prepare_for_downloading()
|
||||||
|
@ -227,6 +229,55 @@ class ClientTestCase(BaseClientTestCase):
|
||||||
def test_check_is_overridden(self):
|
def test_check_is_overridden(self):
|
||||||
self.assertEqual('GET', self.client.requests['check'])
|
self.assertEqual('GET', self.client.requests['check'])
|
||||||
|
|
||||||
|
def test_pull_newer(self):
|
||||||
|
init_modification_time = int(self._prepare_local_test_file_and_get_modification_time())
|
||||||
|
sleep(1)
|
||||||
|
self._prepare_for_downloading(base_path='time/')
|
||||||
|
result = self.client.pull('time/' + self.remote_path_dir, self.local_path_dir)
|
||||||
|
update_modification_time = int(os.path.getmtime(self.pulled_file))
|
||||||
|
self.assertTrue(result)
|
||||||
|
self.assertGreater(update_modification_time, init_modification_time)
|
||||||
|
self.client.clean(remote_path='time/' + self.remote_path_dir)
|
||||||
|
|
||||||
|
def test_pull_older(self):
|
||||||
|
self._prepare_for_downloading(base_path='time/')
|
||||||
|
sleep(1)
|
||||||
|
init_modification_time = int(self._prepare_local_test_file_and_get_modification_time())
|
||||||
|
result = self.client.pull('time/' + self.remote_path_dir, self.local_path_dir)
|
||||||
|
update_modification_time = int(os.path.getmtime(self.pulled_file))
|
||||||
|
self.assertFalse(result)
|
||||||
|
self.assertEqual(update_modification_time, init_modification_time)
|
||||||
|
self.client.clean(remote_path='time/' + self.remote_path_dir)
|
||||||
|
|
||||||
|
def test_push_newer(self):
|
||||||
|
self._prepare_for_downloading(base_path='time/')
|
||||||
|
sleep(1)
|
||||||
|
self._prepare_for_uploading()
|
||||||
|
init_modification_time = self.client.info('time/' + self.remote_path_file)['modified']
|
||||||
|
result = self.client.push('time/' + self.remote_path_dir, self.local_path_dir)
|
||||||
|
update_modification_time = self.client.info('time/' + self.remote_path_file)['modified']
|
||||||
|
self.assertTrue(result)
|
||||||
|
self.assertNotEqual(init_modification_time, update_modification_time)
|
||||||
|
self.client.clean(remote_path='time/' + self.remote_path_dir)
|
||||||
|
|
||||||
|
def test_push_older(self):
|
||||||
|
self._prepare_for_uploading()
|
||||||
|
sleep(1)
|
||||||
|
self._prepare_for_downloading(base_path='time/')
|
||||||
|
init_modification_time = self.client.info('time/' + self.remote_path_file)['modified']
|
||||||
|
result = self.client.push('time/' + self.remote_path_dir, self.local_path_dir)
|
||||||
|
update_modification_time = self.client.info('time/' + self.remote_path_file)['modified']
|
||||||
|
self.assertFalse(result)
|
||||||
|
self.assertEqual(init_modification_time, update_modification_time)
|
||||||
|
self.client.clean(remote_path='time/' + self.remote_path_dir)
|
||||||
|
|
||||||
|
def _prepare_local_test_file_and_get_modification_time(self):
|
||||||
|
if not path.exists(path=self.local_path_dir):
|
||||||
|
os.mkdir(self.local_path_dir)
|
||||||
|
if not path.exists(path=self.local_path_dir + os.sep + self.local_file):
|
||||||
|
shutil.copy(src=self.local_file_path, dst=self.pulled_file)
|
||||||
|
return os.path.getmtime(self.pulled_file)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -671,51 +671,39 @@ class Client(object):
|
||||||
def prune(src, exp):
|
def prune(src, exp):
|
||||||
return [sub(exp, "", item) for item in src]
|
return [sub(exp, "", item) for item in src]
|
||||||
|
|
||||||
|
updated = False
|
||||||
urn = Urn(remote_directory, directory=True)
|
urn = Urn(remote_directory, directory=True)
|
||||||
|
self._validate_remote_directory(urn)
|
||||||
if not self.is_dir(urn.path()):
|
self._validate_local_directory(local_directory)
|
||||||
raise OptionNotValid(name="remote_path", value=remote_directory)
|
|
||||||
|
|
||||||
if not os.path.isdir(local_directory):
|
|
||||||
raise OptionNotValid(name="local_path", value=local_directory)
|
|
||||||
|
|
||||||
if not os.path.exists(local_directory):
|
|
||||||
raise LocalResourceNotFound(local_directory)
|
|
||||||
|
|
||||||
paths = self.list(urn.path())
|
paths = self.list(urn.path())
|
||||||
expression = "{begin}{end}".format(begin="^", end=urn.path())
|
expression = "{begin}{end}".format(begin="^", end=urn.path())
|
||||||
remote_resource_names = prune(paths, expression)
|
remote_resource_names = prune(paths, expression)
|
||||||
|
|
||||||
for local_resource_name in listdir(local_directory):
|
for local_resource_name in listdir(local_directory):
|
||||||
|
|
||||||
local_path = os.path.join(local_directory, local_resource_name)
|
local_path = os.path.join(local_directory, local_resource_name)
|
||||||
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(),
|
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(), resource_name=local_resource_name)
|
||||||
resource_name=local_resource_name)
|
|
||||||
|
|
||||||
if os.path.isdir(local_path):
|
if os.path.isdir(local_path):
|
||||||
if not self.check(remote_path=remote_path):
|
if not self.check(remote_path=remote_path):
|
||||||
self.mkdir(remote_path=remote_path)
|
self.mkdir(remote_path=remote_path)
|
||||||
self.push(remote_directory=remote_path, local_directory=local_path)
|
result = self.push(remote_directory=remote_path, local_directory=local_path)
|
||||||
|
updated = updated or result
|
||||||
else:
|
else:
|
||||||
if local_resource_name in remote_resource_names:
|
if local_resource_name in remote_resource_names and not self.is_local_more_recent(local_path, remote_path):
|
||||||
if self.is_local_more_recent(local_path, remote_path):
|
|
||||||
continue
|
continue
|
||||||
self.upload_file(remote_path=remote_path, local_path=local_path)
|
self.upload_file(remote_path=remote_path, local_path=local_path)
|
||||||
|
updated = True
|
||||||
|
return updated
|
||||||
|
|
||||||
def pull(self, remote_directory, local_directory):
|
def pull(self, remote_directory, local_directory):
|
||||||
def prune(src, exp):
|
def prune(src, exp):
|
||||||
return [sub(exp, "", item) for item in src]
|
return [sub(exp, "", item) for item in src]
|
||||||
|
|
||||||
updated = False
|
updated = False
|
||||||
|
|
||||||
urn = Urn(remote_directory, directory=True)
|
urn = Urn(remote_directory, directory=True)
|
||||||
|
self._validate_remote_directory(urn)
|
||||||
if not self.is_dir(urn.path()):
|
self._validate_local_directory(local_directory)
|
||||||
raise OptionNotValid(name="remote_path", value=remote_directory)
|
|
||||||
|
|
||||||
if not os.path.exists(local_directory):
|
|
||||||
raise LocalResourceNotFound(local_directory)
|
|
||||||
|
|
||||||
local_resource_names = listdir(local_directory)
|
local_resource_names = listdir(local_directory)
|
||||||
|
|
||||||
|
@ -724,22 +712,18 @@ class Client(object):
|
||||||
remote_resource_names = prune(paths, expression)
|
remote_resource_names = prune(paths, expression)
|
||||||
|
|
||||||
for remote_resource_name in remote_resource_names:
|
for remote_resource_name in remote_resource_names:
|
||||||
|
|
||||||
local_path = os.path.join(local_directory, remote_resource_name)
|
local_path = os.path.join(local_directory, remote_resource_name)
|
||||||
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(),
|
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(), resource_name=remote_resource_name)
|
||||||
resource_name=remote_resource_name)
|
|
||||||
|
|
||||||
remote_urn = Urn(remote_path)
|
remote_urn = Urn(remote_path)
|
||||||
|
|
||||||
if remote_urn.path().endswith("/"):
|
if remote_urn.path().endswith("/"):
|
||||||
if not os.path.exists(local_path):
|
if not os.path.exists(local_path):
|
||||||
updated = True
|
updated = True
|
||||||
os.mkdir(local_path)
|
os.mkdir(local_path)
|
||||||
self.pull(remote_directory=remote_path, local_directory=local_path)
|
result = self.pull(remote_directory=remote_path, local_directory=local_path)
|
||||||
|
updated = updated or result
|
||||||
else:
|
else:
|
||||||
if remote_resource_name in local_resource_names:
|
if remote_resource_name in local_resource_names and self.is_local_more_recent(local_path, remote_path):
|
||||||
# Skip pull if local resource is more recent of we can't tell
|
|
||||||
if self.is_local_more_recent(local_path, remote_path) in (True, None):
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.download_file(remote_path=remote_path, local_path=local_path)
|
self.download_file(remote_path=remote_path, local_path=local_path)
|
||||||
|
@ -757,15 +741,13 @@ class Client(object):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
remote_info = self.info(remote_path)
|
remote_info = self.info(remote_path)
|
||||||
# Try to compare modification dates if our server
|
|
||||||
# offers that information
|
|
||||||
remote_last_mod_date = remote_info['modified']
|
remote_last_mod_date = remote_info['modified']
|
||||||
remote_last_mod_date = dateutil_parser.parse(remote_last_mod_date)
|
remote_last_mod_date = dateutil_parser.parse(remote_last_mod_date)
|
||||||
remote_last_mod_date_unix_ts = int(remote_last_mod_date.strftime("%s"))
|
remote_last_mod_date_unix_ts = int(remote_last_mod_date.timestamp())
|
||||||
local_last_mod_date_unix_ts = os.stat(local_path).st_mtime
|
local_last_mod_date_unix_ts = int(os.stat(local_path).st_mtime)
|
||||||
|
|
||||||
return (local_last_mod_date_unix_ts > remote_last_mod_date_unix_ts)
|
return remote_last_mod_date_unix_ts < local_last_mod_date_unix_ts
|
||||||
except:
|
except ValueError or RuntimeWarning or KeyError:
|
||||||
# If there is problem when parsing dates, or cannot get
|
# If there is problem when parsing dates, or cannot get
|
||||||
# last modified information, return None
|
# last modified information, return None
|
||||||
return None
|
return None
|
||||||
|
@ -774,6 +756,18 @@ class Client(object):
|
||||||
self.pull(remote_directory=remote_directory, local_directory=local_directory)
|
self.pull(remote_directory=remote_directory, local_directory=local_directory)
|
||||||
self.push(remote_directory=remote_directory, local_directory=local_directory)
|
self.push(remote_directory=remote_directory, local_directory=local_directory)
|
||||||
|
|
||||||
|
def _validate_remote_directory(self, urn):
|
||||||
|
if not self.is_dir(urn.path()):
|
||||||
|
raise OptionNotValid(name="remote_path", value=urn.path())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_local_directory(local_directory):
|
||||||
|
if not os.path.isdir(local_directory):
|
||||||
|
raise OptionNotValid(name="local_path", value=local_directory)
|
||||||
|
|
||||||
|
if not os.path.exists(local_directory):
|
||||||
|
raise LocalResourceNotFound(local_directory)
|
||||||
|
|
||||||
|
|
||||||
class Resource(object):
|
class Resource(object):
|
||||||
def __init__(self, client, urn):
|
def __init__(self, client, urn):
|
||||||
|
|
Loading…
Add table
Reference in a new issue