exchange work

This commit is contained in:
2026-09-15 13:06:45 -05:00
parent 8a3a0acb75
commit 58610c1e1a
265 changed files with 33534 additions and 69 deletions

View File

@@ -20,6 +20,11 @@ Checks (stdlib only, exit non-zero on any FAIL):
only PrimeControls; dead view params reported as failures
Usage: python3 tools/lint_project.py [--strict] [--project PrimeBAT]
[--namespace PrimeControls]
--namespace names the single folder every view / style class / script package
must live under. It defaults to PrimeControls (PrimeBAT); the shippable,
de-branded copy passes --project AlarmDashboard --namespace AlarmDashboard.
"""
import argparse
import json
@@ -116,7 +121,9 @@ def main():
ap = argparse.ArgumentParser()
ap.add_argument("--strict", action="store_true")
ap.add_argument("--project", default="PrimeBAT")
ap.add_argument("--namespace", default="PrimeControls")
args = ap.parse_args()
ns = args.namespace
proj = os.path.join(ROOT, "ignition", "gateway", "projects", args.project)
if not os.path.isdir(proj):
@@ -171,8 +178,8 @@ def main():
session_schema = sp.get("custom") or {}
if args.strict:
for key in session_schema:
if key != "PrimeControls":
fail(rel(sp_path), "session custom key %r outside PrimeControls" % key)
if key != ns:
fail(rel(sp_path), "session custom key %r outside %s" % (key, ns))
# ---------- page-config contest rules ----------
pc_path = os.path.join(proj, PERSPECTIVE, "page-config", "config.json")
@@ -181,18 +188,18 @@ def main():
pages = pc.get("pages") or {}
if list(pages.keys()) != ["/"]:
fail(rel(pc_path), "pages must be exactly ['/'], got %s" % list(pages.keys()))
elif (pages["/"] or {}).get("viewPath") != "PrimeControls/Dashboard":
fail(rel(pc_path), "page '/' must map to PrimeControls/Dashboard")
elif (pages["/"] or {}).get("viewPath") != "%s/Dashboard" % ns:
fail(rel(pc_path), "page '/' must map to %s/Dashboard" % ns)
if pc.get("sharedDocks"):
fail(rel(pc_path), "sharedDocks must be empty (docked views prohibited)")
# ---------- namespace rule: everything under PrimeControls/ ----------
for p in sorted(view_paths):
if not p.startswith("PrimeControls/"):
fail("views/%s" % p, "view outside PrimeControls/ folder")
if not p.startswith(ns + "/"):
fail("views/%s" % p, "view outside %s/ folder" % ns)
for p in sorted(style_paths):
if not p.startswith("PrimeControls/"):
fail("style-classes/%s" % p, "style class outside PrimeControls/ folder")
if not p.startswith(ns + "/"):
fail("style-classes/%s" % p, "style class outside %s/ folder" % ns)
# ---------- per-view checks ----------
for vp in sorted(view_paths):
@@ -222,8 +229,8 @@ def main():
if isinstance(path_prop, str) and path_prop:
if path_prop not in view_paths:
fail(rv, "%s embeds missing view %r" % (cpath, path_prop))
elif not path_prop.startswith("PrimeControls/"):
fail(rv, "%s embeds non-PrimeControls view %r" % (cpath, path_prop))
elif not path_prop.startswith(ns + "/"):
fail(rv, "%s embeds view %r outside %s/" % (cpath, path_prop, ns))
elif not bound:
warn(rv, "%s embed with no static path and no binding" % cpath)
classes = ((node.get("props") or {}).get("style") or {}).get("classes")
@@ -241,7 +248,8 @@ def main():
if btype not in KNOWN_BINDING_TYPES:
fail(rv, "%s %s: unknown binding type %r" % (owner, key, btype))
if btype == "tag":
fail(rv, "%s %s: tag binding (prohibited in PrimeBAT — journal API only)" % (owner, key))
fail(rv, "%s %s: tag binding (prohibited in %s — journal API only)"
% (owner, key, args.project))
text_blobs = [json.dumps(binding.get("config") or {})]
for tr in binding.get("transforms") or []:
code = tr.get("code", "")
@@ -288,8 +296,8 @@ def main():
fail("ignition/%s" % entry, "unexpected project resource type for submission")
if os.path.isdir(sp_root):
for entry in sorted(os.listdir(sp_root)):
if entry != "PrimeControls":
fail("script-python/%s" % entry, "script package outside PrimeControls")
if entry != ns:
fail("script-python/%s" % entry, "script package outside %s" % ns)
for w in WARNS:
print(w)