PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions | Variables
audit_family_census Namespace Reference

Functions

 scanned_modules ()
 Resolve the module roots into concrete files and their public dotted names.
 
set declared_surfaces ()
 Public surfaces already covered by a registered capability family.
 
dict candidate_surfaces ()
 Public choice points in the CLI, found independently of the registry.
 
tuple classification_of (entry)
 Normalize a census entry into a typed classification and reason.
 
int main ()
 Report uncovered public selector surfaces, typed.
 

Variables

 REPO_ROOT = Path(__file__).resolve().parents[2]
 
str REGISTRY = REPO_ROOT / "tests" / "tooling" / "capability_families.json"
 
str CENSUS = REPO_ROOT / "tests" / "tooling" / "family_census.json"
 
tuple SCANNED_MODULE_ROOTS = ("picurv_cli/core.py", "picurv_cli/storage", "picurv_cli/cli.py")
 
tuple CHOICE_SET_SUFFIXES
 
 _CHOICE_SET_PATTERN = re.compile(r"[A-Z0-9_]+(" + "|".join(CHOICE_SET_SUFFIXES) + r")$")
 
tuple VALID_CLASSIFICATIONS
 
tuple NEEDS_OWNER = ("parameter_of_entry", "spelling_alias")
 

Detailed Description

Report public selector surfaces that no capability family covers.

Function Documentation

◆ scanned_modules()

audit_family_census.scanned_modules ( )

Resolve the module roots into concrete files and their public dotted names.

Returns
List of (repo-relative path, dotted module name) pairs.

Definition at line 24 of file audit_family_census.py.

24def scanned_modules():
25 """!
26 @brief Resolve the module roots into concrete files and their public dotted names.
27 @return List of `(repo-relative path, dotted module name)` pairs.
28 """
29 resolved = []
30 for root in SCANNED_MODULE_ROOTS:
31 path = REPO_ROOT / root
32 if path.is_dir():
33 dotted = root.replace("/", ".")
34 for child in sorted(path.glob("*.py")):
35 if child.name != "__init__.py":
36 resolved.append((str(child.relative_to(REPO_ROOT)), dotted))
37 else:
38 resolved.append((root, root.replace("/", ".")[: -len(".py")]))
39 return resolved
40
41
Here is the caller graph for this function:

◆ declared_surfaces()

set audit_family_census.declared_surfaces ( )

Public surfaces already covered by a registered capability family.

Returns
Set of module::symbol identifiers.

Definition at line 42 of file audit_family_census.py.

42def declared_surfaces() -> set:
43 """!
44 @brief Public surfaces already covered by a registered capability family.
45 @return Set of `module::symbol` identifiers.
46 """
47 registry = json.loads(REGISTRY.read_text(encoding="utf-8"))
48 covered = set()
49 for family in registry["families"]:
50 surface = family.get("public_surface", {})
51 if surface.get("module") and surface.get("symbol"):
52 covered.add(f"{surface['module']}::{surface['symbol']}")
53 return covered
54
55
56# Module-level names with these suffixes declare a closed public choice set. This is
57# the discovery contract: a choice set written as an inline literal at its point of use
58# is invisible to the census, so the rule is that it must be named. Adding a suffix here
59# widens discovery; removing an authoritative constant narrows it, which is why the
60# committed classifications are asserted against this list by the test suite.
Here is the caller graph for this function:

◆ candidate_surfaces()

dict audit_family_census.candidate_surfaces ( )

Public choice points in the CLI, found independently of the registry.

A normalize_* function, or a module-level constant whose name ends in one of CHOICE_SET_SUFFIXES, is how this codebase exposes a user-selectable set. Finding them independently of the registry is the point: a registry that only checks itself cannot report a family nobody registered.

Returns
Mapping of module::symbol to a short description.

Definition at line 69 of file audit_family_census.py.

