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.
@@ -1,11 +1,11 @@
1
- rclone_api/__init__.py,sha256=r0KXLKwt-WLsf1eniHkrAJJfot5Avw7UiYSz7y1YYu0,16324
1
+ rclone_api/__init__.py,sha256=Vtuyxjd7NUWgymTlZxjUeshCRqZ3zLoCmDPxtUtC1Jg,31680
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
5
5
  rclone_api/convert.py,sha256=Mx9Qo7zhkOedJd8LdhPvNGHp8znJzOk4f_2KWnoGc78,1012
6
6
  rclone_api/deprecated.py,sha256=qWKpnZdYcBK7YQZKuVoWWXDwi-uqiAtbjgPcci_efow,590
7
7
  rclone_api/diff.py,sha256=tMoJMAGmLSE6Q_7QhPf6PnCzb840djxMZtDmhc2GlGQ,5227
8
- rclone_api/dir.py,sha256=SoFct0x1P3QiHQPs8jTiRR749Mr3A1vLvK137Z6o8XQ,3434
8
+ rclone_api/dir.py,sha256=_9o-_5tbWVJkL1Vf_Yb8aiQV3xAqvUq5bk3zoJblvEg,3547
9
9
  rclone_api/dir_listing.py,sha256=bSmd8yZtSeyVaDRw2JPB4bCpbCeDzhoa_pomgdJp44c,1884
10
10
  rclone_api/exec.py,sha256=Bq0gkyZ10mEY0FRyzNZgdN4FaWP9vpeCk1kjpg-gN_8,1083
11
11
  rclone_api/file.py,sha256=JLPqjUcW_YVb4UQjX6FQ7PABJqhchFUXVy1W-X9rJLk,5659
@@ -15,14 +15,14 @@ rclone_api/file_stream.py,sha256=_W3qnwCuigqA0hzXl2q5pAxSZDRaUSwet4BkT0lpnzs,143
15
15
  rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
16
16
  rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
17
17
  rclone_api/http_server.py,sha256=LhovQu2AI-Z7zQIWflWelCiCDLnWzisL32Rs5350kxE,8850
18
- rclone_api/install.py,sha256=r8LbWdSd8obOdEVca2iWky2BJk0c_6B5u42FxS4HOPg,2661
19
- rclone_api/log.py,sha256=Lv46jmdD5F_ieEzJ4ucHRfcxJYCcADDYXyXJ5KnI6Ec,1227
18
+ rclone_api/install.py,sha256=jKJWYvN6DPv_ydQ7_kmzwNgmxBOuh8ZmbLZaJbEyzlE,2781
19
+ rclone_api/log.py,sha256=VZHM7pNSXip2ZLBKMP7M1u-rp_F7zoafFDuR8CPUoKI,1271
20
20
  rclone_api/mount.py,sha256=TE_VIBMW7J1UkF_6HRCt8oi_jGdMov4S51bm2OgxFAM,10045
21
21
  rclone_api/process.py,sha256=tGooS5NLdPuqHh7hCH8SfK44A6LGftPQCPQUNgSo0a0,5714
22
22
  rclone_api/rclone_impl.py,sha256=emZjLztunr2tJ2a8YYM4XIQk-8Vb-uEcfNjBAqZAGqg,46184
23
23
  rclone_api/remote.py,sha256=mTgMTQTwxUmbLjTpr-AGTId2ycXKI9mLX5L7PPpDIoc,520
24
24
  rclone_api/rpath.py,sha256=Y1JjQWcie39EgQrq-UtbfDz5yDLCwwfu27W7AQXllSE,2860
25
- rclone_api/scan_missing_folders.py,sha256=-8BZQ4ZYHb2T7-AXwgEckk-xW_WZxBm5Mjcvb-88Rio,4594
25
+ rclone_api/scan_missing_folders.py,sha256=-8NCwpCaHeHrX-IepCoAEsX1rl8S-GOCxcIhTr_w3gA,4747
26
26
  rclone_api/types.py,sha256=2ngxwpdNy88y0teeYJ5Vz5NiLK1rfaFx8Xf99i0J-Js,12155
