Ejemplo n.º 1
0
    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)

        if not self.check(urn.parent()):
            raise RemoteParentNotFound(urn.path())

        self.execute_request(action='upload', path=urn.quote(), data=buff)
Ejemplo n.º 2
0
    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())
        shutil.copyfileobj(response.raw, buff)
Ejemplo n.º 3
0
    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())
        self._check_remote_resource(remote_path, urn)

        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)
Ejemplo n.º 4
0
    def pull(self, remote_directory, local_directory):
        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.exists(local_directory):
            raise LocalResourceNotFound(local_directory)

        local_resource_names = listdir(local_directory)

        paths = self.list(urn.path())
        expression = "{begin}{end}".format(begin="^", end=remote_directory)
        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_urn = Urn(remote_path)

            if self.is_dir(remote_urn.path()):
                if not os.path.exists(local_path):
                    os.mkdir(local_path)
                self.pull(remote_directory=remote_path,
                          local_directory=local_path)
            else:
                if remote_resource_name in local_resource_names:
                    continue
                self.download_file(remote_path=remote_path,
                                   local_path=local_path)
Ejemplo n.º 5
0
    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)
        self._validate_remote_directory(urn)
        self._validate_local_directory(local_directory)

        local_resource_names = listdir(local_directory)

        paths = self.list(urn.path())
        expression = "{begin}{end}".format(begin="^", end=remote_directory)
        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_urn = Urn(remote_path)

            if remote_urn.path().endswith("/"):
                if not os.path.exists(local_path):
                    updated = True
                    os.mkdir(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 and self.is_local_more_recent(
                        local_path, remote_path):
                    continue

                self.download_file(remote_path=remote_path,
                                   local_path=local_path)
                updated = True
        return updated
Ejemplo n.º 6
0
    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 = self.get_full_path(directory_urn)
        return [
            urn.filename() for urn in urns
            if urn.path() != path and urn.path() != path[:-1]
        ]
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
 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__())
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
 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'))
Ejemplo n.º 14
0
 def test_check(self):
     self._prepare_for_downloading()
     resource = Resource(self.client, Urn(self.remote_path_file))
     self.assertTrue(resource.check())
Ejemplo n.º 15
0
 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))
Ejemplo n.º 16
0
class WebDAVSettings(ConnectionSettings):
    ns = "webdav:"
    prefix = "webdav_"
    keys = {
        'hostname', 'login', 'password', 'token', 'root', 'cert_path',
        'key_path', 'recv_speed', 'send_speed', 'verbose', 'disable_check',
        'override_methods', 'timeout'
    }

    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.timeout = 30

        self.options = dict()

        for key in self.keys:
            value = options.get(key, '')
            if not (self.__dict__[key] and not value):
                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)
        self.hostname = self.hostname.rstrip(Urn.separate)

    def is_valid(self):
        if not self.hostname:
            raise OptionNotValid(name="hostname",
                                 value=self.hostname,
                                 ns=self.ns)

        if self.cert_path and not exists(self.cert_path):
            raise OptionNotValid(name="cert_path",
                                 value=self.cert_path,
                                 ns=self.ns)

        if self.key_path and not exists(self.key_path):
            raise OptionNotValid(name="key_path",
                                 value=self.key_path,
                                 ns=self.ns)

        if self.key_path and not self.cert_path:
            raise OptionNotValid(name="cert_path",
                                 value=self.cert_path,
                                 ns=self.ns)

        if self.password and not self.login:
            raise OptionNotValid(name="login", value=self.login, ns=self.ns)

        if not self.token and not self.login:
            raise OptionNotValid(name="login", value=self.login, ns=self.ns)
        return True
Ejemplo n.º 17
0
 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
Ejemplo n.º 18
0
 def resource(self, remote_path):
     urn = Urn(remote_path)
     return Resource(self, urn)
Ejemplo n.º 19
0
    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)
Ejemplo n.º 20
0
 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)
Ejemplo n.º 21
0
 def test_is_dir(self):
     self._prepare_for_downloading()
     resource = Resource(self.client, Urn(self.remote_path_dir))
     self.assertTrue(resource.is_dir())
Ejemplo n.º 22
0
class Resource(object):
    def __init__(self, client, urn):
        self.client = client
        self.urn = urn

    def __str__(self):
        return "resource {path}".format(path=self.urn.path())

    def is_dir(self):
        return self.client.is_dir(self.urn.path())

    def rename(self, new_name):
        old_path = self.urn.path()
        parent_path = self.urn.parent()
        new_name = Urn(new_name).filename()
        new_path = "{directory}{filename}".format(directory=parent_path,
                                                  filename=new_name)

        self.client.move(remote_path_from=old_path, remote_path_to=new_path)
        self.urn = Urn(new_path)

    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 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 info(self, params=None):
        info = self.client.info(self.urn.path())
        if not params:
            return info

        return {key: value for (key, value) in info.items() if key in params}

    def clean(self):
        return self.client.clean(self.urn.path())

    def check(self):
        return self.client.check(self.urn.path())

    def read_from(self, buff):
        self.client.upload_to(buff=buff, remote_path=self.urn.path())

    def read(self, local_path):
        return self.client.upload_sync(local_path=local_path,
                                       remote_path=self.urn.path())

    def read_async(self, local_path, callback=None):
        return self.client.upload_async(local_path=local_path,
                                        remote_path=self.urn.path(),
                                        callback=callback)

    def write_to(self, buff):
        return self.client.download_from(buff=buff,
                                         remote_path=self.urn.path())

    def write(self, local_path):
        return self.client.download_sync(local_path=local_path,
                                         remote_path=self.urn.path())

    def write_async(self, local_path, callback=None):
        return self.client.download_async(local_path=local_path,
                                          remote_path=self.urn.path(),
                                          callback=callback)

    def publish(self):
        return self.client.publish(self.urn.path())

    def unpublish(self):
        return self.client.unpublish(self.urn.path())

    def get_property(self, option):
        return self.client.get_property(remote_path=self.urn.path(),
                                        option=option)

    def set_property(self, option, value):
        option['value'] = value.__str__()
        self.client.set_property(remote_path=self.urn.path(), option=option)
Ejemplo n.º 23
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'))
Ejemplo n.º 24
0
 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)
Ejemplo n.º 25
0
 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)