feat(products): serialize multi-variant + interleaved images (§6.5.1 row grammar)

This commit is contained in:
2026-06-11 21:58:22 -07:00
parent 627e257d4c
commit 7652e92cbe
2 changed files with 73 additions and 5 deletions
+22 -5
View File
@@ -71,7 +71,9 @@ def _drain(buf: io.StringIO) -> str:
def _product_rows(product: CatalogProduct) -> list[dict[str, str]]:
"""The product's CSV rows (§6.5.1 grammar). Task 1: first variant only."""
"""The product's CSV rows (§6.5.1 grammar): product fields + option names on
the first row; one variant per row; images interleaved; image-only rows when
a product has more images than variants."""
base = {"Handle": product.handle, "Title": product.title}
for field, col in _PRODUCT_FIELD_TO_COL.items():
if field in product.fields:
@@ -79,10 +81,25 @@ def _product_rows(product: CatalogProduct) -> list[dict[str, str]]:
for slot, name in enumerate(product.option_names, start=1):
if name:
base[f"Option{slot} Name"] = name
variant = product.variants[0]
row = dict(base)
_write_variant(row, product, variant)
return [row]
count = max(len(product.variants), len(product.images))
rows: list[dict[str, str]] = []
for i in range(count):
# Row 0 carries the product-level fields; later rows carry only Handle.
row = dict(base) if i == 0 else {"Handle": product.handle}
if i < len(product.variants):
_write_variant(row, product, product.variants[i])
if i < len(product.images):
_write_image(row, product.images[i])
rows.append(row)
return rows
def _write_image(row: dict[str, str], image) -> None:
row["Image Src"] = image.source_url
row["Image Position"] = str(image.position)
if image.alt_text is not None:
row["Image Alt Text"] = image.alt_text
def _write_variant(row: dict[str, str], product: CatalogProduct, variant) -> None: