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) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) with open(local_path, "rb") as local_file: self.execute_request(action='upload', path=urn.quote(), data=local_file)
def write_file(self, tag: str, service: ServiceType, dir_name: str, filename: str, buffer: IO): with self.sem: self.ensure_dir(tag, service.value) self.ensure_dir(tag, f"{service.value}/{dir_name}") fp = f"{service.value}/{dir_name}/{filename}" with NamedTemporaryFile() as f: f.write(buffer.read()) f.flush() try: self.client.upload(fp, f.name) except webdav3.exceptions.RemoteParentNotFound as err: print(err) pp = f"{service.value}/{dir_name}" # assert not ServiceKVStore.exists(SERVICE_NAME, pp) # self.client.mkdir(pp) from webdav3.urn import Urn directory_urn = Urn(pp, directory=True) response = self.client.execute_request( action='mkdir', path=directory_urn.quote()) assert response in (200, 201), response ServiceKVStore.put(SERVICE_NAME, pp, {}) self.client.upload(fp, f.name) return fp
def clean(self, remote_path): """Cleans (Deletes) a remote resource on WebDAV server. The name of method is not changed for back compatibility with original library. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_DELETE :param remote_path: the remote resource whisch will be deleted. """ urn = Urn(remote_path) self.execute_request(action='clean', path=urn.quote())
def download_raw(self, remote_path): """Downloads file from WebDAV and writes it in buffer. :param buff: buffer object for writing of downloaded file content. :param remote_path: path to file on WebDAV server. """ urn = Urn(remote_path) response = self.execute_request(action='download', path=urn.quote()) return response.raw.data
def move(self, remote_path_from, remote_path_to, overwrite=False): """Moves resource from one place to another on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MOVE :param remote_path_from: the path to resource which will be moved, :param remote_path_to: the path where resource will be moved. :param overwrite: (optional) the flag, overwrite file if it exists. Defaults is False """ urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) header_destination = "Destination: {path}".format(path=self.get_url(urn_to.quote())) header_overwrite = "Overwrite: {flag}".format(flag="T" if overwrite else "F") self.execute_request(action='move', path=urn_from.quote(), headers_ext=[header_destination, header_overwrite])
def upload_to(self, buff, remote_path): """Uploads file from buffer to remote path on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT :param buff: the buffer with content for file. :param remote_path: the path to save file remotely on WebDAV server. """ urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) self.execute_request(action='upload', path=urn.quote(), data=buff)
def mkdir(self, remote_path): """Makes new directory on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MKCOL :param remote_path: path to directory :return: True if request executed with code 200 or 201 and False otherwise. """ directory_urn = Urn(remote_path, directory=True) response = self.execute_request(action='mkdir', path=directory_urn.quote()) return response.status_code in (200, 201)
def download_from(self, buff, remote_path): """Downloads file from WebDAV and writes it in buffer. :param buff: buffer object for writing of downloaded file content. :param remote_path: path to file on WebDAV server. """ urn = Urn(remote_path) if self.is_dir(urn.path()): raise OptionNotValid(name="remote_path", value=remote_path) response = self.execute_request(action='download', path=urn.quote()) shutil.copyfileobj(response.raw, buff)
def download_file(self, remote_path, local_path): """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) with open(local_path, 'wb') as local_file: response = self.client.execute_request('download', urn.quote()) for block in response.iter_content(1024): local_file.write(block)
def copy(self, remote_path_from, remote_path_to, depth=1): """Copies resource from one place to another on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_COPY :param remote_path_from: the path to resource which will be copied, :param remote_path_to: the path where resource will be copied. :param depth: folder depth to copy """ urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) headers = [ "Destination: {url}".format(url=self.get_url(urn_to.quote())) ] if self.is_dir(urn_from.path()): headers.append("Depth: {depth}".format(depth=depth)) self.execute_request(action='copy', path=urn_from.quote(), headers_ext=headers)
def is_dir(self, remote_path): """Checks is the remote resource directory. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND :param remote_path: the path to remote resource. :return: True in case the remote resource is directory and False otherwise. """ urn = Urn(remote_path) parent_urn = Urn(urn.parent()) response = self.execute_request(action='info', path=parent_urn.quote()) path = self.get_full_path(urn) return WebDavXmlUtils.parse_is_dir_response( content=response.content, path=path, hostname=self.webdav.hostname)
def download_from(self, buff, remote_path): """Downloads file from WebDAV and writes it in buffer. :param buff: buffer object for writing of downloaded file content. :param remote_path: path to file on WebDAV server. """ urn = Urn(remote_path) if self.is_dir(urn.path()): raise OptionNotValid(name="remote_path", value=remote_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) response = self.execute_request(action='download', path=urn.quote()) for chunk in response.iter_content(chunk_size=128): buff.write(chunk)
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 and 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 copy(self, remote_path_from, remote_path_to): """Copies resource from one place to another on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_COPY :param remote_path_from: the path to resource which will be copied, :param remote_path_to: the path where resource will be copied. """ urn_from = Urn(remote_path_from) urn_to = Urn(remote_path_to) header_destination = "Destination: {path}".format( path=self.get_full_path(urn_to)) self.execute_request(action='copy', path=urn_from.quote(), headers_ext=[header_destination])
def upload_file(self, remote_path, local_rb_data, 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. """ urn = Urn(remote_path) if not self.check(urn.parent()): return 0 try: self.execute_request(action='upload', path=urn.quote(), data=local_rb_data) return 1 except: return 0
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 """ urn = Urn(remote_path) try: response = self.execute_request(action='check', path=urn.quote()) except ResponseErrorCode: return False if int(response.status_code) == 200: return True return False
def download_file(self, remote_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 not self.check(urn.path()): return 0 try: response = self.execute_request('download', urn.quote()) return response except: return 0
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) data = WebDavXmlUtils.create_set_property_batch_request_content(option) self.execute_request(action='set_property', path=urn.quote(), data=data)
def get_property(self, remote_path, option): """Gets metadata property of remote resource on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND :param remote_path: the path to remote resource. :param option: the property attribute as dictionary with following keys: `namespace`: (optional) the namespace for XML property which will be set, `name`: the name of property which will be set. :return: the value of property or None if property is not found. """ urn = Urn(remote_path) if not self.check(urn.path()): raise RemoteResourceNotFound(urn.path()) data = WebDavXmlUtils.create_get_property_request_content(option) response = self.execute_request(action='get_property', path=urn.quote(), data=data) return WebDavXmlUtils.parse_get_property_response(response.content, option['name'])
def info(self, remote_path): """Gets information about resource on WebDAV. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND :param remote_path: the path to remote resource. :return: a dictionary of information attributes and them values with following keys: `created`: date of resource creation, `name`: name of resource, `size`: size of resource, `modified`: date of resource modification. """ urn = Urn(remote_path) response = self.execute_request(action='info', path=urn.quote()) path = self.get_full_path(urn) return WebDavXmlUtils.parse_info_response( content=response.content, path=path, hostname=self.webdav.hostname)
def mkdir(self, remote_path): """Makes new directory on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MKCOL :param remote_path: path to directory :return: True if request executed with code 200 or 201 and False otherwise. """ directory_urn = Urn(remote_path, directory=True) if not self.check(directory_urn.parent()): raise RemoteParentNotFound(directory_urn.path()) try: response = self.execute_request(action='mkdir', path=directory_urn.quote()) except MethodNotSupported: # Yandex WebDAV returns 405 status code when directory already exists return True return response.status_code in (200, 201)
def list_data(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) response = self.execute_request(action='list', path=directory_urn.quote()) results = WebDavXmlUtils.parse_get_list_data_response(response.content) path = Urn.normalize_path(self.get_full_path(directory_urn)) return [ result for result in results if Urn.compare_path(path, result['href']) is 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 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 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)