PROP OUT looks in this weekend's Location Assets folder, read on NA Ingest
- prop_bundle_folder takes {date} (the plan's weekend, as the tracks folders): any bundle there counts
- readiness scripts for this Mac run here (NA ProP's Google Drive showed 261025 empty)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -935,8 +935,8 @@
|
||||
"pco_module": "pco-plan",
|
||||
"pco_service_type": "275974",
|
||||
"projects": "~/Library/CloudStorage/GoogleDrive-media@waterschurch.org/Shared drives/Waters Creative/Ableton/Projects",
|
||||
"prop_bundle_folder": "~/Library/CloudStorage/GoogleDrive-media@waterschurch.org/Shared drives/Location Assets/ProPresenter",
|
||||
"prop_bundle_host": "prop",
|
||||
"prop_bundle_folder": "~/Library/CloudStorage/GoogleDrive-media@waterschurch.org/Shared drives/Location Assets/{date}",
|
||||
"prop_bundle_host": "ingest",
|
||||
"prop_bundle_pattern": "*.probundle",
|
||||
"prop_host": "prop",
|
||||
"prop_lists": [
|
||||
|
||||
+23
-7
@@ -137,9 +137,11 @@ def ssh_argv(cfg, host):
|
||||
|
||||
|
||||
def run_remote(cfg, host, script, timeout=60):
|
||||
"""Run a Python script on another Mac (on stdin, at low priority); its last line is JSON."""
|
||||
r = subprocess.run(ssh_argv(cfg, host) + ["nice -n 19 /usr/bin/python3 -"], input=script,
|
||||
capture_output=True, text=True, timeout=timeout)
|
||||
"""Run a Python script on another Mac (on stdin, at low priority), or here when `host` is this Mac
|
||||
(NA Ingest's Google Drive is current; NA ProP's lagged a day behind, 2026-10-21); its last line is JSON."""
|
||||
here = ((cfg.get("hosts") or {}).get(host) or {}).get("self")
|
||||
argv = ["/usr/bin/nice", "-n", "19", "/usr/bin/python3", "-"] if here else ssh_argv(cfg, host) + ["nice -n 19 /usr/bin/python3 -"]
|
||||
r = subprocess.run(argv, input=script, capture_output=True, text=True, timeout=timeout)
|
||||
if r.returncode == 255:
|
||||
raise ReadyError("%s UNREACHABLE" % host.upper())
|
||||
lines = [ln for ln in r.stdout.strip().splitlines() if ln.strip()]
|
||||
@@ -971,8 +973,21 @@ print(json.dumps(sorted([[os.path.basename(f), os.path.getmtime(f)] for f in fil
|
||||
'''
|
||||
|
||||
|
||||
def eval_prop_bundle(rc, files, since):
|
||||
def prop_bundle_folder(rc, plan):
|
||||
"""Where this weekend's bundle goes: "{date}" is the weekend's folder (Location Assets/261025, the
|
||||
user 2026-10-21: "it should be looking at the latest weekends folder in location assets")."""
|
||||
return str(rc.get("prop_bundle_folder", "")).replace("{date}", datetime.fromtimestamp(plan["time"]).strftime("%y%m%d"))
|
||||
|
||||
|
||||
def eval_prop_bundle(rc, files, since, folder=None):
|
||||
line = Line()
|
||||
if "{date}" in str(rc.get("prop_bundle_folder", "")):
|
||||
# This weekend's own folder: any bundle in it is this weekend's.
|
||||
if not files:
|
||||
line.fault(ERR, "NOT IN " + os.path.basename(str(folder or "").rstrip("/")), "no %s in %s" % (rc.get("prop_bundle_pattern"), folder))
|
||||
else:
|
||||
line.info = "SENT " + datetime.fromtimestamp(files[0][1]).strftime("%a %H:%M").upper()
|
||||
return line
|
||||
fresh = [f for f in files if f[1] >= since]
|
||||
if not fresh:
|
||||
last = datetime.fromtimestamp(files[0][1]).strftime("%-m/%-d") if files else "NEVER"
|
||||
@@ -1021,8 +1036,8 @@ def look(cfg, now=None, data_dir=None, sources=None):
|
||||
resolume=lambda: http_json(rc.get("resolume_url", "").rstrip("/") + "/api/v1/composition", timeout=6),
|
||||
macros=lambda paths: run_remote(cfg, rc["prop_host"], MACRO_SCRIPT % json.dumps({"paths": paths}), timeout=60),
|
||||
companion=lambda n: companion_page(cfg, n),
|
||||
prop_bundle=lambda: run_remote(cfg, rc["prop_bundle_host"], BUNDLE_SCRIPT % json.dumps(
|
||||
{"folder": rc.get("prop_bundle_folder", ""), "pattern": rc.get("prop_bundle_pattern", "*.probundle")}), timeout=30))
|
||||
prop_bundle=lambda plan: run_remote(cfg, rc["prop_bundle_host"], BUNDLE_SCRIPT % json.dumps(
|
||||
{"folder": prop_bundle_folder(rc, plan), "pattern": rc.get("prop_bundle_pattern", "*.probundle")}), timeout=30))
|
||||
src.update(sources or {})
|
||||
lines = {}
|
||||
|
||||
@@ -1103,7 +1118,8 @@ def look(cfg, now=None, data_dir=None, sources=None):
|
||||
lines["mics"] = mics
|
||||
if rc.get("prop_bundle_host"):
|
||||
try:
|
||||
lines["prop_bundle"] = eval_prop_bundle(rc, src["prop_bundle"](), week_start(now, rc.get("reset_day", "mon")))
|
||||
lines["prop_bundle"] = eval_prop_bundle(rc, src["prop_bundle"](plan), week_start(now, rc.get("reset_day", "mon")),
|
||||
prop_bundle_folder(rc, plan))
|
||||
except Exception as e: # noqa: BLE001
|
||||
failed(["prop_bundle"], e)
|
||||
out = {"time": now, "items": {k: v.as_dict() for k, v in lines.items()}}
|
||||
|
||||
@@ -399,7 +399,8 @@ field("ready.resolume_deck", "str", "", "The deck Resolume must be on.", "Ready"
|
||||
field("ready.prop_host", "str", None, "The ProPresenter computer: its macros and presentation files are read to find "
|
||||
"the Resolume columns Sunday's slides call up.", "Ready")
|
||||
field("ready.prop_bundle_host", "str", None, "The computer that saves the ProPresenter bundle.", "Ready")
|
||||
field("ready.prop_bundle_folder", "path", "", "Where the bundle for the locations goes.", "Ready")
|
||||
field("ready.prop_bundle_folder", "path", "", "Where the bundle for the locations goes. {date} is this weekend's folder "
|
||||
"(Location Assets/{date} -> Location Assets/261025): any bundle in it counts as sent.", "Ready")
|
||||
field("ready.prop_bundle_pattern", "str", "*.probundle", "The bundle's file name pattern.", "Ready", advanced=True)
|
||||
field("ready.vocal_positions", "list", ["Vocalist", "[Leader]"], "PCO positions that need a vocal mic.", "Ready")
|
||||
field("ready.mic_positions", "dict", {}, "Other PCO positions and the mic they need (MC -> MC).", "Ready")
|
||||
|
||||
+18
-3
@@ -338,10 +338,19 @@ class TestLineupCrossBundle(unittest.TestCase):
|
||||
def test_the_macro_reader_runs(self):
|
||||
compile(rd.MACRO_SCRIPT % json.dumps({"paths": ["/x.pro"]}), "remote", "exec")
|
||||
|
||||
def test_prop_bundle_in_this_weekends_folder(self):
|
||||
rc = dict(RC, prop_bundle_folder="~/Shared drives/Location Assets/{date}")
|
||||
plan = {"time": datetime(2026, 10, 25, 9, 0).timestamp()}
|
||||
folder = rd.prop_bundle_folder(rc, plan)
|
||||
self.assertEqual(folder, "~/Shared drives/Location Assets/261025")
|
||||
self.assertEqual(msgs(rd.eval_prop_bundle(rc, [["WORSHIP BUNDLE.probundle", WEDNESDAY - 86400 * 10]], WEDNESDAY, folder)), [])
|
||||
self.assertEqual(msgs(rd.eval_prop_bundle(rc, [], WEDNESDAY, folder)), ["NOT IN 261025"])
|
||||
|
||||
def test_prop_bundle_this_week(self):
|
||||
since = rd.week_start(WEDNESDAY)
|
||||
self.assertEqual(msgs(rd.eval_prop_bundle(RC, [["Message Templates.probundle", WEDNESDAY - 3600]], since)), [])
|
||||
self.assertEqual(msgs(rd.eval_prop_bundle(RC, [["Old.probundle", since - 86400]], since)), ["NOT SENT (LAST 10/11)"])
|
||||
rc = dict(RC, prop_bundle_folder="~/Shared drives/Location Assets/ProPresenter") # one folder for every week
|
||||
self.assertEqual(msgs(rd.eval_prop_bundle(rc, [["Message Templates.probundle", WEDNESDAY - 3600]], since)), [])
|
||||
self.assertEqual(msgs(rd.eval_prop_bundle(rc, [["Old.probundle", since - 86400]], since)), ["NOT SENT (LAST 10/11)"])
|
||||
|
||||
def test_mics_from_pco(self):
|
||||
self.assertEqual(rd.mics_needed(RC, plan()), "2 VOX MC TIM")
|
||||
@@ -351,7 +360,7 @@ class TestLook(unittest.TestCase):
|
||||
def sources(self, **over):
|
||||
src = dict(pco=plan, prop=lambda p: prop(), ableton=lambda p: ableton(),
|
||||
lineup=lambda: lineup(["Jonah Perdue", "Krista Perdue", "Kevin Michel", "Anthony Hoyt", "Tim Hatch"]),
|
||||
resolume=composition, prop_bundle=lambda: [["Message Templates.probundle", WEDNESDAY]],
|
||||
resolume=composition, prop_bundle=lambda plan: [["Message Templates.probundle", WEDNESDAY]],
|
||||
macros=macros_found, companion=lambda n: COMPANION.get(n, {}))
|
||||
src.update(over)
|
||||
return src
|
||||
@@ -609,3 +618,9 @@ class TestOtherCampuses(unittest.TestCase):
|
||||
finally:
|
||||
rd.http_json, rd.pco_get, rd.pco_login = real_http, real_get, real_login
|
||||
self.assertEqual(len([c for c in calls if "/1113969/" in c[1] and c[0] == "POST"]), len(res["songs"])) # one note per location song
|
||||
|
||||
|
||||
class TestRunHere(unittest.TestCase):
|
||||
def test_a_script_for_this_mac_runs_here_without_ssh(self):
|
||||
cfg = {"hosts": {"ingest": {"self": True}}}
|
||||
self.assertEqual(rd.run_remote(cfg, "ingest", "import json; print(json.dumps({'ok': 1}))"), {"ok": 1})
|
||||
|
||||
Reference in New Issue
Block a user