Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/contrib/local-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ The flowcounts weekly reads its record parser and schema, routing data and stati
Use `python3 tools/recipes.py why tools/bloomery/hf.py --recipe weekly-gpu-ds41-flowcounts` to inspect that boundary.
The script walk is conservative: a helper's prose must not turn the self-tests that use it into dependencies of
the helper itself. The regression holds both the absent hub input and the retained executable inputs.
Includes and repository-path literals on inner lines of a multiline Rust attribute are inputs too.
The recipe self-test checks that changing either selects the compiling recipes; attribute contents
must not bypass input discovery while the module/`cfg` scanner skips their syntax.

The gate-batch self-test waits for stopped fixture lanes and their registered
items to finish before a case can remove its tree. A delayed TERM-handler case
Expand Down
27 changes: 22 additions & 5 deletions tools/recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1245,11 +1245,8 @@ def _walk(self, rel: str, moddir: str, acc: ModuleTree, test: bool, modpath: tup
s = line.strip()
if not s or s.startswith("//"):
continue
if attr_depth > 0:
attr_depth += s.count("[") - s.count("]")
continue
indent = len(line) - len(line.lstrip())
if s == "}" and inline and inline[-1][0] == indent:
if attr_depth == 0 and s == "}" and inline and inline[-1][0] == indent:
inline.pop()
continue
here = inline[-1][2] if inline else test
Expand All @@ -1267,6 +1264,9 @@ def _walk(self, rel: str, moddir: str, acc: ModuleTree, test: bool, modpath: tup
(acc.test_files if here else acc.files).add(p)
else:
self.unresolved.append(f"{rel}: include of {inc} ({p} not found)")
if attr_depth > 0:
attr_depth += s.count("[") - s.count("]")
continue
# `#[cfg(test)] mod x;`, `#[path = "x.rs"] mod x;`, `#[cfg(test)] #[path = "x.rs"]`: each
# one-line attribute counts as if on a line of its own, then the item after them is read
attrs, rest = self.lead_attrs(s)
Expand Down Expand Up @@ -9629,13 +9629,23 @@ def module_gate_self_test(expect) -> None:
'mod plain;\n#[cfg(feature = "fy")]\nmod gated;\n#[cfg(not(feature = "fy"))]\nmod off;\n'
'#[cfg(all(feature = "fy", feature = "fz"))]\n#[allow(dead_code)]\nmod inl {\n mod deep;\n'
' const D: &str = include_str!("../data/d.txt");\n}\n#[cfg(any(test, feature = "fy"))]\nmod either;\n'
'#[cfg(test)]\nmod attr_test {\n'
' #[doc = concat!(stringify!({\n}\n ),\n'
' include_str!("../../../attribute-test.txt"),\n'
' "tools/attribute-test-data.txt"\n )]\n'
' pub struct Item;\n const AFTER: &str = include_str!("../../../after-attribute.txt");\n}\n'
),
"crates/g/src/plain.rs": "",
"crates/g/src/plain.rs": '#[doc = concat!(\n include_str!("../../../attribute.txt"),\n "tools/attribute-data.txt"\n)]\npub struct Plain;\n',
"crates/g/src/gated.rs": "",
"crates/g/src/off.rs": "",
"crates/g/src/inl/deep.rs": "",
"crates/g/src/either.rs": "",
"crates/g/data/d.txt": "",
"attribute.txt": "attribute1\n",
"tools/attribute-data.txt": "literal1\n",
"attribute-test.txt": "test attribute\n",
"tools/attribute-test-data.txt": "test literal\n",
"after-attribute.txt": "after attribute\n",
"crates/g/src/bin/x.rs": '#[cfg(feature = "fy")]\nmod xg;\nfn main() {}\n',
"crates/g/src/bin/xg.rs": "",
"crates/g/src/bin/y.rs": "fn main() {}\n",
Expand All @@ -9661,6 +9671,8 @@ def module_gate_self_test(expect) -> None:
fy = {"gate-xy", "gate-yz", "gate-liby", "gate-all"} | whole
cases = [
("an ungated module", "plain.rs", every),
("an include on an inner attribute line", "../../../attribute.txt", every),
("a path literal on an inner attribute line", "../../../tools/attribute-data.txt", every),
("a module under feature = fy", "gated.rs", fy),
("a module under not(feature = fy)", "off.rs", {"gate-x", "gate-lib"} | whole),
("a module under any(test, feature = fy), which a test build compiles whatever the features", "either.rs", every),
Expand All @@ -9673,6 +9685,11 @@ def module_gate_self_test(expect) -> None:
sels, _, _ = select([os.path.normpath(os.path.join("crates/g/src", rel))], side, side, GATE_PREFIX)
got = {x.recipe for x in sels}
expect(got == want, f"module gate: {what} selects {sorted(got)}, not {sorted(want)}")
for rel in ("attribute-test.txt", "tools/attribute-test-data.txt", "after-attribute.txt"):
sels, _, _ = select([rel], side, side, GATE_PREFIX)
got = {x.recipe for x in sels} - whole
expect(got == {"gate-lib", "gate-liby", "gate-all"},
f"module gate: an attribute brace must leave {rel} test-only, selected {sorted(got)}")
expect(not side.tree.unresolved, f"module gate: unresolved {side.tree.unresolved[:2]}")


Expand Down
Loading