27
27
  rclone_api/util.py,sha256=39-hAIx-ziLl7zARooO7ef_HEpawp1t8Qffle7c7bVc,9281
28
28
  rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
@@ -31,11 +31,11 @@ rclone_api/cmd/copy_large_s3.py,sha256=E0B7P-JJTuOM7wMZtwQHJCpoLhccJleh0mnMq8ZiS
31
31
  rclone_api/cmd/copy_large_s3_finish.py,sha256=SNCqkvu8YtxPKmBp37WVMP876YhxV0kJDoYuOSNPaPY,2309
32
32
  rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
33
33
  rclone_api/cmd/save_to_db.py,sha256=ylvnhg_yzexM-m6Zr7XDiswvoDVSl56ELuFAdb9gqBY,1957
34
- rclone_api/db/__init__.py,sha256=J00wN2CQdca9bxdnBvVSRWlQcCX9jP5fidyX7yj7ZnQ,37
34
+ rclone_api/db/__init__.py,sha256=OSRUdnSWUlDTOHmjdjVmxYTUNpTbtaJ5Ll9sl-PfZg0,40
35
35
  rclone_api/db/db.py,sha256=YRnYrCaXHwytQt07uEZ_mMpvPHo9-0IWcOb95fVOOfs,10086
36
36
  rclone_api/db/models.py,sha256=v7qaXUehvsDvU51uk69JI23fSIs9JFGcOa-Tv1c_wVs,1600
37
37
  rclone_api/detail/copy_file_parts_resumable.py,sha256=RoUWV2eBWEvuuTfsvrz5BhtvX3BmX-DVmQKdARhRF80,1248
38
- rclone_api/detail/walk.py,sha256=6hHAg-6njmGvekxj6uDvbQxyl5Q235euuK7nyv0VCVs,3253
38
+ rclone_api/detail/walk.py,sha256=-54NVE8EJcCstwDoaC_UtHm73R2HrZwVwQmsnv55xNU,3369
39
39
  rclone_api/experimental/flags.py,sha256=qCVD--fSTmzlk9hloRLr0q9elzAOFzPsvVpKM3aB1Mk,2739
40
40
  rclone_api/experimental/flags_base.py,sha256=ajU_czkTcAxXYU-SlmiCfHY7aCQGHvpCLqJ-Z8uZLk0,2102
41
41
  rclone_api/s3/api.py,sha256=6E4xEOxtpP6niiAFEpgB1-ckWJclNyRsJ3D11Qm4RwU,4069
@@ -50,11 +50,11 @@ rclone_api/s3/multipart/merge_state.py,sha256=ziTB9CYV-OWaky5C1fOT9hifSY2zgUrk5H
50
50
  rclone_api/s3/multipart/upload_info.py,sha256=d6_OfzFR_vtDzCEegFfzCfWi2kUBUV4aXZzqAEVp1c4,1874
51
51
  rclone_api/s3/multipart/upload_parts_inline.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9akiew3MFjGmufLo2w,12503
52
52
  rclone_api/s3/multipart/upload_parts_resumable.py,sha256=diJoUpVYow6No_dNgOZIYVsv43k4evb6zixqpzWJaUk,9771
53
- rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=WwVxunCFNvjSiskNCDLfwtVHzmDmN-TsrF0rRTfZnRY,17494
53
+ rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=Fp2pdrs5dONQI9LkfNolgAGj1-Z2V1SsRd0r0sreuXI,18040
54
54
  rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
