rclone-api 1.3.23__tar.gz → 1.3.25__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 (99) hide show
  1. {rclone_api-1.3.23 → rclone_api-1.3.25}/PKG-INFO +1 -1
  2. {rclone_api-1.3.23 → rclone_api-1.3.25}/pyproject.toml +1 -1
  3. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/chunk_task.py +5 -0
  4. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/upload_file_multipart.py +45 -27
  5. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/types.py +41 -1
  6. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api.egg-info/PKG-INFO +1 -1
  7. {rclone_api-1.3.23 → rclone_api-1.3.25}/.aiderignore +0 -0
  8. {rclone_api-1.3.23 → rclone_api-1.3.25}/.github/workflows/lint.yml +0 -0
  9. {rclone_api-1.3.23 → rclone_api-1.3.25}/.github/workflows/push_macos.yml +0 -0
  10. {rclone_api-1.3.23 → rclone_api-1.3.25}/.github/workflows/push_ubuntu.yml +0 -0
  11. {rclone_api-1.3.23 → rclone_api-1.3.25}/.github/workflows/push_win.yml +0 -0
  12. {rclone_api-1.3.23 → rclone_api-1.3.25}/.gitignore +0 -0
  13. {rclone_api-1.3.23 → rclone_api-1.3.25}/.pylintrc +0 -0
  14. {rclone_api-1.3.23 → rclone_api-1.3.25}/.vscode/launch.json +0 -0
  15. {rclone_api-1.3.23 → rclone_api-1.3.25}/.vscode/settings.json +0 -0
  16. {rclone_api-1.3.23 → rclone_api-1.3.25}/.vscode/tasks.json +0 -0
  17. {rclone_api-1.3.23 → rclone_api-1.3.25}/LICENSE +0 -0
  18. {rclone_api-1.3.23 → rclone_api-1.3.25}/MANIFEST.in +0 -0
  19. {rclone_api-1.3.23 → rclone_api-1.3.25}/README.md +0 -0
  20. {rclone_api-1.3.23 → rclone_api-1.3.25}/clean +0 -0
  21. {rclone_api-1.3.23 → rclone_api-1.3.25}/install +0 -0
  22. {rclone_api-1.3.23 → rclone_api-1.3.25}/lint +0 -0
  23. {rclone_api-1.3.23 → rclone_api-1.3.25}/requirements.testing.txt +0 -0
  24. {rclone_api-1.3.23 → rclone_api-1.3.25}/setup.cfg +0 -0
  25. {rclone_api-1.3.23 → rclone_api-1.3.25}/setup.py +0 -0
  26. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/__init__.py +0 -0
  27. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/assets/example.txt +0 -0
  28. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/cli.py +0 -0
  29. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/cmd/analyze.py +0 -0
  30. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/cmd/copy_large_s3.py +0 -0
  31. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/cmd/list_files.py +0 -0
  32. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/cmd/save_to_db.py +0 -0
  33. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/completed_process.py +0 -0
  34. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/config.py +0 -0
  35. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/convert.py +0 -0
  36. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/db/__init__.py +0 -0
  37. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/db/db.py +0 -0
  38. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/db/models.py +0 -0
  39. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/deprecated.py +0 -0
  40. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/diff.py +0 -0
  41. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/dir.py +0 -0
  42. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/dir_listing.py +0 -0
  43. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/exec.py +0 -0
  44. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/experimental/flags.py +0 -0
  45. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/experimental/flags_base.py +0 -0
  46. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/file.py +0 -0
  47. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/file_item.py +0 -0
  48. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/filelist.py +0 -0
  49. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/group_files.py +0 -0
  50. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/http_server.py +0 -0
  51. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/log.py +0 -0
  52. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/mount.py +0 -0
  53. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/mount_read_chunker.py +0 -0
  54. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/process.py +0 -0
  55. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/profile/mount_copy_bytes.py +0 -0
  56. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/rclone.py +0 -0
  57. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/remote.py +0 -0
  58. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/rpath.py +0 -0
  59. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/api.py +0 -0
  60. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/basic_ops.py +0 -0
  61. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/chunk_types.py +0 -0
  62. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/create.py +0 -0
  63. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/s3/types.py +0 -0
  64. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/scan_missing_folders.py +0 -0
  65. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/util.py +0 -0
  66. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api/walk.py +0 -0
  67. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api.egg-info/SOURCES.txt +0 -0
  68. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  69. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api.egg-info/entry_points.txt +0 -0
  70. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api.egg-info/requires.txt +0 -0
  71. {rclone_api-1.3.23 → rclone_api-1.3.25}/src/rclone_api.egg-info/top_level.txt +0 -0
  72. {rclone_api-1.3.23 → rclone_api-1.3.25}/test +0 -0
  73. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/archive/test_paramiko.py.disabled +0 -0
  74. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_cmd_list_files.py +0 -0
  75. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_copy.py +0 -0
  76. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_copy_bytes.py +0 -0
  77. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_copy_file_resumable_s3.py +0 -0
  78. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_copy_files.py +0 -0
  79. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_db.py +0 -0
  80. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_diff.py +0 -0
  81. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_file_item.py +0 -0
  82. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_group_files.py +0 -0
  83. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_is_synced.py +0 -0
  84. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_ls.py +0 -0
  85. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_ls_stream_files.py +0 -0
  86. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_mount.py +0 -0
  87. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_mount_s3.py +0 -0
  88. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_obscure.py +0 -0
  89. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_rclone_config.py +0 -0
  90. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_remote_control.py +0 -0
  91. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_remotes.py +0 -0
  92. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_s3.py +0 -0
  93. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_scan_missing_folders.py +0 -0
  94. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_serve_http.py +0 -0
  95. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_size_files.py +0 -0
  96. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_size_suffix.py +0 -0
  97. {rclone_api-1.3.23 → rclone_api-1.3.25}/tests/test_walk.py +0 -0
  98. {rclone_api-1.3.23 → rclone_api-1.3.25}/tox.ini +0 -0
  99. {rclone_api-1.3.23 → rclone_api-1.3.25}/upload_package.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.3.23
