← back to Maya Width Fix
widthlib.py
69 lines
#!/usr/bin/env python3
"""
widthlib — pure, deterministic helpers for classifying/parsing Maya Romanoff
width strings scraped from mayaromanoff.com collection spec tables.
TK-11029. No I/O, no network, no DB — safe to unit-test in isolation.
Vocabulary of decisions a raw width string maps to:
META_POLLUTION the scraped meta-tag leak ('=device-width, initial-scale=1">')
-> unrecoverable from the string; needs re-scrape or rep.
SINGLE exactly one roll width -> width_inches is derivable.
MULTI_WIDTH the vendor genuinely offers ONE pattern in >1 roll width and
no per-SKU width exists -> keep the full string, width_inches=NULL
(ambiguous BY DESIGN, never guessed).
UNPARSEABLE a non-empty, non-pollution string we cannot classify.
EMPTY NULL / blank.
"""
import re
META_POLLUTION_MARKER = "device-width"
# One roll-width measurement, e.g. "36 in untrimmed", '27" untrimmed', '54” trimmed'.
# Accepts straight/curly/prime inch marks and the word 'in'. Trailing (un)trimmed anchors it.
_MEASURE_RX = re.compile(r'(\d+(?:\.\d+)?)\s*(?:in|["”″])\s*(?:un)?trimmed', re.I)
def is_meta_pollution(width: str) -> bool:
"""True iff the width holds the scraped meta-tag garbage."""
return bool(width) and META_POLLUTION_MARKER in width
def width_measurements(width: str):
"""Return the ordered list of inch measurements found in the string."""
if not width:
return []
return [m.group(1) for m in _MEASURE_RX.finditer(width)]
def classify_width(width):
"""
Classify a raw width string.
Returns (decision, width_inches) where width_inches is a str|None.
- SINGLE -> the single inch value as a normalized numeric string
- MULTI_WIDTH -> None (ambiguous by design)
- META_POLLUTION / EMPTY / UNPARSEABLE -> None
"""
if width is None or str(width).strip() == "":
return ("EMPTY", None)
width = str(width)
if is_meta_pollution(width):
return ("META_POLLUTION", None)
meas = width_measurements(width)
if len(meas) == 1:
return ("SINGLE", _norm_num(meas[0]))
if len(meas) > 1:
return ("MULTI_WIDTH", None)
return ("UNPARSEABLE", None)
def _norm_num(s: str) -> str:
"""'36.0' -> '36', '28.50' -> '28.5', '28.5' -> '28.5'."""
f = float(s)
return str(int(f)) if f == int(f) else str(f).rstrip("0").rstrip(".")
if __name__ == "__main__":
import sys, json
print(json.dumps(list(classify_width(sys.argv[1] if len(sys.argv) > 1 else ""))))