rclone-api 1.5.44__py3-none-any.whl → 1.5.46__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.
@@ -2,6 +2,7 @@
2
2
  Unit test file.
3
3
  """
4
4
 
5
+ import logging
5
6
  import platform
6
7
  from pathlib import Path
7
8
 
@@ -9,6 +10,9 @@ from rclone_api.install import rclone_download
9
10
 
10
11
 
11
12
  def main() -> None:
13
+ # set the root logger level to DEBUG
14
+ root_logger = logging.getLogger()
15
+ root_logger.setLevel(logging.DEBUG)
12
16
  rclone_exe = "rclone"
13
17
  if platform.system() == "Windows":
14
18
  rclone_exe += ".exe"
rclone_api/install.py CHANGED
@@ -1,95 +1,139 @@
1
- import os
2
- import platform
3
- import shutil
4
- from pathlib import Path
5
- from tempfile import TemporaryDirectory
6
- from warnings import warn
7
-
8
- from download import download
9
-
10
- URL_WINDOWS = "https://downloads.rclone.org/rclone-current-windows-amd64.zip"
11
- URL_LINUX = "https://downloads.rclone.org/rclone-current-linux-amd64.zip"
12
- URL_MACOS_ARM = "https://downloads.rclone.org/rclone-current-osx-arm64.zip"
13
- URL_MACOS_X86 = "https://downloads.rclone.org/rclone-current-osx-amd64.zip"
14
-
15
-
16
- def rclone_download_url() -> str:
17
- system = platform.system()
18
- arch = platform.machine()
19
- if system == "Windows":
20
- assert "arm" not in arch, f"Unsupported arch: {arch}"
21
- return URL_WINDOWS
22
- elif system == "Linux":
23
- assert "arm" not in arch, f"Unsupported arch: {arch}"
24
- return URL_LINUX
25
- elif system == "Darwin":
26
- if "x86" in arch:
27
- return URL_MACOS_X86
28
- elif "arm" in arch:
29
- return URL_MACOS_ARM
30
- else:
31
- raise Exception(f"Unsupported arch: {arch}")
32
- else:
33
- raise Exception("Unsupported system")
34
-
35
-
36
- def _remove_signed_binary_requirements(out: Path) -> None:
37
- if platform.system() == "Windows":
38
- return
39
- # mac os
40
- if platform.system() == "Darwin":
41
- # remove signed binary requirements
42
- #
43
- # xattr -d com.apple.quarantine rclone
44
- import subprocess
45
-
46
- subprocess.run(
47
- ["xattr", "-d", "com.apple.quarantine", str(out)],
48
- capture_output=True,
49
- check=False,
50
- )
51
- return
52
-
53
-
54
- def _make_executable(out: Path) -> None:
55
- if platform.system() == "Windows":
56
- return
57
- # linux and mac os
58
- os.chmod(out, 0o755)
59
-
60
-
61
- def _find_rclone_exe(start: Path) -> Path | None:
62
- for root, dirs, files in os.walk(start):
63
- if platform.system() == "Windows":
64
- if "rclone.exe" in files:
65
- return Path(root) / "rclone.exe"
66
- else:
67
- if "rclone" in files:
68
- return Path(root) / "rclone"
69
- return None
70
-
71
-
72
- def rclone_download(out: Path, replace=False) -> Exception | None:
73
- if out.exists() and not replace:
74
- return None
75
- try:
76
- url = rclone_download_url()
77
- with TemporaryDirectory() as tmpdir:
78
- tmp = Path(tmpdir)
79
- download(url, tmp, kind="zip", replace=True)
80
- exe = _find_rclone_exe(tmp)
81
- if exe is None:
82
- raise FileNotFoundError("rclone executable not found")
83
- if os.path.exists(out):
84
- os.remove(out)
85
- out.parent.mkdir(parents=True, exist_ok=True)
86
- shutil.move(exe, out)
87
- _remove_signed_binary_requirements(out)
88
- _make_executable(out)
89
- return None
90
- except Exception as e:
91
- import traceback
92
-
93
- stacktrace = traceback.format_exc()
94
- warn(f"Failed to download rclone: {e}\n{stacktrace}")
95
- return e
1
+ import logging
2
+ import os
3
+ import platform
4
+ import shutil
5
+ from pathlib import Path
6
+ from tempfile import TemporaryDirectory
7
+ from warnings import warn
8
+
9
+ from download import download
10
+
11
+ URL_WINDOWS = "https://downloads.rclone.org/rclone-current-windows-amd64.zip"
12
+ URL_LINUX = "https://downloads.rclone.org/rclone-current-linux-amd64.zip"
13
+ URL_MACOS_ARM = "https://downloads.rclone.org/rclone-current-osx-arm64.zip"
14
+ URL_MACOS_X86 = "https://downloads.rclone.org/rclone-current-osx-amd64.zip"
15
+
16
+ logger = logging.getLogger(__name__)
17
+ logging.basicConfig(level=logging.DEBUG)
18
+
19
+
20
+ def rclone_download_url() -> str:
21
+ system = platform.system()
22
+ arch = platform.machine()
23
+ if system == "Windows":
24
+ assert "arm" not in arch, f"Unsupported arch: {arch}"
25
+ return URL_WINDOWS
26
+ elif system == "Linux":
27
+ assert "arm" not in arch, f"Unsupported arch: {arch}"
28
+ return URL_LINUX
29
+ elif system == "Darwin":
30
+ if "x86" in arch:
31
+ return URL_MACOS_X86
32
+ elif "arm" in arch:
33
+ return URL_MACOS_ARM
34
+ else:
35
+ raise Exception(f"Unsupported arch: {arch}")
36
+ else:
37
+ raise Exception("Unsupported system")
38
+
39
+
40
+ def _remove_signed_binary_requirements(out: Path) -> None:
41
+ if platform.system() == "Windows":
42
+ return
43
+ # mac os
44
+ if platform.system() == "Darwin":
45
+ # remove signed binary requirements
46
+ #
47
+ # xattr -d com.apple.quarantine rclone
48
+ import subprocess
49
+
50
+ subprocess.run(
51
+ ["xattr", "-d", "com.apple.quarantine", str(out)],
52
+ capture_output=True,
53
+ check=False,
54
+ )
55
+ return
56
+
57
+
58
+ def _make_executable(out: Path) -> None:
59
+ if platform.system() == "Windows":
60
+ return
61
+ # linux and mac os
62
+ os.chmod(out, 0o755)
63
+
64
+
65
+ def _find_rclone_exe(start: Path) -> Path | None:
66
+ for root, dirs, files in os.walk(start):
67
+ if platform.system() == "Windows":
68
+ if "rclone.exe" in files:
69
+ return Path(root) / "rclone.exe"
70
+ else:
71
+ if "rclone" in files:
72
+ return Path(root) / "rclone"
73
+ return None
74
+
75
+
76
+ def _move_to_standard_linux_paths(exe_path: Path) -> None:
77
+ """Move rclone to standard paths on Linux systems and create a symlink in the original location."""
78
+ if platform.system() != "Linux":
79
+ return
80
+
81
+ try:
82
+ # Create directory in standard path if it doesn't exist
83
+ bin_path = Path("/usr/local/bin/rclone")
84
+
85
+ if os.access("/usr/local/bin", os.W_OK):
86
+ # Remove existing binary if it exists
87
+ if bin_path.exists():
88
+ if bin_path.is_symlink():
89
+ bin_path.unlink()
90
+ else:
91
+ os.remove(bin_path)
92
+
93
+ # Move the binary to standard path
94
+ shutil.move(str(exe_path), str(bin_path))
95
+
96
+ # Make it executable
97
+ os.chmod(bin_path, 0o755)
98
+
99
+ # Create a symlink in the original location
100
+ exe_path.symlink_to(bin_path)
101
+
102
+ logger.info(f"Moved rclone to {bin_path} and created symlink at {exe_path}")
103
+ else:
104
+ logger.warning(
105
+ "No write permission to /usr/local/bin, skipping move operation"
106
+ )
107
+ except Exception as e:
108
+ logger.warning(f"Failed to move rclone to standard paths: {e}")
109
+
110
+
111
+ def rclone_download(out: Path, replace=False) -> Exception | None:
112
+ if out.exists() and not replace:
113
+ return None
114
+ try:
115
+ url = rclone_download_url()
116
+ with TemporaryDirectory() as tmpdir:
117
+ tmp = Path(tmpdir)
118
+ logging.info(f"Downloading rclone from {url} to {tmp.absolute()}")
119
+ download(url, tmp, kind="zip", replace=True)
120
+ exe = _find_rclone_exe(tmp)
121
+ if exe is None:
122
+ raise FileNotFoundError("rclone executable not found")
123
+ if os.path.exists(out):
124
+ os.remove(out)
125
+ out.parent.mkdir(parents=True, exist_ok=True)
126
+ shutil.move(exe, out)
127
+ _remove_signed_binary_requirements(out)
128
+ _make_executable(out)
129
+
130
+ # Move to standard paths on Linux
131
+ _move_to_standard_linux_paths(out)
132
+
133
+ return None
134
+ except Exception as e:
135
+ import traceback
136
+
137
+ stacktrace = traceback.format_exc()
138
+ warn(f"Failed to download rclone: {e}\n{stacktrace}")
139
+ return e
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rclone_api
3
- Version: 1.5.44
3
+ Version: 1.5.46
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -16,7 +16,7 @@ rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
16
16
  rclone_api/fs.py,sha256=xUkoSV2R9dByKgueZ3x2GjyCn9fM7tK1ydgK1Whiph0,8933
17
17
  rclone_api/group_files.py,sha256=H92xPW9lQnbNw5KbtZCl00bD6iRh9yRbCuxku4j_3dg,8036
18
18
  rclone_api/http_server.py,sha256=P-LT2GqCEM9tGbyzzr-CrSOc3FyCw1qXUSQ5bY2KBHU,12113
19
- rclone_api/install.py,sha256=Xb1BRn8rQcSpSd4dzmvIOELP2zM2DytUeIZ6jzv738A,2893
19
+ rclone_api/install.py,sha256=db7l5KoVBr84HbFxih1Sd82tUfzhOuczKfBLb_Dn3XU,4507
20
20
  rclone_api/log.py,sha256=VZHM7pNSXip2ZLBKMP7M1u-rp_F7zoafFDuR8CPUoKI,1271
21
21
  rclone_api/mount.py,sha256=LZqEhuKZunbWVqmsOIqkkCotaxWJpdFRS1InXveoU5E,1428
22
22
  rclone_api/mount_util.py,sha256=jqhJEVTHV6c6lOOzUYb4FLMbqDMHdz7-QRcdH-IobFc,10154
@@ -31,7 +31,7 @@ rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8
31
31
  rclone_api/cmd/analyze.py,sha256=RHbvk1G5ZUc3qLqlm1AZEyQzd_W_ZjcbCNDvW4YpTKQ,1252
32
32
  rclone_api/cmd/copy_large_s3.py,sha256=E0B7P-JJTuOM7wMZtwQHJCpoLhccJleh0mnMq8ZiSUo,3234
33
33
  rclone_api/cmd/copy_large_s3_finish.py,sha256=SNCqkvu8YtxPKmBp37WVMP876YhxV0kJDoYuOSNPaPY,2309
34
- rclone_api/cmd/install_rclone.py,sha256=iy8XMZL_YSGhFVfVBPwGST8G3VcZGYBK9ctdg5UqKas,326
34
+ rclone_api/cmd/install_rclone.py,sha256=F2iqbrla02SS45-On-PDX92EGQw3T7nRsjBftupNqQ0,460
35
35
  rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
36
36
  rclone_api/cmd/save_to_db.py,sha256=ylvnhg_yzexM-m6Zr7XDiswvoDVSl56ELuFAdb9gqBY,1957
37
37
  rclone_api/db/__init__.py,sha256=OSRUdnSWUlDTOHmjdjVmxYTUNpTbtaJ5Ll9sl-PfZg0,40
@@ -55,9 +55,9 @@ rclone_api/s3/multipart/upload_parts_inline.py,sha256=V7syKjFyVIe4U9Ahl5XgqVTzt9
55
55
  rclone_api/s3/multipart/upload_parts_resumable.py,sha256=6-nlMclS8jyVvMvFbQDcZOX9MY1WbCcKA_s9bwuYxnk,9793
56
56
  rclone_api/s3/multipart/upload_parts_server_side_merge.py,sha256=Fp2pdrs5dONQI9LkfNolgAGj1-Z2V1SsRd0r0sreuXI,18040
57
57
  rclone_api/s3/multipart/upload_state.py,sha256=f-Aq2NqtAaMUMhYitlICSNIxCKurWAl2gDEUVizLIqw,6019
58
- rclone_api-1.5.44.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
59
- rclone_api-1.5.44.dist-info/METADATA,sha256=PY16Qd_EUh8ozilT737GPVqua1WVpkbKZ8PYT9YWGik,37305
60
- rclone_api-1.5.44.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
61
- rclone_api-1.5.44.dist-info/entry_points.txt,sha256=ognh2e11HTjn73_KL5MWI67pBKS2jekBi-QTiRXySXA,316
62
- rclone_api-1.5.44.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
63
- rclone_api-1.5.44.dist-info/RECORD,,
58
+ rclone_api-1.5.46.dist-info/licenses/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
59
+ rclone_api-1.5.46.dist-info/METADATA,sha256=KqRtpIh195KJQ-8gY8HYZLcY4Qm1KUFVXC5XCw_av8o,37305
60
+ rclone_api-1.5.46.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
61
+ rclone_api-1.5.46.dist-info/entry_points.txt,sha256=ognh2e11HTjn73_KL5MWI67pBKS2jekBi-QTiRXySXA,316
62
+ rclone_api-1.5.46.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
63
+ rclone_api-1.5.46.dist-info/RECORD,,