← back to Novasuede Onboard
tweak_two.py
56 lines
#!/usr/bin/env python3
"""Micro-tweak two colorway names that the swatch verification refined:
Terracotta: Oatmeal -> Camel (swatch reads warmer than oatmeal)
Olive: Mocha -> Loden (dark drab green-brown; keep the olive cast)
Changes the `Color:` tag, the bare colorway tag, AND the body text together so
tag and prose never disagree (the 2026-06-24 QA lesson). Backs up to the same
rollback.ndjson FIRST. Dry-run unless --commit.
"""
import sys, json, re, time, urllib.request, pathlib
ROOT = pathlib.Path(__file__).resolve().parent; DATA = ROOT/"data"
env = pathlib.Path.home()/"Projects/secrets-manager/.env"
TOKEN = next(l.split("=",1)[1].strip().strip('"') for l in env.read_text().splitlines()
if l.startswith("SHOPIFY_ADMIN_TOKEN="))
API = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
COMMIT = "--commit" in sys.argv
TWEAKS = {7821431046195: ("Oatmeal","Camel"), # Terracotta
7692852887603: ("Mocha","Loden")} # Olive
def req(method, path, body=None):
data = json.dumps(body).encode() if body is not None else None
r = urllib.request.Request(API+path, data=data, method=method,
headers={"X-Shopify-Access-Token":TOKEN,"Content-Type":"application/json"})
for _ in range(6):
try:
with urllib.request.urlopen(r, timeout=30) as resp: return json.load(resp)
except urllib.error.HTTPError as e:
if e.code==429: time.sleep(2.5); continue
raise
raise RuntimeError("retries exhausted")
def retag(tags, old, new):
out=[]
for t in (x.strip() for x in tags.split(",")):
if t == old: out.append(new) # bare colorway tag
elif t == f"Color: {old}": out.append(f"Color: {new}") # primary color tag
else: out.append(t)
return ", ".join(out)
rb = (DATA/"rollback.ndjson").open("a") if COMMIT else None
for pid,(old,new) in TWEAKS.items():
cur = req("GET", f"/products/{pid}.json?fields=id,title,tags,body_html")["product"]
new_tags = retag(cur["tags"], old, new)
# whole-word, case-sensitive body swap (handles description + the "Color: X" trailer)
new_body = re.sub(rf"\b{re.escape(old)}\b", new, cur["body_html"])
print(f"\n# {cur['title']} ({old} -> {new})")
print(" tags Color: ->", [t for t in new_tags.split(", ") if t.startswith("Color:")])
print(" body[:140] ->", re.sub('<[^>]+>',' ',new_body).strip()[:140])
if COMMIT:
rb.write(json.dumps({"id":cur["id"],"tags":cur["tags"],"body_html":cur["body_html"]})+"\n"); rb.flush()
req("PUT", f"/products/{pid}.json",
{"product":{"id":pid,"tags":new_tags,"body_html":new_body}})
print(" ✓ written"); time.sleep(0.6)
if rb: rb.close()
print(f"\n{'COMMITTED' if COMMIT else 'DRY RUN — no writes'}")