rclone-api 1.1.1__tar.gz → 1.1.3__tar.gz
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-1.1.1 → rclone_api-1.1.3}/PKG-INFO +1 -1
- {rclone_api-1.1.1 → rclone_api-1.1.3}/pyproject.toml +1 -1
- rclone_api-1.1.3/src/rclone_api/experimental/flags.py +82 -0
- rclone_api-1.1.3/src/rclone_api/experimental/flags_base.py +58 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/s3/chunk_uploader.py +37 -4
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api.egg-info/PKG-INFO +1 -1
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api.egg-info/SOURCES.txt +1 -0
- rclone_api-1.1.1/src/rclone_api/experimental/flags.py +0 -121
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.aiderignore +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.github/workflows/lint.yml +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.github/workflows/push_macos.yml +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.github/workflows/push_ubuntu.yml +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.github/workflows/push_win.yml +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.gitignore +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.pylintrc +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.vscode/launch.json +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.vscode/settings.json +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/.vscode/tasks.json +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/LICENSE +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/MANIFEST.in +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/README.md +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/clean +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/install +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/lint +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/requirements.testing.txt +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/setup.cfg +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/setup.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/__init__.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/assets/example.txt +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/cli.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/cmd/copy_large_s3.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/cmd/list_files.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/completed_process.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/config.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/convert.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/deprecated.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/diff.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/dir.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/dir_listing.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/exec.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/file.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/filelist.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/group_files.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/process.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/rclone.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/remote.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/rpath.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/s3/api.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/s3/basic_ops.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/s3/create.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/s3/types.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/scan_missing_folders.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/types.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/util.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api/walk.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api.egg-info/dependency_links.txt +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api.egg-info/entry_points.txt +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api.egg-info/requires.txt +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/src/rclone_api.egg-info/top_level.txt +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/test +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/archive/test_paramiko.py.disabled +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_cmd_list_files.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_copy.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_copy_files.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_diff.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_group_files.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_is_synced.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_ls.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_mount.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_mount_s3.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_mount_webdav.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_mounted_ranged_download.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_obscure.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_rclone_config.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_remote_control.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_remotes.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_s3.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_scan_missing_folders.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_size_files.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tests/test_walk.py +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/tox.ini +0 -0
- {rclone_api-1.1.1 → rclone_api-1.1.3}/upload_package.sh +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from rclone_api.experimental.flags_base import BaseFlags, merge_flags
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class CopyFlags(BaseFlags):
|
|
8
|
+
check_first: bool | None = None
|
|
9
|
+
checksum: bool | None = False
|
|
10
|
+
compare_dest: list[str] | None = None
|
|
11
|
+
copy_dest: list[str] | None = None
|
|
12
|
+
cutoff_mode: str | None = None
|
|
13
|
+
ignore_case_sync: bool | None = None
|
|
14
|
+
ignore_checksum: bool | None = None
|
|
15
|
+
ignore_existing: bool | None = None
|
|
16
|
+
ignore_size: bool | None = None
|
|
17
|
+
ignore_times: bool | None = None
|
|
18
|
+
immutable: bool | None = None
|
|
19
|
+
inplace: bool | None = None
|
|
20
|
+
links: bool | None = None
|
|
21
|
+
max_backlog: int | None = None
|
|
22
|
+
max_duration: str | None = None
|
|
23
|
+
max_transfer: str | None = None
|
|
24
|
+
metadata: bool | None = None
|
|
25
|
+
modify_window: str | None = None
|
|
26
|
+
multi_thread_chunk_size: str | None = None
|
|
27
|
+
multi_thread_cutoff: str | None = None
|
|
28
|
+
multi_thread_streams: int | None = None
|
|
29
|
+
multi_thread_write_buffer_size: str | None = None
|
|
30
|
+
no_check_dest: bool | None = None
|
|
31
|
+
no_traverse: bool | None = None
|
|
32
|
+
no_update_dir_modtime: bool | None = None
|
|
33
|
+
no_update_modtime: bool | None = None
|
|
34
|
+
order_by: str | None = None
|
|
35
|
+
partial_suffix: str | None = None
|
|
36
|
+
refresh_times: bool | None = None
|
|
37
|
+
server_side_across_configs: bool | None = None
|
|
38
|
+
size_only: bool | None = None
|
|
39
|
+
streaming_upload_cutoff: str | None = None
|
|
40
|
+
update: bool | None = None
|
|
41
|
+
|
|
42
|
+
def to_args(self) -> list[str]:
|
|
43
|
+
return super().to_args()
|
|
44
|
+
|
|
45
|
+
def merge(self, other: "CopyFlags") -> "CopyFlags":
|
|
46
|
+
return merge_flags(CopyFlags, self, other)
|
|
47
|
+
|
|
48
|
+
def __repr__(self):
|
|
49
|
+
return super().__repr__()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class Flags(BaseFlags):
|
|
54
|
+
copy: CopyFlags | None = None
|
|
55
|
+
|
|
56
|
+
def to_args(self) -> list[str]:
|
|
57
|
+
return super().to_args()
|
|
58
|
+
|
|
59
|
+
def merge(self, other: "Flags") -> "Flags":
|
|
60
|
+
return merge_flags(Flags, self, other)
|
|
61
|
+
|
|
62
|
+
def __repr__(self):
|
|
63
|
+
return super().__repr__()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def unit_test() -> None:
|
|
67
|
+
copy_flags_a = CopyFlags(compare_dest=["a", "b"])
|
|
68
|
+
copy_flags_b = CopyFlags(checksum=False)
|
|
69
|
+
flags_a = copy_flags_a.merge(copy_flags_b)
|
|
70
|
+
print("A:", flags_a)
|
|
71
|
+
|
|
72
|
+
copy_flags_c = CopyFlags(checksum=True)
|
|
73
|
+
copy_flags_d = CopyFlags(checksum=False)
|
|
74
|
+
|
|
75
|
+
merged_c_d = copy_flags_c.merge(copy_flags_d)
|
|
76
|
+
print("B:", merged_c_d)
|
|
77
|
+
merged_d_c = copy_flags_d.merge(copy_flags_c)
|
|
78
|
+
print("C:", merged_d_c)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if __name__ == "__main__":
|
|
82
|
+
unit_test()
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from dataclasses import dataclass, fields, is_dataclass
|
|
2
|
+
from typing import Type, TypeVar
|
|
3
|
+
|
|
4
|
+
T = TypeVar("T")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def merge_flags(cls: Type[T], dataclass_a: T, dataclass_b: T) -> T:
|
|
8
|
+
if not is_dataclass(dataclass_a) or not is_dataclass(dataclass_b):
|
|
9
|
+
raise ValueError("Both inputs must be dataclass instances")
|
|
10
|
+
if type(dataclass_a) is not type(dataclass_b):
|
|
11
|
+
raise ValueError("Dataclass instances must be of the same type")
|
|
12
|
+
|
|
13
|
+
merged_kwargs = {}
|
|
14
|
+
for field in fields(dataclass_a):
|
|
15
|
+
a_value = getattr(dataclass_a, field.name)
|
|
16
|
+
b_value = getattr(dataclass_b, field.name)
|
|
17
|
+
|
|
18
|
+
if is_dataclass(a_value) and is_dataclass(b_value):
|
|
19
|
+
merged_kwargs[field.name] = merge_flags(type(a_value), a_value, b_value)
|
|
20
|
+
else:
|
|
21
|
+
merged_kwargs[field.name] = b_value if b_value is not None else a_value
|
|
22
|
+
|
|
23
|
+
return cls(**merged_kwargs)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _field_name_to_flag(field_name: str) -> str:
|
|
27
|
+
return f"--{field_name.replace('_', '-')}"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class BaseFlags:
|
|
32
|
+
"""provides to_args(), merge() and __repr__ methods for flags dataclasses"""
|
|
33
|
+
|
|
34
|
+
def to_args(self) -> list[str]:
|
|
35
|
+
args = []
|
|
36
|
+
for field in fields(self):
|
|
37
|
+
value = getattr(self, field.name)
|
|
38
|
+
if value is None:
|
|
39
|
+
continue
|
|
40
|
+
# If the field value is a nested dataclass that supports to_args, use it.
|
|
41
|
+
if is_dataclass(value) and hasattr(value, "to_args"):
|
|
42
|
+
to_args = getattr(value, "to_args")
|
|
43
|
+
args.extend(to_args())
|
|
44
|
+
elif isinstance(value, bool):
|
|
45
|
+
# Only include the flag if the boolean is True.
|
|
46
|
+
if value:
|
|
47
|
+
args.append(_field_name_to_flag(field.name))
|
|
48
|
+
else:
|
|
49
|
+
args.append(_field_name_to_flag(field.name))
|
|
50
|
+
if isinstance(value, list):
|
|
51
|
+
# Join list values with a comma.
|
|
52
|
+
args.append(",".join(map(str, value)))
|
|
53
|
+
else:
|
|
54
|
+
args.append(str(value))
|
|
55
|
+
return args
|
|
56
|
+
|
|
57
|
+
def __repr__(self):
|
|
58
|
+
return str(self.to_args())
|
|
@@ -127,6 +127,13 @@ class UploadState:
|
|
|
127
127
|
lock: Lock = Lock()
|
|
128
128
|
parts: list[FinishedPiece | None] = field(default_factory=list)
|
|
129
129
|
|
|
130
|
+
def update_source_file(self, src_file: Path) -> None:
|
|
131
|
+
new_file_size = os.path.getsize(src_file)
|
|
132
|
+
if new_file_size != self.upload_info.file_size:
|
|
133
|
+
raise ValueError("File size changed, cannot resume")
|
|
134
|
+
self.upload_info.src_file_path = src_file
|
|
135
|
+
self.save()
|
|
136
|
+
|
|
130
137
|
def is_done(self) -> bool:
|
|
131
138
|
return self.remaining() == 0
|
|
132
139
|
|
|
@@ -264,15 +271,22 @@ def _get_chunk_tmpdir() -> Path:
|
|
|
264
271
|
def _get_file_size(file_path: Path, timeout: int = 60) -> int:
|
|
265
272
|
sleep_time = timeout / 60 if timeout > 0 else 1
|
|
266
273
|
start = time.time()
|
|
274
|
+
not_windows = os.name != "nt"
|
|
267
275
|
while True:
|
|
276
|
+
expired = time.time() - start > timeout
|
|
268
277
|
try:
|
|
278
|
+
time.sleep(sleep_time)
|
|
279
|
+
if not_windows:
|
|
280
|
+
# Force a refresh of the directory cache
|
|
281
|
+
os.system(f"ls -l {file_path.parent}")
|
|
269
282
|
if file_path.exists():
|
|
270
283
|
return file_path.stat().st_size
|
|
271
|
-
except FileNotFoundError:
|
|
272
|
-
|
|
273
|
-
|
|
284
|
+
except FileNotFoundError as e:
|
|
285
|
+
if expired:
|
|
286
|
+
print(f"File not found: {file_path}, exception is {e}")
|
|
287
|
+
raise
|
|
288
|
+
if expired:
|
|
274
289
|
raise TimeoutError(f"File {file_path} not found after {timeout} seconds")
|
|
275
|
-
time.sleep(sleep_time)
|
|
276
290
|
|
|
277
291
|
|
|
278
292
|
def file_chunker(
|
|
@@ -426,6 +440,18 @@ def prepare_upload_file_multipart(
|
|
|
426
440
|
return upload_info
|
|
427
441
|
|
|
428
442
|
|
|
443
|
+
def _abort_previous_upload(upload_state: UploadState) -> None:
|
|
444
|
+
if upload_state.upload_info.upload_id:
|
|
445
|
+
try:
|
|
446
|
+
upload_state.upload_info.s3_client.abort_multipart_upload(
|
|
447
|
+
Bucket=upload_state.upload_info.bucket_name,
|
|
448
|
+
Key=upload_state.upload_info.object_name,
|
|
449
|
+
UploadId=upload_state.upload_info.upload_id,
|
|
450
|
+
)
|
|
451
|
+
except Exception as e:
|
|
452
|
+
locked_print(f"Error aborting previous upload: {e}")
|
|
453
|
+
|
|
454
|
+
|
|
429
455
|
def upload_file_multipart(
|
|
430
456
|
s3_client: BaseClient,
|
|
431
457
|
bucket_name: str,
|
|
@@ -481,6 +507,13 @@ def upload_file_multipart(
|
|
|
481
507
|
|
|
482
508
|
filechunks: Queue[FileChunk | None] = Queue(10)
|
|
483
509
|
upload_state = get_upload_state() or make_new_state()
|
|
510
|
+
try:
|
|
511
|
+
upload_state.update_source_file(file_path)
|
|
512
|
+
except ValueError as e:
|
|
513
|
+
locked_print(f"Cannot resume upload: {e}, size changed, starting over")
|
|
514
|
+
_abort_previous_upload(upload_state)
|
|
515
|
+
upload_state = make_new_state()
|
|
516
|
+
upload_state.save()
|
|
484
517
|
if upload_state.is_done():
|
|
485
518
|
return MultiUploadResult.ALREADY_DONE
|
|
486
519
|
finished = upload_state.finished()
|
|
@@ -51,6 +51,7 @@ src/rclone_api/assets/example.txt
|
|
|
51
51
|
src/rclone_api/cmd/copy_large_s3.py
|
|
52
52
|
src/rclone_api/cmd/list_files.py
|
|
53
53
|
src/rclone_api/experimental/flags.py
|
|
54
|
+
src/rclone_api/experimental/flags_base.py
|
|
54
55
|
src/rclone_api/s3/api.py
|
|
55
56
|
src/rclone_api/s3/basic_ops.py
|
|
56
57
|
src/rclone_api/s3/chunk_uploader.py
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass, fields, is_dataclass
|
|
2
|
-
from typing import Type, TypeVar
|
|
3
|
-
|
|
4
|
-
T = TypeVar("T")
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def _merge(cls: Type[T], dataclass_a: T, dataclass_b: T) -> T:
|
|
8
|
-
if not is_dataclass(dataclass_a) or not is_dataclass(dataclass_b):
|
|
9
|
-
raise ValueError("Both inputs must be dataclass instances")
|
|
10
|
-
if type(dataclass_a) is not type(dataclass_b):
|
|
11
|
-
raise ValueError("Dataclass instances must be of the same type")
|
|
12
|
-
|
|
13
|
-
merged_kwargs = {}
|
|
14
|
-
for field in fields(dataclass_a):
|
|
15
|
-
a_value = getattr(dataclass_a, field.name)
|
|
16
|
-
b_value = getattr(dataclass_b, field.name)
|
|
17
|
-
|
|
18
|
-
if is_dataclass(a_value) and is_dataclass(b_value):
|
|
19
|
-
merged_kwargs[field.name] = _merge(type(a_value), a_value, b_value)
|
|
20
|
-
else:
|
|
21
|
-
merged_kwargs[field.name] = b_value if b_value is not None else a_value
|
|
22
|
-
|
|
23
|
-
return cls(**merged_kwargs)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _field_name_to_flag(field_name: str) -> str:
|
|
27
|
-
return f"--{field_name.replace('_', '-')}"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@dataclass
|
|
31
|
-
class BaseFlags:
|
|
32
|
-
def to_args(self) -> list[str]:
|
|
33
|
-
args = []
|
|
34
|
-
for field in fields(self):
|
|
35
|
-
value = getattr(self, field.name)
|
|
36
|
-
if value is None:
|
|
37
|
-
continue
|
|
38
|
-
# If the field value is a nested dataclass that supports to_args, use it.
|
|
39
|
-
if is_dataclass(value) and hasattr(value, "to_args"):
|
|
40
|
-
to_args = getattr(value, "to_args")
|
|
41
|
-
args.extend(to_args())
|
|
42
|
-
elif isinstance(value, bool):
|
|
43
|
-
# Only include the flag if the boolean is True.
|
|
44
|
-
if value:
|
|
45
|
-
args.append(_field_name_to_flag(field.name))
|
|
46
|
-
else:
|
|
47
|
-
args.append(_field_name_to_flag(field.name))
|
|
48
|
-
if isinstance(value, list):
|
|
49
|
-
# Join list values with a comma.
|
|
50
|
-
args.append(",".join(map(str, value)))
|
|
51
|
-
else:
|
|
52
|
-
args.append(str(value))
|
|
53
|
-
return args
|
|
54
|
-
|
|
55
|
-
def merge(self, other: "BaseFlags") -> "BaseFlags":
|
|
56
|
-
# Use the type of self, so merging CopyFlags returns a CopyFlags instance.
|
|
57
|
-
return _merge(type(self), self, other)
|
|
58
|
-
|
|
59
|
-
def __repr__(self):
|
|
60
|
-
return str(self.to_args())
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@dataclass(repr=False)
|
|
64
|
-
class CopyFlags(BaseFlags):
|
|
65
|
-
check_first: bool | None = None
|
|
66
|
-
checksum: bool | None = False
|
|
67
|
-
compare_dest: list[str] | None = None
|
|
68
|
-
copy_dest: list[str] | None = None
|
|
69
|
-
cutoff_mode: str | None = None
|
|
70
|
-
ignore_case_sync: bool | None = None
|
|
71
|
-
ignore_checksum: bool | None = None
|
|
72
|
-
ignore_existing: bool | None = None
|
|
73
|
-
ignore_size: bool | None = None
|
|
74
|
-
ignore_times: bool | None = None
|
|
75
|
-
immutable: bool | None = None
|
|
76
|
-
inplace: bool | None = None
|
|
77
|
-
links: bool | None = None
|
|
78
|
-
max_backlog: int | None = None
|
|
79
|
-
max_duration: str | None = None
|
|
80
|
-
max_transfer: str | None = None
|
|
81
|
-
metadata: bool | None = None
|
|
82
|
-
modify_window: str | None = None
|
|
83
|
-
multi_thread_chunk_size: str | None = None
|
|
84
|
-
multi_thread_cutoff: str | None = None
|
|
85
|
-
multi_thread_streams: int | None = None
|
|
86
|
-
multi_thread_write_buffer_size: str | None = None
|
|
87
|
-
no_check_dest: bool | None = None
|
|
88
|
-
no_traverse: bool | None = None
|
|
89
|
-
no_update_dir_modtime: bool | None = None
|
|
90
|
-
no_update_modtime: bool | None = None
|
|
91
|
-
order_by: str | None = None
|
|
92
|
-
partial_suffix: str | None = None
|
|
93
|
-
refresh_times: bool | None = None
|
|
94
|
-
server_side_across_configs: bool | None = None
|
|
95
|
-
size_only: bool | None = None
|
|
96
|
-
streaming_upload_cutoff: str | None = None
|
|
97
|
-
update: bool | None = None
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
@dataclass(repr=False)
|
|
101
|
-
class Flags(BaseFlags):
|
|
102
|
-
copy: CopyFlags | None = None
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def unit_test() -> None:
|
|
106
|
-
copy_flags_a = CopyFlags(compare_dest=["a", "b"])
|
|
107
|
-
copy_flags_b = CopyFlags(checksum=False)
|
|
108
|
-
flags_a = copy_flags_a.merge(copy_flags_b)
|
|
109
|
-
print("A:", flags_a)
|
|
110
|
-
|
|
111
|
-
copy_flags_c = CopyFlags(checksum=True)
|
|
112
|
-
copy_flags_d = CopyFlags(checksum=False)
|
|
113
|
-
|
|
114
|
-
merged_c_d = copy_flags_c.merge(copy_flags_d)
|
|
115
|
-
print("B:", merged_c_d)
|
|
116
|
-
merged_d_c = copy_flags_d.merge(copy_flags_c)
|
|
117
|
-
print("C:", merged_d_c)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if __name__ == "__main__":
|
|
121
|
-
unit_test()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|