rclone-api 1.5.13__py3-none-any.whl → 1.5.21__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
rclone_api/__init__.py CHANGED
@@ -24,6 +24,7 @@ from .dir_listing import DirListing # Directory contents representation
24
24
  from .file import File, FileItem # File representation
25
25
  from .file_stream import FilesStream # Streaming file listings
26
26
  from .filelist import FileList # File list utilities
27
+ from .fs import FSPath, RemoteFS # Filesystem utilities
27
28
  from .http_server import HttpFetcher, HttpServer, Range # HTTP serving capabilities
28
29
 
29
30
  # Import logging configuration utilities
@@ -119,6 +120,27 @@ class Rclone:
119
120
  """
120
121
  return self.impl.webgui(other_args=other_args)
121
122
 
123
+ def filesystem(self, src: str) -> RemoteFS:
124
+ """
125
+ Get a RealFS object for interacting with the local filesystem.
126
+
127
+ Returns:
128
+ RealFS object for local filesystem operations
129
+ """
130
+ return self.impl.filesystem(src=src)
131
+
132
+ def cwd(self, src: str) -> FSPath:
133
+ """
134
+ Get the local root path for a filesystem.
135
+
136
+ Args:
137
+ src: Source path for the filesystem
138
+
139
+ Returns:
140
+ FSPath object representing the root of the filesystem
141
+ """
142
+ return self.impl.cwd(src=src)
143
+
122
144
  def launch_server(
123
145
  self,
124
146
  addr: str,
@@ -841,7 +863,7 @@ class Rclone:
841
863
  def serve_http(
842
864
  self,
843
865
  src: str,
844
- addr: str = "localhost:8080",
866
+ addr: str | None = None,
845
867
  other_args: list[str] | None = None,
846
868
  ) -> HttpServer:
847
869
  """
