rclone-api 1.0.2__tar.gz → 1.0.4__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 (36) hide show
  1. {rclone_api-1.0.2 → rclone_api-1.0.4}/.gitignore +1 -0
  2. {rclone_api-1.0.2/src/rclone_api.egg-info → rclone_api-1.0.4}/PKG-INFO +1 -1
  3. {rclone_api-1.0.2 → rclone_api-1.0.4}/pyproject.toml +1 -1
  4. rclone_api-1.0.4/src/rclone_api/__init__.py +8 -0
  5. rclone_api-1.0.4/src/rclone_api/config.py +19 -0
  6. rclone_api-1.0.4/src/rclone_api/dir.py +27 -0
  7. rclone_api-1.0.4/src/rclone_api/file.py +35 -0
  8. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api/rclone.py +57 -43
  9. rclone_api-1.0.4/src/rclone_api/remote.py +8 -0
  10. rclone_api-1.0.2/src/rclone_api/file.py → rclone_api-1.0.4/src/rclone_api/rpath.py +45 -9
  11. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api/types.py +0 -10
  12. {rclone_api-1.0.2 → rclone_api-1.0.4/src/rclone_api.egg-info}/PKG-INFO +1 -1
  13. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api.egg-info/SOURCES.txt +4 -0
  14. rclone_api-1.0.2/src/rclone_api/__init__.py +0 -4
  15. {rclone_api-1.0.2 → rclone_api-1.0.4}/.pylintrc +0 -0
  16. {rclone_api-1.0.2 → rclone_api-1.0.4}/.vscode/launch.json +0 -0
  17. {rclone_api-1.0.2 → rclone_api-1.0.4}/.vscode/settings.json +0 -0
  18. {rclone_api-1.0.2 → rclone_api-1.0.4}/.vscode/tasks.json +0 -0
  19. {rclone_api-1.0.2 → rclone_api-1.0.4}/LICENSE +0 -0
  20. {rclone_api-1.0.2 → rclone_api-1.0.4}/MANIFEST.in +0 -0
  21. {rclone_api-1.0.2 → rclone_api-1.0.4}/README.md +0 -0
  22. {rclone_api-1.0.2 → rclone_api-1.0.4}/clean +0 -0
  23. {rclone_api-1.0.2 → rclone_api-1.0.4}/install +0 -0
  24. {rclone_api-1.0.2 → rclone_api-1.0.4}/lint +0 -0
  25. {rclone_api-1.0.2 → rclone_api-1.0.4}/requirements.testing.txt +0 -0
  26. {rclone_api-1.0.2 → rclone_api-1.0.4}/setup.cfg +0 -0
  27. {rclone_api-1.0.2 → rclone_api-1.0.4}/setup.py +0 -0
  28. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api/assets/example.txt +0 -0
  29. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api/cli.py +0 -0
  30. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api/util.py +0 -0
  31. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api.egg-info/dependency_links.txt +0 -0
  32. {rclone_api-1.0.2 → rclone_api-1.0.4}/src/rclone_api.egg-info/top_level.txt +0 -0
  33. {rclone_api-1.0.2 → rclone_api-1.0.4}/test +0 -0
  34. {rclone_api-1.0.2 → rclone_api-1.0.4}/tests/test_simple.py +0 -0
  35. {rclone_api-1.0.2 → rclone_api-1.0.4}/tox.ini +0 -0
  36. {rclone_api-1.0.2 → rclone_api-1.0.4}/upload_package.sh +0 -0
@@ -139,3 +139,4 @@ activate
139
139
  # Generated by mac
140
140
  **/.DS_Store
141
141
  uv.lock
142
+ .aider*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -14,7 +14,7 @@ dependencies = [
14
14
 
15
15
  ]
16
16
  # Change this with the version number bump.
17
- version = "1.0.2"
17
+ version = "1.0.4"
18
18
 
19
19
  [tool.setuptools]
20
20
  package-dir = {"" = "src"}
