rclone-api 1.0.7__tar.gz → 1.0.8__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.0.7/src/rclone_api.egg-info → rclone_api-1.0.8}/PKG-INFO +1 -1
- {rclone_api-1.0.7 → rclone_api-1.0.8}/pyproject.toml +1 -1
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/dir.py +2 -2
- rclone_api-1.0.8/src/rclone_api/walk.py +82 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8/src/rclone_api.egg-info}/PKG-INFO +1 -1
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api.egg-info/SOURCES.txt +1 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/.gitignore +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/.pylintrc +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/.vscode/launch.json +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/.vscode/settings.json +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/.vscode/tasks.json +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/LICENSE +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/MANIFEST.in +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/README.md +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/clean +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/install +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/lint +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/requirements.testing.txt +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/setup.cfg +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/setup.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/__init__.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/assets/example.txt +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/cli.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/config.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/dir_listing.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/file.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/rclone.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/remote.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/rpath.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/types.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api/util.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api.egg-info/dependency_links.txt +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/src/rclone_api.egg-info/top_level.txt +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/test +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/tests/test_simple.py +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/tox.ini +0 -0
- {rclone_api-1.0.7 → rclone_api-1.0.8}/upload_package.sh +0 -0
@@ -8,10 +8,10 @@ class Dir:
|
|
8
8
|
def __init__(self, path: RPath) -> None:
|
9
9
|
self.path = path
|
10
10
|
|
11
|
-
def ls(self) -> DirListing:
|
11
|
+
def ls(self, max_depth: int = 0) -> DirListing:
|
12
12
|
"""List files and directories in the given path."""
|
13
13
|
assert self.path.rclone is not None
|
14
|
-
return self.path.rclone.ls(self.path.path)
|
14
|
+
return self.path.rclone.ls(self.path.path, max_depth=max_depth)
|
15
15
|
|
16
16
|
def __str__(self) -> str:
|
17
17
|
return str(self.path)
|
@@ -0,0 +1,82 @@
|
|
1
|
+
from concurrent.futures import ThreadPoolExecutor
|
2
|
+
from queue import Empty, Queue
|
3
|
+
from typing import Generator
|
4
|
+
|
5
|
+
from rclone_api import Dir
|
6
|
+
from rclone_api.dir_listing import DirListing
|
7
|
+
|
8
|
+
|
9
|
+
def walk(
|
10
|
+
dir: Dir, max_depth: int = -1, max_workers: int = 4
|
11
|
+
) -> Generator[DirListing, None, None]:
|
12
|
+
"""Walk through the given directory recursively.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
dir: Directory to walk through
|
16
|
+
max_depth: Maximum depth to traverse (-1 for unlimited)
|
17
|
+
|
18
|
+
Yields:
|
19
|
+
DirListing: Directory listing for each directory encountered
|
20
|
+
"""
|
21
|
+
pending: Queue[tuple[Dir | None, int]] = Queue()
|
22
|
+
results: Queue[DirListing | Exception] = Queue()
|
23
|
+
|
24
|
+
def worker():
|
25
|
+
while True:
|
26
|
+
try:
|
27
|
+
# Add timeout to allow checking for sentinel value
|
28
|
+
try:
|
29
|
+
current_dir, depth = pending.get(timeout=0.1)
|
30
|
+
except Empty:
|
31
|
+
continue
|
32
|
+
|
33
|
+
# Check for sentinel value
|
34
|
+
if current_dir is None:
|
35
|
+
pending.task_done()
|
36
|
+
break
|
37
|
+
|
38
|
+
listing = current_dir.ls()
|
39
|
+
results.put(listing)
|
40
|
+
|
41
|
+
if max_depth == -1 or depth < max_depth:
|
42
|
+
for d in listing.dirs:
|
43
|
+
pending.put((d, depth + 1))
|
44
|
+
|
45
|
+
pending.task_done()
|
46
|
+
except Exception as e:
|
47
|
+
results.put(e)
|
48
|
+
pending.task_done()
|
49
|
+
break
|
50
|
+
return None
|
51
|
+
|
52
|
+
# Start workers
|
53
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
54
|
+
workers = [executor.submit(worker) for _ in range(max_workers)]
|
55
|
+
|
56
|
+
# Start walking
|
57
|
+
pending.put((dir, 0))
|
58
|
+
|
59
|
+
# Process results while workers are running
|
60
|
+
completed = 0
|
61
|
+
while completed < max_workers:
|
62
|
+
try:
|
63
|
+
result = results.get(timeout=0.1)
|
64
|
+
if isinstance(result, Exception):
|
65
|
+
# Propagate exception
|
66
|
+
raise result
|
67
|
+
yield result
|
68
|
+
except Empty:
|
69
|
+
# Check if any workers have completed
|
70
|
+
completed = sum(1 for w in workers if w.done())
|
71
|
+
continue
|
72
|
+
|
73
|
+
# Signal workers to stop
|
74
|
+
for _ in range(max_workers):
|
75
|
+
pending.put((None, 0))
|
76
|
+
|
77
|
+
# Drain any remaining results
|
78
|
+
while not results.empty():
|
79
|
+
result = results.get()
|
80
|
+
if isinstance(result, Exception):
|
81
|
+
raise result
|
82
|
+
yield result
|
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
|