rclone_api/fs.py ADDED
@@ -0,0 +1,234 @@
1
+ import abc
2
+ import shutil
3
+ from pathlib import Path
4
+
5
+ from rclone_api.config import Config
6
+
7
+
8
+ class FS(abc.ABC):
9
+ def __init__(self) -> None:
10
+ pass
11
+
12
+ @abc.abstractmethod
13
+ def copy(self, src: Path | str, dest: Path | str) -> None:
14
+ pass
15
+
16
+ @abc.abstractmethod
17
+ def read_binary(self, path: Path | str) -> bytes:
18
+ pass
19
+
20
+ @abc.abstractmethod
21
+ def exists(self, path: Path | str) -> bool:
22
+ pass
23
+
24
+ @abc.abstractmethod
25
+ def write_binary(self, path: Path | str, data: bytes) -> None:
26
+ pass
27
+
28
+ @abc.abstractmethod
29
+ def mkdir(self, path: str, parents=True, exist_ok=True) -> None:
30
+ pass
31
+
32
+ @abc.abstractmethod
33
+ def ls(self, path: Path | str) -> list[str]:
34
+ pass
35
+
36
+ @abc.abstractmethod
37
+ def cwd(self) -> "FSPath":
38
+ pass
39
+
40
+ @abc.abstractmethod
41
+ def get_path(self, path: str) -> "FSPath":
42
+ pass
43
+
44
+ def read_text(self, path: Path | str) -> str:
45
+ utf = self.read_binary(path)
46
+ return utf.decode("utf-8")
47
+
48
+ def write_text(self, path: Path | str, data: str, encoding: str | None) -> None:
49
+ encoding = encoding or "utf-8"
50
+ utf = data.encode(encoding)
51
+ self.write_binary(path, utf)
52
+
53
+
54
+ class RealFS(FS):
55
+
56
+ @staticmethod
57
+ def from_path(path: Path | str) -> "FSPath":
58
+ path_str = Path(path).as_posix()
59
+ return FSPath(RealFS(), path_str)
60
+
61
+ def __init__(self) -> None:
62
+ super().__init__()
63
+
64
+ def ls(self, path: Path | str) -> list[str]:
65
+ return [str(p) for p in Path(path).iterdir()]
66
+
67
+ def cwd(self) -> "FSPath":
68
+ return RealFS.from_path(Path.cwd())
69
+
70
+ def copy(self, src: Path | str, dest: Path | str) -> None:
71
+ shutil.copy(str(src), str(dest))
72
+
73
+ def read_binary(self, path: Path | str) -> bytes:
74
+ with open(path, "rb") as f:
75
+ return f.read()
76
+
77
+ def write_binary(self, path: Path | str, data: bytes) -> None:
78
+ with open(path, "wb") as f:
79
+ f.write(data)
80
+
81
+ def exists(self, path: Path | str) -> bool:
82
+ return Path(path).exists()
83
+
84
+ def mkdir(self, path: str, parents=True, exist_ok=True) -> None:
85
+ Path(path).mkdir(parents=parents, exist_ok=exist_ok)
86
+
87
+ def get_path(self, path: str) -> "FSPath":
88
+ return FSPath(self, path)
89
+
90
+
91
+ class RemoteFS(FS):
92
+
93
+ @staticmethod
94
+ def from_rclone_config(
95
+ src: str, rclone_conf: Path | Config | str | None
96
+ ) -> "RemoteFS":
97
+ if isinstance(rclone_conf, str):
98
+ rclone_conf = Config(text=rclone_conf)
99
+ if rclone_conf is None:
100
+ curr_dir = Path.cwd() / "rclone.conf"
101
+ if curr_dir.exists():
102
+ rclone_conf = curr_dir
103
+ else:
104
+ raise ValueError("rclone_conf not found")
105
+ return RemoteFS(rclone_conf, src)
106
+
107
+ def __init__(self, rclone_conf: Path | Config, src: str) -> None:
108
+ from rclone_api import HttpServer, Rclone
109
+
110
+ super().__init__()
111
+ self.src = src
112
+ self.rclone_conf = rclone_conf
113
+ self.rclone: Rclone = Rclone(rclone_conf)
114
+ self.server: HttpServer = self.rclone.serve_http(src=src)
115
+ self.shutdown = False
116
+
117
+ def root(self) -> "FSPath":
118
+ return FSPath(self, self.src)
119
+
120
+ def cwd(self) -> "FSPath":
121
+ return self.root()
122
+
123
+ def _to_str(self, path: Path | str) -> str:
124
+ if isinstance(path, Path):
125
+ return path.as_posix()
126
+ return path
127
+
128
+ def copy(self, src: Path | str, dest: Path | str) -> None:
129
+ src = self._to_str(src)
130
+ dest = self._to_str(dest)
131
+ self.rclone.copy(src, dest)
132
+
133
+ def read_binary(self, path: Path | str) -> bytes:
134
+ path = self._to_str(path)
135
+ err = self.rclone.read_bytes(path)
136
+ if isinstance(err, Exception):
137
+ raise FileNotFoundError(f"File not found: {path}")
138
+ return err
139
+
140
+ def write_binary(self, path: Path | str, data: bytes) -> None:
141
+ path = self._to_str(path)
142
+ self.rclone.write_bytes(data, path)
143
+
144
+ def exists(self, path: Path | str) -> bool:
145
+ path = self._to_str(path)
146
+ return self.server.exists(path)
147
+
148
+ def mkdir(self, path: str, parents=True, exist_ok=True) -> None:
149
+ raise NotImplementedError("RemoteFS does not support mkdir")
150
+
151
+ def is_dir(self, path: Path | str) -> bool:
152
+ path = self._to_str(path)
153
+ err = self.server.list(path)
154
+ return isinstance(err, list)
155
+
156
+ def is_file(self, path: Path | str) -> bool:
157
+ path = self._to_str(path)
158
+ err = self.server.list(path)
159
+ # Make faster.
160
+ return isinstance(err, Exception) and self.exists(path)
161
+
162
+ def ls(self, path: Path | str) -> list[str]:
163
+ path = self._to_str(path)
164
+ err = self.server.list(path)
165
+ if isinstance(err, Exception):
166
+ raise FileNotFoundError(f"File not found: {path}, because of {err}")
167
+ return err
168
+
169
+ def get_path(self, path: str) -> "FSPath":
170
+ return FSPath(self, path)
171
+
172
+ def dispose(self) -> None:
173
+ if self.shutdown:
174
+ return
175
+ self.shutdown = True
176
+ self.server.shutdown()
177
+
178
+ def __del__(self) -> None:
179
+ self.dispose()
180
+
181
+
182
+ class FSPath:
183
+ def __init__(self, fs: FS, path: str) -> None:
184
+ self.fs = fs
185
+ self.path = path
186
+
187
+ def read_text(self) -> str:
188
+ return self.fs.read_text(self.path)
189
+
190
+ def read_binary(self) -> bytes:
191
+ return self.fs.read_binary(self.path)
192
+
193
+ def exists(self) -> bool:
194
+ return self.fs.exists(self.path)
195
+
196
+ def __str__(self) -> str:
197
+ return self.path
198
+
199
+ def __repr__(self) -> str:
200
+ return f"FSPath({self.path})"
201
+
202
+ def mkdir(self, parents=True, exist_ok=True) -> None:
203
+ self.fs.mkdir(self.path, parents=parents, exist_ok=exist_ok)
204
+
205
+ def write_text(self, data: str, encoding: str | None = None) -> None:
206
+ self.fs.write_text(self.path, data, encoding=encoding)
207
+
208
+ def rmtree(self, ignore_errors=False) -> None:
209
+ assert self.exists(), f"Path does not exist: {self.path}"
210
+ # check fs is RealFS
211
+ assert isinstance(self.fs, RealFS)
212
+ shutil.rmtree(self.path, ignore_errors=ignore_errors)
213
+
214
+ def ls(self) -> "list[FSPath]":
215
+ names: list[str] = self.fs.ls(self.path)
216
+ return [self / name for name in names]
217
+
218
+ @property
219
+ def name(self) -> str:
220
+ return Path(self.path).name
221
+
222
+ @property
223
+ def parent(self) -> "FSPath":
224
+ parent_path = Path(self.path).parent
225
+ parent_str = parent_path.as_posix()
226
+ return FSPath(self.fs, parent_str)
227
+
228
+ def __truediv__(self, other: str) -> "FSPath":
229
+ new_path = Path(self.path) / other
230
+ return FSPath(self.fs, new_path.as_posix())
231
+
232
+ # hashable
233
+ def __hash__(self) -> int:
234
+ return hash(f"{repr(self.fs)}:{self.path}")
rclone_api/http_server.py CHANGED
@@ -11,6 +11,7 @@ from threading import Semaphore
11
11
  from typing import Any
