rclone-api 1.5.11__py3-none-any.whl → 1.5.13__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
@@ -862,7 +862,9 @@ class Rclone:
862
862
  Returns:
863
863
  HttpServer object with methods for accessing the served content
864
864
  """
865
- return self.impl.serve_http(src=src, addr=addr, other_args=other_args)
865
+ return self.impl.serve_http(
866
+ src=src, cache_mode="minimal", addr=addr, other_args=other_args
867
+ )
866
868
 
867
869
  def size_files(
868
870
  self,
rclone_api/http_server.py CHANGED
@@ -17,6 +17,7 @@ from rclone_api.process import Process
17
17
  from rclone_api.types import Range, SizeSuffix, get_chunk_tmpdir
18
18
 
19
19
  _TIMEOUT = 10 * 60 # 10 minutes
20
+ _PUT_WARNED = False
20
21
 
21
22
 
22
23
  _range = range
@@ -46,6 +47,18 @@ class HttpServer:
46
47
  file.seek(0)
47
48
  return file.read()
48
49
 
50
+ def exists(self, path: str) -> bool:
51
+ """Check if the file exists on the server."""
52
+ try:
53
+ assert self.process is not None
54
+ # response = httpx.head(f"{self.url}/{path}")
55
+ url = self._get_file_url(path)
56
+ response = httpx.head(url)
57
+ return response.status_code == 200
58
+ except Exception as e:
59
+ warnings.warn(f"Failed to check if {self.url}/{path} exists: {e}")
60
+ return False
61
+
49
62
  def size(self, path: str) -> int | Exception:
50
63
  """Get size of the file from the server."""
51
64
  try:
@@ -60,6 +73,36 @@ class HttpServer:
60
73
  warnings.warn(f"Failed to get size of {self.url}/{path}: {e}")
61
74
  return e
62
75
 
76
+ def put(self, path: str, data: bytes) -> Exception | None:
77
+ """Put bytes to the server."""
78
+ global _PUT_WARNED
79
+ if not _PUT_WARNED:
80
+ _PUT_WARNED = True
81
+ warnings.warn("PUT method not implemented on the rclone binary as of 1.69")
82
+ try:
83
+ assert self.process is not None
84
+ url = self._get_file_url(path)
85
+ headers = {"Content-Type": "application/octet-stream"}
86
+ response = httpx.post(url, content=data, timeout=_TIMEOUT, headers=headers)
87
+ print("Allowed methods:", response.headers.get("Allow"))
88
+ response.raise_for_status()
89
+ return None
90
+ except Exception as e:
91
+ warnings.warn(f"Failed to put {path} to {self.url}: {e}")
92
+ return e
93
+
94
+ def delete(self, path: str) -> Exception | None:
95
+ """Remove file from the server."""
96
+ try:
97
+ assert self.process is not None
98
+ url = self._get_file_url(path)
99
+ response = httpx.delete(url)
100
+ response.raise_for_status()
101
+ return None
102
+ except Exception as e:
103
+ warnings.warn(f"Failed to remove {path} from {self.url}: {e}")
104
+ return e
105
+
63
106
  def download(
64
107
  self, path: str, dst: Path, range: Range | None = None
65
108
  ) -> Path | Exception:
@@ -199,11 +242,8 @@ class HttpServer:
199
242
  def shutdown(self) -> None:
200
243
  """Shutdown the server."""
201
244
  if self.process:
202
- self.process.terminate()
203
- if self.process.stdout:
204
- self.process.stdout.close()
205
- if self.process.stderr:
206
- self.process.stderr.close()
245
+ self.process.dispose()
246
+ self.process = None
207
247
 
208
248
 
209
249
  class HttpFetcher:
rclone_api/process.py CHANGED
@@ -30,6 +30,7 @@ class Process:
30
30
  ), f"rclone executable not found: {args.rclone_exe}"
31
31
  self.args = args
32
32
  self.log = args.log
33
+ self.cleaned_up = False
33
34
  self.tempfile: Path | None = None
34
35
 
35
36
  verbose = get_verbose(args.verbose)
@@ -75,11 +76,17 @@ class Process:
75
76
  def __enter__(self) -> "Process":
76
77
  return self
77
78
 
78
- def __exit__(self, exc_type, exc_val, exc_tb) -> None:
79
+ def dispose(self) -> None:
80
+ if self.cleaned_up:
81
+ return
82
+ self.cleaned_up = True
79
83
  self.terminate()
80
84
  self.wait()
81
85
  self.cleanup()
82
86
 
87
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
88
+ self.dispose()
89
+
83
90
  def cleanup(self) -> None:
84
91
  if self.tempfile:
85
92
  clear_temp_config_file(self.tempfile)
rclone_api/rclone_impl.py CHANGED
@@ -6,6 +6,7 @@ import os
6
6
  import random
7
7
  import subprocess
8
8
  import time
9
+ import tracemalloc
9
10
  import warnings
10
11
  from concurrent.futures import Future, ThreadPoolExecutor
11
12
  from datetime import datetime
@@ -51,6 +52,9 @@ from rclone_api.util import (
51
52
  to_path,
52
53
  )
53
54
 
55
+ # Enable tracing memory usage always
56
+ tracemalloc.start()
57
+
54
58
 
55
59
  def rclone_verbose(verbose: bool | None) -> bool:
56
60
  if verbose is not None:
@@ -1164,6 +1168,7 @@ class RcloneImpl:
1164
1168
  def serve_http(
1165
1169
  self,
1166
1170
  src: str,
1171
+ cache_mode: str | None,
1167
1172
  addr: str | None = None,
1168
1173
  serve_http_log: Path | None = None,
1169
1174
  other_args: list[str] | None = None,
@@ -1186,9 +1191,13 @@ class RcloneImpl:
1186
1191
  "0",
1187
1192
  "--vfs-read-chunk-size-limit",
1188
1193
  "512M",
1189
- "--vfs-cache-mode",
1190
- "off",
1191
1194
  ]
1195
+
1196
+ if cache_mode:
1197
+ cmd_list += [
1198
+ "--vfs-cache-mode",
1199
+ cache_mode,
1200
+ ]
1192
1201
  if serve_http_log:
1193
1202
  cmd_list += ["--log-file", str(serve_http_log)]
1194
1203
  cmd_list += ["-vvvv"]
@@ -232,7 +232,7 @@ def upload_parts_resumable(
232
232
 
233
233
  atexit.register(lambda: shutil.rmtree(tmp_dir, ignore_errors=True))
234
234
 
235
- with self.serve_http(src_dir) as http_server:
235
+ with self.serve_http(src_dir, cache_mode="minimal") as http_server:
236
236
  tmpdir: Path = Path(tmp_dir)
237
237
  write_semaphore = threading.Semaphore(threads)
238
238
  with ThreadPoolExecutor(max_workers=threads) as upload_executor:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rclone_api
3
- Version: 1.5.11
3
+ Version: 1.5.13
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -1,4 +1,4 @@
1
- rclone_api/__init__.py,sha256=uhoHM66jDRlk0Hq4PTrk7QZE6VcJqiu5Jeo9nj34edk,32380
1
+ rclone_api/__init__.py,sha256=nUDuo5YZQZybVsd0fiExyDPOOwxwZGSrD8Sx6Asb57U,32426
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
@@ -14,13 +14,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
16
  rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
17
- rclone_api/http_server.py,sha256=LhovQu2AI-Z7zQIWflWelCiCDLnWzisL32Rs5350kxE,8850
17
+ rclone_api/http_server.py,sha256=p1_S9VAViVvGif6NA_rxrDgMqnOmPTxJaHQ7B43FK70,10431
18
18
  rclone_api/install.py,sha256=Xb1BRn8rQcSpSd4dzmvIOELP2zM2DytUeIZ6jzv738A,2893
19
19
  rclone_api/log.py,sha256=VZHM7pNSXip2ZLBKMP7M1u-rp_F7zoafFDuR8CPUoKI,1271
20
20
  rclone_api/mount.py,sha256=LZqEhuKZunbWVqmsOIqkkCotaxWJpdFRS1InXveoU5E,1428
21
21
  rclone_api/mount_util.py,sha256=jqhJEVTHV6c6lOOzUYb4FLMbqDMHdz7-QRcdH-IobFc,10154
22
- rclone_api/process.py,sha256=tGooS5NLdPuqHh7hCH8SfK44A6LGftPQCPQUNgSo0a0,5714
23
- rclone_api/rclone_impl.py,sha256=kr0gvOSuiwxU15rvATYZmSzpWYDiAzjZ2WNe1wqI6NM,46345
22
+ rclone_api/process.py,sha256=MeWiN-TrrN0HmtWexBPxGwf84z6f-_E5yaXE-YtLYpY,5879
23
+ rclone_api/rclone_impl.py,sha256=STHQ_hT0chyp2yj3Cp-Vd0xXc1Pdpo3p9J3bTQEm0XE,46531
24
24
  rclone_api/remote.py,sha256=mTgMTQTwxUmbLjTpr-AGTId2ycXKI9mLX5L7PPpDIoc,520
25
25
  rclone_api/rpath.py,sha256=Y1JjQWcie39EgQrq-UtbfDz5yDLCwwfu27W7AQXllSE,2860
26
26
  rclone_api/scan_missing_folders.py,sha256=-8NCwpCaHeHrX-IepCoAEsX1rl8S-GOCxcIhTr_w3gA,4747
@@ -50,12 +50,12 @@ rclone_api/s3/multipart/info_json.py,sha256=-e8UCwrqjAP64U8PmH-o2ciJ6TN48DwHktJf
50
50
  rclone_api/s3/multipart/merge_state.py,sha256=ziTB9CYV-OWaky5C1fOT9hifSY2zgUrk5HmX1Xeu2UA,4978
51
51
  rclone_api/s3/multipart/upload_info.py,sha256=d6_OfzFR_vtDzCEegFfzCfWi2kUBUV4aXZzqAEVp1c4,1874
52
52
  rclone_api/s3/multipart/upload_parts_inline.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9akiew3MFjGmufLo2w,12503
53
- rclone_api/s3/multipart/upload_parts_resumable.py,sha256=diJoUpVYow6No_dNgOZIYVsv43k4evb6zixqpzWJaUk,9771
53
+ rclone_api/s3/multipart/upload_parts_resumable.py,sha256=6-nlMclS8jyVvMvFbQDcZOX9MY1WbCcKA_s9bwuYxnk,9793
54
54
  rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=Fp2pdrs5dONQI9LkfNolgAGj1-Z2V1SsRd0r0sreuXI,18040
55
55
  rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
56
- rclone_api-1.5.11.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
57
- rclone_api-1.5.11.dist-info/METADATA,sha256=eCGnadYvv_mHa4-aQsgYKcHwDOPx6CSIsNPt-XVDLMY,32657
58
- rclone_api-1.5.11.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
59
- rclone_api-1.5.11.dist-info/entry_points.txt,sha256=fJteOlYVwgX3UbNuL9jJ0zUTuX2O79JFAeNgK7Sw7EQ,255
60
- rclone_api-1.5.11.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
61
- rclone_api-1.5.11.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (77.0.1)
2
+ Generator: setuptools (77.0.3)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5