rclone-api 1.1.30__py2.py3-none-any.whl → 1.1.31__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/exec.py +4 -1
- rclone_api/mount.py +5 -4
- rclone_api/process.py +5 -7
- rclone_api/profiling/mount_copy_bytes.py +145 -0
- rclone_api/rclone.py +20 -11
- {rclone_api-1.1.30.dist-info → rclone_api-1.1.31.dist-info}/METADATA +2 -1
- {rclone_api-1.1.30.dist-info → rclone_api-1.1.31.dist-info}/RECORD +11 -10
- {rclone_api-1.1.30.dist-info → rclone_api-1.1.31.dist-info}/LICENSE +0 -0
- {rclone_api-1.1.30.dist-info → rclone_api-1.1.31.dist-info}/WHEEL +0 -0
- {rclone_api-1.1.30.dist-info → rclone_api-1.1.31.dist-info}/entry_points.txt +0 -0
- {rclone_api-1.1.30.dist-info → rclone_api-1.1.31.dist-info}/top_level.txt +0 -0
rclone_api/exec.py
CHANGED
|
@@ -23,7 +23,9 @@ class RcloneExec:
|
|
|
23
23
|
cmd, self.rclone_config, self.rclone_exe, check=check, capture=capture
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
-
def launch_process(
|
|
26
|
+
def launch_process(
|
|
27
|
+
self, cmd: list[str], capture: bool | None, log: Path | None
|
|
28
|
+
) -> Process:
|
|
27
29
|
"""Launch rclone process."""
|
|
28
30
|
|
|
29
31
|
args: ProcessArgs = ProcessArgs(
|
|
@@ -32,6 +34,7 @@ class RcloneExec:
|
|
|
32
34
|
rclone_exe=self.rclone_exe,
|
|
33
35
|
cmd_list=cmd,
|
|
34
36
|
capture_stdout=capture,
|
|
37
|
+
log=log,
|
|
35
38
|
)
|
|
36
39
|
process = Process(args)
|
|
37
40
|
return process
|
rclone_api/mount.py
CHANGED
|
@@ -105,8 +105,8 @@ def clean_mount(mount: Mount | Path, verbose: bool = False, wait=True) -> None:
|
|
|
105
105
|
mount_path = mount.mount_path if isinstance(mount, Mount) else mount
|
|
106
106
|
try:
|
|
107
107
|
mount_exists = mount_path.exists()
|
|
108
|
-
except OSError
|
|
109
|
-
warnings.warn(f"Error checking {mount_path}: {e}")
|
|
108
|
+
except OSError:
|
|
109
|
+
# warnings.warn(f"Error checking {mount_path}: {e}")
|
|
110
110
|
mount_exists = True
|
|
111
111
|
|
|
112
112
|
# Give the system a moment (if unmount is in progress, etc.)
|
|
@@ -139,8 +139,9 @@ def clean_mount(mount: Mount | Path, verbose: bool = False, wait=True) -> None:
|
|
|
139
139
|
mount_path.rmdir()
|
|
140
140
|
if verbose:
|
|
141
141
|
print(f"Successfully removed mount directory {mount_path}")
|
|
142
|
-
except Exception
|
|
143
|
-
warnings.warn(f"Failed to remove mount {mount_path}: {e}")
|
|
142
|
+
except Exception:
|
|
143
|
+
# warnings.warn(f"Failed to remove mount {mount_path}: {e}")
|
|
144
|
+
pass
|
|
144
145
|
else:
|
|
145
146
|
warnings.warn(f"Unsupported platform: {_SYSTEM}")
|
|
146
147
|
|
rclone_api/process.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import atexit
|
|
2
|
-
import os
|
|
3
2
|
import subprocess
|
|
4
3
|
import threading
|
|
5
4
|
import time
|
|
@@ -13,12 +12,6 @@ from rclone_api.config import Config
|
|
|
13
12
|
from rclone_api.util import get_verbose
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
def _get_verbose(verbose: bool | None) -> bool:
|
|
17
|
-
if verbose is not None:
|
|
18
|
-
return verbose
|
|
19
|
-
return bool(int(os.getenv("RCLONE_API_VERBOSE", "0")))
|
|
20
|
-
|
|
21
|
-
|
|
22
15
|
@dataclass
|
|
23
16
|
class ProcessArgs:
|
|
24
17
|
cmd: list[str]
|
|
@@ -27,12 +20,14 @@ class ProcessArgs:
|
|
|
27
20
|
cmd_list: list[str]
|
|
28
21
|
verbose: bool | None = None
|
|
29
22
|
capture_stdout: bool | None = None
|
|
23
|
+
log: Path | None = None
|
|
30
24
|
|
|
31
25
|
|
|
32
26
|
class Process:
|
|
33
27
|
def __init__(self, args: ProcessArgs) -> None:
|
|
34
28
|
assert args.rclone_exe.exists()
|
|
35
29
|
self.args = args
|
|
30
|
+
self.log = args.log
|
|
36
31
|
self.tempdir: TemporaryDirectory | None = None
|
|
37
32
|
verbose = get_verbose(args.verbose)
|
|
38
33
|
if isinstance(args.rclone_conf, Config):
|
|
@@ -52,6 +47,9 @@ class Process:
|
|
|
52
47
|
+ ["--config", str(rclone_conf.resolve())]
|
|
53
48
|
+ args.cmd
|
|
54
49
|
)
|
|
50
|
+
if self.args.log:
|
|
51
|
+
self.args.log.parent.mkdir(parents=True, exist_ok=True)
|
|
52
|
+
self.cmd += ["--log-file", str(self.args.log)]
|
|
55
53
|
if verbose:
|
|
56
54
|
cmd_str = subprocess.list2cmdline(self.cmd)
|
|
57
55
|
print(f"Running: {cmd_str}")
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit test file.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import time
|
|
7
|
+
import unittest
|
|
8
|
+
|
|
9
|
+
import psutil
|
|
10
|
+
from dotenv import load_dotenv
|
|
11
|
+
|
|
12
|
+
from rclone_api import Config, Rclone, SizeSuffix
|
|
13
|
+
|
|
14
|
+
load_dotenv()
|
|
15
|
+
|
|
16
|
+
BUCKET_NAME = os.getenv("BUCKET_NAME") # Default if not in .env
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _generate_rclone_config() -> Config:
|
|
20
|
+
|
|
21
|
+
# assert that .env exists for this test
|
|
22
|
+
assert os.path.exists(
|
|
23
|
+
".env"
|
|
24
|
+
), "this test requires that the secret .env file exists with the credentials"
|
|
25
|
+
|
|
26
|
+
# BUCKET_NAME = os.getenv("BUCKET_NAME", "TorrentBooks") # Default if not in .env
|
|
27
|
+
|
|
28
|
+
# Load additional environment variables
|
|
29
|
+
BUCKET_KEY_SECRET = os.getenv("BUCKET_KEY_SECRET")
|
|
30
|
+
BUCKET_KEY_PUBLIC = os.getenv("BUCKET_KEY_PUBLIC")
|
|
31
|
+
SRC_SFTP_HOST = os.getenv("SRC_SFTP_HOST")
|
|
32
|
+
SRC_SFTP_USER = os.getenv("SRC_SFTP_USER")
|
|
33
|
+
SRC_SFTP_PORT = os.getenv("SRC_SFTP_PORT")
|
|
34
|
+
SRC_SFTP_PASS = os.getenv("SRC_SFTP_PASS")
|
|
35
|
+
# BUCKET_URL = os.getenv("BUCKET_URL")
|
|
36
|
+
BUCKET_URL = "sfo3.digitaloceanspaces.com"
|
|
37
|
+
|
|
38
|
+
config_text = f"""
|
|
39
|
+
[dst]
|
|
40
|
+
type = s3
|
|
41
|
+
provider = DigitalOcean
|
|
42
|
+
access_key_id = {BUCKET_KEY_PUBLIC}
|
|
43
|
+
secret_access_key = {BUCKET_KEY_SECRET}
|
|
44
|
+
endpoint = {BUCKET_URL}
|
|
45
|
+
bucket = {BUCKET_NAME}
|
|
46
|
+
|
|
47
|
+
[src]
|
|
48
|
+
type = sftp
|
|
49
|
+
host = {SRC_SFTP_HOST}
|
|
50
|
+
user = {SRC_SFTP_USER}
|
|
51
|
+
port = {SRC_SFTP_PORT}
|
|
52
|
+
pass = {SRC_SFTP_PASS}
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
# _CONFIG_PATH.write_text(config_text, encoding="utf-8")
|
|
56
|
+
# print(f"Config file written to: {_CONFIG_PATH}")
|
|
57
|
+
return Config(config_text)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class RcloneProfileCopyBytes(unittest.TestCase):
|
|
61
|
+
"""Test rclone functionality."""
|
|
62
|
+
|
|
63
|
+
def setUp(self) -> None:
|
|
64
|
+
"""Check if all required environment variables are set before running tests."""
|
|
65
|
+
required_vars = [
|
|
66
|
+
"BUCKET_NAME",
|
|
67
|
+
"BUCKET_KEY_SECRET",
|
|
68
|
+
"BUCKET_KEY_PUBLIC",
|
|
69
|
+
"BUCKET_URL",
|
|
70
|
+
]
|
|
71
|
+
missing = [var for var in required_vars if not os.getenv(var)]
|
|
72
|
+
if missing:
|
|
73
|
+
self.skipTest(
|
|
74
|
+
f"Missing required environment variables: {', '.join(missing)}"
|
|
75
|
+
)
|
|
76
|
+
os.environ["RCLONE_API_VERBOSE"] = "1"
|
|
77
|
+
|
|
78
|
+
def test_profile_copy_bytes(self) -> None:
|
|
79
|
+
rclone = Rclone(_generate_rclone_config())
|
|
80
|
+
sizes = [
|
|
81
|
+
1024 * 1024 * 1,
|
|
82
|
+
1024 * 1024 * 2,
|
|
83
|
+
1024 * 1024 * 4,
|
|
84
|
+
1024 * 1024 * 8,
|
|
85
|
+
1024 * 1024 * 16,
|
|
86
|
+
1024 * 1024 * 32,
|
|
87
|
+
1024 * 1024 * 64,
|
|
88
|
+
]
|
|
89
|
+
# transfer_list = [1, 2, 4, 8, 16]
|
|
90
|
+
transfer_list = [1, 2, 4]
|
|
91
|
+
|
|
92
|
+
# src_file = "dst:rclone-api-unit-test/zachs_video/internaly_ai_alignment.mp4"
|
|
93
|
+
# sftp mount
|
|
94
|
+
src_file = "src:aa_misc_data/aa_misc_data/world_lending_library_2024_11.tar.zst"
|
|
95
|
+
|
|
96
|
+
for size in sizes:
|
|
97
|
+
for transfers in transfer_list:
|
|
98
|
+
print("\n\n")
|
|
99
|
+
print("#" * 80)
|
|
100
|
+
print(
|
|
101
|
+
f"# Started test download of {SizeSuffix(size)} with {transfers} transfers"
|
|
102
|
+
)
|
|
103
|
+
print("#" * 80)
|
|
104
|
+
net_io_start = psutil.net_io_counters()
|
|
105
|
+
start = time.time()
|
|
106
|
+
bytes_or_err: bytes | Exception = rclone.copy_bytes(
|
|
107
|
+
src=src_file,
|
|
108
|
+
offset=0,
|
|
109
|
+
length=size,
|
|
110
|
+
direct_io=True,
|
|
111
|
+
transfers=transfers,
|
|
112
|
+
)
|
|
113
|
+
diff = time.time() - start
|
|
114
|
+
net_io_end = psutil.net_io_counters()
|
|
115
|
+
if isinstance(bytes_or_err, Exception):
|
|
116
|
+
print(bytes_or_err)
|
|
117
|
+
self.fail(f"Error: {bytes_or_err}")
|
|
118
|
+
assert isinstance(bytes_or_err, bytes)
|
|
119
|
+
self.assertEqual(len(bytes_or_err), size)
|
|
120
|
+
|
|
121
|
+
# print io stats
|
|
122
|
+
bytes_sent = net_io_end.bytes_sent - net_io_start.bytes_sent
|
|
123
|
+
bytes_recv = net_io_end.bytes_recv - net_io_start.bytes_recv
|
|
124
|
+
packets_sent = net_io_end.packets_sent - net_io_start.packets_sent
|
|
125
|
+
efficiency = size / (bytes_recv)
|
|
126
|
+
efficiency_100 = efficiency * 100
|
|
127
|
+
efficiency_str = f"{efficiency_100:.2f}"
|
|
128
|
+
|
|
129
|
+
bytes_send_suffix = SizeSuffix(bytes_sent)
|
|
130
|
+
bytes_recv_suffix = SizeSuffix(bytes_recv)
|
|
131
|
+
range_size = SizeSuffix(size)
|
|
132
|
+
|
|
133
|
+
print(f"\nFinished downloading {range_size} with {transfers} transfers")
|
|
134
|
+
print("Net IO stats:")
|
|
135
|
+
print(f"Bytes sent: {bytes_send_suffix}")
|
|
136
|
+
print(f"Bytes received: {bytes_recv_suffix}")
|
|
137
|
+
print(f"Packets sent: {packets_sent}")
|
|
138
|
+
print(f"Efficiency: {efficiency_str}%")
|
|
139
|
+
print(f"Time: {diff:.1f} seconds")
|
|
140
|
+
|
|
141
|
+
print("done")
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
unittest.main()
|
rclone_api/rclone.py
CHANGED
|
@@ -80,8 +80,10 @@ class Rclone:
|
|
|
80
80
|
) -> subprocess.CompletedProcess:
|
|
81
81
|
return self._exec.execute(cmd, check=check, capture=capture)
|
|
82
82
|
|
|
83
|
-
def _launch_process(
|
|
84
|
-
|
|
83
|
+
def _launch_process(
|
|
84
|
+
self, cmd: list[str], capture: bool | None = None, log: Path | None = None
|
|
85
|
+
) -> Process:
|
|
86
|
+
return self._exec.launch_process(cmd, capture=capture, log=log)
|
|
85
87
|
|
|
86
88
|
def webgui(self, other_args: list[str] | None = None) -> Process:
|
|
87
89
|
"""Launch the Rclone web GUI."""
|
|
@@ -684,6 +686,7 @@ class Rclone:
|
|
|
684
686
|
verbose: bool | None = None,
|
|
685
687
|
max_chunks_before_suspension: int | None = None,
|
|
686
688
|
mount_path: Path | None = None,
|
|
689
|
+
mount_log: Path | None = None,
|
|
687
690
|
) -> MultiUploadResult:
|
|
688
691
|
"""For massive files that rclone can't handle in one go, this function will copy the file in chunks to an S3 store"""
|
|
689
692
|
from rclone_api.s3.api import S3Client
|
|
@@ -724,6 +727,7 @@ class Rclone:
|
|
|
724
727
|
use_links=True,
|
|
725
728
|
vfs_cache_mode="minimal",
|
|
726
729
|
verbose=False,
|
|
730
|
+
log=mount_log,
|
|
727
731
|
other_args=other_args,
|
|
728
732
|
):
|
|
729
733
|
path_info: S3PathInfo = split_s3_path(dst)
|
|
@@ -816,10 +820,11 @@ class Rclone:
|
|
|
816
820
|
src: str,
|
|
817
821
|
offset: int,
|
|
818
822
|
length: int,
|
|
819
|
-
transfers: int =
|
|
820
|
-
outfile
|
|
821
|
-
|
|
822
|
-
|
|
823
|
+
transfers: int = 1, # Note, increasing transfers can result in devestating drop in performance.
|
|
824
|
+
# If outfile is supplied then bytes are written to this file and success returns bytes(0)
|
|
825
|
+
outfile: Path | None = None,
|
|
826
|
+
mount_log: Path | None = None,
|
|
827
|
+
direct_io: bool = True,
|
|
823
828
|
) -> bytes | Exception:
|
|
824
829
|
"""Copy bytes from a file to another file."""
|
|
825
830
|
from rclone_api.util import random_str
|
|
@@ -828,8 +833,7 @@ class Rclone:
|
|
|
828
833
|
src_parent_path = Path(src).parent.as_posix()
|
|
829
834
|
src_file = Path(src).name
|
|
830
835
|
other_args: list[str] = ["--no-modtime", "--vfs-read-wait", "1s"]
|
|
831
|
-
|
|
832
|
-
vfs_read_chunk_size = unit_chunk_size
|
|
836
|
+
vfs_read_chunk_size = length // transfers
|
|
833
837
|
vfs_read_chunk_size_limit = length
|
|
834
838
|
vfs_read_chunk_streams = transfers
|
|
835
839
|
vfs_disk_space_total_size = length
|
|
@@ -838,7 +842,8 @@ class Rclone:
|
|
|
838
842
|
other_args += ["--vfs-read-chunk-streams", str(vfs_read_chunk_streams)]
|
|
839
843
|
other_args += ["--vfs-disk-space-total-size", str(vfs_disk_space_total_size)]
|
|
840
844
|
other_args += ["--read-only"]
|
|
841
|
-
|
|
845
|
+
if direct_io:
|
|
846
|
+
other_args += ["--direct-io"]
|
|
842
847
|
|
|
843
848
|
try:
|
|
844
849
|
# use scoped mount to do the read, then write the bytes to the destination
|
|
@@ -846,9 +851,10 @@ class Rclone:
|
|
|
846
851
|
src_parent_path,
|
|
847
852
|
tmp_mnt,
|
|
848
853
|
use_links=True,
|
|
849
|
-
verbose=
|
|
854
|
+
verbose=mount_log is not None,
|
|
850
855
|
vfs_cache_mode="minimal",
|
|
851
856
|
other_args=other_args,
|
|
857
|
+
log=mount_log,
|
|
852
858
|
):
|
|
853
859
|
src_file_mnt = tmp_mnt / src_file
|
|
854
860
|
with open(src_file_mnt, "rb") as f:
|
|
@@ -896,6 +902,7 @@ class Rclone:
|
|
|
896
902
|
use_links: bool | None = None,
|
|
897
903
|
vfs_cache_mode: str | None = None,
|
|
898
904
|
verbose: bool | None = None,
|
|
905
|
+
log: Path | None = None,
|
|
899
906
|
other_args: list[str] | None = None,
|
|
900
907
|
) -> Mount:
|
|
901
908
|
"""Mount a remote or directory to a local path.
|
|
@@ -930,7 +937,7 @@ class Rclone:
|
|
|
930
937
|
cmd_list.append("-vvvv")
|
|
931
938
|
if other_args:
|
|
932
939
|
cmd_list += other_args
|
|
933
|
-
proc = self._launch_process(cmd_list)
|
|
940
|
+
proc = self._launch_process(cmd_list, log=log)
|
|
934
941
|
mount_read_only = "--read-only" in cmd_list # hint to allow fast teardown
|
|
935
942
|
mount: Mount = Mount(mount_path=outdir, process=proc, read_only=mount_read_only)
|
|
936
943
|
return mount
|
|
@@ -944,6 +951,7 @@ class Rclone:
|
|
|
944
951
|
use_links: bool | None = None,
|
|
945
952
|
vfs_cache_mode: str | None = None,
|
|
946
953
|
verbose: bool | None = None,
|
|
954
|
+
log: Path | None = None,
|
|
947
955
|
other_args: list[str] | None = None,
|
|
948
956
|
) -> Generator[Mount, None, None]:
|
|
949
957
|
"""Like mount, but can be used in a context manager."""
|
|
@@ -956,6 +964,7 @@ class Rclone:
|
|
|
956
964
|
use_links=use_links,
|
|
957
965
|
vfs_cache_mode=vfs_cache_mode,
|
|
958
966
|
verbose=verbose,
|
|
967
|
+
log=log,
|
|
959
968
|
other_args=other_args,
|
|
960
969
|
)
|
|
961
970
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: rclone_api
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.31
|
|
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,6 +12,7 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: pyright>=1.1.393
|
|
13
13
|
Requires-Dist: python-dotenv>=1.0.0
|
|
14
14
|
Requires-Dist: certifi>=2025.1.31
|
|
15
|
+
Requires-Dist: psutil
|
|
15
16
|
Requires-Dist: boto3<=1.35.99,>=1.20.1
|
|
16
17
|
Dynamic: home-page
|
|
17
18
|
|
|
@@ -7,13 +7,13 @@ rclone_api/deprecated.py,sha256=qWKpnZdYcBK7YQZKuVoWWXDwi-uqiAtbjgPcci_efow,590
|
|
|
7
7
|
rclone_api/diff.py,sha256=tMoJMAGmLSE6Q_7QhPf6PnCzb840djxMZtDmhc2GlGQ,5227
|
|
8
8
|
rclone_api/dir.py,sha256=i4h7LX5hB_WmVixxDRWL_l1nifvscrdWct_8Wx7wHZc,3540
|
|
9
9
|
rclone_api/dir_listing.py,sha256=GoziW8Sne6FY90MLNcb2aO3aaa3jphB6H8ExYrV0Ryo,1882
|
|
10
|
-
rclone_api/exec.py,sha256=
|
|
10
|
+
rclone_api/exec.py,sha256=Pd7pUBd8ib5MzqvMybG2DQISPRbDRu20VjVRL2mLAVY,1076
|
|
11
11
|
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
|
-
rclone_api/mount.py,sha256=
|
|
15
|
-
rclone_api/process.py,sha256=
|
|
16
|
-
rclone_api/rclone.py,sha256=
|
|
14
|
+
rclone_api/mount.py,sha256=ryAjkX4_kFeFZWLiBVpcGy2VilpvVhFbWeWfEX4jMKs,6104
|
|
15
|
+
rclone_api/process.py,sha256=rBj_S86jC6nqCYop-jq8r9eMSteKeObxUrJMgH8LZvI,5084
|
|
16
|
+
rclone_api/rclone.py,sha256=meZkXmIM1M_L0Xu2hf0fcm-tG1cF5t6AHSIM6TOXUQM,42624
|
|
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
|
|
@@ -25,6 +25,7 @@ rclone_api/cmd/copy_large_s3.py,sha256=-rfedi-ZzPUdCSP8ai9LRL0y1xVkvN-viQQlk8HVU
|
|
|
25
25
|
rclone_api/cmd/list_files.py,sha256=x8FHODEilwKqwdiU1jdkeJbLwOqUkUQuDWPo2u_zpf0,741
|
|
26
26
|
rclone_api/experimental/flags.py,sha256=qCVD--fSTmzlk9hloRLr0q9elzAOFzPsvVpKM3aB1Mk,2739
|
|
27
27
|
rclone_api/experimental/flags_base.py,sha256=ajU_czkTcAxXYU-SlmiCfHY7aCQGHvpCLqJ-Z8uZLk0,2102
|
|
28
|
+
rclone_api/profiling/mount_copy_bytes.py,sha256=SgorSAG9lOlqMxzLt5N2UX_fepANpFWKM5NaQiBrsFE,4745
|
|
28
29
|
rclone_api/s3/api.py,sha256=qxtRDUpHYqJ7StJRtP8U_PbF_BvYRg705568SyvF-R0,3770
|
|
29
30
|
rclone_api/s3/basic_ops.py,sha256=hK3366xhVEzEcjz9Gk_8lFx6MRceAk72cax6mUrr6ko,2104
|
|
30
31
|
rclone_api/s3/chunk_file.py,sha256=YELR-EzR7RHpzCDGpYdzlwu21NZW5wttIDvLoONI4aU,3477
|
|
@@ -32,9 +33,9 @@ rclone_api/s3/chunk_types.py,sha256=LbXayXY1KgVU1LkdbASD_BQ7TpVpwVnzMjtz--8LBaE,
|
|
|
32
33
|
rclone_api/s3/create.py,sha256=wgfkapv_j904CfKuWyiBIWJVxfAx_ftemFSUV14aT68,3149
|
|
33
34
|
rclone_api/s3/types.py,sha256=yBnJ38Tjk6RlydJ-sqZ7DSfyFloy8KDYJ0mv3vlOzLE,1388
|
|
34
35
|
rclone_api/s3/upload_file_multipart.py,sha256=1jQAdk35Fa9Tcq36bS65262cs7AcNG2DAFQ-NdYlWSw,9961
|
|
35
|
-
rclone_api-1.1.
|
|
36
|
-
rclone_api-1.1.
|
|
37
|
-
rclone_api-1.1.
|
|
38
|
-
rclone_api-1.1.
|
|
39
|
-
rclone_api-1.1.
|
|
40
|
-
rclone_api-1.1.
|
|
36
|
+
rclone_api-1.1.31.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
|
|
37
|
+
rclone_api-1.1.31.dist-info/METADATA,sha256=5gEXYe7terl_H8vFbUZkWyD2wy2c05W-6EKuNgQya6Y,4537
|
|
38
|
+
rclone_api-1.1.31.dist-info/WHEEL,sha256=rF4EZyR2XVS6irmOHQIJx2SUqXLZKRMUrjsg8UwN-XQ,109
|
|
39
|
+
rclone_api-1.1.31.dist-info/entry_points.txt,sha256=6eNqTRXKhVf8CpWNjXiOa_0Du9tHiW_HD2iQSXRsUg8,132
|
|
40
|
+
rclone_api-1.1.31.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
|
|
41
|
+
rclone_api-1.1.31.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|