Skip to content

Commit 37c3d40

Browse files
committed
core: guard provider branding after stream presentation
1 parent 955614d commit 37c3d40

1 file changed

Lines changed: 115 additions & 0 deletions

File tree

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env python3
2+
"""Keep provider branding as the final Core stream presentation layer.
3+
4+
Branding must run after stream fact extraction/presentation: many upstream providers
5+
encode quality/language/codec facts in their original stream name. Running the
6+
branding wrapper earlier would erase those facts before the shared presentation
7+
layer can normalize them. This normalizer materializes and then guards that ordering
8+
inside apply_provider_overrides.py for every provider.
9+
"""
10+
from __future__ import annotations
11+
12+
import argparse
13+
from pathlib import Path
14+
15+
ROOT = Path(__file__).resolve().parents[1]
16+
TARGET = ROOT / "scripts/apply_provider_overrides.py"
17+
CONST = 'GLOBAL_PROVIDER_BRANDING = "scripts/provider_patches/global_provider_branding_v1.py"'
18+
PRESENTATION_CONST = 'GLOBAL_STREAM_PRESENTATION = "scripts/provider_patches/global_stream_presentation_v1.py"'
19+
BRANDING_MARKER = ' "NUVIO_GLOBAL_PROVIDER_BRANDING_V1",\n'
20+
PRESENTATION_MARKER = ' "NUVIO_GLOBAL_STREAM_PRESENTATION_V1",\n'
21+
ANCHOR = ''' if text != before:
22+
applied.append({
23+
"type": "patch_script",
24+
"path": GLOBAL_STREAM_PRESENTATION,
25+
"phase": phase,
26+
"scope": "global_stream_presentation",
27+
})
28+
29+
if text == original_text:
30+
'''
31+
REPLACEMENT = ''' if text != before:
32+
applied.append({
33+
"type": "patch_script",
34+
"path": GLOBAL_STREAM_PRESENTATION,
35+
"phase": phase,
36+
"scope": "global_stream_presentation",
37+
})
38+
39+
# Provider branding is deliberately the final Core stream layer. Upstream
40+
# stream names can contain quality/language/codec facts; presentation must
41+
# read those originals before the committed emoji/name replaces the local
42+
# row label and title prefix.
43+
before = text
44+
text = _apply_patch_script(text, provider_id, GLOBAL_PROVIDER_BRANDING, {}, None)
45+
if text != before:
46+
applied.append({
47+
"type": "patch_script",
48+
"path": GLOBAL_PROVIDER_BRANDING,
49+
"phase": phase,
50+
"scope": "global_provider_branding",
51+
})
52+
53+
if text == original_text:
54+
'''
55+
56+
57+
def normalize(text: str) -> tuple[str, list[str]]:
58+
changed: list[str] = []
59+
if CONST not in text:
60+
if PRESENTATION_CONST not in text:
61+
raise ValueError("GLOBAL_STREAM_PRESENTATION constant anchor missing")
62+
text = text.replace(PRESENTATION_CONST, PRESENTATION_CONST + "\n" + CONST, 1)
63+
changed.append("branding_constant")
64+
65+
if BRANDING_MARKER not in text:
66+
if PRESENTATION_MARKER not in text:
67+
raise ValueError("generated Core tail presentation marker anchor missing")
68+
text = text.replace(PRESENTATION_MARKER, PRESENTATION_MARKER + BRANDING_MARKER, 1)
69+
changed.append("branding_tail_marker")
70+
71+
if '"scope": "global_provider_branding"' not in text:
72+
if ANCHOR not in text:
73+
raise ValueError("global presentation application anchor missing")
74+
text = text.replace(ANCHOR, REPLACEMENT, 1)
75+
changed.append("post_presentation_branding")
76+
return text, changed
77+
78+
79+
def assert_contract(text: str) -> None:
80+
if text.count(CONST) != 1:
81+
raise ValueError("GLOBAL_PROVIDER_BRANDING constant must exist exactly once")
82+
if text.count('"scope": "global_provider_branding"') != 1:
83+
raise ValueError("global provider branding application must exist exactly once")
84+
presentation = text.find('"scope": "global_stream_presentation"')
85+
branding = text.find('"scope": "global_provider_branding"')
86+
final_return = text.find(" if text == original_text:", branding)
87+
if presentation < 0 or branding < 0 or final_return < 0 or not (presentation < branding < final_return):
88+
raise ValueError("Core order must be stream presentation -> provider branding -> return")
89+
if text.count(BRANDING_MARKER) != 1:
90+
raise ValueError("provider branding generated-tail marker must exist exactly once")
91+
92+
93+
def main() -> int:
94+
parser = argparse.ArgumentParser()
95+
parser.add_argument("--apply", action="store_true")
96+
parser.add_argument("--check", action="store_true")
97+
args = parser.parse_args()
98+
if args.apply == args.check:
99+
raise SystemExit("choose exactly one of --apply or --check")
100+
current = TARGET.read_text(encoding="utf-8")
101+
normalized, changed = normalize(current)
102+
assert_contract(normalized)
103+
if args.check and changed:
104+
raise SystemExit("provider branding pipeline normalization required: " + ", ".join(changed))
105+
if args.apply and normalized != current:
106+
TARGET.write_text(normalized, encoding="utf-8")
107+
print(
108+
"FIELD_PROVIDER_BRANDING_PIPELINE "
109+
f"changed={len(changed)} order=presentation_then_branding facts_preserved=true"
110+
)
111+
return 0
112+
113+
114+
if __name__ == "__main__":
115+
raise SystemExit(main())

0 commit comments

Comments
 (0)