rclone-api 1.1.14__py2.py3-none-any.whl → 1.1.16__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/process.py CHANGED
@@ -1,5 +1,9 @@
1
+ import atexit
1
2
  import os
2
3
  import subprocess
4
+ import threading
5
+ import time
6
+ import weakref
3
7
  from dataclasses import dataclass
4
8
  from pathlib import Path
5
9
  from tempfile import TemporaryDirectory
@@ -8,44 +12,10 @@ from typing import Any
8
12
  from rclone_api.config import Config
9
13
  from rclone_api.util import get_verbose
10
14
 
11
- # def rclone_launch_process(
12
- # cmd: list[str],
13
- # rclone_conf: Path | Config,
14
- # rclone_exe: Path,
15
- # verbose: bool | None = None,
16
- # ) -> subprocess.Popen:
17
- # tempdir: TemporaryDirectory | None = None
18
- # verbose = _get_verbose(verbose)
19
- # assert verbose is not None
20
-
21
- # try:
22
- # if isinstance(rclone_conf, Config):
23
- # tempdir = TemporaryDirectory()
24
- # tmpfile = Path(tempdir.name) / "rclone.conf"
25
- # tmpfile.write_text(rclone_conf.text, encoding="utf-8")
26
- # rclone_conf = tmpfile
27
- # cmd = (
28
- # [str(rclone_exe.resolve())] + ["--config", str(rclone_conf.resolve())] + cmd
29
- # )
30
- # if verbose:
31
- # cmd_str = subprocess.list2cmdline(cmd)
32
- # print(f"Running: {cmd_str}")
33
- # cp = subprocess.Popen(
34
- # cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False
35
- # )
36
- # return cp
37
- # finally:
38
- # if tempdir:
39
- # try:
40
- # tempdir.cleanup()
41
- # except Exception as e:
42
- # print(f"Error cleaning up tempdir: {e}")
43
-
44
15
 
45
16
  def _get_verbose(verbose: bool | None) -> bool:
46
17
  if verbose is not None:
47
18
  return verbose
48
- # get it from the environment
49
19
  return bool(int(os.getenv("RCLONE_API_VERBOSE", "0")))
50
20
 
51
21
 
@@ -93,6 +63,17 @@ class Process:
93
63
 
94
64
  self.process = subprocess.Popen(self.cmd, **kwargs) # type: ignore
95
65
 
66
+ # Register an atexit callback using a weak reference to avoid
67
+ # keeping the Process instance alive solely due to the callback.
68
+ self_ref = weakref.ref(self)
69
+
70
+ def exit_cleanup():
71
+ obj = self_ref()
72
+ if obj is not None:
73
+ obj._atexit_terminate()
74
+
75
+ atexit.register(exit_cleanup)
76
+
96
77
  def cleanup(self) -> None:
97
78
  if self.tempdir and self.needs_cleanup:
98
79
  try:
@@ -100,6 +81,41 @@ class Process:
100
81
  except Exception as e:
101
82
  print(f"Error cleaning up tempdir: {e}")
102
83
 
84
+ def _atexit_terminate(self) -> None:
85
+ """
86
+ Registered via atexit, this method attempts to gracefully terminate the process.
87
+ If the process does not exit within a short timeout, it is aggressively killed.
88
+ """
89
+ if self.process.poll() is None: # Process is still running
90
+
91
+ def terminate_sequence():
92
+ try:
93
+ # Try to terminate gracefully.
94
+ self.process.terminate()
95
+ except Exception as e:
96
+ print(f"Error calling terminate on process {self.process.pid}: {e}")
97
+ # Allow time for graceful shutdown.
98
+ timeout = 2 # seconds
99
+ start = time.time()
100
+ while self.process.poll() is None and (time.time() - start) < timeout:
101
+ time.sleep(0.1)
102
+ # If still running, kill aggressively.
103
+ if self.process.poll() is None:
104
+ try:
105
+ self.process.kill()
106
+ except Exception as e:
107
+ print(f"Error calling kill on process {self.process.pid}: {e}")
108
+ # Optionally wait briefly for termination.
109
+ try:
110
+ self.process.wait(timeout=1)
111
+ except Exception:
112
+ pass
113
+
114
+ # Run the termination sequence in a separate daemon thread.
115
+ t = threading.Thread(target=terminate_sequence, daemon=True)
116
+ t.start()
117
+ t.join(timeout=3)
118
+
103
119
  @property
