Example #1
0
    async def upload_directory(
        self,
        remote_path: Union[str, "os.PathLike[str]"],
        local_path: Union[str, "os.PathLike[str]"],
        progress: Optional[Callable[[int, int, Tuple], None]] = None,
        progress_args: Optional[Tuple] = ()
    ) -> None:
        """
        Uploads directory to remote path on WebDAV server. In case directory is exist 
        on remote server it will delete it and then upload directory with nested files 
        and directories.
        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT

        WARNING: DESTRUCTIVE METHOD

        Parameters:    
            remote_path (``str``):
                The path to directory for uploading on WebDAV server.

            local_path (``str``):
                The path to local directory for uploading.

            progress (``callable``, *optional*):
                Pass a callback function to view the file transmission progress.
                The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
                detailed description) and will be called back each time a new file chunk has been successfully
                transmitted.

            progress_args (``tuple``, *optional*):
                Extra custom arguments for the progress callback function.
                You can pass anything you need to be available in the progress callback scope.

        Other Parameters:
            current (``int``):
                The amount of bytes transmitted so far.

            total (``int``):
                The total size of the file.

            *args (``tuple``, *optional*):
                Extra custom arguments as defined in the ``progress_args`` parameter.
                You can either keep ``*args`` or add every single extra argument in your function signature.
        """

        urn = Urn(remote_path, directory=True)
        if not urn.is_dir():
            raise OptionNotValid(name="remote_path", value=remote_path)

        if not os.path.isdir(local_path):
            raise OptionNotValid(name="local_path", value=local_path)

        if not os.path.exists(local_path):
            raise LocalResourceNotFound(local_path)

        if (await self.exists(urn.path())):
            await self.unlink(urn.path())

        await self.create_directory(remote_path)

        for resource_name in os.listdir(local_path):
            _remote_path = f"{urn.path()}{resource_name}".replace('\\', '')
            _local_path = os.path.join(local_path, resource_name)
            await self.upload(local_path=_local_path,
                              remote_path=_remote_path,
                              progress=progress,
                              progress_args=progress_args)
Example #2
0
    async def upload_to(
        self,
        path: Union[str, "os.PathLike[str]"],
        buffer: Union[IO, AsyncGenerator[bytes, None]],
        buffer_size: Optional[int] = None,
        progress: Optional[Callable[[int, int, Tuple], None]] = None,
        progress_args: Optional[Tuple] = ()
    ) -> None:
        """
        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

        Parameters:    
            path (``str``):
                The path to remote resource

            buffer (``IO``)
                IO like object to read the data or a asynchronous generator to get buffer data.
                In order do you select use a async generator `progress` callback cannot be called.

            progress (``callable``, *optional*):
                Pass a callback function to view the file transmission progress.
                The function must take *(current, total)* as positional arguments (look at Other Parameters below for a
                detailed description) and will be called back each time a new file chunk has been successfully
                transmitted.

            progress_args (``tuple``, *optional*):
                Extra custom arguments for the progress callback function.
                You can pass anything you need to be available in the progress callback scope.

        Other Parameters:
            current (``int``):
                The amount of bytes transmitted so far.

            total (``int``):
                The total size of the file.

            *args (``tuple``, *optional*):
                Extra custom arguments as defined in the ``progress_args`` parameter.
                You can either keep ``*args`` or add every single extra argument in your function signature.

        Example:
            .. code-block:: python

                ...
                # Keep track of the progress while uploading
                def progress(current, total):
                    print(f"{current * 100 / total:.1f}%")

                async with aiofiles.open('file.zip', 'rb') as file:
                    await client.upload_to('/path/to/file.zip', file, progress=progress)
                ...
        """

        urn = Urn(path)
        if urn.is_dir():
            raise OptionNotValid(name="path", value=path)

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

        if callable(progress) and not asyncio.iscoroutinefunction(buffer):

            async def file_sender(buff: IO):
                current = 0

                if asyncio.iscoroutinefunction(progress):
                    await progress(current, buffer_size, *progress_args)
                else:
                    progress(current, buffer_size, *progress_args)

                while current < buffer_size:
                    chunk = await buffer.read(self._chunk_size) if isinstance(buffer, AsyncBufferedIOBase) \
                        else buffer.read(self._chunk_size)
                    if not chunk:
                        break

                    current += len(chunk)

                    if asyncio.iscoroutinefunction(progress):
                        await progress(current, buffer_size, *progress_args)
                    else:
                        progress(current, buffer_size, *progress_args)
                    yield chunk

            await self._execute_request(action='upload',
                                        path=urn.quote(),
                                        data=file_sender(buffer))
        else:
            await self._execute_request(action='upload',
                                        path=urn.quote(),
                                        data=buffer)