Fix issues and tests

This commit is contained in:
Evgeny Ezhov 2020-01-26 21:24:26 -08:00
parent 85b10d53c9
commit 8c7ee2e372
3 changed files with 111 additions and 56 deletions

View file

@ -35,29 +35,39 @@ class BaseClientTestCase(unittest.TestCase):
def setUp(self):
self.client = Client(self.options)
if path.exists(path=self.local_path_dir):
shutil.rmtree(path=self.local_path_dir)
self.clean_local_dir(self.local_path_dir)
def tearDown(self):
if path.exists(path=self.local_path_dir):
shutil.rmtree(path=self.local_path_dir)
if self.client.check(remote_path=self.remote_path_dir):
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)
self.clean_local_dir(self.local_path_dir)
self.clean_remote_dir(self.remote_path_dir)
self.clean_remote_dir(self.remote_path_dir2)
def _prepare_for_downloading(self, inner_dir=False):
if not self.client.check(remote_path=self.remote_path_dir):
self.client.mkdir(remote_path=self.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)
def clean_remote_dir(self, remote_path_dir):
if self.client.check(remote_path=remote_path_dir):
self.client.clean(remote_path=remote_path_dir)
@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):
os.makedirs(self.local_path_dir)
if inner_dir:
if not self.client.check(remote_path=self.remote_inner_path_dir):
self.client.mkdir(remote_path=self.remote_inner_path_dir)
if not self.client.check(remote_path=self.remote_inner_path_file):
self.client.upload_file(remote_path=self.remote_inner_path_file, local_path=self.local_file_path)
self._prepare_dir_for_downloading(base_path + self.remote_inner_path_dir, base_path + self.remote_inner_path_file, self.local_file_path)
def _prepare_dir_for_downloading(self, remote_path_dir, remote_path_file, 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):
if not self.client.check(remote_path=self.remote_path_dir):

View file

@ -1,4 +1,5 @@
import os.path
import shutil
import unittest
from io import BytesIO, StringIO
from os import path
@ -9,6 +10,7 @@ from webdav3.exceptions import MethodNotSupported, OptionNotValid, RemoteResourc
class ClientTestCase(BaseClientTestCase):
pulled_file = BaseClientTestCase.local_path_dir + os.sep + BaseClientTestCase.local_file
def test_list(self):
self._prepare_for_downloading()
@ -227,6 +229,55 @@ class ClientTestCase(BaseClientTestCase):
def test_check_is_overridden(self):
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__':
unittest.main()

View file

@ -671,51 +671,39 @@ class Client(object):
def prune(src, exp):
return [sub(exp, "", item) for item in src]
updated = False
urn = Urn(remote_directory, directory=True)
if not self.is_dir(urn.path()):
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)
self._validate_remote_directory(urn)
self._validate_local_directory(local_directory)
paths = self.list(urn.path())
expression = "{begin}{end}".format(begin="^", end=urn.path())
remote_resource_names = prune(paths, expression)
for local_resource_name in listdir(local_directory):
local_path = os.path.join(local_directory, local_resource_name)
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(),
resource_name=local_resource_name)
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(), resource_name=local_resource_name)
if os.path.isdir(local_path):
if not self.check(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:
if local_resource_name in remote_resource_names:
if self.is_local_more_recent(local_path, remote_path):
if local_resource_name in remote_resource_names and not self.is_local_more_recent(local_path, remote_path):
continue
self.upload_file(remote_path=remote_path, local_path=local_path)
updated = True
return updated
def pull(self, remote_directory, local_directory):
def prune(src, exp):
return [sub(exp, "", item) for item in src]
updated = False
urn = Urn(remote_directory, directory=True)
if not self.is_dir(urn.path()):
raise OptionNotValid(name="remote_path", value=remote_directory)
if not os.path.exists(local_directory):
raise LocalResourceNotFound(local_directory)
self._validate_remote_directory(urn)
self._validate_local_directory(local_directory)
local_resource_names = listdir(local_directory)
@ -724,22 +712,18 @@ class Client(object):
remote_resource_names = prune(paths, expression)
for remote_resource_name in remote_resource_names:
local_path = os.path.join(local_directory, remote_resource_name)
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(),
resource_name=remote_resource_name)
remote_path = "{remote_directory}{resource_name}".format(remote_directory=urn.path(), resource_name=remote_resource_name)
remote_urn = Urn(remote_path)
if remote_urn.path().endswith("/"):
if not os.path.exists(local_path):
updated = True
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:
if remote_resource_name in local_resource_names:
# 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):
if remote_resource_name in local_resource_names and self.is_local_more_recent(local_path, remote_path):
continue
self.download_file(remote_path=remote_path, local_path=local_path)
@ -757,15 +741,13 @@ class Client(object):
"""
try:
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 = dateutil_parser.parse(remote_last_mod_date)
remote_last_mod_date_unix_ts = int(remote_last_mod_date.strftime("%s"))
local_last_mod_date_unix_ts = os.stat(local_path).st_mtime
remote_last_mod_date_unix_ts = int(remote_last_mod_date.timestamp())
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)
except:
return remote_last_mod_date_unix_ts < local_last_mod_date_unix_ts
except ValueError or RuntimeWarning or KeyError:
# If there is problem when parsing dates, or cannot get
# last modified information, return None
return None
@ -774,6 +756,18 @@ class Client(object):
self.pull(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):
def __init__(self, client, urn):