104
120
  def pid(self) -> int:
105
121
  return self.process.pid
rclone_api/rclone.py CHANGED
@@ -711,6 +711,9 @@ class Rclone:
711
711
  vfs_disk_space_total_size.as_str(),
712
712
  ]
713
713
  other_args += ["--read-only"]
714
+ other_args += ["--direct-io"]
715
+ # --vfs-cache-max-size
716
+ other_args += ["--vfs-cache-max-size", vfs_disk_space_total_size.as_str()]
714
717
  mount_path = mount_path or Path("tmp_mnts") / random_str(12)
715
718
  src_path = Path(src)
716
719
  name = src_path.name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.1.14
3
+ Version: 1.1.16
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -12,8 +12,8 @@ rclone_api/file.py,sha256=EP5yT2dZ0H2p7CY5n0y5k5pHhIliV25pm8KOwBklUTk,1863
12
12
  rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
13
13
  rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
14
14
  rclone_api/mount.py,sha256=g9YkKCGJbWvGF7gzSKtWa8pEgphuW0-e0SySxtOirH4,6093
15
- rclone_api/process.py,sha256=xYUgU17txkZfZdr4vtRfvD8YjvSfdrbjM7PYW1npAMI,4264
16
- rclone_api/rclone.py,sha256=lCqHJ_IznQxVQTsmAyF4cym-rkc088or-EIs4NYhbO8,40102
15
+ rclone_api/process.py,sha256=Hgn8MGEPkBt8C6C4oIuh-n1t1GkFF2miPlIE1lh_Zbc,5045
16
+ rclone_api/rclone.py,sha256=OvzshnLhcnDWvcoXwnMYg5NfNPpn_b2Ws1qB-UPoSBQ,40254
17
17
  rclone_api/remote.py,sha256=O9WDUFQy9f6oT1HdUbTixK2eg0xtBBm8k4Xl6aa6K00,431
18
18
  rclone_api/rpath.py,sha256=8ZA_1wxWtskwcy0I8V2VbjKDmzPkiWd8Q2JQSvh-sYE,2586
19
19
  rclone_api/scan_missing_folders.py,sha256=Kulca2Q6WZodt00ATFHkmqqInuoPvBkhTcS9703y6po,4740
@@ -32,9 +32,9 @@ rclone_api/s3/chunk_types.py,sha256=vUmaTl3hGPodriM9DW1nAsYm0kHGfNT8nPWv6ur22Jo,
32
32
  rclone_api/s3/chunk_uploader.py,sha256=7Qumc2emQ-SpbnTL8PBN4ElpghnFWJfozVHPhm6LrQ4,9683
33
33
  rclone_api/s3/create.py,sha256=SK3IGHZwsSkoG4Zb4NCphcVg9_f7VifDKng-tExMS2s,3088
34
34
  rclone_api/s3/types.py,sha256=yBnJ38Tjk6RlydJ-sqZ7DSfyFloy8KDYJ0mv3vlOzLE,1388
35
- rclone_api-1.1.14.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
36
- rclone_api-1.1.14.dist-info/METADATA,sha256=oc-3Ju-_0eikBf6sP_EOVwgcWTMwxaY1zRvbCVaz5q0,4479
37
- rclone_api-1.1.14.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
38
- rclone_api-1.1.14.dist-info/entry_points.txt,sha256=6eNqTRXKhVf8CpWNjXiOa_0Du9tHiW_HD2iQSXRsUg8,132
39
- rclone_api-1.1.14.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
40
- rclone_api-1.1.14.dist-info/RECORD,,
35
+ rclone_api-1.1.16.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
36
+ rclone_api-1.1.16.dist-info/METADATA,sha256=rJCrejq4GzvZXK-wJ6E6MScUVadEjwbzQHZP3CLgD7k,4479
37
+ rclone_api-1.1.16.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
38
+ rclone_api-1.1.16.dist-info/entry_points.txt,sha256=6eNqTRXKhVf8CpWNjXiOa_0Du9tHiW_HD2iQSXRsUg8,132
39
+ rclone_api-1.1.16.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
40
+ rclone_api-1.1.16.dist-info/RECORD,,