def list(self, remote_path=root): """Returns list of nested files and directories for remote WebDAV directory by path. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND :param remote_path: path to remote directory. :return: list of nested file or directory names. """ directory_urn = Urn(remote_path, directory=True) if directory_urn.path() != Client.root: if not self.check(directory_urn.path()): raise RemoteResourceNotFound(directory_urn.path()) response = self.execute_request(action='list', path=directory_urn.quote()) urns = WebDavXmlUtils.parse_get_list_response(response.content) path = Urn.normalize_path(self.get_full_path(directory_urn)) return [ urn.filename() for urn in urns if Urn.compare_path(path, urn.path()) is False ]
def check(self, remote_path=root): """Checks an existence of remote resource on WebDAV server by remote path. More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4 :param remote_path: (optional) path to resource on WebDAV server. Defaults is root directory of WebDAV. :return: True if resource is exist or False otherwise """ if self.webdav.disable_check: return True urn = Urn(remote_path) try: response = self.execute_request(action='check', path=urn.quote()) except RemoteResourceNotFound: return False except ResponseErrorCode: return False if int(response.status_code) == 200: return True return False
def list(self, remote_path=root, get_info=False): """Returns list of nested files and directories for remote WebDAV directory by path. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND :param remote_path: path to remote directory. :param get_info: path and element info to remote directory, like cmd 'ls -l'. :return: if get_info=False it returns list of nested file or directory names, otherwise it returns list of information, the information is a dictionary and it values with following keys: `created`: date of resource creation, `name`: name of resource, `size`: size of resource, `modified`: date of resource modification, `etag`: etag of resource, `content_type`: content type of resource, `isdir`: type of resource, `path`: path of resource. """ directory_urn = Urn(remote_path, directory=True) if directory_urn.path() != Client.root and not self.check( directory_urn.path()): raise RemoteResourceNotFound(directory_urn.path()) path = Urn.normalize_path(self.get_full_path(directory_urn)) response = self.execute_request(action='list', path=directory_urn.quote()) if get_info: subfiles = WebDavXmlUtils.parse_get_list_info_response( response.content) return [ subfile for subfile in subfiles if Urn.compare_path(path, subfile.get('path')) is False ] urns = WebDavXmlUtils.parse_get_list_response(response.content) return [ urn.filename() for urn in urns if Urn.compare_path(path, urn.path()) is False ]
def upload_file(self, remote_path, local_path, progress=None): """Uploads file to remote path on WebDAV server. File should be 2Gb or less. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT :param remote_path: the path to uploading file on WebDAV server. :param local_path: the path to local file for uploading. :param progress: Progress function. Not supported now. """ if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name="local_path", value=local_path) with open(local_path, "rb") as local_file: self.execute_request(action='upload', path=urn.quote(), data=local_file)
def download_file(self, remote_path, local_path, progress=None): """Downloads file from WebDAV server and save it locally. More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4 :param remote_path: the path to remote file for downloading. :param local_path: the path to save file locally. :param progress: progress function. Not supported now. """ urn = Urn(remote_path) if self.is_dir(urn.path()): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name="local_path", value=local_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) with open(local_path, 'wb') as local_file: response = self.execute_request('download', urn.quote()) for block in response.iter_content(1024): local_file.write(block)
def download_directory(self, remote_path, local_path, progress=None): """Downloads directory and downloads all nested files and directories from remote WebDAV to local. If there is something on local path it deletes directories and files then creates new. :param remote_path: the path to directory for downloading form WebDAV server. :param local_path: the path to local directory for saving downloaded files and directories. :param progress: Progress function. Not supported now. """ urn = Urn(remote_path, directory=True) if not self.is_dir(urn.path()): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.exists(local_path): shutil.rmtree(local_path) os.makedirs(local_path) for resource_name in self.list(urn.path()): if urn.path().endswith(resource_name): continue _remote_path = "{parent}{name}".format(parent=urn.path(), name=resource_name) _local_path = os.path.join(local_path, resource_name) self.download(local_path=_local_path, remote_path=_remote_path, progress=progress)
def __init__(self, options): self.hostname = None self.login = None self.password = None self.token = None self.root = None self.cert_path = None self.key_path = None self.recv_speed = None self.send_speed = None self.verbose = None self.disable_check = False self.override_methods = {} self.options = dict() for key in self.keys: value = options.get(key, '') self.options[key] = value self.__dict__[key] = value self.root = Urn(self.root).quote() if self.root else '' self.root = self.root.rstrip(Urn.separate)
def list(self, remote_path="/"): def parse(directory_urn, response): try: response_str = response.content tree = etree.fromstring(response_str) hrees = [unquote(hree.text) for hree in tree.findall(".//{DAV:}href")] etags = [unquote(etag.text) for etag in tree.findall(".//{DAV:}getetag")] i=0 ret = [] for hree in hrees: if(i == 0): i = i+1 continue urn = MyUrn(hree, etags[i], remote_path) ret.append(urn) i = i+1 return ret except etree.XMLSyntaxError: return list() try: directory_urn = Urn(remote_path, directory=True) if directory_urn.path() != wc.Client.root: if not self.client.check(directory_urn.path()): raise RemoteResourceNotFound(directory_urn.path()) response = BytesIO() response = self.client.execute_request(action='list', path=directory_urn.quote()) urns = parse(directory_urn, response) return urns except Exception: raise NotConnection(self.client.webdav.hostname)
def test_check(self): self._prepare_for_downloading() resource = Resource(self.client, Urn(self.remote_path_file)) self.assertTrue(resource.check())
def copy(self, remote_path): urn = Urn(remote_path) self.client.copy(remote_path_from=self.urn.path(), remote_path_to=remote_path) return Resource(self.client, urn)
def move(self, remote_path): new_urn = Urn(remote_path) self.client.move(remote_path_from=self.urn.path(), remote_path_to=new_urn.path()) self.urn = new_urn
def resource(self, remote_path): urn = Urn(remote_path) return Resource(self, urn)
def _check_remote_resource(self, remote_path, urn): if not self.check(urn.path()) and not self.check( Urn(remote_path, directory=True).path()): raise RemoteResourceNotFound(remote_path)
def push_force(self, remote_directory, local_directory): """ Validate remote folder with local via put method, check bit-bit and replace remote if mismatch :param remote_directory: :param local_directory: :return: """ def prune(src, exp): return [sub(exp, "", item) for item in src] 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) paths = self.list(urn.path()) paths_local = os.listdir(local_directory) expression = "{begin}{end}".format(begin="^", end=urn.path()) remote_resource_names = prune(paths, expression) local_resources = prune(paths_local, expression) ##clean shit for each in remote_resource_names: remote_path = "{remote_directory}{resource_name}".format( remote_directory=urn.path(), resource_name=each) if each not in local_resources: print("removing " + remote_path) self.execute_request("clean", remote_path) continue 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) if os.path.isdir(local_path): if not self.check(remote_path=remote_path): self.mkdir(remote_path=remote_path) self.push_force(remote_directory=remote_path, local_directory=local_path) else: if local_resource_name in remote_resource_names: response = self.execute_request("check", remote_path) if os.path.isdir(local_path): continue local_hash = self.getHash(file=local_path) if (response.headers["ETag"] == local_hash): continue print("diff for " + local_resource_name) self.upload_file(remote_path=remote_path, local_path=local_path) print("uploading " + local_path) self.upload_file(remote_path=remote_path, local_path=local_path)
def test_str(self): self._prepare_for_downloading() resource = Resource(self.client, Urn(self.remote_path_file)) self.assertEqual('resource /test_dir/test.txt', resource.__str__())
def test_read_and_write(self): self._prepare_for_uploading() resource = Resource(self.client, Urn(self.remote_path_file)) resource.read(self.local_file_path) resource.write(self.local_path_dir + sep + 'test2.txt') self.assertTrue(path.exists(self.local_path_dir + sep + 'test2.txt'))
def test_is_dir(self): self._prepare_for_downloading() resource = Resource(self.client, Urn(self.remote_path_dir)) self.assertTrue(resource.is_dir())
def test_clean(self): self._prepare_for_downloading() resource = Resource(self.client, Urn(self.remote_path_file)) resource.clean() self.assertFalse(self.client.check(self.remote_path_file))
def test_info(self): self._prepare_for_downloading() resource = Resource(self.client, Urn(self.remote_path_file)) info = resource.info() self.assertIsNotNone(info) self.assertGreater(len(info), 0)
def test_rename(self): self._prepare_for_downloading() resource = Resource(self.client, Urn(self.remote_path_file)) resource.rename('new_name.text') self.assertTrue(self.client.check(self.remote_path_dir + '/new_name.text'))