15Validator for ONE global target configuration packages.
17What this script checks:
181) Target INI existence & minimal required keys (TARGET, BACKEND).
192) Command schema files (codegen.py, profile.py) exist for BACKEND.
203) Command schema is importable without ONE runtime by shimming `onelib.argumentparse`.
214) "Required" arguments are present in schemas:
22 - codegen: DriverName, TargetOption, input{,_path}, output{,_path}
23 - profile: DriverName, TargetOption, input{,_path}
26 python tools/validate_global_conf.py --root . \
27 --target {TARGET_NAME} --backend {BACKEND_NAME}
29You can also point to the "installed" layout:
30 python tools/validate_global_conf.py --installed \
31 --target {TARGET_NAME} --backend {BACKEND_NAME}
40from dataclasses
import dataclass, field
41from typing
import Dict, List, Optional, Tuple
65 names: Tuple[str, ...]
67 dtype: Optional[type] =
None
72 A very small recorder that emulates the subset used by command_schema().
75 self.args: List[_ArgSpec] = []
77 def add_argument(self, *names: str, action=_Action, dtype: Optional[type] =
None):
79 raise ValueError(
"add_argument requires at least one name")
81 names = tuple(str(n)
for n
in names)
82 self.args.append(
_ArgSpec(names=names, action=action, dtype=dtype))
88 mod_onelib = types.ModuleType(
"onelib")
89 mod_argparse = types.ModuleType(
"onelib.argumentparse")
90 mod_argparse.ArgumentParser = ArgumentParser
91 mod_argparse.DriverName = DriverName
92 mod_argparse.TargetOption = TargetOption
93 mod_argparse.NormalOption = NormalOption
98 sys.modules[
"onelib"] = mod_onelib
99 sys.modules[
"onelib.argumentparse"] = mod_argparse
100 mod_onelib.argumentparse = mod_argparse
110 messages: List[str] = field(default_factory=list)
113def _load_schema(file_path: str) -> Tuple[List[_ArgSpec], SchemaReport]:
115 if not os.path.isfile(file_path):
116 rep.messages.append(f
"Missing schema file: {file_path}")
120 spec = importlib.util.spec_from_file_location(
"schema_module", file_path)
121 mod = importlib.util.module_from_spec(spec)
123 assert spec
and spec.loader
124 spec.loader.exec_module(mod)
125 except Exception
as e:
126 rep.messages.append(f
"Import error: {e}")
128 if not hasattr(mod,
"command_schema"):
129 rep.messages.append(
"Schema module has no `command_schema()` function.")
132 parser = mod.command_schema()
133 except Exception
as e:
134 rep.messages.append(f
"command_schema() execution failed: {e}")
136 if not isinstance(parser, ArgumentParser):
138 "command_schema() did not return an ArgumentParser instance (shim).")
142 return parser.args, rep
146 return any(a.action
is action_type
for a
in args)
160 errs.append(
"Missing DriverName action.")
162 errs.append(
"Missing TargetOption action.")
164 errs.append(
"Missing input/input_path argument.")
166 errs.append(
"Missing --output/--output_path option.")
173 errs.append(
"Missing DriverName action.")
175 errs.append(
"Missing TargetOption action.")
177 errs.append(
"Missing input/input_path argument.")
183 parser = configparser.ConfigParser(strict=
False,
187 parser.optionxform = str
188 with io.open(path,
"r", encoding=
"utf-8")
as f:
190 content =
"[DEFAULT]\n" + f.read()
191 parser.read_string(content)
192 return dict(parser[
"DEFAULT"])
197 target_ini = f
"/usr/share/one/target/{target}.ini"
198 codegen_py = f
"/usr/share/one/backends/command/{backend}/codegen.py"
199 profile_py = f
"/usr/share/one/backends/command/{backend}/profile.py"
201 target_ini = os.path.join(root,
"target", target, f
"{target}.ini")
202 codegen_py = os.path.join(root,
"backend", backend,
"one-cmds",
"codegen.py")
203 profile_py = os.path.join(root,
"backend", backend,
"one-cmds",
"profile.py")
204 return target_ini, codegen_py, profile_py
208 ap = argparse.ArgumentParser(
209 description=
"Validate ONE global target configuration package.")
210 ap.add_argument(
"--root", default=
".", help=
"Repo root (for source-tree validation).")
211 ap.add_argument(
"--target", required=
True, help=
"Target name, e.g., Rose")
212 ap.add_argument(
"--backend", required=
True, help=
"Backend name, e.g., dummy")
213 ap.add_argument(
"--installed",
215 help=
"Validate installed paths instead of source tree.")
216 args = ap.parse_args()
218 target_ini, codegen_py, profile_py =
_resolve_paths(args.root, args.target,
219 args.backend, args.installed)
221 print(
"== ONE Global Conf Validator ==")
222 print(f
"Mode : {'installed' if args.installed else 'source-tree'}")
223 print(f
"Target INI: {target_ini}")
224 print(f
"Codegen : {codegen_py}")
225 print(f
"Profile : {profile_py}")
229 if not os.path.isfile(target_ini):
230 print(f
"[ERROR] Target INI not found: {target_ini}")
234 for k
in (
"TARGET",
"BACKEND"):
235 if k
not in kv
or not kv[k].strip():
236 errors.append(f
"Missing required key {k} in INI.")
239 print(f
"[ERROR] {e}")
242 target_val = kv[
"TARGET"].strip()
243 backend_val = kv[
"BACKEND"].strip()
244 if target_val != args.target:
245 print(f
"[WARN] TARGET in INI is '{target_val}' but --target is '{args.target}'")
246 if backend_val != args.backend:
248 f
"[WARN] BACKEND in INI is '{backend_val}' but --backend is '{args.backend}'")
256 def print_report(name: str, rep: SchemaReport):
258 status =
"OK" if rep.ok
else "FAIL"
259 print(f
"[{name}] {rep.file_path}: {status}")
260 for m
in rep.messages:
265 print_report(
"SCHEMA", codegen_rep)
266 print_report(
"SCHEMA", profile_rep)
272 print(f
"[ERROR] codegen schema: {e}")
273 ok = ok
and not cerrs
277 print(f
"[ERROR] profile schema: {e}")
279 print(f
"[WARN] profile schema: {w}")
280 ok = ok
and not perrs
284 print(
"[PASS] Validation succeeded.")
287 print(
"[FAIL] Validation failed.")
291if __name__ ==
"__main__":
add_argument(self, *str names, action=_Action, Optional[type] dtype=None)
Tuple[List[str], List[str]] _check_profile_contract(List[_ArgSpec] args)
Tuple[List[_ArgSpec], SchemaReport] _load_schema(str file_path)
Dict[str, str] _read_ini(str path)
_resolve_paths(str root, str target, str backend, bool installed)
bool _has_any_name(List[_ArgSpec] args, List[str] names)
bool _has_action(List[_ArgSpec] args, type action_type)
List[str] _check_codegen_contract(List[_ArgSpec] args)