12
12
 
13
13
  import httpx
14
+ from bs4 import BeautifulSoup
14
15
 
15
16
  from rclone_api.file_part import FilePart
16
17
  from rclone_api.process import Process
@@ -23,6 +24,25 @@ _PUT_WARNED = False
23
24
  _range = range
24
25
 
25
26
 
27
+ def _parse_files(html: str) -> list[str]:
28
+ soup = BeautifulSoup(html, "html.parser")
29
+ files = []
30
+ # Find each table row with class "file"
31
+ for tr in soup.find_all("tr", class_="file"):
32
+ name_span = tr.find("span", class_="name") # type: ignore
33
+ if not name_span:
34
+ continue
35
+ a_tag = name_span.find("a") # type: ignore
36
+ if not a_tag:
37
+ continue
38
+ # Get the text from the <a> tag
39
+ file_name = a_tag.get_text(strip=True) # type: ignore
40
+ # Skip directories (they end with a slash)
41
+ if not file_name.endswith("/"):
42
+ files.append(file_name)
43
+ return files
44
+
45
+
26
46
  class HttpServer:
27
47
  """HTTP server configuration."""
28
48
 
@@ -103,6 +123,24 @@ class HttpServer:
103
123
  warnings.warn(f"Failed to remove {path} from {self.url}: {e}")
104
124
  return e
105
125
 
126
+ # curl "http://localhost:5572/?list"
127
+
128
+ def list(self, path: str) -> list[str] | Exception:
129
+ """List files on the server."""
130
+
131
+ try:
132
+ assert self.process is not None
133
+ url = self.url
134
+ if path:
135
+ url += f"/{path}"
136
+ url += "/?list"
137
+ response = httpx.get(url)
138
+ response.raise_for_status()
139
+ return _parse_files(response.content.decode())
140
+ except Exception as e:
141
+ warnings.warn(f"Failed to list files on {self.url}: {e}")
142
+ return e
143
+
106
144
  def download(
107
145
  self, path: str, dst: Path, range: Range | None = None
108
146
  ) -> Path | Exception:
