rclone-api 1.0.98__tar.gz → 1.0.99__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.
Files changed (81) hide show
  1. {rclone_api-1.0.98 → rclone_api-1.0.99}/PKG-INFO +1 -1
  2. {rclone_api-1.0.98 → rclone_api-1.0.99}/pyproject.toml +1 -1
  3. rclone_api-1.0.99/src/rclone_api/experimental/flags.py +121 -0
  4. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/rclone.py +1 -0
  5. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/s3/chunk_uploader.py +16 -1
  6. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api.egg-info/PKG-INFO +1 -1
  7. rclone_api-1.0.98/src/rclone_api/experimental/flags.py +0 -93
  8. {rclone_api-1.0.98 → rclone_api-1.0.99}/.aiderignore +0 -0
  9. {rclone_api-1.0.98 → rclone_api-1.0.99}/.github/workflows/lint.yml +0 -0
  10. {rclone_api-1.0.98 → rclone_api-1.0.99}/.github/workflows/push_macos.yml +0 -0
  11. {rclone_api-1.0.98 → rclone_api-1.0.99}/.github/workflows/push_ubuntu.yml +0 -0
  12. {rclone_api-1.0.98 → rclone_api-1.0.99}/.github/workflows/push_win.yml +0 -0
  13. {rclone_api-1.0.98 → rclone_api-1.0.99}/.gitignore +0 -0
  14. {rclone_api-1.0.98 → rclone_api-1.0.99}/.pylintrc +0 -0
  15. {rclone_api-1.0.98 → rclone_api-1.0.99}/.vscode/launch.json +0 -0
  16. {rclone_api-1.0.98 → rclone_api-1.0.99}/.vscode/settings.json +0 -0
  17. {rclone_api-1.0.98 → rclone_api-1.0.99}/.vscode/tasks.json +0 -0
  18. {rclone_api-1.0.98 → rclone_api-1.0.99}/LICENSE +0 -0
  19. {rclone_api-1.0.98 → rclone_api-1.0.99}/MANIFEST.in +0 -0
  20. {rclone_api-1.0.98 → rclone_api-1.0.99}/README.md +0 -0
  21. {rclone_api-1.0.98 → rclone_api-1.0.99}/clean +0 -0
  22. {rclone_api-1.0.98 → rclone_api-1.0.99}/install +0 -0
  23. {rclone_api-1.0.98 → rclone_api-1.0.99}/lint +0 -0
  24. {rclone_api-1.0.98 → rclone_api-1.0.99}/requirements.testing.txt +0 -0
  25. {rclone_api-1.0.98 → rclone_api-1.0.99}/setup.cfg +0 -0
  26. {rclone_api-1.0.98 → rclone_api-1.0.99}/setup.py +0 -0
  27. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/__init__.py +0 -0
  28. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/assets/example.txt +0 -0
  29. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/cli.py +0 -0
  30. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/cmd/copy_large_s3.py +0 -0
  31. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/cmd/list_files.py +0 -0
  32. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/completed_process.py +0 -0
  33. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/config.py +0 -0
  34. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/convert.py +0 -0
  35. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/deprecated.py +0 -0
  36. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/diff.py +0 -0
  37. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/dir.py +0 -0
  38. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/dir_listing.py +0 -0
  39. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/exec.py +0 -0
  40. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/file.py +0 -0
  41. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/filelist.py +0 -0
  42. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/group_files.py +0 -0
  43. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/process.py +0 -0
  44. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/remote.py +0 -0
  45. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/rpath.py +0 -0
  46. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/s3/api.py +0 -0
  47. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/s3/basic_ops.py +0 -0
  48. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/s3/create.py +0 -0
  49. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/s3/types.py +0 -0
  50. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/scan_missing_folders.py +0 -0
  51. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/types.py +0 -0
  52. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/util.py +0 -0
  53. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api/walk.py +0 -0
  54. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api.egg-info/SOURCES.txt +0 -0
  55. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  56. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api.egg-info/entry_points.txt +0 -0
  57. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api.egg-info/requires.txt +0 -0
  58. {rclone_api-1.0.98 → rclone_api-1.0.99}/src/rclone_api.egg-info/top_level.txt +0 -0
  59. {rclone_api-1.0.98 → rclone_api-1.0.99}/test +0 -0
  60. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/archive/test_paramiko.py.disabled +0 -0
  61. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_cmd_list_files.py +0 -0
  62. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_copy.py +0 -0
  63. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_copy_files.py +0 -0
  64. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_diff.py +0 -0
  65. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_group_files.py +0 -0
  66. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_is_synced.py +0 -0
  67. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_ls.py +0 -0
  68. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_mount.py +0 -0
  69. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_mount_s3.py +0 -0
  70. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_mount_webdav.py +0 -0
  71. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_mounted_ranged_download.py +0 -0
  72. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_obscure.py +0 -0
  73. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_rclone_config.py +0 -0
  74. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_remote_control.py +0 -0
  75. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_remotes.py +0 -0
  76. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_s3.py +0 -0
  77. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_scan_missing_folders.py +0 -0
  78. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_size_files.py +0 -0
  79. {rclone_api-1.0.98 → rclone_api-1.0.99}/tests/test_walk.py +0 -0
  80. {rclone_api-1.0.98 → rclone_api-1.0.99}/tox.ini +0 -0
  81. {rclone_api-1.0.98 → rclone_api-1.0.99}/upload_package.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.98
