← 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 ""))))