rclone_api/rclone_impl.py CHANGED
@@ -26,6 +26,7 @@ from rclone_api.dir_listing import DirListing
26
26
  from rclone_api.exec import RcloneExec
27
27
  from rclone_api.file import File
28
28
  from rclone_api.file_stream import FilesStream
29
+ from rclone_api.fs import FSPath, RemoteFS
29
30
  from rclone_api.group_files import group_files
30
31
  from rclone_api.http_server import HttpServer
31
32
  from rclone_api.mount import Mount
@@ -103,6 +104,12 @@ class RcloneImpl:
103
104
  cmd += other_args
104
105
  return self._launch_process(cmd, capture=False)
105
106
 
107
+ def filesystem(self, src: str) -> RemoteFS:
108
+ return RemoteFS(self.config, src)
109
+
110
+ def cwd(self, src: str) -> FSPath:
111
+ return self.filesystem(src).cwd()
112
+
106
113
  def launch_server(
107
114
  self,
108
115
  addr: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rclone_api
3
- Version: 1.5.13
3
+ Version: 1.5.21
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -19,6 +19,7 @@ Requires-Dist: psycopg2-binary>=2.9.10
19
19
  Requires-Dist: httpx>=0.28.1
20
20
  Requires-Dist: download>=0.3.5
21
21
  Requires-Dist: appdirs>=1.4.4
22
+ Requires-Dist: beautifulsoup4>=4.13.3
22
23
  Dynamic: home-page
23
24
  Dynamic: license-file
24
25
 
@@ -42,6 +43,10 @@ This library was built out of necessity to transfer large amounts of AI training
42
43
 
43
44
  You can have [rclone](https://rclone.org/) in your path or else the api will download it.
44
45
 
46
+ ## VFS
47
+
48
+ There is a virtual file system called `FSPath` which emulates common operators for `pathlib.Path`. You can get an instance of an `FSPath` from an `Rclone` instance using the `rclone.cwd("src:path/to")` function.
49
+
45
50
  # Install
46
51
 
47
52
  `pip install rclone-api`
@@ -102,6 +107,71 @@ def test_ls_glob_png(self) -> None:
102
107
  ```python
103
108
 
104
109
  from rclone_api import Rclone
110
+ """
111
+ Rclone API - Python interface for the Rclone command-line tool.
112
+
113
+ This package provides a high-level API for interacting with Rclone,
114
+ allowing file operations across various cloud storage providers.
115
+ The API wraps the rclone command-line tool, providing a Pythonic interface
116
+ for common operations like copying, listing, and managing remote storage.
117
+ """
118
+
119
+ # Import core components and utilities
120
+ from datetime import datetime
121
+ from pathlib import Path
122
+ from typing import Generator
123
+
124
+ # Import logging utilities
125
+ from rclone_api import log
126
+
127
+ # Import data structures and models
128
+ from .completed_process import CompletedProcess
129
+ from .config import Config, Parsed, Section # Configuration handling
130
+ from .diff import DiffItem, DiffOption, DiffType # File comparison utilities
131
+ from .dir import Dir # Directory representation
132
+ from .dir_listing import DirListing # Directory contents representation
133
+ from .file import File, FileItem # File representation
134
+ from .file_stream import FilesStream # Streaming file listings
135
+ from .filelist import FileList # File list utilities
136
+ from .fs import FSPath, RemoteFS # Filesystem utilities
137
+ from .http_server import HttpFetcher, HttpServer, Range # HTTP serving capabilities
138
+
139
+ # Import logging configuration utilities
140
+ from .log import configure_logging, setup_default_logging
141
+ from .mount import Mount # Mount remote filesystems
142
+ from .process import Process # Process management
143
+ from .remote import Remote # Remote storage representation
144
+ from .rpath import RPath # Remote path utilities
145
+ from .s3.types import MultiUploadResult # S3-specific types
146
+ from .types import ( # Common types
147
+ ListingOption,
148
+ Order,
149
+ PartInfo,
150
+ SizeResult,
151
+ SizeSuffix,
152
+ )
153
+
154
+ # Set up default logging configuration when the package is imported
155
+ setup_default_logging()
156
+
157
+
158
+ def rclone_verbose(val: bool | None) -> bool:
159
+ """
160
+ Get or set the global verbosity setting for rclone operations.
161
+
162
+ Controls whether rclone commands will produce detailed output.
163
+ When enabled, commands will show more information about their operation.
164
+
165
+ Args:
166
+ val: If provided, sets the verbosity level. If None, returns the current setting.
167
+
168
+ Returns:
169
+ The current verbosity setting after any change.
170
+ """
171
+ from rclone_api.rclone_impl import rclone_verbose as _rclone_verbose
172
+
173
+ return _rclone_verbose(val)
174
+
105
175
 
106
176
  class Rclone:
107
177
  """
@@ -159,6 +229,27 @@ class Rclone:
159
229
  """
160
230
  return self.impl.webgui(other_args=other_args)
161
231
 
232
+ def filesystem(self, src: str) -> RemoteFS:
233
+ """
234
+ Get a RealFS object for interacting with the local filesystem.
235
+
236
+ Returns:
237
+ RealFS object for local filesystem operations
238
+ """
239
+ return self.impl.filesystem(src=src)
240
+
241
+ def cwd(self, src: str) -> FSPath:
242
+ """
243
+ Get the local root path for a filesystem.
244
+
245
+ Args:
246
+ src: Source path for the filesystem
247
+
248
+ Returns:
249
+ FSPath object representing the root of the filesystem
250
+ """
251
+ return self.impl.cwd(src=src)
252
+
162
253
  def launch_server(
163
254
  self,
164
255
  addr: str,
@@ -881,7 +972,7 @@ class Rclone:
881
972
  def serve_http(
882
973
  self,
883
974
  src: str,
884
- addr: str = "localhost:8080",
975
+ addr: str | None = None,
885
976
  other_args: list[str] | None = None,
886
977
  ) -> HttpServer:
887
978
  """
@@ -902,7 +993,9 @@ class Rclone:
902
993
  Returns:
903
994
  HttpServer object with methods for accessing the served content
904
995
  """
905
- return self.impl.serve_http(src=src, addr=addr, other_args=other_args)
996
+ return self.impl.serve_http(
997
+ src=src, cache_mode="minimal", addr=addr, other_args=other_args
998
+ )
906
999
 
907
1000
  def size_files(
908
1001
  self,
@@ -952,6 +1045,43 @@ class Rclone:
952
1045
  SizeSuffix object representing the file size, or Exception if an error occurred
953
1046
  """
954
1047
  return self.impl.size_file(src=src)
1048
+
1049
+
1050
+ # Export public API components
1051
+ __all__ = [
1052
+ # Main classes
1053
+ "Rclone", # Primary interface
1054
+ "File", # File representation
1055
+ "Config", # Configuration handling
1056
+ "Remote", # Remote storage
1057
+ "Dir", # Directory representation
1058
+ "RPath", # Remote path utilities
1059
+ "DirListing", # Directory listing
1060
+ "FileList", # File list
1061
+ "FileItem", # File item
1062
+ "Process", # Process management
1063
+ "DiffItem", # Difference item
1064
+ "DiffType", # Difference type
1065
+ # Functions
1066
+ "rclone_verbose", # Verbosity control
1067
+ # Data classes and enums
1068
+ "CompletedProcess", # Process result
1069
+ "DiffOption", # Difference options
1070
+ "ListingOption", # Listing options
1071
+ "Order", # Sorting order
1072
+ "SizeResult", # Size result
1073
+ "Parsed", # Parsed configuration
1074
+ "Section", # Configuration section
1075
+ "MultiUploadResult", # S3 upload result
1076
+ "SizeSuffix", # Size with suffix
1077
+ # Utilities
1078
+ "configure_logging", # Logging configuration
1079
+ "log", # Logging utilities
1080
+ "HttpServer", # HTTP server
1081
+ "Range", # HTTP range
1082
+ "HttpFetcher", # HTTP fetcher
1083
+ "PartInfo", # Part information for uploads
1084
+ ]
955
1085
  ```
956
1086
 
957
1087
 
@@ -1,4 +1,4 @@
1
- rclone_api/__init__.py,sha256=nUDuo5YZQZybVsd0fiExyDPOOwxwZGSrD8Sx6Asb57U,32426
1
+ rclone_api/__init__.py,sha256=2B3NUnmPmEfV3f6hLKqMxioJIIB4Ry7jxpPjvA1JxLo,33064
2
2
  rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
3
3
  rclone_api/completed_process.py,sha256=_IZ8IWK7DM1_tsbDEkH6wPZ-bbcrgf7A7smls854pmg,1775
4
4
  rclone_api/config.py,sha256=f6jEAxVorGFr31oHfcsu5AJTtOJj2wR5tTSsbGGZuIw,2558
@@ -13,14 +13,15 @@ rclone_api/file_item.py,sha256=cH-AQYsxedhNPp4c8NHY1ad4Z7St4yf_VGbmiGD59no,1770
13
13
  rclone_api/file_part.py,sha256=i6ByS5_sae8Eba-4imBVTxd-xKC8ExWy7NR8QGr0ors,6155
14
14
  rclone_api/file_stream.py,sha256=_W3qnwCuigqA0hzXl2q5pAxSZDRaUSwet4BkT0lpnzs,1431
15
15
  rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
16
+ rclone_api/fs.py,sha256=2UM0-iphSDC8peovirW3pHMV5goghZtYkx4EIoAdxns,6761
16
17
  rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
17
- rclone_api/http_server.py,sha256=p1_S9VAViVvGif6NA_rxrDgMqnOmPTxJaHQ7B43FK70,10431
18
+ rclone_api/http_server.py,sha256=ZdL-rGaq0zIjcaIiRIbPBQ4OIWZ7dCu71aq0nRlKtY4,11686
18
19
  rclone_api/install.py,sha256=Xb1BRn8rQcSpSd4dzmvIOELP2zM2DytUeIZ6jzv738A,2893
19
20
  rclone_api/log.py,sha256=VZHM7pNSXip2ZLBKMP7M1u-rp_F7zoafFDuR8CPUoKI,1271
20
21
  rclone_api/mount.py,sha256=LZqEhuKZunbWVqmsOIqkkCotaxWJpdFRS1InXveoU5E,1428
21
22
  rclone_api/mount_util.py,sha256=jqhJEVTHV6c6lOOzUYb4FLMbqDMHdz7-QRcdH-IobFc,10154
22
23
  rclone_api/process.py,sha256=MeWiN-TrrN0HmtWexBPxGwf84z6f-_E5yaXE-YtLYpY,5879
23
- rclone_api/rclone_impl.py,sha256=STHQ_hT0chyp2yj3Cp-Vd0xXc1Pdpo3p9J3bTQEm0XE,46531
24
+ rclone_api/rclone_impl.py,sha256=tIoNJtjMYIKTp9SVpH878pd7tFW3v1APO4FuU2RnJTk,46747
24
25
  rclone_api/remote.py,sha256=mTgMTQTwxUmbLjTpr-AGTId2ycXKI9mLX5L7PPpDIoc,520
25
26
  rclone_api/rpath.py,sha256=Y1JjQWcie39EgQrq-UtbfDz5yDLCwwfu27W7AQXllSE,2860
26
27
  rclone_api/scan_missing_folders.py,sha256=-8NCwpCaHeHrX-IepCoAEsX1rl8S-GOCxcIhTr_w3gA,4747
@@ -53,9 +54,9 @@ rclone_api/s3/multipart/upload_parts_inline.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9
53
54
  rclone_api/s3/multipart/upload_parts_resumable.py,sha256=6-nlMclS8jyVvMvFbQDcZOX9MY1WbCcKA_s9bwuYxnk,9793
54
55
  rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=Fp2pdrs5dONQI9LkfNolgAGj1-Z2V1SsRd0r0sreuXI,18040
55
56
  rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
56
- rclone_api-1.5.13.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
57
- rclone_api-1.5.13.dist-info/METADATA,sha256=GZbzZ8SIa3OXE_8lB_hGrK0y10KHCG5jUkn2sjPPQE0,32657
58
- rclone_api-1.5.13.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
59
- rclone_api-1.5.13.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
60
- rclone_api-1.5.13.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
61
- rclone_api-1.5.13.dist-info/RECORD,,
57
+ rclone_api-1.5.21.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
58
+ rclone_api-1.5.21.dist-info/METADATA,sha256=ZbT2xwQPsbd2isP_btzLGa4nxpgRdkGaf_UemDMRgX4,37155
59
+ rclone_api-1.5.21.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
60
+ rclone_api-1.5.21.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
61
+ rclone_api-1.5.21.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
62
+ rclone_api-1.5.21.dist-info/RECORD,,