3
+ Version: 1.0.99
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -21,7 +21,7 @@ dependencies = [
21
21
  ]
22
22
 
23
23
  # Change this with the version number bump.
24
- version = "1.0.98"
24
+ version = "1.0.99"
25
25
 
26
26
  [tool.setuptools]
27
27
  package-dir = {"" = "src"}
@@ -0,0 +1,121 @@
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()
@@ -919,6 +919,7 @@ class Rclone:
919
919
  if outdir.exists():
920
920
  print(f"{outdir} mount still exists, attempting to remove")
921
921
  if not _IS_WINDOWS:
922
+
922
923
  def exec(cmd: str) -> int:
923
924
  if verbose:
924
925
  print(f"Executing: {cmd}")
@@ -260,6 +260,20 @@ def _get_chunk_tmpdir() -> Path:
260
260
  return out
261
261
 
262
262
 
263
+ def _get_file_size(file_path: Path, timeout: int = 60) -> int:
264
+ sleep_time = timeout / 60 if timeout > 0 else 1
265
+ start = time.time()
266
+ while True:
267
+ try:
268
+ if file_path.exists():
269
+ return file_path.stat().st_size
270
+ except FileNotFoundError:
271
+ pass
272
+ if time.time() - start > timeout:
273
+ raise TimeoutError(f"File {file_path} not found after {timeout} seconds")
274
+ time.sleep(sleep_time)
275
+
276
+
263
277
  def file_chunker(
264
278
  upload_state: UploadState, max_chunks: int | None, output: Queue[FileChunk | None]
265
279
  ) -> None:
@@ -279,7 +293,8 @@ def file_chunker(
279
293
  file_path = upload_info.src_file_path
280
294
  chunk_size = upload_info.chunk_size
281
295
  src = Path(file_path)
282
- file_size = os.path.getsize(file_path)
296
+ # Mounted files may take a while to appear, so keep retrying.
297
+ file_size = _get_file_size(src, timeout=60)
283
298
  part_number = 1
284
299
  done_part_numbers: set[int] = {
285
300
  p.part_number for p in upload_state.parts if p is not None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.98
3
+ Version: 1.0.99
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,93 +0,0 @@
1
- from dataclasses import dataclass, field
2
-
3
-
4
- @dataclass
5
- class CopyFlags:
6
- check_first: bool = False
7
- checksum: bool = False
8
- ignore_existing: bool = False
9
- ignore_times: bool = False
10
- immutable: bool = False
11
- inplace: bool = False
12
- links: bool = False
13
- metadata: bool = False
14
-
15
-
16
- @dataclass
17
- class SyncFlags:
18
- backup_dir: str | None = None
19
- delete_after: bool = False
20
- delete_before: bool = False
21
- delete_during: bool = False
22
- ignore_errors: bool = False
23
- track_renames: bool = False
24
-
25
-
26
- @dataclass
27
- class ImportantFlags:
28
- dry_run: bool = False
29
- interactive: bool = False
30
- verbose: int = 0 # 0 = default, 1 = -v, 2 = -vv, etc.
31
-
32
-
33
- @dataclass
34
- class NetworkingFlags:
35
- bwlimit: str | None = None
36
- timeout: str | None = "5m0s"
37
- tpslimit: float | None = None
38
- user_agent: str | None = "rclone/v1.69.1"
39
-
40
-
41
- @dataclass
42
- class PerformanceFlags:
43
- buffer_size: str | None = "16MiB"
44
- checkers: int = 8
45
- transfers: int = 4
46
-
47
-
48
- @dataclass
49
- class ConfigFlags:
50
- config: str | None = None
51
- ask_password: bool = True
52
- auto_confirm: bool = False
53
-
54
-
55
- @dataclass
56
- class DebuggingFlags:
57
- cpuprofile: str | None = None
58
- memprofile: str | None = None
59
-
60
-
61
- @dataclass
62
- class FilterFlags:
63
- exclude: list[str] = field(default_factory=list)
64
- include: list[str] = field(default_factory=list)
65
- max_age: str | None = None
66
- min_size: str | None = None
67
-
68
-
69
- @dataclass
70
- class ListingFlags:
71
- fast_list: bool = False
72
-
73
-
74
- @dataclass
75
- class LoggingFlags:
76
- log_file: str | None = None
77
- log_level: str = "NOTICE" # Options: DEBUG, INFO, NOTICE, ERROR
78
- stats: str | None = "1m0s"
79
- progress: bool = False
80
-
81
-
82
- @dataclass
83
- class Flags:
84
- copy: CopyFlags | None = None
85
- sync: SyncFlags | None = None
86
- important: ImportantFlags | None = None
87
- networking: NetworkingFlags | None = None
88
- performance: PerformanceFlags | None = None
89
- config: ConfigFlags | None = None
90
- debugging: DebuggingFlags | None = None
91
- filter: FilterFlags | None = None
92
- listing: ListingFlags | None = None
93
- logging: LoggingFlags | None = None
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