69def candidate_surfaces() -> dict:
70 """!
71 @brief Public choice points in the CLI, found independently of the registry.
72
73 @details A `normalize_*` function, or a module-level constant whose name ends in one
74 of CHOICE_SET_SUFFIXES, is how this codebase exposes a user-selectable set.
75 Finding them independently of the registry is the point: a registry that
76 only checks itself cannot report a family nobody registered.
77 @return Mapping of `module::symbol` to a short description.
78 """
79 found: dict = {}
80 for module, dotted in scanned_modules():
81 path = REPO_ROOT / module
82 if not path.is_file():
83 continue
84 tree = ast.parse(path.read_text(encoding="utf-8"))
85 for node in tree.body:
86 if isinstance(node, ast.FunctionDef) and re.fullmatch(r"normalize_\w+", node.name):
87 found[f"{dotted}::{node.name}"] = "normalizer"
88 elif isinstance(node, ast.Assign):
89 for target in node.targets:
90 if isinstance(target, ast.Name) and _CHOICE_SET_PATTERN.fullmatch(target.id):
91 found[f"{dotted}::{target.id}"] = "choice set"
92 return found
93
94
95# Every discovered surface must land in exactly one of these. The vocabulary is the
96# result of the explicit census: a closed choice set is either documented as a
97# capability family, or it is one of these five things, and saying which is a
98# deliberate act rather than an omission.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ classification_of()

tuple audit_family_census.classification_of (   entry)

Normalize a census entry into a typed classification and reason.

Older entries were free-text, which let a pending public family be summarized as "not a public family". A typed record cannot do that.

Parameters
[in]entryCensus entry, either a mapping or a legacy string.
Returns
Tuple of (classification, reason).

Definition at line 112 of file audit_family_census.py.

112def classification_of(entry) -> tuple:
113 """!
114 @brief Normalize a census entry into a typed classification and reason.
115
116 @details Older entries were free-text, which let a pending public family be
117 summarized as "not a public family". A typed record cannot do that.
118 @param[in] entry Census entry, either a mapping or a legacy string.
119 @return Tuple of (classification, reason).
120 """
121 if isinstance(entry, dict):
122 return entry.get("classification", ""), entry.get("reason", "")
123 text = str(entry)
124 if "not a public capability family" in text:
125 return "not_public", text
126 return "public_pending", text
127
128
Here is the caller graph for this function:

◆ main()

int audit_family_census.main ( )

Report uncovered public selector surfaces, typed.

Fails when a surface is undiscovered, when a classification is invalid, when a not_public entry gives no reason, or when any public family remains pending. Publication cannot proceed while a public family is undocumented.

Returns
Process status code.

Definition at line 129 of file audit_family_census.py.

129def main() -> int:
130 """!
131 @brief Report uncovered public selector surfaces, typed.
132
133 @details Fails when a surface is undiscovered, when a classification is invalid,
134 when a `not_public` entry gives no reason, or when any public family
135 remains pending. Publication cannot proceed while a public family is
136 undocumented.
137 @return Process status code.
138 """
139 census = json.loads(CENSUS.read_text(encoding="utf-8")) if CENSUS.is_file() else {}
140 acknowledged = census.get("acknowledged_uncovered", {})
141 covered = declared_surfaces()
142 candidates = candidate_surfaces()
143
144 uncovered = {k: v for k, v in candidates.items() if k not in covered}
145 unacknowledged = sorted(k for k in uncovered if k not in acknowledged)
146 stale = sorted(k for k in acknowledged if k not in candidates)
147
148 pending: list = []
149 not_public: list = []
150 malformed: list = []
151 for key, entry in sorted(acknowledged.items()):
152 classification, reason = classification_of(entry)
153 if classification not in VALID_CLASSIFICATIONS:
154 malformed.append(f"{key}: classification '{classification}' is not one of {list(VALID_CLASSIFICATIONS)}")
155 continue
156 if classification != "public_pending" and not reason.strip():
157 malformed.append(
158 f"{key}: classified {classification} but gives no reason. Every "
159 f"classification other than public_pending is a claim, and a claim owes "
160 f"its reasoning"
161 )
162 continue
163 owner = entry.get("owner") if isinstance(entry, dict) else None
164 if classification in NEEDS_OWNER and not owner:
165 malformed.append(
166 f"{key}: classified {classification} but names no owner. Say which "
167 f"capability entry or canonical value it belongs to"
168 )
169 continue
170 (pending if classification == "public_pending" else not_public).append(key)
171
172 problems: list = []
173 if stale:
174 problems += [f"census acknowledges '{k}', which no longer exists" for k in stale]
175 if unacknowledged:
176 problems += [f"'{k}' ({candidates[k]}) has no capability family and no census entry" for k in unacknowledged]
177 problems += malformed
178
179 if problems:
180 print("Capability family census violations:", file=sys.stderr)
181 for problem in problems:
182 print(f" {problem}", file=sys.stderr)
183 print(
184 "\nRegister a family in capability_families.json, or classify the surface in\n"
185 "family_census.json as one of "
186 + ", ".join(VALID_CLASSIFICATIONS) + ",\nwith a reason. An unregistered "
187 "family is invisible to every other gate.",
188 file=sys.stderr,
189 )
190 return 1
191
192 from collections import Counter
193 spread = Counter(classification_of(entry)[0] for entry in acknowledged.values())
194 breakdown = ", ".join(f"{count} {name}" for name, count in sorted(spread.items()))
195 print(
196 f"Family census: {len(covered)} covered by a family; {breakdown} "
197 f"({len(candidates)} surfaces examined)."
198 )
199 if pending:
200 print("\nPublic capability families still awaiting Tier-2 backfill:", file=sys.stderr)
201 for key in pending:
202 print(f" {key}", file=sys.stderr)
203 print(
204 "\nThese are public choice points with no documented capability entries.\n"
205 "Publication cannot proceed while any public family is pending.",
206 file=sys.stderr,
207 )
208 return 1
209 return 0
210
211
int main(int argc, char **argv)
Entry point for the postprocessor executable.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ REPO_ROOT

