Skip to content

Commit f49db5f

Browse files
committed
build: include monitoring-aws in the 'all' extra + guard completeness
'all' omitted monitoring-aws (the AWS botocore OTel instrumentation), so 'pip install orb-py[all]' lacked AWS-specific tracing despite including both aws and monitoring. Add it, and add a unit test asserting 'all' transitively covers every runtime extra except an explicit denylist (test/dev tooling + the deprecated k8s-legacy plugin), so a future extra can't silently drift out of 'all'.
1 parent 7c7cfa7 commit f49db5f

3 files changed

Lines changed: 94 additions & 2 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ monitoring-aws = [
187187
# groups (reflex→click>=8.2 vs semgrep→click<8.2), so never combine
188188
# `--extra all` with `--group ci`/`--group dev`; use `--no-dev` when syncing it.
189189
all = [
190-
"orb-py[cli,api,sql,monitoring,all-providers,ui]",
190+
"orb-py[cli,api,sql,monitoring,monitoring-aws,all-providers,ui]",
191191
]
192192

193193
# ── Test extras ────────────────────────────────────────────────────────────
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"""Guard: the `all` extra must cover every runtime optional-dependency.
2+
3+
`all` is a hand-curated union of the runtime extras. Nothing in packaging
4+
enforces that a newly-added runtime extra is also wired into `all`, so it is
5+
easy to add e.g. a new provider extra and silently leave `pip install
6+
orb-py[all]` incomplete. This test asserts `all` transitively includes every
7+
runtime extra except an explicit denylist:
8+
9+
- test/tooling extras (`ci`, `dev`, `test-*`) are not runtime features;
10+
- `k8s-legacy` is the deprecated Symphony HostFactory plugin whose heavy legacy
11+
deps are intentionally kept out of `all`.
12+
13+
If this fails after adding an extra, either add it to `all` or, if it is
14+
deliberately excluded, add it to `_DENYLIST` with a reason.
15+
"""
16+
17+
from __future__ import annotations
18+
19+
import tomllib
20+
from pathlib import Path
21+
22+
_PYPROJECT = Path(__file__).resolve().parents[2] / "pyproject.toml"
23+
24+
# Extras that are intentionally NOT part of `all` (with rationale above).
25+
_DENYLIST = frozenset(
26+
{
27+
"all", # self
28+
"ci", # test/lint tooling, not runtime
29+
"dev", # dev tooling, not runtime
30+
"test-aws", # test-only
31+
"test-k8s", # test-only
32+
"k8s-legacy", # deprecated legacy plugin, heavy deps kept out of `all`
33+
}
34+
)
35+
36+
37+
def _load_extras() -> dict[str, list[str]]:
38+
data = tomllib.loads(_PYPROJECT.read_text(encoding="utf-8"))
39+
return data["project"]["optional-dependencies"]
40+
41+
42+
def _resolve(name: str, extras: dict[str, list[str]], seen: set[str] | None = None) -> set[str]:
43+
"""Return the set of concrete package names an extra pulls in, following
44+
``orb-py[...]`` self-references transitively."""
45+
seen = seen if seen is not None else set()
46+
if name in seen:
47+
return set()
48+
seen.add(name)
49+
pkgs: set[str] = set()
50+
for dep in extras.get(name, []):
51+
if dep.startswith("orb-py["):
52+
inner = dep[dep.index("[") + 1 : dep.index("]")]
53+
for ref in inner.split(","):
54+
pkgs |= _resolve(ref.strip(), extras, seen)
55+
else:
56+
# Strip version/marker/sub-extra to get the bare distribution name.
57+
pkgs.add(dep.split(">")[0].split("=")[0].split("[")[0].split(";")[0].strip())
58+
return pkgs
59+
60+
61+
def test_all_extra_covers_every_runtime_extra() -> None:
62+
extras = _load_extras()
63+
assert "all" in extras, "pyproject is missing the `all` extra"
64+
65+
all_pkgs = _resolve("all", extras)
66+
runtime_extras = [name for name in extras if name not in _DENYLIST]
67+
68+
missing: dict[str, list[str]] = {}
69+
for name in runtime_extras:
70+
gap = _resolve(name, extras) - all_pkgs
71+
if gap:
72+
missing[name] = sorted(gap)
73+
74+
assert not missing, (
75+
"The `all` extra does not cover these runtime extras — add them to `all` "
76+
f"(or to _DENYLIST if deliberately excluded): {missing}"
77+
)
78+
79+
80+
def test_denylisted_extras_still_exist() -> None:
81+
"""Keep the denylist honest: every denylisted name (except `all` itself)
82+
must be a real extra, so a renamed/removed extra doesn't rot silently."""
83+
extras = _load_extras()
84+
for name in _DENYLIST - {"all"}:
85+
assert name in extras, f"_DENYLIST names '{name}', which is not an extra anymore"
86+
87+
88+
if __name__ == "__main__":
89+
test_all_extra_covers_every_runtime_extra()
90+
test_denylisted_extras_still_exist()
91+
print("ok")

uv.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)