droppass-cli 0.1.3__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.
- droppass_cli-0.1.3/PKG-INFO +51 -0
- droppass_cli-0.1.3/README.md +31 -0
- droppass_cli-0.1.3/droppass_cli/__init__.py +3 -0
- droppass_cli-0.1.3/droppass_cli/__main__.py +5 -0
- droppass_cli-0.1.3/droppass_cli/_version.py +1 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-darwin-arm64 +0 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-darwin-x64 +0 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-linux-arm +0 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-linux-arm64 +0 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-linux-x64 +0 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-win32-arm64.exe +0 -0
- droppass_cli-0.1.3/droppass_cli/bin/droppass-win32-x64.exe +0 -0
- droppass_cli-0.1.3/droppass_cli/launcher.py +106 -0
- droppass_cli-0.1.3/droppass_cli.egg-info/PKG-INFO +51 -0
- droppass_cli-0.1.3/droppass_cli.egg-info/SOURCES.txt +19 -0
- droppass_cli-0.1.3/droppass_cli.egg-info/dependency_links.txt +1 -0
- droppass_cli-0.1.3/droppass_cli.egg-info/entry_points.txt +2 -0
- droppass_cli-0.1.3/droppass_cli.egg-info/top_level.txt +1 -0
- droppass_cli-0.1.3/pyproject.toml +39 -0
- droppass_cli-0.1.3/setup.cfg +4 -0
- droppass_cli-0.1.3/tests/test_launcher.py +107 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: droppass-cli
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: droppass CLI distributed via pip
|
|
5
|
+
Author: AFK Surf
|
|
6
|
+
License-Expression: LicenseRef-UNLICENSED
|
|
7
|
+
Project-URL: Homepage, https://github.com/AFK-surf/droppass
|
|
8
|
+
Project-URL: Repository, https://github.com/AFK-surf/droppass
|
|
9
|
+
Keywords: droppass,cli,secrets,agent
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# droppass-cli
|
|
22
|
+
|
|
23
|
+
Install globally with pip:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install droppass-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The package ships a Python launcher plus prebuilt `droppass` binaries for the
|
|
30
|
+
same targets as the standalone release assets:
|
|
31
|
+
|
|
32
|
+
- `darwin-x64`
|
|
33
|
+
- `darwin-arm64`
|
|
34
|
+
- `linux-x64`
|
|
35
|
+
- `linux-arm64`
|
|
36
|
+
- `linux-arm`
|
|
37
|
+
- `win32-x64`
|
|
38
|
+
- `win32-arm64`
|
|
39
|
+
|
|
40
|
+
The launcher selects the matching embedded binary at runtime.
|
|
41
|
+
|
|
42
|
+
Maintainer release flow:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd cli
|
|
46
|
+
node ./scripts/build-pip-package.mjs
|
|
47
|
+
python3 -m build --outdir ./dist/pip/dist ./dist/pip/package
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
CI publishes the package to PyPI from `v*` tags. See `cli/RELEASING.md`
|
|
51
|
+
for the full release workflow.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# droppass-cli
|
|
2
|
+
|
|
3
|
+
Install globally with pip:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install droppass-cli
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The package ships a Python launcher plus prebuilt `droppass` binaries for the
|
|
10
|
+
same targets as the standalone release assets:
|
|
11
|
+
|
|
12
|
+
- `darwin-x64`
|
|
13
|
+
- `darwin-arm64`
|
|
14
|
+
- `linux-x64`
|
|
15
|
+
- `linux-arm64`
|
|
16
|
+
- `linux-arm`
|
|
17
|
+
- `win32-x64`
|
|
18
|
+
- `win32-arm64`
|
|
19
|
+
|
|
20
|
+
The launcher selects the matching embedded binary at runtime.
|
|
21
|
+
|
|
22
|
+
Maintainer release flow:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd cli
|
|
26
|
+
node ./scripts/build-pip-package.mjs
|
|
27
|
+
python3 -m build --outdir ./dist/pip/dist ./dist/pip/package
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
CI publishes the package to PyPI from `v*` tags. See `cli/RELEASING.md`
|
|
31
|
+
for the full release workflow.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.3"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import stat
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from importlib import resources
|
|
9
|
+
|
|
10
|
+
TARGETS = {
|
|
11
|
+
"darwin-x64": {
|
|
12
|
+
"platform": "darwin",
|
|
13
|
+
"arch": "x64",
|
|
14
|
+
"binary_name": "droppass-darwin-x64",
|
|
15
|
+
},
|
|
16
|
+
"darwin-arm64": {
|
|
17
|
+
"platform": "darwin",
|
|
18
|
+
"arch": "arm64",
|
|
19
|
+
"binary_name": "droppass-darwin-arm64",
|
|
20
|
+
},
|
|
21
|
+
"linux-x64": {
|
|
22
|
+
"platform": "linux",
|
|
23
|
+
"arch": "x64",
|
|
24
|
+
"binary_name": "droppass-linux-x64",
|
|
25
|
+
},
|
|
26
|
+
"linux-arm64": {
|
|
27
|
+
"platform": "linux",
|
|
28
|
+
"arch": "arm64",
|
|
29
|
+
"binary_name": "droppass-linux-arm64",
|
|
30
|
+
},
|
|
31
|
+
"linux-arm": {
|
|
32
|
+
"platform": "linux",
|
|
33
|
+
"arch": "arm",
|
|
34
|
+
"binary_name": "droppass-linux-arm",
|
|
35
|
+
},
|
|
36
|
+
"win32-x64": {
|
|
37
|
+
"platform": "win32",
|
|
38
|
+
"arch": "x64",
|
|
39
|
+
"binary_name": "droppass-win32-x64.exe",
|
|
40
|
+
},
|
|
41
|
+
"win32-arm64": {
|
|
42
|
+
"platform": "win32",
|
|
43
|
+
"arch": "arm64",
|
|
44
|
+
"binary_name": "droppass-win32-arm64.exe",
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def format_target(runtime_platform: str, runtime_arch: str) -> str:
|
|
50
|
+
return f"{runtime_platform}-{runtime_arch}"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def detect_target() -> dict[str, str]:
|
|
54
|
+
runtime_platform = "win32" if sys.platform.startswith("win") else sys.platform
|
|
55
|
+
machine = platform.machine().lower()
|
|
56
|
+
|
|
57
|
+
if runtime_platform == "darwin":
|
|
58
|
+
runtime_arch = "arm64" if machine in {"arm64", "aarch64"} else "x64"
|
|
59
|
+
elif runtime_platform == "linux":
|
|
60
|
+
if machine in {"x86_64", "amd64"}:
|
|
61
|
+
runtime_arch = "x64"
|
|
62
|
+
elif machine in {"aarch64", "arm64"}:
|
|
63
|
+
runtime_arch = "arm64"
|
|
64
|
+
elif machine.startswith("armv7") or machine.startswith("armv6") or machine == "arm":
|
|
65
|
+
runtime_arch = "arm"
|
|
66
|
+
else:
|
|
67
|
+
runtime_arch = machine
|
|
68
|
+
elif runtime_platform == "win32":
|
|
69
|
+
if machine in {"arm64", "aarch64"}:
|
|
70
|
+
runtime_arch = "arm64"
|
|
71
|
+
else:
|
|
72
|
+
runtime_arch = "x64"
|
|
73
|
+
else:
|
|
74
|
+
runtime_arch = machine
|
|
75
|
+
|
|
76
|
+
key = format_target(runtime_platform, runtime_arch)
|
|
77
|
+
target = TARGETS.get(key)
|
|
78
|
+
if not target:
|
|
79
|
+
supported = ", ".join(sorted(TARGETS))
|
|
80
|
+
raise RuntimeError(f"Unsupported platform {key}. Supported targets: {supported}")
|
|
81
|
+
return target
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def resolve_binary_path() -> str:
|
|
85
|
+
target = detect_target()
|
|
86
|
+
binary = resources.files("droppass_cli").joinpath("bin", target["binary_name"])
|
|
87
|
+
if not binary.is_file():
|
|
88
|
+
raise RuntimeError(
|
|
89
|
+
f"Missing embedded binary {target['binary_name']} for "
|
|
90
|
+
f"{format_target(target['platform'], target['arch'])}."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
path = os.fspath(binary)
|
|
94
|
+
if not path.endswith(".exe"):
|
|
95
|
+
mode = os.stat(path).st_mode
|
|
96
|
+
if not mode & stat.S_IXUSR:
|
|
97
|
+
os.chmod(path, mode | stat.S_IXUSR)
|
|
98
|
+
return path
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def main(argv: list[str] | None = None) -> int:
|
|
102
|
+
binary_path = resolve_binary_path()
|
|
103
|
+
completed = subprocess.run([binary_path, *(argv if argv is not None else sys.argv[1:])])
|
|
104
|
+
if completed.returncode < 0:
|
|
105
|
+
os.kill(os.getpid(), -completed.returncode)
|
|
106
|
+
return completed.returncode
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: droppass-cli
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: droppass CLI distributed via pip
|
|
5
|
+
Author: AFK Surf
|
|
6
|
+
License-Expression: LicenseRef-UNLICENSED
|
|
7
|
+
Project-URL: Homepage, https://github.com/AFK-surf/droppass
|
|
8
|
+
Project-URL: Repository, https://github.com/AFK-surf/droppass
|
|
9
|
+
Keywords: droppass,cli,secrets,agent
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# droppass-cli
|
|
22
|
+
|
|
23
|
+
Install globally with pip:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install droppass-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The package ships a Python launcher plus prebuilt `droppass` binaries for the
|
|
30
|
+
same targets as the standalone release assets:
|
|
31
|
+
|
|
32
|
+
- `darwin-x64`
|
|
33
|
+
- `darwin-arm64`
|
|
34
|
+
- `linux-x64`
|
|
35
|
+
- `linux-arm64`
|
|
36
|
+
- `linux-arm`
|
|
37
|
+
- `win32-x64`
|
|
38
|
+
- `win32-arm64`
|
|
39
|
+
|
|
40
|
+
The launcher selects the matching embedded binary at runtime.
|
|
41
|
+
|
|
42
|
+
Maintainer release flow:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd cli
|
|
46
|
+
node ./scripts/build-pip-package.mjs
|
|
47
|
+
python3 -m build --outdir ./dist/pip/dist ./dist/pip/package
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
CI publishes the package to PyPI from `v*` tags. See `cli/RELEASING.md`
|
|
51
|
+
for the full release workflow.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
droppass_cli/__init__.py
|
|
4
|
+
droppass_cli/__main__.py
|
|
5
|
+
droppass_cli/_version.py
|
|
6
|
+
droppass_cli/launcher.py
|
|
7
|
+
droppass_cli.egg-info/PKG-INFO
|
|
8
|
+
droppass_cli.egg-info/SOURCES.txt
|
|
9
|
+
droppass_cli.egg-info/dependency_links.txt
|
|
10
|
+
droppass_cli.egg-info/entry_points.txt
|
|
11
|
+
droppass_cli.egg-info/top_level.txt
|
|
12
|
+
droppass_cli/bin/droppass-darwin-arm64
|
|
13
|
+
droppass_cli/bin/droppass-darwin-x64
|
|
14
|
+
droppass_cli/bin/droppass-linux-arm
|
|
15
|
+
droppass_cli/bin/droppass-linux-arm64
|
|
16
|
+
droppass_cli/bin/droppass-linux-x64
|
|
17
|
+
droppass_cli/bin/droppass-win32-arm64.exe
|
|
18
|
+
droppass_cli/bin/droppass-win32-x64.exe
|
|
19
|
+
tests/test_launcher.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
droppass_cli
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "droppass-cli"
|
|
7
|
+
version = "0.1.3"
|
|
8
|
+
description = "droppass CLI distributed via pip"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "LicenseRef-UNLICENSED"
|
|
12
|
+
keywords = ["droppass", "cli", "secrets", "agent"]
|
|
13
|
+
authors = [{ name = "AFK Surf" }]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Operating System :: MacOS",
|
|
18
|
+
"Operating System :: Microsoft :: Windows",
|
|
19
|
+
"Operating System :: POSIX :: Linux",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Topic :: Utilities",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/AFK-surf/droppass"
|
|
27
|
+
Repository = "https://github.com/AFK-surf/droppass"
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
droppass = "droppass_cli.__main__:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
include-package-data = true
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
include = ["droppass_cli*"]
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.package-data]
|
|
39
|
+
"droppass_cli" = ["bin/*"]
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import stat
|
|
5
|
+
import tempfile
|
|
6
|
+
import unittest
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from types import SimpleNamespace
|
|
9
|
+
from unittest import mock
|
|
10
|
+
|
|
11
|
+
from droppass_cli import launcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DetectTargetTests(unittest.TestCase):
|
|
15
|
+
def test_detect_target_linux_x64(self) -> None:
|
|
16
|
+
with (
|
|
17
|
+
mock.patch.object(launcher.sys, "platform", "linux"),
|
|
18
|
+
mock.patch.object(launcher.platform, "machine", return_value="x86_64"),
|
|
19
|
+
):
|
|
20
|
+
target = launcher.detect_target()
|
|
21
|
+
|
|
22
|
+
self.assertEqual(target, launcher.TARGETS["linux-x64"])
|
|
23
|
+
|
|
24
|
+
def test_detect_target_linux_arm64(self) -> None:
|
|
25
|
+
with (
|
|
26
|
+
mock.patch.object(launcher.sys, "platform", "linux"),
|
|
27
|
+
mock.patch.object(launcher.platform, "machine", return_value="aarch64"),
|
|
28
|
+
):
|
|
29
|
+
target = launcher.detect_target()
|
|
30
|
+
|
|
31
|
+
self.assertEqual(target, launcher.TARGETS["linux-arm64"])
|
|
32
|
+
|
|
33
|
+
def test_detect_target_windows_x64(self) -> None:
|
|
34
|
+
with (
|
|
35
|
+
mock.patch.object(launcher.sys, "platform", "win32"),
|
|
36
|
+
mock.patch.object(launcher.platform, "machine", return_value="AMD64"),
|
|
37
|
+
):
|
|
38
|
+
target = launcher.detect_target()
|
|
39
|
+
|
|
40
|
+
self.assertEqual(target, launcher.TARGETS["win32-x64"])
|
|
41
|
+
|
|
42
|
+
def test_detect_target_unsupported_platform_raises(self) -> None:
|
|
43
|
+
with (
|
|
44
|
+
mock.patch.object(launcher.sys, "platform", "linux"),
|
|
45
|
+
mock.patch.object(launcher.platform, "machine", return_value="ppc64le"),
|
|
46
|
+
):
|
|
47
|
+
with self.assertRaisesRegex(RuntimeError, "Unsupported platform linux-ppc64le"):
|
|
48
|
+
launcher.detect_target()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ResolveBinaryPathTests(unittest.TestCase):
|
|
52
|
+
def test_resolve_binary_path_sets_execute_bit(self) -> None:
|
|
53
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
54
|
+
package_root = Path(temp_dir)
|
|
55
|
+
bin_dir = package_root / "bin"
|
|
56
|
+
bin_dir.mkdir(parents=True)
|
|
57
|
+
binary_path = bin_dir / "droppass-linux-x64"
|
|
58
|
+
binary_path.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8")
|
|
59
|
+
binary_path.chmod(0o644)
|
|
60
|
+
|
|
61
|
+
with (
|
|
62
|
+
mock.patch.object(launcher, "detect_target", return_value=launcher.TARGETS["linux-x64"]),
|
|
63
|
+
mock.patch.object(launcher.resources, "files", return_value=package_root),
|
|
64
|
+
):
|
|
65
|
+
resolved = launcher.resolve_binary_path()
|
|
66
|
+
|
|
67
|
+
self.assertEqual(resolved, os.fspath(binary_path))
|
|
68
|
+
self.assertTrue(os.stat(resolved).st_mode & stat.S_IXUSR)
|
|
69
|
+
|
|
70
|
+
def test_resolve_binary_path_missing_binary_raises(self) -> None:
|
|
71
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
72
|
+
package_root = Path(temp_dir)
|
|
73
|
+
|
|
74
|
+
with (
|
|
75
|
+
mock.patch.object(launcher, "detect_target", return_value=launcher.TARGETS["linux-x64"]),
|
|
76
|
+
mock.patch.object(launcher.resources, "files", return_value=package_root),
|
|
77
|
+
):
|
|
78
|
+
with self.assertRaisesRegex(RuntimeError, "Missing embedded binary droppass-linux-x64"):
|
|
79
|
+
launcher.resolve_binary_path()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class MainTests(unittest.TestCase):
|
|
83
|
+
def test_main_invokes_embedded_binary_with_args(self) -> None:
|
|
84
|
+
completed = SimpleNamespace(returncode=0)
|
|
85
|
+
|
|
86
|
+
with (
|
|
87
|
+
mock.patch.object(launcher, "resolve_binary_path", return_value="/tmp/droppass"),
|
|
88
|
+
mock.patch.object(launcher.subprocess, "run", return_value=completed) as run_mock,
|
|
89
|
+
):
|
|
90
|
+
exit_code = launcher.main(["version"])
|
|
91
|
+
|
|
92
|
+
run_mock.assert_called_once_with(["/tmp/droppass", "version"])
|
|
93
|
+
self.assertEqual(exit_code, 0)
|
|
94
|
+
|
|
95
|
+
def test_main_forwards_signal_exit(self) -> None:
|
|
96
|
+
completed = SimpleNamespace(returncode=-15)
|
|
97
|
+
|
|
98
|
+
with (
|
|
99
|
+
mock.patch.object(launcher, "resolve_binary_path", return_value="/tmp/droppass"),
|
|
100
|
+
mock.patch.object(launcher.subprocess, "run", return_value=completed),
|
|
101
|
+
mock.patch.object(launcher.os, "getpid", return_value=1234),
|
|
102
|
+
mock.patch.object(launcher.os, "kill") as kill_mock,
|
|
103
|
+
):
|
|
104
|
+
exit_code = launcher.main(["version"])
|
|
105
|
+
|
|
106
|
+
kill_mock.assert_called_once_with(1234, 15)
|
|
107
|
+
self.assertEqual(exit_code, -15)
|