55
- rclone_api-1.5.0.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
56
- rclone_api-1.5.0.dist-info/METADATA,sha256=OE-4B22gg5bY3Fr3INb3F9KKLSl0wwajAxmxUQhvJXU,18481
57
- rclone_api-1.5.0.dist-info/WHEEL,sha256=SrDKpSbFN1G94qcmBqS9nyHcDMp9cUS9OC06hC0G3G0,109
58
- rclone_api-1.5.0.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
59
- rclone_api-1.5.0.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
60
- rclone_api-1.5.0.dist-info/RECORD,,
55
+ rclone_api-1.5.1.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
56
+ rclone_api-1.5.1.dist-info/METADATA,sha256=Un8V4Cd69VDmCMRXc50OAqjAU8OS7PSgDLVZkQYtoYo,32776
57
+ rclone_api-1.5.1.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
58
+ rclone_api-1.5.1.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
59
+ rclone_api-1.5.1.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
60
+ rclone_api-1.5.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (75.8.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -1,574 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: rclone_api
3
- Version: 1.5.0
4
- Summary: rclone api in python
5
- Home-page: https://github.com/zackees/rclone-api
6
- License: BSD 3-Clause License
7
- Keywords: rclone,api,python,fast,sftp,s3,backblaze
8
- Classifier: Programming Language :: Python :: 3
9
- Requires-Python: >=3.10
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: pyright>=1.1.393
13
- Requires-Dist: python-dotenv>=1.0.0
14
- Requires-Dist: certifi>=2025.1.31
15
- Requires-Dist: psutil
16
- Requires-Dist: boto3<=1.35.99,>=1.20.1
17
- Requires-Dist: sqlmodel>=0.0.23
18
- Requires-Dist: psycopg2-binary>=2.9.10
19
- Requires-Dist: httpx>=0.28.1
20
- Requires-Dist: download>=0.3.5
21
- Requires-Dist: appdirs>=1.4.4
22
- Dynamic: home-page
23
-
24
- # rclone-api
25
-
26
-
27
- ![perpetualmaniac_faster_400fd528-df15-4a04-8ad3-3cca786d7bca (2)](https://github.com/user-attachments/assets/65138e38-b115-447c-849a-4adbd27e4b67)
28
-
29
-
30
- <!--
31
- [![Linting](https://github.com/zackees/rclone-api/actions/workflows/lint.yml/badge.svg)](https://github.com/zackees/rclone-api/actions/workflows/lint.yml)
32
- [![MacOS_Tests](https://github.com/zackees/rclone-api/actions/workflows/push_macos.yml/badge.svg)](https://github.com/zackees/rclone-api/actions/workflows/push_macos.yml)
33
- [![Ubuntu_Tests](https://github.com/zackees/rclone-api/actions/workflows/push_ubuntu.yml/badge.svg)](https://github.com/zackees/rclone-api/actions/workflows/push_ubuntu.yml)
34
- [![Win_Tests](https://github.com/zackees/rclone-api/actions/workflows/push_win.yml/badge.svg)](https://github.com/zackees/rclone-api/actions/workflows/push_win.yml)
35
- -->
36
-
37
-
38
- Got a lot of data to transfer quickly? This package is for you.
39
-
40
- This library was built out of necessity to transfer large amounts of AI training data. Aggressive defaults means this api will transfer faster than rclone does in stock settings.
41
-
42
- You can have [rclone](https://rclone.org/) in your path or else the api will download it.
43
-
44
- # Install
45
-
46
- `pip install rclone-api`
47
-
48
- pypi link: https://pypi.org/project/rclone-api/
49
-
50
- # Quick
51
-
52
- In addition to providing easy python use for rclone, this package provides additional features:
53
-
54
- * Aggressive default settings for copying / syncing operations for extreme performance.
55
- * Database Support: Dump repo information to an sqlite/postgres/mysql database.
56
- * One repo path -> table.
57
- * Scoped objects for:
58
- * Mounts.
59
- * File servers.
60
- * Enforces correct cleanup
61
- * Mounts are easier - platform specific setup and teardown.
62
- * Resumable multi-part uploads when s3 is the destination.
63
- * Fast diffing src/dst repos as a stream of `list[str]`.
64
- * Find which files need are missing and need to be copied.
65
- * Efficiently build pipelines to select copy strategy based on file size.
66
- * Walk a directory.
67
- * Breath first.
68
- * Depth first.
69
- * Use the HttpServer to slice out byte ranges from extremely large files.
70
-
71
-
72
- ## Example
73
-
74
- ```python
75
-
76
- from rclone_api import Rclone, DirListing, Config
77
-
78
- RCLONE_CONFIG = Config("""
79
- [dst]
80
- type = s3
81
- account = *********
82
- key = ************
83
- """)
84
-
85
-
86
- def test_ls_glob_png(self) -> None:
87
- rclone = Rclone(RCLONE_CONFIG)
88
- path = f"dst:{BUCKET_NAME}/my_data"
89
- listing: DirListing = rclone.ls(path, glob="*.png")
90
- self.assertGreater(len(listing.files), 0)
91
- for file in listing.files:
92
- self.assertIsInstance(file, File)
93
- # test that it ends with .png
94
- self.assertTrue(file.name.endswith(".png"))
95
- # there should be no directories with this glob
96
- self.assertEqual(len(listing.dirs), 0)
97
- ```
98
-
99
- ## API
100
-
101
- ```python
102
-
103
- # from rclone_api import Rclone
104
- # Rclone is the main api entry point.
105
- class Rclone:
106
- def __init__(
107
- self, rclone_conf: Path | Config, rclone_exe: Path | None = None
108
- ) -> None:
109
- from rclone_api.rclone_impl import RcloneImpl
110
-
111
- self.impl: RcloneImpl = RcloneImpl(rclone_conf, rclone_exe)
112
-
113
- def webgui(self, other_args: list[str] | None = None) -> Process:
114
- """Launch the Rclone web GUI."""
115
- return self.impl.webgui(other_args=other_args)
116
-
117
- def launch_server(
118
- self,
119
- addr: str,
120
- user: str | None = None,
121
- password: str | None = None,
122
- other_args: list[str] | None = None,
123
- ) -> Process:
124
- """Launch the Rclone server so it can receive commands"""
125
- return self.impl.launch_server(
126
- addr=addr, user=user, password=password, other_args=other_args
127
- )
128
-
129
- def remote_control(
130
- self,
131
- addr: str,
132
- user: str | None = None,
133
- password: str | None = None,
134
- capture: bool | None = None,
135
- other_args: list[str] | None = None,
136
- ) -> CompletedProcess:
137
- return self.impl.remote_control(
138
- addr=addr,
139
- user=user,
140
- password=password,
141
- capture=capture,
142
- other_args=other_args,
143
- )
144
-
145
- def obscure(self, password: str) -> str:
146
- """Obscure a password for use in rclone config files."""
147
- return self.impl.obscure(password=password)
148
-
149
- def ls_stream(
150
- self,
151
- path: str,
152
- max_depth: int = -1,
153
- fast_list: bool = False,
154
- ) -> FilesStream:
155
- """
156
- List files in the given path
157
-
158
- Args:
159
- src: Remote path to list
160
- max_depth: Maximum recursion depth (-1 for unlimited)
161
- fast_list: Use fast list (only use when getting THE entire data repository from the root/bucket, or it's small)
162
- """
163
- return self.impl.ls_stream(path=path, max_depth=max_depth, fast_list=fast_list)
164
-
165
- def save_to_db(
166
- self,
167
- src: str,
168
- db_url: str,
169
- max_depth: int = -1,
170
- fast_list: bool = False,
171
- ) -> None:
172
- """
173
- Save files to a database (sqlite, mysql, postgres)
174
-
175
- Args:
176
- src: Remote path to list, this will be used to populate an entire table, so always use the root-most path.
177
- db_url: Database URL, like sqlite:///data.db or mysql://user:pass@localhost/db or postgres://user:pass@localhost/db
178
- max_depth: Maximum depth to traverse (-1 for unlimited)
179
- fast_list: Use fast list (only use when getting THE entire data repository from the root/bucket)
180
-
181
- """
182
- return self.impl.save_to_db(
183
- src=src, db_url=db_url, max_depth=max_depth, fast_list=fast_list
184
- )
185
-
186
- def ls(
187
- self,
188
- path: Dir | Remote | str | None = None,
189
- max_depth: int | None = None,
190
- glob: str | None = None,
191
- order: Order = Order.NORMAL,
192
- listing_option: ListingOption = ListingOption.ALL,
193
- ) -> DirListing:
194
- return self.impl.ls(
195
- path=path,
196
- max_depth=max_depth,
197
- glob=glob,
198
- order=order,
199
- listing_option=listing_option,
200
- )
201
-
202
- def listremotes(self) -> list[Remote]:
203
- return self.impl.listremotes()
204
-
205
- def diff(
206
- self,
207
- src: str,
208
- dst: str,
209
- min_size: (
210
- str | None
211
- ) = None, # e. g. "1MB" - see rclone documentation: https://rclone.org/commands/rclone_check/
212
- max_size: (
213
- str | None
214
- ) = None, # e. g. "1GB" - see rclone documentation: https://rclone.org/commands/rclone_check/
215
- diff_option: DiffOption = DiffOption.COMBINED,
216
- fast_list: bool = True,
217
- size_only: bool | None = None,
218
- checkers: int | None = None,
219
- other_args: list[str] | None = None,
220
- ) -> Generator[DiffItem, None, None]:
221
- """Be extra careful with the src and dst values. If you are off by one
222
- parent directory, you will get a huge amount of false diffs."""
223
- return self.impl.diff(
224
- src=src,
225
- dst=dst,
226
- min_size=min_size,
227
- max_size=max_size,
228
- diff_option=diff_option,
229
- fast_list=fast_list,
230
- size_only=size_only,
231
- checkers=checkers,
232
- other_args=other_args,
233
- )
234
-
235
- def walk(
236
- self,
237
- path: Dir | Remote | str,
238
- max_depth: int = -1,
239
- breadth_first: bool = True,
240
- order: Order = Order.NORMAL,
241
- ) -> Generator[DirListing, None, None]:
242
- """Walk through the given path recursively.
243
-
244
- Args:
245
- path: Remote path or Remote object to walk through
246
- max_depth: Maximum depth to traverse (-1 for unlimited)
247
-
248
- Yields:
249
- DirListing: Directory listing for each directory encountered
250
- """
251
- return self.impl.walk(
252
- path=path, max_depth=max_depth, breadth_first=breadth_first, order=order
253
- )
254
-
255
- def scan_missing_folders(
256
- self,
257
- src: Dir | Remote | str,
258
- dst: Dir | Remote | str,
259
- max_depth: int = -1,
260
- order: Order = Order.NORMAL,
261
- ) -> Generator[Dir, None, None]:
262
- """Walk through the given path recursively.
263
-
264
- WORK IN PROGRESS!!
265
-
266
- Args:
267
- src: Source directory or Remote to walk through
268
- dst: Destination directory or Remote to walk through
269
- max_depth: Maximum depth to traverse (-1 for unlimited)
270
-
271
- Yields:
272
- DirListing: Directory listing for each directory encountered
273
- """
274
- return self.impl.scan_missing_folders(
275
- src=src, dst=dst, max_depth=max_depth, order=order
276
- )
277
-
278
- def cleanup(
279
- self, path: str, other_args: list[str] | None = None
280
- ) -> CompletedProcess:
281
- """Cleanup any resources used by the Rclone instance."""
282
- return self.impl.cleanup(path=path, other_args=other_args)
283
-
284
- def copy_to(
285
- self,
286
- src: File | str,
287
- dst: File | str,
288
- check: bool | None = None,
289
- verbose: bool | None = None,
290
- other_args: list[str] | None = None,
291
- ) -> CompletedProcess:
292
- """Copy one file from source to destination.
293
-
294
- Warning - slow.
295
-
296
- """
297
- return self.impl.copy_to(
298
- src=src, dst=dst, check=check, verbose=verbose, other_args=other_args
299
- )
300
-
301
- def copy_files(
302
- self,
303
- src: str,
304
- dst: str,
305
- files: list[str] | Path,
306
- check: bool | None = None,
307
- max_backlog: int | None = None,
308
- verbose: bool | None = None,
309
- checkers: int | None = None,
310
- transfers: int | None = None,
311
- low_level_retries: int | None = None,
312
- retries: int | None = None,
313
- retries_sleep: str | None = None,
314
- metadata: bool | None = None,
315
- timeout: str | None = None,
316
- max_partition_workers: int | None = None,
317
- multi_thread_streams: int | None = None,
318
- other_args: list[str] | None = None,
319
- ) -> list[CompletedProcess]:
320
- """Copy multiple files from source to destination.
321
-
322
- Args:
323
- payload: Dictionary of source and destination file paths
324
- """
325
- return self.impl.copy_files(
326
- src=src,
327
- dst=dst,
328
- files=files,
329
- check=check,
330
- max_backlog=max_backlog,
331
- verbose=verbose,
332
- checkers=checkers,
333
- transfers=transfers,
334
- low_level_retries=low_level_retries,
335
- retries=retries,
336
- retries_sleep=retries_sleep,
337
- metadata=metadata,
338
- timeout=timeout,
339
- max_partition_workers=max_partition_workers,
340
- multi_thread_streams=multi_thread_streams,
341
- other_args=other_args,
342
- )
343
-
344
- def copy(
345
- self,
346
- src: Dir | str,
347
- dst: Dir | str,
348
- check: bool | None = None,
349
- transfers: int | None = None,
350
- checkers: int | None = None,
351
- multi_thread_streams: int | None = None,
352
- low_level_retries: int | None = None,
353
- retries: int | None = None,
354
- other_args: list[str] | None = None,
355
- ) -> CompletedProcess:
356
- """Copy files from source to destination.
357
-
358
- Args:
359
- src: Source directory
360
- dst: Destination directory
361
- """
362
- return self.impl.copy(
363
- src=src,
364
- dst=dst,
365
- check=check,
366
- transfers=transfers,
367
- checkers=checkers,
368
- multi_thread_streams=multi_thread_streams,
369
- low_level_retries=low_level_retries,
370
- retries=retries,
371
- other_args=other_args,
372
- )
373
-
374
- def purge(self, path: Dir | str) -> CompletedProcess:
375
- """Purge a directory"""
376
- return self.impl.purge(path=path)
377
-
378
- def delete_files(
379
- self,
380
- files: str | File | list[str] | list[File],
381
- check: bool | None = None,
382
- rmdirs=False,
383
- verbose: bool | None = None,
384
- max_partition_workers: int | None = None,
385
- other_args: list[str] | None = None,
386
- ) -> CompletedProcess:
387
- """Delete a directory"""
388
- return self.impl.delete_files(
389
- files=files,
390
- check=check,
391
- rmdirs=rmdirs,
392
- verbose=verbose,
393
- max_partition_workers=max_partition_workers,
394
- other_args=other_args,
395
- )
396
-
397
- def exists(self, path: Dir | Remote | str | File) -> bool:
398
- """Check if a file or directory exists."""
399
- return self.impl.exists(path=path)
400
-
401
- def is_synced(self, src: str | Dir, dst: str | Dir) -> bool:
402
- """Check if two directories are in sync."""
403
- return self.impl.is_synced(src=src, dst=dst)
404
-
405
- def modtime(self, src: str) -> str | Exception:
406
- """Get the modification time of a file or directory."""
407
- return self.impl.modtime(src=src)
408
-
409
- def modtime_dt(self, src: str) -> datetime | Exception:
410
- """Get the modification time of a file or directory."""
411
- return self.impl.modtime_dt(src=src)
412
-
413
- def write_text(
414
- self,
415
- text: str,
416
- dst: str,
417
- ) -> Exception | None:
418
- """Write text to a file."""
419
- return self.impl.write_text(text=text, dst=dst)
420
-
421
- def write_bytes(
422
- self,
423
- data: bytes,
424
- dst: str,
425
- ) -> Exception | None:
426
- """Write bytes to a file."""
427
- return self.impl.write_bytes(data=data, dst=dst)
428
-
429
- def read_bytes(self, src: str) -> bytes | Exception:
430
- """Read bytes from a file."""
431
- return self.impl.read_bytes(src=src)
432
-
433
- def read_text(self, src: str) -> str | Exception:
434
- """Read text from a file."""
435
- return self.impl.read_text(src=src)
436
-
437
- def copy_bytes(
438
- self,
439
- src: str,
440
- offset: int | SizeSuffix,
441
- length: int | SizeSuffix,
442
- outfile: Path,
443
- other_args: list[str] | None = None,
444
- ) -> Exception | None:
445
- """Copy a slice of bytes from the src file to dst."""
446
- return self.impl.copy_bytes(
447
- src=src,
448
- offset=offset,
449
- length=length,
450
- outfile=outfile,
451
- other_args=other_args,
452
- )
453
-
454
- def copy_dir(
455
- self, src: str | Dir, dst: str | Dir, args: list[str] | None = None
456
- ) -> CompletedProcess:
457
- """Copy a directory from source to destination."""
458
- # convert src to str, also dst
459
- return self.impl.copy_dir(src=src, dst=dst, args=args)
460
-
461
- def copy_remote(
462
- self, src: Remote, dst: Remote, args: list[str] | None = None
463
- ) -> CompletedProcess:
464
- """Copy a remote to another remote."""
465
- return self.impl.copy_remote(src=src, dst=dst, args=args)
466
-
467
- def copy_file_s3_resumable(
468
- self,
469
- src: str, # src:/Bucket/path/myfile.large.zst
470
- dst: str, # dst:/Bucket/path/myfile.large.zst
471
- part_infos: list[PartInfo] | None = None,
472
- upload_threads: int = 8, # Number of reader and writer threads to use
473
- merge_threads: int = 4, # Number of threads to use for merging the parts
474
- ) -> Exception | None:
475
- """Copy a file in parts."""
476
- return self.impl.copy_file_s3_resumable(
477
- src=src,
478
- dst=dst,
479
- part_infos=part_infos,
480
- upload_threads=upload_threads,
481
- merge_threads=merge_threads,
482
- )
483
-
484
- def mount(
485
- self,
486
- src: Remote | Dir | str,
487
- outdir: Path,
488
- allow_writes: bool | None = False,
489
- use_links: bool | None = None,
490
- vfs_cache_mode: str | None = None,
491
- verbose: bool | None = None,
492
- cache_dir: Path | None = None,
493
- cache_dir_delete_on_exit: bool | None = None,
494
- log: Path | None = None,
495
- other_args: list[str] | None = None,
496
- ) -> Mount:
497
- """Mount a remote or directory to a local path.
498
-
499
- Args:
500
- src: Remote or directory to mount
501
- outdir: Local path to mount to
502
-
503
- Returns:
504
- CompletedProcess from the mount command execution
505
-
506
- Raises:
507
- subprocess.CalledProcessError: If the mount operation fails
508
- """
509
- return self.impl.mount(
510
- src=src,
511
- outdir=outdir,
512
- allow_writes=allow_writes,
513
- use_links=use_links,
514
- vfs_cache_mode=vfs_cache_mode,
515
- verbose=verbose,
516
- cache_dir=cache_dir,
517
- cache_dir_delete_on_exit=cache_dir_delete_on_exit,
518
- log=log,
519
- other_args=other_args,
520
- )
521
-
522
- def serve_http(
523
- self,
524
- src: str,
525
- addr: str = "localhost:8080",
526
- other_args: list[str] | None = None,
527
- ) -> HttpServer:
528
- """Serve a remote or directory via HTTP. The returned HttpServer has a client which can be used to
529
- fetch files or parts.
530
-
531
- Args:
532
- src: Remote or directory to serve
533
- addr: Network address and port to serve on (default: localhost:8080)
534
- """
535
- return self.impl.serve_http(src=src, addr=addr, other_args=other_args)
536
-
537
- def size_files(
538
- self,
539
- src: str,
540
- files: list[str],
541
- fast_list: bool = False, # Recommend that this is False
542
- other_args: list[str] | None = None,
543
- check: bool | None = False,
544
- verbose: bool | None = None,
545
- ) -> SizeResult | Exception:
546
- """Get the size of a list of files. Example of files items: "remote:bucket/to/file"."""
547
- return self.impl.size_files(
548
- src=src,
549
- files=files,
550
- fast_list=fast_list,
551
- other_args=other_args,
552
- check=check,
553
- verbose=verbose,
554
- )
555
-
556
- def size_file(self, src: str) -> SizeSuffix | Exception:
557
- """Get the size of a file."""
558
- return self.impl.size_file(src=src)
559
- ```
560
-
561
-
562
- # Contributing
563
-
564
- ```bash
565
- git clone https://github.comn/zackees/rclone-api
566
- cd rclone-api
567
- ./install
568
- ./lint
569
- ./test
570
- ```
571
-
572
- # Windows
573
-
574
- This environment requires you to use `git-bash`.