@@ -0,0 +1,8 @@
1
+ from .dir import Dir
2
+ from .file import File
3
+ from .rclone import Rclone
4
+ from .remote import Remote
5
+ from .rpath import RPath
6
+ from .types import Config
7
+
8
+ __all__ = ["Rclone", "File", "Config", "Remote", "Dir", "RPath"]
@@ -0,0 +1,19 @@
1
+ import subprocess
2
+ from dataclasses import dataclass
3
+ from pathlib import Path
4
+
5
+ from rclone_api.types import Config
6
+
7
+
8
+ @dataclass
9
+ class RcloneExec:
10
+ """Rclone execution dataclass."""
11
+
12
+ rclone_config: Path | Config
13
+ rclone_exe: Path
14
+
15
+ def execute(self, cmd: list[str]) -> subprocess.CompletedProcess:
16
+ """Execute rclone command."""
17
+ from rclone_api.util import rclone_execute
18
+
19
+ return rclone_execute(cmd, self.rclone_config, self.rclone_exe)
@@ -0,0 +1,27 @@
1
+ from rclone_api.file import File
2
+ from rclone_api.rpath import RPath
3
+
4
+
5
+ class Dir:
6
+ """Remote file dataclass."""
7
+
8
+ def __init__(self, path: RPath) -> None:
9
+ self.path = path
10
+
11
+ def ls(self) -> tuple[list["Dir"], list[File]]:
12
+ """List files and directories in the given path."""
13
+ cmd = ["lsjson", "--files-only", "--dirs-only", "--json", str(self.path)]
14
+ assert self.path.rclone is not None
15
+ cp = self.path.rclone._run(cmd)
16
+ text = cp.stdout
17
+ tmp: list[RPath] = RPath.from_json_str(text)
18
+ for t in tmp:
19
+ t.set_rclone(self.path.rclone)
20
+ # dirs = [o for o in out if o.is_dir]
21
+ # files = [o for o in out if not o.is_dir]
22
+ dirs = [Dir(p) for p in tmp if p.is_dir]
23
+ files = [File(p) for p in tmp if not p.is_dir]
24
+ return dirs, files
25
+
26
+ def __str__(self) -> str:
27
+ return str(self.path)
@@ -0,0 +1,35 @@
1
+ import json
2
+
3
+ from rclone_api.rpath import RPath
4
+
5
+
6
+ class File:
7
+ """Remote file dataclass."""
8
+
9
+ def __init__(
10
+ self,
11
+ path: RPath,
12
+ ) -> None:
13
+ self.path = path
14
+
15
+ def read_text(self) -> str:
16
+ """Read the file contents as bytes.
17
+
18
+ Returns:
19
+ bytes: The file contents
20
+
21
+ Raises:
22
+ RuntimeError: If no rclone instance is associated with this file
23
+ RuntimeError: If the path represents a directory
24
+ """
25
+ if self.path.rclone is None:
26
+ raise RuntimeError("No rclone instance associated with this file")
27
+ if self.path.is_dir:
28
+ raise RuntimeError("Cannot read a directory as bytes")
29
+
30
+ result = self.path.rclone._run(["cat", self.path.path])
31
+ return result.stdout
32
+
33
+ def __str__(self) -> str:
34
+ out = self.path.to_json()
35
+ return json.dumps(out)
@@ -1,43 +1,57 @@
1
- """
2
- Unit test file.
3
- """
4
-
5
- import subprocess
6
- from pathlib import Path
7
-
8
- from rclone_api.file import File
9
- from rclone_api.types import Config, RcloneExec, Remote
10
- from rclone_api.util import get_rclone_exe
11
-
12
-
13
- class Rclone:
14
- def __init__(
15
- self, rclone_conf: Path | Config, rclone_exe: Path | None = None
16
- ) -> None:
17
- if isinstance(rclone_conf, Path):
18
- if not rclone_conf.exists():
19
- raise ValueError(f"Rclone config file not found: {rclone_conf}")
20
- self._exec = RcloneExec(rclone_conf, get_rclone_exe(rclone_exe))
21
-
22
- def _run(self, cmd: list[str]) -> subprocess.CompletedProcess:
23
- return self._exec.execute(cmd)
24
-
25
- def ls(self, path: str | Remote) -> list[File]:
26
- cmd = ["lsjson", str(path)]
27
- cp = self._run(cmd)
28
- text = cp.stdout
29
- out: list[File] = File.from_json_str(text)
30
- for o in out:
31
- o.set_rclone(self)
32
- return out
33
-
34
- def listremotes(self) -> list[Remote]:
35
- cmd = ["listremotes"]
36
- cp = self._run(cmd)
37
- text: str = cp.stdout
38
- tmp = text.splitlines()
39
- tmp = [t.strip() for t in tmp]
40
- # strip out ":" from the end
41
- tmp = [t.replace(":", "") for t in tmp]
42
- out = [Remote(name=t) for t in tmp]
43
- return out
1
+ """
2
+ Unit test file.
3
+ """
4
+
5
+ import subprocess
6
+ from pathlib import Path
7
+
8
+ from rclone_api.remote import Remote
9
+ from rclone_api.rpath import RPath
10
+ from rclone_api.types import Config, RcloneExec
11
+ from rclone_api.util import get_rclone_exe
12
+
13
+
14
+ class Rclone:
15
+ def __init__(
16
+ self, rclone_conf: Path | Config, rclone_exe: Path | None = None
17
+ ) -> None:
18
+ if isinstance(rclone_conf, Path):
19
+ if not rclone_conf.exists():
20
+ raise ValueError(f"Rclone config file not found: {rclone_conf}")
21
+ self._exec = RcloneExec(rclone_conf, get_rclone_exe(rclone_exe))
22
+
23
+ def _run(self, cmd: list[str]) -> subprocess.CompletedProcess:
24
+ return self._exec.execute(cmd)
25
+
26
+ def ls(self, path: str | Remote, max_depth: int = 0) -> list[RPath]:
27
+ """List files in the given path.
28
+
29
+ Args:
30
+ path: Remote path or Remote object to list
31
+ max_depth: Maximum recursion depth (0 means no recursion)
32
+
33
+ Returns:
34
+ List of File objects found at the path
35
+ """
36
+ cmd = ["lsjson"]
37
+ if max_depth > 0:
38
+ cmd.extend(["--recursive", "--max-depth", str(max_depth)])
39
+ cmd.append(str(path))
40
+
41
+ cp = self._run(cmd)
42
+ text = cp.stdout
43
+ out: list[RPath] = RPath.from_json_str(text)
44
+ for o in out:
45
+ o.set_rclone(self)
46
+ return out
47
+
48
+ def listremotes(self) -> list[Remote]:
49
+ cmd = ["listremotes"]
50
+ cp = self._run(cmd)
51
+ text: str = cp.stdout
52
+ tmp = text.splitlines()
53
+ tmp = [t.strip() for t in tmp]
54
+ # strip out ":" from the end
55
+ tmp = [t.replace(":", "") for t in tmp]
56
+ out = [Remote(name=t) for t in tmp]
57
+ return out
@@ -0,0 +1,8 @@
1
+ class Remote:
2
+ """Remote dataclass."""
3
+
4
+ def __init__(self, name: str) -> None:
5
+ self.name = name
6
+
7
+ def __str__(self) -> str:
8
+ return f"{self.name}:"
@@ -1,8 +1,9 @@
1
1
  import json
