rclone-api 1.5.0__py2.py3-none-any.whl → 1.5.1__py2.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
@@ -1,523 +1,931 @@
1
- # Import logging module to activate default configuration
2
-
3
- from datetime import datetime
4
- from pathlib import Path
5
- from typing import Generator
6
-
7
- from rclone_api import log
8
-
9
- from .completed_process import CompletedProcess
10
- from .config import Config, Parsed, Section
11
- from .diff import DiffItem, DiffOption, DiffType
12
- from .dir import Dir
13
- from .dir_listing import DirListing
14
- from .file import File, FileItem
15
- from .file_stream import FilesStream
16
- from .filelist import FileList
17
- from .http_server import HttpFetcher, HttpServer, Range
18
-
19
- # Import the configure_logging function to make it available at package level
20
- from .log import configure_logging, setup_default_logging
21
- from .mount import Mount
22
- from .process import Process
23
- from .remote import Remote
24
- from .rpath import RPath
25
- from .s3.types import MultiUploadResult
26
- from .types import ListingOption, Order, PartInfo, SizeResult, SizeSuffix
27
-
28
- setup_default_logging()
29
-
30
-
31
- def rclone_verbose(val: bool | None) -> bool:
32
- from rclone_api.rclone_impl import rclone_verbose as _rclone_verbose
33
-
34
- return _rclone_verbose(val)
35
-
36
-
37
- class Rclone:
38
- def __init__(
39
- self, rclone_conf: Path | Config, rclone_exe: Path | None = None
40
- ) -> None:
41
- from rclone_api.rclone_impl import RcloneImpl
42
-
43
- self.impl: RcloneImpl = RcloneImpl(rclone_conf, rclone_exe)
44
-
45
- def webgui(self, other_args: list[str] | None = None) -> Process:
46
- """Launch the Rclone web GUI."""
47
- return self.impl.webgui(other_args=other_args)
48
-
49
- def launch_server(
50
- self,
51
- addr: str,
52
- user: str | None = None,
53
- password: str | None = None,
54
- other_args: list[str] | None = None,
55
- ) -> Process:
56
- """Launch the Rclone server so it can receive commands"""
57
- return self.impl.launch_server(
58
- addr=addr, user=user, password=password, other_args=other_args
59
- )
60
-
61
- def remote_control(
62
- self,
63
- addr: str,
64
- user: str | None = None,
65
- password: str | None = None,
66
- capture: bool | None = None,
67
- other_args: list[str] | None = None,
68
- ) -> CompletedProcess:
69
- return self.impl.remote_control(
70
- addr=addr,
71
- user=user,
72
- password=password,
73
- capture=capture,
74
- other_args=other_args,
75
- )
76
-
77
- def obscure(self, password: str) -> str:
78
- """Obscure a password for use in rclone config files."""
79
- return self.impl.obscure(password=password)
80
-
81
- def ls_stream(
82
- self,
83
- path: str,
84
- max_depth: int = -1,
85
- fast_list: bool = False,
86
- ) -> FilesStream:
87
- """
88
- List files in the given path
89
-
90
- Args:
91
- src: Remote path to list
92
- max_depth: Maximum recursion depth (-1 for unlimited)
93
- fast_list: Use fast list (only use when getting THE entire data repository from the root/bucket, or it's small)
94
- """
95
- return self.impl.ls_stream(path=path, max_depth=max_depth, fast_list=fast_list)
96
-
97
- def save_to_db(
98
- self,
99
- src: str,
100
- db_url: str,
101
- max_depth: int = -1,
102
- fast_list: bool = False,
103
- ) -> None:
104
- """
105
- Save files to a database (sqlite, mysql, postgres)
106
-
107
- Args:
108
- src: Remote path to list, this will be used to populate an entire table, so always use the root-most path.
109
- db_url: Database URL, like sqlite:///data.db or mysql://user:pass@localhost/db or postgres://user:pass@localhost/db
110
- max_depth: Maximum depth to traverse (-1 for unlimited)
111
- fast_list: Use fast list (only use when getting THE entire data repository from the root/bucket)
112
-
113
- """
114
- return self.impl.save_to_db(
115
- src=src, db_url=db_url, max_depth=max_depth, fast_list=fast_list
116
- )
117
-
118
- def ls(
119
- self,
120
- path: Dir | Remote | str | None = None,
121
- max_depth: int | None = None,
122
- glob: str | None = None,
123
- order: Order = Order.NORMAL,
124
- listing_option: ListingOption = ListingOption.ALL,
125
- ) -> DirListing:
126
- return self.impl.ls(
127
- path=path,
128
- max_depth=max_depth,
129
- glob=glob,
130
- order=order,
131
- listing_option=listing_option,
132
- )
133
-
134
- def listremotes(self) -> list[Remote]:
135
- return self.impl.listremotes()
136
-
137
- def diff(
138
- self,
139
- src: str,
140
- dst: str,
141
- min_size: (
142
- str | None
143
- ) = None, # e. g. "1MB" - see rclone documentation: https://rclone.org/commands/rclone_check/
144
- max_size: (
145
- str | None
146
- ) = None, # e. g. "1GB" - see rclone documentation: https://rclone.org/commands/rclone_check/
147
- diff_option: DiffOption = DiffOption.COMBINED,
148
- fast_list: bool = True,
149
- size_only: bool | None = None,
150
- checkers: int | None = None,
151
- other_args: list[str] | None = None,
152
- ) -> Generator[DiffItem, None, None]:
153
- """Be extra careful with the src and dst values. If you are off by one
154
- parent directory, you will get a huge amount of false diffs."""
155
- return self.impl.diff(
156
- src=src,
157
- dst=dst,
158
- min_size=min_size,
159
- max_size=max_size,
160
- diff_option=diff_option,
161
- fast_list=fast_list,
162
- size_only=size_only,
163
- checkers=checkers,
164
- other_args=other_args,
165
- )
166
-
167
- def walk(
168
- self,
169
- path: Dir | Remote | str,
170
- max_depth: int = -1,
171
- breadth_first: bool = True,
172
- order: Order = Order.NORMAL,
173
- ) -> Generator[DirListing, None, None]:
174
- """Walk through the given path recursively.
175
-
176
- Args:
177
- path: Remote path or Remote object to walk through
178
- max_depth: Maximum depth to traverse (-1 for unlimited)
179
-
180
- Yields:
181
- DirListing: Directory listing for each directory encountered
182
- """
183
- return self.impl.walk(
184
- path=path, max_depth=max_depth, breadth_first=breadth_first, order=order
185
- )
186
-
187
- def scan_missing_folders(
188
- self,
189
- src: Dir | Remote | str,
190
- dst: Dir | Remote | str,
191
- max_depth: int = -1,
192
- order: Order = Order.NORMAL,
193
- ) -> Generator[Dir, None, None]:
194
- """Walk through the given path recursively.
195
-
196
- WORK IN PROGRESS!!
197
-
198
- Args:
199
- src: Source directory or Remote to walk through
200
- dst: Destination directory or Remote to walk through
201
- max_depth: Maximum depth to traverse (-1 for unlimited)
202
-
203
- Yields:
204
- DirListing: Directory listing for each directory encountered
205
- """
206
- return self.impl.scan_missing_folders(
207
- src=src, dst=dst, max_depth=max_depth, order=order
208
- )
209
-
210
- def cleanup(
211
- self, path: str, other_args: list[str] | None = None
212
- ) -> CompletedProcess:
213
- """Cleanup any resources used by the Rclone instance."""
214
- return self.impl.cleanup(path=path, other_args=other_args)
215
-
216
- def copy_to(
217
- self,
218
- src: File | str,
219
- dst: File | str,
220
- check: bool | None = None,
221
- verbose: bool | None = None,
222
- other_args: list[str] | None = None,
223
- ) -> CompletedProcess:
224
- """Copy one file from source to destination.
225
-
226
- Warning - slow.
227
-
228
- """
229
- return self.impl.copy_to(
230
- src=src, dst=dst, check=check, verbose=verbose, other_args=other_args
231
- )
232
-
233
- def copy_files(
234
- self,
235
- src: str,
236
- dst: str,
237
- files: list[str] | Path,
238
- check: bool | None = None,
239
- max_backlog: int | None = None,
240
- verbose: bool | None = None,
241
- checkers: int | None = None,
242
- transfers: int | None = None,
243
- low_level_retries: int | None = None,
244
- retries: int | None = None,
245
- retries_sleep: str | None = None,
246
- metadata: bool | None = None,
247
- timeout: str | None = None,
248
- max_partition_workers: int | None = None,
249
- multi_thread_streams: int | None = None,
250
- other_args: list[str] | None = None,
251
- ) -> list[CompletedProcess]:
252
- """Copy multiple files from source to destination.
253
-
254
- Args:
255
- payload: Dictionary of source and destination file paths
256
- """
257
- return self.impl.copy_files(
258
- src=src,
259
- dst=dst,
260
- files=files,
261
- check=check,
262
- max_backlog=max_backlog,
263
- verbose=verbose,
264
- checkers=checkers,
265
- transfers=transfers,
266
- low_level_retries=low_level_retries,
267
- retries=retries,
268
- retries_sleep=retries_sleep,
269
- metadata=metadata,
270
- timeout=timeout,
271
- max_partition_workers=max_partition_workers,
272
- multi_thread_streams=multi_thread_streams,
273
- other_args=other_args,
274
- )
275
-
276
- def copy(
277
- self,
278
- src: Dir | str,
279
- dst: Dir | str,
280
- check: bool | None = None,
281
- transfers: int | None = None,
282
- checkers: int | None = None,
283
- multi_thread_streams: int | None = None,
284
- low_level_retries: int | None = None,
285
- retries: int | None = None,
286
- other_args: list[str] | None = None,
287
- ) -> CompletedProcess:
288
- """Copy files from source to destination.
289
-
290
- Args:
291
- src: Source directory
292
- dst: Destination directory
293
- """
294
- return self.impl.copy(
295
- src=src,
296
- dst=dst,
297
- check=check,
298
- transfers=transfers,
299
- checkers=checkers,
300
- multi_thread_streams=multi_thread_streams,
301
- low_level_retries=low_level_retries,
302
- retries=retries,
303
- other_args=other_args,
304
- )
305
-
306
- def purge(self, path: Dir | str) -> CompletedProcess:
307
- """Purge a directory"""
308
- return self.impl.purge(path=path)
309
-
310
- def delete_files(
311
- self,
312
- files: str | File | list[str] | list[File],
313
- check: bool | None = None,
314
- rmdirs=False,
315
- verbose: bool | None = None,
316
- max_partition_workers: int | None = None,
317
- other_args: list[str] | None = None,
318
- ) -> CompletedProcess:
319
- """Delete a directory"""
320
- return self.impl.delete_files(
321
- files=files,
322
- check=check,
323
- rmdirs=rmdirs,
324
- verbose=verbose,
325
- max_partition_workers=max_partition_workers,
326
- other_args=other_args,
327
- )
328
-
329
- def exists(self, path: Dir | Remote | str | File) -> bool:
330
- """Check if a file or directory exists."""
331
- return self.impl.exists(path=path)
332
-
333
- def is_synced(self, src: str | Dir, dst: str | Dir) -> bool:
334
- """Check if two directories are in sync."""
335
- return self.impl.is_synced(src=src, dst=dst)
336
-
337
- def modtime(self, src: str) -> str | Exception:
338
- """Get the modification time of a file or directory."""
339
- return self.impl.modtime(src=src)
340
-
341
- def modtime_dt(self, src: str) -> datetime | Exception:
342
- """Get the modification time of a file or directory."""
343
- return self.impl.modtime_dt(src=src)
344
-
345
- def write_text(
346
- self,
347
- text: str,
348
- dst: str,
349
- ) -> Exception | None:
350
- """Write text to a file."""
351
- return self.impl.write_text(text=text, dst=dst)
352
-
353
- def write_bytes(
354
- self,
355
- data: bytes,
356
- dst: str,
357
- ) -> Exception | None:
358
- """Write bytes to a file."""
359
- return self.impl.write_bytes(data=data, dst=dst)
360
-
361
- def read_bytes(self, src: str) -> bytes | Exception:
362
- """Read bytes from a file."""
363
- return self.impl.read_bytes(src=src)
364
-
365
- def read_text(self, src: str) -> str | Exception:
366
- """Read text from a file."""
367
- return self.impl.read_text(src=src)
368
-
369
- def copy_bytes(
370
- self,
371
- src: str,
372
- offset: int | SizeSuffix,
373
- length: int | SizeSuffix,
374
- outfile: Path,
375
- other_args: list[str] | None = None,
376
- ) -> Exception | None:
377
- """Copy a slice of bytes from the src file to dst."""
378
- return self.impl.copy_bytes(
379
- src=src,
380
- offset=offset,
381
- length=length,
382
- outfile=outfile,
383
- other_args=other_args,
384
- )
385
-
386
- def copy_dir(
387
- self, src: str | Dir, dst: str | Dir, args: list[str] | None = None
388
- ) -> CompletedProcess:
389
- """Copy a directory from source to destination."""
390
- # convert src to str, also dst
391
- return self.impl.copy_dir(src=src, dst=dst, args=args)
392
-
393
- def copy_remote(
394
- self, src: Remote, dst: Remote, args: list[str] | None = None
395
- ) -> CompletedProcess:
396
- """Copy a remote to another remote."""
397
- return self.impl.copy_remote(src=src, dst=dst, args=args)
398
-
399
- def copy_file_s3_resumable(
400
- self,
401
- src: str, # src:/Bucket/path/myfile.large.zst
402
- dst: str, # dst:/Bucket/path/myfile.large.zst
403
- part_infos: list[PartInfo] | None = None,
404
- upload_threads: int = 8, # Number of reader and writer threads to use
405
- merge_threads: int = 4, # Number of threads to use for merging the parts
406
- ) -> Exception | None:
407
- """Copy a file in parts."""
408
- return self.impl.copy_file_s3_resumable(
409
- src=src,
410
- dst=dst,
411
- part_infos=part_infos,
412
- upload_threads=upload_threads,
413
- merge_threads=merge_threads,
414
- )
415
-
416
- def mount(
417
- self,
418
- src: Remote | Dir | str,
419
- outdir: Path,
420
- allow_writes: bool | None = False,
421
- use_links: bool | None = None,
422
- vfs_cache_mode: str | None = None,
423
- verbose: bool | None = None,
424
- cache_dir: Path | None = None,
425
- cache_dir_delete_on_exit: bool | None = None,
426
- log: Path | None = None,
427
- other_args: list[str] | None = None,
428
- ) -> Mount:
429
- """Mount a remote or directory to a local path.
430
-
431
- Args:
432
- src: Remote or directory to mount
433
- outdir: Local path to mount to
434
-
435
- Returns:
436
- CompletedProcess from the mount command execution
437
-
438
- Raises:
439
- subprocess.CalledProcessError: If the mount operation fails
440
- """
441
- return self.impl.mount(
442
- src=src,
443
- outdir=outdir,
444
- allow_writes=allow_writes,
445
- use_links=use_links,
446
- vfs_cache_mode=vfs_cache_mode,
447
- verbose=verbose,
448
- cache_dir=cache_dir,
449
- cache_dir_delete_on_exit=cache_dir_delete_on_exit,
450
- log=log,
451
- other_args=other_args,
452
- )
453
-
454
- def serve_http(
455
- self,
456
- src: str,
457
- addr: str = "localhost:8080",
458
- other_args: list[str] | None = None,
459
- ) -> HttpServer:
460
- """Serve a remote or directory via HTTP. The returned HttpServer has a client which can be used to
461
- fetch files or parts.
462
-
463
- Args:
464
- src: Remote or directory to serve
465
- addr: Network address and port to serve on (default: localhost:8080)
466
- """
467
- return self.impl.serve_http(src=src, addr=addr, other_args=other_args)
468
-
469
- def size_files(
470
- self,
471
- src: str,
472
- files: list[str],
473
- fast_list: bool = False, # Recommend that this is False
474
- other_args: list[str] | None = None,
475
- check: bool | None = False,
476
- verbose: bool | None = None,
477
- ) -> SizeResult | Exception:
478
- """Get the size of a list of files. Example of files items: "remote:bucket/to/file"."""
479
- return self.impl.size_files(
480
- src=src,
481
- files=files,
482
- fast_list=fast_list,
483
- other_args=other_args,
484
- check=check,
485
- verbose=verbose,
486
- )
487
-
488
- def size_file(self, src: str) -> SizeSuffix | Exception:
489
- """Get the size of a file."""
490
- return self.impl.size_file(src=src)
491
-
492
-
493
- __all__ = [
494
- "Rclone",
495
- "File",
496
- "Config",
497
- "Remote",
498
- "Dir",
499
- "RPath",
500
- "DirListing",
501
- "FileList",
502
- "FileItem",
503
- "Process",
504
- "DiffItem",
505
- "DiffType",
506
- "rclone_verbose",
507
- "CompletedProcess",
508
- "DiffOption",
509
- "ListingOption",
510
- "Order",
511
- "ListingOption",
512
- "SizeResult",
513
- "Parsed",
514
- "Section",
515
- "MultiUploadResult",
516
- "SizeSuffix",
517
- "configure_logging",
518
- "log",
519
- "HttpServer",
520
- "Range",
521
- "HttpFetcher",
522
- "PartInfo",
523
- ]
1
+ """
2
+ Rclone API - Python interface for the Rclone command-line tool.
3
+
4
+ This package provides a high-level API for interacting with Rclone,
5
+ allowing file operations across various cloud storage providers.
6
+ The API wraps the rclone command-line tool, providing a Pythonic interface
7
+ for common operations like copying, listing, and managing remote storage.
8
+ """
9
+
10
+ # Import core components and utilities
11
+ from datetime import datetime
12
+ from pathlib import Path
13
+ from typing import Generator
14
+
15
+ # Import logging utilities
16
+ from rclone_api import log
17
+
18
+ # Import data structures and models
19
+ from .completed_process import CompletedProcess
20
+ from .config import Config, Parsed, Section # Configuration handling
21
+ from .diff import DiffItem, DiffOption, DiffType # File comparison utilities
22
+ from .dir import Dir # Directory representation
23
+ from .dir_listing import DirListing # Directory contents representation
24
+ from .file import File, FileItem # File representation
25
+ from .file_stream import FilesStream # Streaming file listings
26
+ from .filelist import FileList # File list utilities
27
+ from .http_server import HttpFetcher, HttpServer, Range # HTTP serving capabilities
28
+
29
+ # Import logging configuration utilities
30
+ from .log import configure_logging, setup_default_logging
31
+ from .mount import Mount # Mount remote filesystems
32
+ from .process import Process # Process management
33
+ from .remote import Remote # Remote storage representation
34
+ from .rpath import RPath # Remote path utilities
35
+ from .s3.types import MultiUploadResult # S3-specific types
36
+ from .types import ( # Common types
37
+ ListingOption,
38
+ Order,
39
+ PartInfo,
40
+ SizeResult,
41
+ SizeSuffix,
42
+ )
43
+
44
+ # Set up default logging configuration when the package is imported
45
+ setup_default_logging()
46
+
47
+
48
+ def rclone_verbose(val: bool | None) -> bool:
49
+ """
50
+ Get or set the global verbosity setting for rclone operations.
51
+
52
+ Controls whether rclone commands will produce detailed output.
53
+ When enabled, commands will show more information about their operation.
54
+
55
+ Args:
56
+ val: If provided, sets the verbosity level. If None, returns the current setting.
57
+
58
+ Returns:
59
+ The current verbosity setting after any change.
60
+ """
61
+ from rclone_api.rclone_impl import rclone_verbose as _rclone_verbose
62
+
63
+ return _rclone_verbose(val)
64
+
65
+
66
+ class Rclone:
67
+ """
68
+ Main interface for interacting with Rclone.
69
+
70
+ This class provides methods for all major Rclone operations including
71
+ file transfers, listing, mounting, and remote management.
72
+
73
+ It serves as the primary entry point for the API, wrapping the underlying
74
+ implementation details and providing a clean, consistent interface.
75
+ """
76
+
77
+ def __init__(
78
+ self, rclone_conf: Path | Config, rclone_exe: Path | None = None
79
+ ) -> None:
80
+ """
81
+ Initialize the Rclone interface.
82
+
83
+ Args:
84
+ rclone_conf: Path to rclone config file or Config object
85
+ rclone_exe: Optional path to rclone executable. If None, will search in PATH.
86
+ """
87
+ from rclone_api.rclone_impl import RcloneImpl
88
+
89
+ self.impl: RcloneImpl = RcloneImpl(rclone_conf, rclone_exe)
90
+
91
+ def webgui(self, other_args: list[str] | None = None) -> Process:
92
+ """
93
+ Launch the Rclone web GUI.
94
+
95
+ Starts the built-in web interface for interacting with rclone.
96
+
97
+ Args:
98
+ other_args: Additional command-line arguments to pass to rclone
99
+
100
+ Returns:
101
+ Process object representing the running web GUI
102
+ """
103
+ return self.impl.webgui(other_args=other_args)
104
+
105
+ def launch_server(
106
+ self,
107
+ addr: str,
108
+ user: str | None = None,
109
+ password: str | None = None,
110
+ other_args: list[str] | None = None,
111
+ ) -> Process:
112
+ """
113
+ Launch the Rclone server so it can receive commands.
114
+
115
+ Starts an rclone server that can be controlled remotely.
116
+
117
+ Args:
118
+ addr: Address and port to listen on (e.g., "localhost:5572")
119
+ user: Optional username for authentication
120
+ password: Optional password for authentication
121
+ other_args: Additional command-line arguments
122
+
123
+ Returns:
124
+ Process object representing the running server
125
+ """
126
+ return self.impl.launch_server(
127
+ addr=addr, user=user, password=password, other_args=other_args
128
+ )
129
+
130
+ def remote_control(
131
+ self,
132
+ addr: str,
133
+ user: str | None = None,
134
+ password: str | None = None,
135
+ capture: bool | None = None,
136
+ other_args: list[str] | None = None,
137
+ ) -> CompletedProcess:
138
+ """
139
+ Send commands to a running rclone server.
140
+
141
+ Args:
142
+ addr: Address of the rclone server (e.g., "localhost:5572")
143
+ user: Optional username for authentication
144
+ password: Optional password for authentication
145
+ capture: Whether to capture and return command output
146
+ other_args: Additional command-line arguments
147
+
148
+ Returns:
149
+ CompletedProcess containing the command result
150
+ """
151
+ return self.impl.remote_control(
152
+ addr=addr,
153
+ user=user,
154
+ password=password,
155
+ capture=capture,
156
+ other_args=other_args,
157
+ )
158
+
159
+ def obscure(self, password: str) -> str:
160
+ """
161
+ Obscure a password for use in rclone config files.
162
+
163
+ Converts a plaintext password to rclone's obscured format.
164
+ Note that this is not secure encryption, just light obfuscation.
165
+
166
+ Args:
167
+ password: The plaintext password to obscure
168
+
169
+ Returns:
170
+ The obscured password string
171
+ """
172
+ return self.impl.obscure(password=password)
173
+
174
+ def ls_stream(
175
+ self,
176
+ path: str,
177
+ max_depth: int = -1,
178
+ fast_list: bool = False,
179
+ ) -> FilesStream:
180
+ """
181
+ List files in the given path as a stream of results.
182
+
183
+ This method is memory-efficient for large directories as it yields
184
+ results incrementally rather than collecting them all at once.
185
+
186
+ Args:
187
+ path: Remote path to list
188
+ max_depth: Maximum recursion depth (-1 for unlimited)
189
+ fast_list: Use fast list (only recommended for listing entire repositories or small datasets)
190
+
191
+ Returns:
192
+ A stream of file entries that can be iterated over
193
+ """
194
+ return self.impl.ls_stream(path=path, max_depth=max_depth, fast_list=fast_list)
195
+
196
+ def save_to_db(
197
+ self,
198
+ src: str,
199
+ db_url: str, # sqalchemy style url, use sqlite:///data.db or mysql://user:pass@localhost/db or postgres://user:pass@localhost/db
200
+ max_depth: int = -1,
201
+ fast_list: bool = False,
202
+ ) -> None:
203
+ """
204
+ Save files to a database (sqlite, mysql, postgres).
205
+
206
+ Lists all files in the source path and stores their metadata in a database.
207
+ Useful for creating searchable indexes of remote storage.
208
+
209
+ Args:
210
+ src: Remote path to list, this will be used to populate an entire table, so always use the root-most path.
211
+ db_url: Database URL, like sqlite:///data.db or mysql://user:pass@localhost/db or postgres://user:pass@localhost/db
212
+ max_depth: Maximum depth to traverse (-1 for unlimited)
213
+ fast_list: Use fast list (only use when getting THE entire data repository from the root/bucket)
214
+ """
215
+ return self.impl.save_to_db(
216
+ src=src, db_url=db_url, max_depth=max_depth, fast_list=fast_list
217
+ )
218
+
219
+ def ls(
220
+ self,
221
+ path: Dir | Remote | str | None = None,
222
+ max_depth: int | None = None,
223
+ glob: str | None = None,
224
+ order: Order = Order.NORMAL,
225
+ listing_option: ListingOption = ListingOption.ALL,
226
+ ) -> DirListing:
227
+ """
228
+ List files and directories at the specified path.
229
+
230
+ Provides a detailed listing with file metadata.
231
+
232
+ Args:
233
+ path: Path to list (Dir, Remote, or string path)
234
+ max_depth: Maximum recursion depth (None for default)
235
+ glob: Optional glob pattern to filter results
236
+ order: Sorting order for the results
237
+ listing_option: What types of entries to include
238
+
239
+ Returns:
240
+ DirListing object containing the results
241
+ """
242
+ return self.impl.ls(
243
+ path=path,
244
+ max_depth=max_depth,
245
+ glob=glob,
246
+ order=order,
247
+ listing_option=listing_option,
248
+ )
249
+
250
+ def listremotes(self) -> list[Remote]:
251
+ """
252
+ List all configured remotes.
253
+
254
+ Returns a list of all remotes defined in the rclone configuration.
255
+
256
+ Returns:
257
+ List of Remote objects
258
+ """
259
+ return self.impl.listremotes()
260
+
261
+ def diff(
262
+ self,
263
+ src: str,
264
+ dst: str,
265
+ min_size: (
266
+ str | None
267
+ ) = None, # e. g. "1MB" - see rclone documentation: https://rclone.org/commands/rclone_check/
268
+ max_size: (
269
+ str | None
270
+ ) = None, # e. g. "1GB" - see rclone documentation: https://rclone.org/commands/rclone_check/
271
+ diff_option: DiffOption = DiffOption.COMBINED,
272
+ fast_list: bool = True,
273
+ size_only: bool | None = None,
274
+ checkers: int | None = None,
275
+ other_args: list[str] | None = None,
276
+ ) -> Generator[DiffItem, None, None]:
277
+ """
278
+ Compare two directories and yield differences.
279
+
280
+ Be extra careful with the src and dst values. If you are off by one
281
+ parent directory, you will get a huge amount of false diffs.
282
+
283
+ Args:
284
+ src: Rclone style src path
285
+ dst: Rclone style dst path
286
+ min_size: Minimum file size to check (e.g., "1MB")
287
+ max_size: Maximum file size to check (e.g., "1GB")
288
+ diff_option: How to report differences
289
+ fast_list: Whether to use fast listing
290
+ size_only: Compare only file sizes, not content
291
+ checkers: Number of checker threads
292
+ other_args: Additional command-line arguments
293
+
294
+ Yields:
295
+ DiffItem objects representing each difference found
296
+ """
297
+ return self.impl.diff(
298
+ src=src,
299
+ dst=dst,
300
+ min_size=min_size,
301
+ max_size=max_size,
302
+ diff_option=diff_option,
303
+ fast_list=fast_list,
304
+ size_only=size_only,
305
+ checkers=checkers,
306
+ other_args=other_args,
307
+ )
308
+
309
+ def walk(
310
+ self,
311
+ path: Dir | Remote | str,
312
+ max_depth: int = -1,
313
+ breadth_first: bool = True,
314
+ order: Order = Order.NORMAL,
315
+ ) -> Generator[DirListing, None, None]:
316
+ """
317
+ Walk through the given path recursively, yielding directory listings.
318
+
319
+ Similar to os.walk(), but for remote storage. Traverses directories
320
+ and yields their contents.
321
+
322
+ Args:
323
+ path: Remote path, Dir, or Remote object to walk through
324
+ max_depth: Maximum depth to traverse (-1 for unlimited)
325
+ breadth_first: If True, use breadth-first traversal, otherwise depth-first
326
+ order: Sorting order for directory entries
327
+
328
+ Yields:
329
+ DirListing: Directory listing for each directory encountered
330
+ """
331
+ return self.impl.walk(
332
+ path=path, max_depth=max_depth, breadth_first=breadth_first, order=order
333
+ )
334
+
335
+ def scan_missing_folders(
336
+ self,
337
+ src: Dir | Remote | str,
338
+ dst: Dir | Remote | str,
339
+ max_depth: int = -1,
340
+ order: Order = Order.NORMAL,
341
+ ) -> Generator[Dir, None, None]:
342
+ """
343
+ Find folders that exist in source but are missing in destination.
344
+
345
+ Useful for identifying directories that need to be created before
346
+ copying files.
347
+
348
+ Args:
349
+ src: Source directory or Remote to scan
350
+ dst: Destination directory or Remote to compare against
351
+ max_depth: Maximum depth to traverse (-1 for unlimited)
352
+ order: Sorting order for directory entries
353
+
354
+ Yields:
355
+ Dir: Each directory that exists in source but not in destination
356
+ """
357
+ return self.impl.scan_missing_folders(
358
+ src=src, dst=dst, max_depth=max_depth, order=order
359
+ )
360
+
361
+ def cleanup(
362
+ self, path: str, other_args: list[str] | None = None
363
+ ) -> CompletedProcess:
364
+ """
365
+ Cleanup any resources used by the Rclone instance.
366
+
367
+ Removes temporary files and directories created by rclone.
368
+
369
+ Args:
370
+ path: Path to clean up
371
+ other_args: Additional command-line arguments
372
+
373
+ Returns:
374
+ CompletedProcess with the result of the cleanup operation
375
+ """
376
+ return self.impl.cleanup(path=path, other_args=other_args)
377
+
378
+ def copy_to(
379
+ self,
380
+ src: File | str,
381
+ dst: File | str,
382
+ check: bool | None = None,
383
+ verbose: bool | None = None,
384
+ other_args: list[str] | None = None,
385
+ ) -> CompletedProcess:
386
+ """
387
+ Copy one file from source to destination.
388
+
389
+ Warning - this can be slow for large files or when copying between
390
+ different storage providers.
391
+
392
+ Args:
393
+ src: Rclone style src path
394
+ dst: Rclone style dst path
395
+ check: Whether to verify the copy with checksums
396
+ verbose: Whether to show detailed progress
397
+ other_args: Additional command-line arguments
398
+
399
+ Returns:
400
+ CompletedProcess with the result of the copy operation
401
+ """
402
+ return self.impl.copy_to(
403
+ src=src, dst=dst, check=check, verbose=verbose, other_args=other_args
404
+ )
405
+
406
+ def copy_files(
407
+ self,
408
+ src: str,
409
+ dst: str,
410
+ files: list[str] | Path,
411
+ check: bool | None = None,
412
+ max_backlog: int | None = None,
413
+ verbose: bool | None = None,
414
+ checkers: int | None = None,
415
+ transfers: int | None = None,
416
+ low_level_retries: int | None = None,
417
+ retries: int | None = None,
418
+ retries_sleep: str | None = None,
419
+ metadata: bool | None = None,
420
+ timeout: str | None = None,
421
+ max_partition_workers: int | None = None,
422
+ multi_thread_streams: int | None = None,
423
+ other_args: list[str] | None = None,
424
+ ) -> list[CompletedProcess]:
425
+ """
426
+ Copy multiple files from source to destination.
427
+
428
+ Efficiently copies a list of files, potentially in parallel.
429
+
430
+ Args:
431
+ src: Rclone style src path
432
+ dst: Rclone style dst path
433
+ files: List of file paths relative to src, or Path to a file containing the list
434
+ check: Whether to verify copies with checksums
435
+ max_backlog: Maximum number of queued transfers
436
+ verbose: Whether to show detailed progress
437
+ checkers: Number of checker threads
438
+ transfers: Number of file transfers to run in parallel
439
+ low_level_retries: Number of low-level retries
440
+ retries: Number of high-level retries
441
+ retries_sleep: Sleep interval between retries (e.g., "10s")
442
+ metadata: Whether to preserve metadata
443
+ timeout: IO idle timeout (e.g., "5m")
444
+ max_partition_workers: Maximum number of partition workers
445
+ multi_thread_streams: Number of streams for multi-thread copy
446
+ other_args: Additional command-line arguments
447
+
448
+ Returns:
449
+ List of CompletedProcess objects for each copy operation
450
+ """
451
+ return self.impl.copy_files(
452
+ src=src,
453
+ dst=dst,
454
+ files=files,
455
+ check=check,
456
+ max_backlog=max_backlog,
457
+ verbose=verbose,
458
+ checkers=checkers,
459
+ transfers=transfers,
460
+ low_level_retries=low_level_retries,
461
+ retries=retries,
462
+ retries_sleep=retries_sleep,
463
+ metadata=metadata,
464
+ timeout=timeout,
465
+ max_partition_workers=max_partition_workers,
466
+ multi_thread_streams=multi_thread_streams,
467
+ other_args=other_args,
468
+ )
469
+
470
+ def copy(
471
+ self,
472
+ src: Dir | str,
473
+ dst: Dir | str,
474
+ check: bool | None = None,
475
+ transfers: int | None = None,
476
+ checkers: int | None = None,
477
+ multi_thread_streams: int | None = None,
478
+ low_level_retries: int | None = None,
479
+ retries: int | None = None,
480
+ other_args: list[str] | None = None,
481
+ ) -> CompletedProcess:
482
+ """
483
+ Copy files from source to destination.
484
+
485
+ Recursively copies all files from src to dst.
486
+
487
+ Args:
488
+ src: Rclone style src path
489
+ dst: Rclone style dst path
490
+ check: Whether to verify copies with checksums
491
+ transfers: Number of file transfers to run in parallel
492
+ checkers: Number of checker threads
493
+ multi_thread_streams: Number of streams for multi-thread copy
494
+ low_level_retries: Number of low-level retries
495
+ retries: Number of high-level retries
496
+ other_args: Additional command-line arguments
497
+
498
+ Returns:
499
+ CompletedProcess with the result of the copy operation
500
+ """
501
+ return self.impl.copy(
502
+ src=src,
503
+ dst=dst,
504
+ check=check,
505
+ transfers=transfers,
506
+ checkers=checkers,
507
+ multi_thread_streams=multi_thread_streams,
508
+ low_level_retries=low_level_retries,
509
+ retries=retries,
510
+ other_args=other_args,
511
+ )
512
+
513
+ def purge(self, path: Dir | str) -> CompletedProcess:
514
+ """
515
+ Purge a directory.
516
+
517
+ Removes a directory and all its contents.
518
+
519
+ Args:
520
+ path: Rclone style path
521
+
522
+ Returns:
523
+ CompletedProcess with the result of the purge operation
524
+ """
525
+ return self.impl.purge(path=path)
526
+
527
+ def delete_files(
528
+ self,
529
+ files: str | File | list[str] | list[File],
530
+ check: bool | None = None,
531
+ rmdirs=False,
532
+ verbose: bool | None = None,
533
+ max_partition_workers: int | None = None,
534
+ other_args: list[str] | None = None,
535
+ ) -> CompletedProcess:
536
+ """
537
+ Delete files or directories.
538
+
539
+ Args:
540
+ files: Files to delete (single file/path or list)
541
+ check: Whether to verify deletions
542
+ rmdirs: Whether to remove empty directories
543
+ verbose: Whether to show detailed progress
544
+ max_partition_workers: Maximum number of partition workers
545
+ other_args: Additional command-line arguments
546
+
547
+ Returns:
548
+ CompletedProcess with the result of the delete operation
549
+ """
550
+ return self.impl.delete_files(
551
+ files=files,
552
+ check=check,
553
+ rmdirs=rmdirs,
554
+ verbose=verbose,
555
+ max_partition_workers=max_partition_workers,
556
+ other_args=other_args,
557
+ )
558
+
559
+ def exists(self, path: Dir | Remote | str | File) -> bool:
560
+ """
561
+ Check if a file or directory exists.
562
+
563
+ Args:
564
+ path: Path to check (Dir, Remote, File, or path string)
565
+
566
+ Returns:
567
+ True if the path exists, False otherwise
568
+ """
569
+ return self.impl.exists(path=path)
570
+
571
+ def is_synced(self, src: str | Dir, dst: str | Dir) -> bool:
572
+ """
573
+ Check if two directories are in sync.
574
+
575
+ Compares the contents of src and dst to determine if they match.
576
+
577
+ Args:
578
+ src: Source directory (Dir object or path string)
579
+ dst: Destination directory (Dir object or path string)
580
+
581
+ Returns:
582
+ True if the directories are in sync, False otherwise
583
+ """
584
+ return self.impl.is_synced(src=src, dst=dst)
585
+
586
+ def modtime(self, src: str) -> str | Exception:
587
+ """
588
+ Get the modification time of a file or directory.
589
+
590
+ Args:
591
+ src: Path to the file or directory
592
+
593
+ Returns:
594
+ Modification time as a string, or Exception if an error occurred
595
+ """
596
+ return self.impl.modtime(src=src)
597
+
598
+ def modtime_dt(self, src: str) -> datetime | Exception:
599
+ """
600
+ Get the modification time of a file or directory as a datetime object.
601
+
602
+ Args:
603
+ src: Path to the file or directory
604
+
605
+ Returns:
606
+ Modification time as a datetime object, or Exception if an error occurred
607
+ """
608
+ return self.impl.modtime_dt(src=src)
609
+
610
+ def write_text(
611
+ self,
612
+ text: str,
613
+ dst: str,
614
+ ) -> Exception | None:
615
+ """
616
+ Write text to a file.
617
+
618
+ Creates or overwrites the file at dst with the given text.
619
+
620
+ Args:
621
+ text: Text content to write
622
+ dst: Destination file path
623
+
624
+ Returns:
625
+ None if successful, Exception if an error occurred
626
+ """
627
+ return self.impl.write_text(text=text, dst=dst)
628
+
629
+ def write_bytes(
630
+ self,
631
+ data: bytes,
632
+ dst: str,
633
+ ) -> Exception | None:
634
+ """
635
+ Write bytes to a file.
636
+
637
+ Creates or overwrites the file at dst with the given binary data.
638
+
639
+ Args:
640
+ data: Binary content to write
641
+ dst: Destination file path
642
+
643
+ Returns:
644
+ None if successful, Exception if an error occurred
645
+ """
646
+ return self.impl.write_bytes(data=data, dst=dst)
647
+
648
+ def read_bytes(self, src: str) -> bytes | Exception:
649
+ """
650
+ Read bytes from a file.
651
+
652
+ Args:
653
+ src: Source file path
654
+
655
+ Returns:
656
+ File contents as bytes, or Exception if an error occurred
657
+ """
658
+ return self.impl.read_bytes(src=src)
659
+
660
+ def read_text(self, src: str) -> str | Exception:
661
+ """
662
+ Read text from a file.
663
+
664
+ Args:
665
+ src: Source file path
666
+
667
+ Returns:
668
+ File contents as a string, or Exception if an error occurred
669
+ """
670
+ return self.impl.read_text(src=src)
671
+
672
+ def copy_bytes(
673
+ self,
674
+ src: str,
675
+ offset: int | SizeSuffix,
676
+ length: int | SizeSuffix,
677
+ outfile: Path,
678
+ other_args: list[str] | None = None,
679
+ ) -> Exception | None:
680
+ """
681
+ Copy a slice of bytes from the src file to dst.
682
+
683
+ Extracts a portion of a file based on offset and length.
684
+
685
+ Args:
686
+ src: Source file path
687
+ offset: Starting position in the source file
688
+ length: Number of bytes to copy
689
+ outfile: Local file path to write the bytes to
690
+ other_args: Additional command-line arguments
691
+
692
+ Returns:
693
+ None if successful, Exception if an error occurred
694
+ """
695
+ return self.impl.copy_bytes(
696
+ src=src,
697
+ offset=offset,
698
+ length=length,
699
+ outfile=outfile,
700
+ other_args=other_args,
701
+ )
702
+
703
+ def copy_dir(
704
+ self, src: str | Dir, dst: str | Dir, args: list[str] | None = None
705
+ ) -> CompletedProcess:
706
+ """
707
+ Copy a directory from source to destination.
708
+
709
+ Recursively copies all files and subdirectories.
710
+
711
+ Args:
712
+ src: Source directory (Dir object or path string)
713
+ dst: Destination directory (Dir object or path string)
714
+ args: Additional command-line arguments
715
+
716
+ Returns:
717
+ CompletedProcess with the result of the copy operation
718
+ """
719
+ # convert src to str, also dst
720
+ return self.impl.copy_dir(src=src, dst=dst, args=args)
721
+
722
+ def copy_remote(
723
+ self, src: Remote, dst: Remote, args: list[str] | None = None
724
+ ) -> CompletedProcess:
725
+ """
726
+ Copy a remote to another remote.
727
+
728
+ Copies all contents from one remote storage to another.
729
+
730
+ Args:
731
+ src: Source remote
732
+ dst: Destination remote
733
+ args: Additional command-line arguments
734
+
735
+ Returns:
736
+ CompletedProcess with the result of the copy operation
737
+ """
738
+ return self.impl.copy_remote(src=src, dst=dst, args=args)
739
+
740
+ def copy_file_s3_resumable(
741
+ self,
742
+ src: str, # src:/Bucket/path/myfile.large.zst
743
+ dst: str, # dst:/Bucket/path/myfile.large.zst
744
+ part_infos: list[PartInfo] | None = None,
745
+ upload_threads: int = 8, # Number of reader and writer threads to use
746
+ merge_threads: int = 4, # Number of threads to use for merging the parts
747
+ ) -> Exception | None:
748
+ """
749
+ Copy a large file to S3 with resumable upload capability.
750
+
751
+ This method splits the file into parts for parallel upload and can
752
+ resume interrupted transfers using a custom algorithm in python.
753
+
754
+ Particularly useful for very large files where network interruptions
755
+ are likely.
756
+
757
+ Args:
758
+ src: Source file path (format: remote:bucket/path/file)
759
+ dst: Destination file path (format: remote:bucket/path/file)
760
+ part_infos: Optional list of part information for resuming uploads
761
+ upload_threads: Number of parallel upload threads
762
+ merge_threads: Number of threads for merging uploaded parts
763
+
764
+ Returns:
765
+ None if successful, Exception if an error occurred
766
+ """
767
+ return self.impl.copy_file_s3_resumable(
768
+ src=src,
769
+ dst=dst,
770
+ part_infos=part_infos,
771
+ upload_threads=upload_threads,
772
+ merge_threads=merge_threads,
773
+ )
774
+
775
+ def mount(
776
+ self,
777
+ src: Remote | Dir | str,
778
+ outdir: Path,
779
+ allow_writes: bool | None = False,
780
+ use_links: bool | None = None,
781
+ vfs_cache_mode: str | None = None,
782
+ verbose: bool | None = None,
783
+ cache_dir: Path | None = None,
784
+ cache_dir_delete_on_exit: bool | None = None,
785
+ log: Path | None = None,
786
+ other_args: list[str] | None = None,
787
+ ) -> Mount:
788
+ """
789
+ Mount a remote or directory to a local path.
790
+
791
+ Makes remote storage accessible as a local filesystem.
792
+
793
+ Args:
794
+ src: Remote or directory to mount
795
+ outdir: Local path to mount to
796
+ allow_writes: Whether to allow write operations
797
+ use_links: Whether to use symbolic links
798
+ vfs_cache_mode: VFS cache mode (e.g., "full", "minimal")
799
+ verbose: Whether to show detailed output
800
+ cache_dir: Directory to use for caching
801
+ cache_dir_delete_on_exit: Whether to delete cache on exit
802
+ log: Path to write logs to
803
+ other_args: Additional command-line arguments
804
+
805
+ Returns:
806
+ Mount object representing the mounted filesystem
807
+ """
808
+ return self.impl.mount(
809
+ src=src,
810
+ outdir=outdir,
811
+ allow_writes=allow_writes,
812
+ use_links=use_links,
813
+ vfs_cache_mode=vfs_cache_mode,
814
+ verbose=verbose,
815
+ cache_dir=cache_dir,
816
+ cache_dir_delete_on_exit=cache_dir_delete_on_exit,
817
+ log=log,
818
+ other_args=other_args,
819
+ )
820
+
821
+ def serve_http(
822
+ self,
823
+ src: str,
824
+ addr: str = "localhost:8080",
825
+ other_args: list[str] | None = None,
826
+ ) -> HttpServer:
827
+ """
828
+ Serve a remote or directory via HTTP.
829
+
830
+ Creates an HTTP server that provides access to the specified remote.
831
+ The returned HttpServer object includes a client for fetching files.
832
+
833
+ This is useful for providing web access to remote storage or for
834
+ accessing remote files from applications that support HTTP but not
835
+ the remote's native protocol.
836
+
837
+ Args:
838
+ src: Remote or directory to serve
839
+ addr: Network address and port to serve on (default: localhost:8080)
840
+ other_args: Additional arguments to pass to rclone
841
+
842
+ Returns:
843
+ HttpServer object with methods for accessing the served content
844
+ """
845
+ return self.impl.serve_http(src=src, addr=addr, other_args=other_args)
846
+
847
+ def size_files(
848
+ self,
849
+ src: str,
850
+ files: list[str],
851
+ fast_list: bool = False, # Recommend that this is False
852
+ other_args: list[str] | None = None,
853
+ check: bool | None = False,
854
+ verbose: bool | None = None,
855
+ ) -> SizeResult | Exception:
856
+ """
857
+ Get the size of a list of files.
858
+
859
+ Calculates the total size of the specified files.
860
+
861
+ Args:
862
+ src: Base path for the files
863
+ files: List of file paths relative to src
864
+ fast_list: Whether to use fast listing (not recommended for accuracy)
865
+ other_args: Additional command-line arguments
866
+ check: Whether to verify file integrity
867
+ verbose: Whether to show detailed output
868
+
869
+ Returns:
870
+ SizeResult with size information, or Exception if an error occurred
871
+
872
+ Example:
873
+ size_files("remote:bucket", ["path/to/file1", "path/to/file2"])
874
+ """
875
+ return self.impl.size_files(
876
+ src=src,
877
+ files=files,
878
+ fast_list=fast_list,
879
+ other_args=other_args,
880
+ check=check,
881
+ verbose=verbose,
882
+ )
883
+
884
+ def size_file(self, src: str) -> SizeSuffix | Exception:
885
+ """
886
+ Get the size of a file.
887
+
888
+ Args:
889
+ src: Path to the file
890
+
891
+ Returns:
892
+ SizeSuffix object representing the file size, or Exception if an error occurred
893
+ """
894
+ return self.impl.size_file(src=src)
895
+
896
+
897
+ # Export public API components
898
+ __all__ = [
899
+ # Main classes
900
+ "Rclone", # Primary interface
901
+ "File", # File representation
902
+ "Config", # Configuration handling
903
+ "Remote", # Remote storage
904
+ "Dir", # Directory representation
905
+ "RPath", # Remote path utilities
906
+ "DirListing", # Directory listing
907
+ "FileList", # File list
908
+ "FileItem", # File item
909
+ "Process", # Process management
910
+ "DiffItem", # Difference item
911
+ "DiffType", # Difference type
912
+ # Functions
913
+ "rclone_verbose", # Verbosity control
914
+ # Data classes and enums
915
+ "CompletedProcess", # Process result
916
+ "DiffOption", # Difference options
917
+ "ListingOption", # Listing options
918
+ "Order", # Sorting order
919
+ "SizeResult", # Size result
920
+ "Parsed", # Parsed configuration
921
+ "Section", # Configuration section
922
+ "MultiUploadResult", # S3 upload result
923
+ "SizeSuffix", # Size with suffix
924
+ # Utilities
925
+ "configure_logging", # Logging configuration
926
+ "log", # Logging utilities
927
+ "HttpServer", # HTTP server
928
+ "Range", # HTTP range
929
+ "HttpFetcher", # HTTP fetcher
930
+ "PartInfo", # Part information for uploads
931
+ ]