audit_family_census.REPO_ROOT = Path(__file__).resolve().parents[2]

Definition at line 13 of file audit_family_census.py.

◆ REGISTRY

str audit_family_census.REGISTRY = REPO_ROOT / "tests" / "tooling" / "capability_families.json"

Definition at line 14 of file audit_family_census.py.

◆ CENSUS

str audit_family_census.CENSUS = REPO_ROOT / "tests" / "tooling" / "family_census.json"

Definition at line 15 of file audit_family_census.py.

◆ SCANNED_MODULE_ROOTS

tuple audit_family_census.SCANNED_MODULE_ROOTS = ("picurv_cli/core.py", "picurv_cli/storage", "picurv_cli/cli.py")

Definition at line 21 of file audit_family_census.py.

◆ CHOICE_SET_SUFFIXES

tuple audit_family_census.CHOICE_SET_SUFFIXES
Initial value:
1= (
2 "MAP", "SPECS", "MODES", "TYPES", "TASKS", "CHOICES", "POLICIES",
3 "STRUCTURES", "MODELS", "OUTPUTS", "FORMATS", "SPELLINGS", "EXTENSIONS",
4 "SYMBOLS", "NAMES", "PROFILES", "METHODS", "OPERATORS", "KINDS", "SPELLINGS",
5)

Definition at line 61 of file audit_family_census.py.

◆ _CHOICE_SET_PATTERN

audit_family_census._CHOICE_SET_PATTERN = re.compile(r"[A-Z0-9_]+(" + "|".join(CHOICE_SET_SUFFIXES) + r")$")
protected

Definition at line 66 of file audit_family_census.py.

◆ VALID_CLASSIFICATIONS

tuple audit_family_census.VALID_CLASSIFICATIONS
Initial value:
1= (
2 "public_pending", # A public family that owes Tier-1/Tier-2 coverage.
3 "parameter_of_entry", # A knob an existing capability entry already owns.
4 "spelling_alias", # Accepted spellings resolving to a canonical value.
5 "structural", # Free-form or externally-owned; no closed PICurv set.
6 "cli_inventory_sufficient", # The generated CLI reference answers it fully.
7 "not_public", # Internal; not reachable as a user choice.
8)

Definition at line 99 of file audit_family_census.py.

◆ NEEDS_OWNER

tuple audit_family_census.NEEDS_OWNER = ("parameter_of_entry", "spelling_alias")

Definition at line 109 of file audit_family_census.py.