2
+ from pathlib import Path
2
3
  from typing import Any
3
4
 
4
5
 
5
- class File:
6
+ class RPath:
6
7
  """Remote file dataclass."""
7
8
 
8
9
  def __init__(
@@ -32,9 +33,9 @@ class File:
32
33
  self.rclone = rclone
33
34
 
34
35
  @staticmethod
35
- def from_dict(data: dict) -> "File":
36
+ def from_dict(data: dict) -> "RPath":
36
37
  """Create a File from a dictionary."""
37
- return File(
38
+ return RPath(
38
39
  data["Path"],
39
40
  data["Name"],
40
41
  data["Size"],
@@ -45,21 +46,21 @@ class File:
45
46
  )
46
47
 
47
48
  @staticmethod
48
- def from_array(data: list[dict]) -> list["File"]:
49
+ def from_array(data: list[dict]) -> list["RPath"]:
49
50
  """Create a File from a dictionary."""
50
- out: list[File] = []
51
+ out: list[RPath] = []
51
52
  for d in data:
52
- file: File = File.from_dict(d)
53
+ file: RPath = RPath.from_dict(d)
53
54
  out.append(file)
54
55
  return out
55
56
 
56
57
  @staticmethod
57
- def from_json_str(json_str: str) -> list["File"]:
58
+ def from_json_str(json_str: str) -> list["RPath"]:
58
59
  """Create a File from a JSON string."""
59
60
  json_obj = json.loads(json_str)
60
61
  if isinstance(json_obj, dict):
61
- return [File.from_dict(json_obj)]
62
- return File.from_array(json_obj)
62
+ return [RPath.from_dict(json_obj)]
63
+ return RPath.from_array(json_obj)
63
64
 
64
65
  def to_json(self) -> dict:
65
66
  return {
@@ -72,6 +73,41 @@ class File:
72
73
  # "IsBucket": self.is_bucket,
73
74
  }
74
75
 
76
+ def read_text(self) -> str:
77
+ """Read the file contents as bytes.
78
+
79
+ Returns:
80
+ bytes: The file contents
81
+
82
+ Raises:
83
+ RuntimeError: If no rclone instance is associated with this file
84
+ RuntimeError: If the path represents a directory
85
+ """
86
+ if self.rclone is None:
87
+ raise RuntimeError("No rclone instance associated with this file")
88
+ if self.is_dir:
89
+ raise RuntimeError("Cannot read a directory as bytes")
90
+
91
+ result = self.rclone._run(["cat", self.path])
92
+ return result.stdout
93
+
94
+ def read(self, dest: Path) -> None:
95
+ """Copy the remote file to a local destination path.
96
+
97
+ Args:
98
+ dest: Local destination path where the file will be copied
99
+
100
+ Raises:
101
+ RuntimeError: If no rclone instance is associated with this file
102
+ RuntimeError: If the path represents a directory
103
+ """
104
+ if self.rclone is None:
105
+ raise RuntimeError("No rclone instance associated with this file")
106
+ if self.is_dir:
107
+ raise RuntimeError("Cannot read a directory as a file")
108
+
109
+ self.rclone._run(["copyto", self.path, str(dest)])
110
+
75
111
  def __str__(self) -> str:
76
112
  out = self.to_json()
77
113
  return json.dumps(out)
@@ -22,13 +22,3 @@ class RcloneExec:
22
22
  from rclone_api.util import rclone_execute
23
23
 
24
24
  return rclone_execute(cmd, self.rclone_config, self.rclone_exe)
25
-
26
-
27
- class Remote:
28
- """Remote dataclass."""
29
-
30
- def __init__(self, name: str) -> None:
31
- self.name = name
32
-
33
- def __str__(self) -> str:
34
- return f"{self.name}:"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rclone_api
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: rclone api in python
5
5
  Home-page: https://github.com/zackees/rclone-api
6
6
  Maintainer: Zachary Vorhies
@@ -17,8 +17,12 @@ upload_package.sh
17
17
  .vscode/tasks.json
18
18
  src/rclone_api/__init__.py
19
19
  src/rclone_api/cli.py
20
+ src/rclone_api/config.py
21
+ src/rclone_api/dir.py
20
22
  src/rclone_api/file.py
21
23
  src/rclone_api/rclone.py
24
+ src/rclone_api/remote.py
25
+ src/rclone_api/rpath.py
22
26
  src/rclone_api/types.py
23
27
  src/rclone_api/util.py
24
28
  src/rclone_api.egg-info/PKG-INFO
@@ -1,4 +0,0 @@
1
- from .rclone import File, Rclone
2
- from .types import Config, Remote
3
-
4
- __all__ = ["Rclone", "File", "Config", "Remote"]
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