3
+ Version: 1.3.25
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
@@ -25,7 +25,7 @@ dependencies = [
25
25
  ]
26
26
 
27
27
  # Change this with the version number bump.
28
- version = "1.3.23"
28
+ version = "1.3.25"
29
29
 
30
30
  [tool.setuptools]
31
31
  package-dir = {"" = "src"}
@@ -184,11 +184,16 @@ def file_chunker(
184
184
  logger.info(
185
185
  f"Reading chunk {curr_part_number} of {num_parts} for {file_path}"
186
186
  )
187
+ logger.debug(
188
+ f"Fetching part {curr_part_number} with offset {offset} and size {fetch_size}"
189
+ )
187
190
  fut = fetcher(
188
191
  offset, fetch_size, S3FileInfo(upload_info.upload_id, curr_part_number)
189
192
  )
190
193
  fut.add_done_callback(callback.on_complete)
191
194
  # wait until the queue_upload queue can accept the next chunk
195
+ qsize = queue_upload.qsize()
196
+ print(f"queue_upload_size: {qsize}")
192
197
  while queue_upload.full():
193
198
  time.sleep(0.1)
194
199
  except Exception as e:
@@ -25,7 +25,10 @@ _MIN_UPLOAD_CHUNK_SIZE = 5 * 1024 * 1024 # 5MB
25
25
 
26
26
 
27
27
  def upload_task(
28
- info: UploadInfo, chunk: FilePart, part_number: int, retries: int
28
+ info: UploadInfo,
29
+ chunk: FilePart,
30
+ part_number: int,
31
+ retries: int,
29
32
  ) -> FinishedPiece:
30
33
  file_or_err: Path | Exception = chunk.get_file()
31
34
  if isinstance(file_or_err, Exception):
@@ -139,6 +142,40 @@ def _abort_previous_upload(upload_state: UploadState) -> None:
139
142
  locked_print(f"Error aborting previous upload: {e}")
140
143
 
141
144
 
145
+ def upload_runner(
146
+ upload_state: UploadState,
147
+ upload_info: UploadInfo,
148
+ upload_threads: int,
149
+ queue_upload: Queue[FilePart | EndOfStream],
150
+ cancel_chunker_event: Event,
151
+ ) -> None:
152
+ with ThreadPoolExecutor(max_workers=upload_threads) as executor:
153
+ try:
154
+ while True:
155
+ file_chunk: FilePart | EndOfStream = queue_upload.get()
156
+ if isinstance(file_chunk, EndOfStream):
157
+ break
158
+
159
+ def task(upload_info=upload_info, file_chunk=file_chunk):
160
+ return handle_upload(upload_info, file_chunk)
161
+
162
+ fut = executor.submit(task)
163
+
164
+ def done_cb(fut=fut):
165
+ result = fut.result()
166
+ if isinstance(result, Exception):
167
+ warnings.warn(f"Error uploading part: {result}, skipping")
168
+ return
169
+ # upload_state.finished_parts.put(result)
170
+ upload_state.add_finished(result)
171
+
172
+ fut.add_done_callback(done_cb)
173
+ except Exception:
174
+ cancel_chunker_event.set()
175
+ executor.shutdown(wait=False, cancel_futures=True)
176
+ raise
177
+
178
+
142
179
  def upload_file_multipart(
143
180
  s3_client: BaseClient,
144
181
  chunk_fetcher: Callable[[int, int, Any], Future[FilePart]],
@@ -265,32 +302,13 @@ def upload_file_multipart(
265
302
  try:
266
303
  thread_chunker = Thread(target=chunker_task, daemon=True)
267
304
  thread_chunker.start()
268
-
269
- with ThreadPoolExecutor(max_workers=upload_threads) as executor:
270
- try:
271
- while True:
272
- file_chunk: FilePart | EndOfStream = queue_upload.get()
273
- if isinstance(file_chunk, EndOfStream):
274
- break
275
-
276
- def task(upload_info=upload_info, file_chunk=file_chunk):
277
- return handle_upload(upload_info, file_chunk)
278
-
279
- fut = executor.submit(task)
280
-
281
- def done_cb(fut=fut):
282
- result = fut.result()
283
- if isinstance(result, Exception):
284
- warnings.warn(f"Error uploading part: {result}, skipping")
285
- return
286
- # upload_state.finished_parts.put(result)
287
- upload_state.add_finished(result)
288
-
289
- fut.add_done_callback(done_cb)
290
- except Exception:
291
- cancel_chunker_event.set()
292
- executor.shutdown(wait=False, cancel_futures=True)
293
- raise
305
+ upload_runner(
306
+ upload_state=upload_state,
307
+ upload_info=upload_info,
308
+ upload_threads=upload_threads,
309
+ queue_upload=queue_upload,
310
+ cancel_chunker_event=cancel_chunker_event,
311
+ )
294
312
  # upload_state.finished_parts.put(None) # Signal the end of the queue
295
313
  upload_state.add_finished(EndOfStream())
296
314
  thread_chunker.join()
@@ -6,7 +6,7 @@ import warnings
6
6
  from dataclasses import dataclass
7
7
  from enum import Enum
8
8
  from pathlib import Path
9
- from threading import Lock
9
+ from threading import Lock, Thread
10
10
  from typing import Any
11
11
 
12
12
 
@@ -288,10 +288,38 @@ def _on_exit_cleanup() -> None:
288
288
  atexit.register(_on_exit_cleanup)
289
289
 
290
290
 
291
+ _FILEPARTS: list["FilePart"] = []
292
+
293
+
294
+ class ListFileParts(Thread):
295
+ def __init__(self):
296
+ super().__init__(daemon=True)
297
+ self.start()
298
+
299
+ def run(self):
300
+ while True:
301
+ print("File parts:")
302
+ for part in _FILEPARTS:
303
+ print(part)
304
+ print(part.stacktrace)
305
+ print("\n")
306
+ print("\n\n")
307
+ time.sleep(5)
308
+
309
+
310
+ dbg_thread = ListFileParts()
311
+
312
+
291
313
  class FilePart:
292
314
  def __init__(self, payload: Path | bytes | Exception, extra: Any) -> None:
315
+ import traceback
316
+
293
317
  from rclone_api.util import random_str
294
318
 
319
+ stacktrace = traceback.format_stack()
320
+ self.stacktrace = stacktrace
321
+ _FILEPARTS.append(self)
322
+
295
323
  self.extra = extra
296
324
  self._lock = Lock()
297
325
  self.payload: Path | Exception
@@ -299,6 +327,7 @@ class FilePart:
299
327
  self.payload = payload
300
328
  return
301
329
  if isinstance(payload, bytes):
330
+ print(f"Creating file part with payload: {len(payload)}")
302
331
  self.payload = get_chunk_tmpdir() / f"{random_str(12)}.chunk"
303
332
  with _TMP_DIR_ACCESS_LOCK:
304
333
  if not self.payload.parent.exists():
@@ -306,7 +335,9 @@ class FilePart:
306
335
  self.payload.write_bytes(payload)
307
336
  _add_for_cleanup(self.payload)
308
337
  if isinstance(payload, Path):
338
+ print("Adopting payload: ", payload)
309
339
  self.payload = payload
340
+ _add_for_cleanup(self.payload)
310
341
 
311
342
  def get_file(self) -> Path | Exception:
312
343
  return self.payload
@@ -344,18 +375,27 @@ class FilePart:
344
375
  return isinstance(self.payload, Exception)
345
376
 
346
377
  def dispose(self) -> None:
378
+ _FILEPARTS.remove(self)
379
+ print("Disposing file part")
347
380
  with self._lock:
348
381
  if isinstance(self.payload, Exception):
349
382
  warnings.warn(
350
383
  f"Cannot close file part because the payload represents an error: {self.payload}"
351
384
  )
385
+ print("Cannot close file part because the payload represents an error")
352
386
  return
353
387
  if self.payload.exists():
388
+ print(f"File part {self.payload} exists")
354
389
  try:
390
+ print(f"Unlinking file part {self.payload}")
355
391
  self.payload.unlink()
356
392
  print(f"File part {self.payload} deleted")
357
393
  except Exception as e:
358
394
  warnings.warn(f"Cannot close file part because of error: {e}")
395
+ else:
396
+ warnings.warn(
397
+ f"Cannot close file part because it does not exist: {self.payload}"
398
+ )
359
399
 
360
400
  def __del__(self):
361
401
  self.dispose()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.3.23
3
+ Version: 1.3.25
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  License: BSD 3-Clause License
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