rclone-api 1.0.18__py2.py3-none-any.whl → 1.0.19__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
rclone_api/dir.py CHANGED
@@ -47,12 +47,14 @@ class Dir:
47
47
  dir = Dir(self.path)
48
48
  return self.path.rclone.ls(dir, max_depth=max_depth)
49
49
 
50
- def walk(self, max_depth: int = -1) -> Generator[DirListing, None, None]:
50
+ def walk(
51
+ self, breadth_first: bool, max_depth: int = -1
52
+ ) -> Generator[DirListing, None, None]:
51
53
  """List files and directories in the given path."""
52
54
  from rclone_api.walk import walk
53
55
 
54
56
  assert self.path.rclone is not None
55
- return walk(self, max_depth=max_depth)
57
+ return walk(self, breadth_first=breadth_first, max_depth=max_depth)
56
58
 
57
59
  def to_json(self) -> dict:
58
60
  """Convert the Dir to a JSON serializable dictionary."""
rclone_api/rclone.py CHANGED
@@ -38,6 +38,12 @@ class Rclone:
38
38
  def _launch_process(self, cmd: list[str]) -> Process:
39
39
  return self._exec.launch_process(cmd)
40
40
 
41
+ def obscure(self, password: str) -> str:
42
+ """Obscure a password for use in rclone config files."""
43
+ cmd_list: list[str] = ["obscure", password]
44
+ cp = self._run(cmd_list)
45
+ return cp.stdout.strip()
46
+
41
47
  def ls(
42
48
  self,
43
49
  path: Dir | Remote | str,
@@ -61,8 +67,9 @@ class Rclone:
61
67
 
62
68
  cmd = ["lsjson"]
63
69
  if max_depth is not None:
64
- cmd.append("--recursive")
65
- if max_depth > -1:
70
+ if max_depth < 0:
71
+ cmd.append("--recursive")
72
+ if max_depth > 0:
66
73
  cmd.append("--max-depth")
67
74
  cmd.append(str(max_depth))
68
75
  cmd.append(str(path))
@@ -96,7 +103,7 @@ class Rclone:
96
103
  return out
97
104
 
98
105
  def walk(
99
- self, path: Dir | Remote | str, max_depth: int = -1
106
+ self, path: Dir | Remote | str, max_depth: int = -1, breadth_first: bool = True
100
107
  ) -> Generator[DirListing, None, None]:
101
108
  """Walk through the given path recursively.
102
109
 
@@ -107,6 +114,7 @@ class Rclone:
107
114
  Yields:
108
115
  DirListing: Directory listing for each directory encountered
109
116
  """
117
+ dir_obj: Dir
110
118
  if isinstance(path, Dir):
111
119
  # Create a Remote object for the path
112
120
  remote = path.remote
@@ -126,9 +134,10 @@ class Rclone:
126
134
  elif isinstance(path, Remote):
127
135
  dir_obj = Dir(path)
128
136
  else:
137
+ dir_obj = Dir(path) # shut up pyright
129
138
  assert f"Invalid type for path: {type(path)}"
130
139
 
131
- yield from walk(dir_obj, max_depth=max_depth)
140
+ yield from walk(dir_obj, max_depth=max_depth, breadth_first=breadth_first)
132
141
 
133
142
  def copyfile(self, src: File | str, dst: File | str) -> None:
134
143
  """Copy a single file from source to destination.
rclone_api/walk.py CHANGED
@@ -9,9 +9,11 @@ from rclone_api.remote import Remote
9
9
  _MAX_OUT_QUEUE_SIZE = 50
10
10
 
11
11
 
12
- def _walk_runner(
13
- queue: Queue[Dir], max_depth: int, out_queue: Queue[DirListing | None]
12
+ def _walk_runner_breadth_first(
13
+ dir: Dir, max_depth: int, out_queue: Queue[DirListing | None]
14
14
  ) -> None:
15
+ queue: Queue[Dir] = Queue()
16
+ queue.put(dir)
15
17
  try:
16
18
  while not queue.empty():
17
19
  current_dir = queue.get()
@@ -35,7 +37,35 @@ def _walk_runner(
35
37
  _thread.interrupt_main()
36
38
 
37
39
 
38
- def walk(dir: Dir | Remote, max_depth: int = -1) -> Generator[DirListing, None, None]:
40
+ def _walk_runner_depth_first(
41
+ dir: Dir, max_depth: int, out_queue: Queue[DirListing | None]
42
+ ) -> None:
43
+ try:
44
+ stack = [(dir, max_depth)]
45
+ while stack:
46
+ current_dir, depth = stack.pop()
47
+ dirlisting = current_dir.ls()
48
+ if depth != 0:
49
+ for subdir in reversed(
50
+ dirlisting.dirs
51
+ ): # Process deeper directories first
52
+ # stack.append((child, depth - 1 if depth > 0 else depth))
53
+ next_depth = depth - 1 if depth > 0 else depth
54
+ _walk_runner_depth_first(subdir, next_depth, out_queue)
55
+ out_queue.put(dirlisting)
56
+ out_queue.put(None)
57
+ except KeyboardInterrupt:
58
+ import _thread
59
+
60
+ out_queue.put(None)
61
+ _thread.interrupt_main()
62
+
63
+
64
+ def walk(
65
+ dir: Dir | Remote,
66
+ breadth_first: bool,
67
+ max_depth: int = -1,
68
+ ) -> Generator[DirListing, None, None]:
39
69
  """Walk through the given directory recursively.
40
70
 
41
71
  Args:
@@ -49,14 +79,17 @@ def walk(dir: Dir | Remote, max_depth: int = -1) -> Generator[DirListing, None,
49
79
  # Convert Remote to Dir if needed
50
80
  if isinstance(dir, Remote):
51
81
  dir = Dir(dir)
52
-
53
- in_queue: Queue[Dir] = Queue()
54
82
  out_queue: Queue[DirListing] = Queue(maxsize=_MAX_OUT_QUEUE_SIZE)
55
- in_queue.put(dir)
83
+
84
+ strategy = (
85
+ _walk_runner_breadth_first if breadth_first else _walk_runner_depth_first
86
+ )
56
87
 
57
88
  # Start worker thread
58
89
  worker = Thread(
59
- target=_walk_runner, args=(in_queue, max_depth, out_queue), daemon=True
90
+ target=strategy,
91
+ args=(dir, max_depth, out_queue),
92
+ daemon=True,
60
93
  )
61
94
  worker.start()
62
95
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.18
3
+ Version: 1.0.19
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -10,6 +10,7 @@ Classifier: Programming Language :: Python :: 3
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
+ Requires-Dist: pyright>=1.1.393
13
14
  Requires-Dist: python-dotenv>=1.0.0
14
15
  Dynamic: home-page
15
16
  Dynamic: maintainer
@@ -2,20 +2,20 @@ rclone_api/__init__.py,sha256=UWQMbhE4WOQ3Skfb0LagFKW8PUKUGOm9_T3z--5FHiY,388
2
2
  rclone_api/cli.py,sha256=dibfAZIh0kXWsBbfp3onKLjyZXo54mTzDjUdzJlDlWo,231
3
3
  rclone_api/config.py,sha256=tP6cU9DnCCEIRc_KP9HPur1jFLLg2QGFSxNwFm6_MVw,118
4
4
  rclone_api/convert.py,sha256=Mx9Qo7zhkOedJd8LdhPvNGHp8znJzOk4f_2KWnoGc78,1012
5
- rclone_api/dir.py,sha256=xUV4i9_E7QHrqHld2IPBlon1CGaAp8qQYMKfJTyVvoQ,2088
5
+ rclone_api/dir.py,sha256=vV-bcI2ESijmwF5rPID5WO2K7soAfZa35wv4KRh_GIo,2154
6
6
  rclone_api/dir_listing.py,sha256=8t5Jx9ZVOJPqGKTJbWaES6bjgogUT2bnpbPVWwK1Fcs,1124
7
7
  rclone_api/exec.py,sha256=9qSOpZo8YRYxv3hOvNr57ApnY2KbjxwT1QNr8OgcLM4,883
8
8
  rclone_api/file.py,sha256=D02iHJW1LhfOiM_R_yPHP8_ApnDiYrkuraVcrV8-qkw,1246
9
9
  rclone_api/filelist.py,sha256=xbiusvNgaB_b_kQOZoHMJJxn6TWGtPrWd2J042BI28o,767
10
10
  rclone_api/process.py,sha256=C7vdGEvIKcI4fx-Z702wK1qomzSsFpdke2SQnBHxd-Y,3660
11
- rclone_api/rclone.py,sha256=J9KKPH7o_DBx5PlTf3ZJMsbt5MVB5yVwB9FZVuWyA-g,12330
11
+ rclone_api/rclone.py,sha256=PTHimJPPqRe-iSqe08zv1FrFB_H2T1eD3Y0WgshEye8,12730
12
12
  rclone_api/remote.py,sha256=c9hlRKBCg1BFB9MCINaQIoCg10qyAkeqiS4brl8ce-8,343
13
13
  rclone_api/rpath.py,sha256=8ZA_1wxWtskwcy0I8V2VbjKDmzPkiWd8Q2JQSvh-sYE,2586
14
14
  rclone_api/util.py,sha256=BDRJ2MIceDoKVTjUQBwyhjbA8UwPrZ-0ZSa9xyMJd0E,3343
15
- rclone_api/walk.py,sha256=J78-bY2AhNpt2ICsI5LqmXRE7oC6wVDoKoicIoU6XMg,1953
15
+ rclone_api/walk.py,sha256=kca0t1GAnF6FLclN01G8NG__Qe-ggodLtAbQSHyVPng,2968
16
16
  rclone_api/assets/example.txt,sha256=lTBovRjiz0_TgtAtbA1C5hNi2ffbqnNPqkKg6UiKCT8,54
17
- rclone_api-1.0.18.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
18
- rclone_api-1.0.18.dist-info/METADATA,sha256=ZzHKYzibXGOl9jGvCCKf90tGkI2dGJn2ux8R5_-4iIA,4421
19
- rclone_api-1.0.18.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
20
- rclone_api-1.0.18.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
21
- rclone_api-1.0.18.dist-info/RECORD,,
17
+ rclone_api-1.0.19.dist-info/LICENSE,sha256=b6pOoifSXiUaz_lDS84vWlG3fr4yUKwB8fzkrH9R8bQ,1064
18
+ rclone_api-1.0.19.dist-info/METADATA,sha256=MFSLZe61zLT-ZKKoPb9UiN-r0A-ZbFzQvmo8S-FUnuc,4454
19
+ rclone_api-1.0.19.dist-info/WHEEL,sha256=9Hm2OB-j1QcCUq9Jguht7ayGIIZBRTdOXD1qg9cCgPM,109
20
+ rclone_api-1.0.19.dist-info/top_level.txt,sha256=EvZ7uuruUpe9RiUyEp25d1Keq7PWYNT0O_-mr8FCG5g,11
21
+ rclone_api-1.0.19.dist-info/RECORD,,