podbench 0.1.0b1__py3-none-any.whl

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.
podbench/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ """Top level API.
2
+
3
+ .. data:: __version__
4
+ :type: str
5
+
6
+ Version number as calculated by https://github.com/pypa/setuptools_scm
7
+ """
8
+
9
+ from ._version import __version__
10
+
11
+ __all__ = ["__version__"]
podbench/__main__.py ADDED
@@ -0,0 +1,137 @@
1
+ """Interface for ``python -m podbench``, and the ``podbench`` console script.
2
+
3
+ One binary serves both halves of the tool. On a developer's machine it is
4
+ reached as ``podbench <verb>`` — canonically ``uvx podbench <verb>``, with nothing
5
+ installed — and drives the cluster; inside the debug container the same binary is
6
+ PID 1 (``podbench agent``) and backs the helpers on
7
+ ``PATH`` (``pids``, ``dbg``, ``capreport``, ...). Keeping it as one package means
8
+ the capability logic that decides what a session can do is the same code in both
9
+ places, rather than a launcher's guess and a helper's separate guess.
10
+
11
+ Dispatch is deliberately dumb: each verb names a module, and the module owns its
12
+ own argument parsing. Two of them predate the dispatcher and parse an argv that
13
+ does not include the verb, so those are sliced; the rest are forwarded verbatim.
14
+ Imports are done lazily per verb because ``podbench --version`` runs as the
15
+ image's build-time smoke test, and it should not depend on every module in the
16
+ package importing cleanly.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import sys
22
+ from argparse import REMAINDER, ArgumentParser
23
+ from collections.abc import Callable, Sequence
24
+
25
+ from . import __version__
26
+
27
+ __all__ = ["ENTRY_POINTS", "main"]
28
+
29
+
30
+ def _agent(args: Sequence[str]) -> int:
31
+ from .agent import main as run
32
+
33
+ return run(args)
34
+
35
+
36
+ def _capreport(args: Sequence[str]) -> int:
37
+ from .probe import main as run
38
+
39
+ return run(args)
40
+
41
+
42
+ def _gdbcmd(args: Sequence[str]) -> int:
43
+ from .gdbcmd import main as run
44
+
45
+ return run(args)
46
+
47
+
48
+ def _dev(args: Sequence[str]) -> int:
49
+ from .dev import main as run
50
+
51
+ return run(args)
52
+
53
+
54
+ def _launcher(args: Sequence[str]) -> int:
55
+ from .launcher import main as run
56
+
57
+ return run(args)
58
+
59
+
60
+ def _patch(args: Sequence[str]) -> int:
61
+ from .patch import main as run
62
+
63
+ return run(args)
64
+
65
+
66
+ #: Verb -> (handler, keep_verb). ``keep_verb`` is False for the two modules whose
67
+ #: parsers were written before this dispatcher existed and so do not expect their
68
+ #: own name in argv; the others own a subparser keyed on it and need it kept.
69
+ ENTRY_POINTS: dict[str, tuple[Callable[[Sequence[str]], int], bool]] = {
70
+ # In-pod: PID 1 and the helpers on PATH.
71
+ "agent": (_agent, False),
72
+ "capreport": (_capreport, False),
73
+ "pids": (_gdbcmd, True),
74
+ "dbg": (_gdbcmd, True),
75
+ "dev-bootstrap": (_dev, True),
76
+ "run": (_dev, True),
77
+ "stop": (_dev, True),
78
+ # Laptop side: `podbench ...`.
79
+ "attach": (_launcher, True),
80
+ "ssh-config": (_launcher, True),
81
+ "status": (_launcher, True),
82
+ "list": (_launcher, True),
83
+ "dev": (_dev, True),
84
+ # `patch status` is a *sub*-verb of this parser and does not collide with
85
+ # the launcher's own `status`.
86
+ "patch": (_patch, True),
87
+ }
88
+
89
+ _IN_POD = ("agent", "capreport", "pids", "dbg", "dev-bootstrap", "run", "stop")
90
+ _LAUNCHER = ("attach", "ssh-config", "status", "list", "dev", "patch")
91
+
92
+
93
+ def _build_parser() -> ArgumentParser:
94
+ parser = ArgumentParser(
95
+ prog="podbench",
96
+ description=(
97
+ "A development seat inside a Kubernetes pod. Run `podbench <verb> "
98
+ "--help` for a verb's own options."
99
+ ),
100
+ epilog=(
101
+ "cluster-side verbs: "
102
+ + ", ".join(_LAUNCHER)
103
+ + "; in-pod verbs: "
104
+ + ", ".join(_IN_POD)
105
+ ),
106
+ )
107
+ parser.add_argument("-v", "--version", action="version", version=__version__)
108
+ parser.add_argument(
109
+ "verb",
110
+ nargs="?",
111
+ choices=sorted(ENTRY_POINTS),
112
+ metavar="VERB",
113
+ help="the subcommand to run",
114
+ )
115
+ # REMAINDER hands the verb's own flags through untouched, so that `podbench
116
+ # dbg --launch ./prog --fast` reaches gdbcmd with `--fast` intact instead of
117
+ # being claimed by this parser.
118
+ parser.add_argument("args", nargs=REMAINDER, help="arguments for the verb")
119
+ return parser
120
+
121
+
122
+ def main(args: Sequence[str] | None = None) -> int:
123
+ """Dispatch a verb to the module that implements it."""
124
+ parser = _build_parser()
125
+ parsed = parser.parse_args(args)
126
+ verb: str | None = parsed.verb
127
+ if verb is None:
128
+ parser.print_help()
129
+ return 2
130
+
131
+ handler, keep_verb = ENTRY_POINTS[verb]
132
+ rest: list[str] = list(parsed.args)
133
+ return handler([verb, *rest] if keep_verb else rest)
134
+
135
+
136
+ if __name__ == "__main__":
137
+ sys.exit(main())
podbench/_version.py ADDED
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.1.0b1'
22
+ __version_tuple__ = version_tuple = (0, 1, 0, 'b1')
23
+
24
+ __commit_id__ = commit_id = None