Files
cmautobuy/tools/test_export_thirdparty_catalog_xlsx.py
T

92 lines
4.3 KiB
Python
Raw Normal View History

import csv
import importlib.util
import sys
import tempfile
import unittest
from pathlib import Path
from xml.sax.saxutils import escape
from zipfile import ZIP_DEFLATED, ZipFile
MODULE_PATH = Path(__file__).with_name("export_thirdparty_catalog_xlsx.py")
SPEC = importlib.util.spec_from_file_location("thirdparty_export", MODULE_PATH)
assert SPEC and SPEC.loader
catalog = importlib.util.module_from_spec(SPEC)
sys.modules[SPEC.name] = catalog
SPEC.loader.exec_module(catalog)
HEADERS = [
"Parent SKU", "产品标题", "sku", "变种属性名称一", "变种属性名称二",
"变种属性值一", "变种属性值二", "主图(URL)地址", "来源URL", "店铺名",
"产品id", "更新时间",
]
def inline_cell(column, row, value):
return f'<c r="{column}{row}" t="inlineStr"><is><t>{escape(value)}</t></is></c>'
def make_xlsx(path, data_rows):
rows = []
for row_number, values in enumerate([HEADERS, *data_rows], start=1):
cells = "".join(inline_cell(chr(65 + index), row_number, value) for index, value in enumerate(values))
rows.append(f'<row r="{row_number}">{cells}</row>')
worksheet = (
'<?xml version="1.0" encoding="UTF-8"?>'
'<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'
'<dimension ref="A1"/><sheetData>' + "".join(rows) + '</sheetData></worksheet>'
)
with ZipFile(path, "w", ZIP_DEFLATED) as archive:
archive.writestr("xl/worksheets/sheet1.xml", worksheet)
class ThirdPartyCatalogExportTest(unittest.TestCase):
def make_source(self, rows):
temp = tempfile.TemporaryDirectory()
root = Path(temp.name) / "source"
source = root / "pinduoduo 域名" / "sample.xlsx"
source.parent.mkdir(parents=True)
make_xlsx(source, rows)
self.addCleanup(temp.cleanup)
return root, source, Path(temp.name) / "output"
def test_错误_dimension_仍导出完整数据和规范_pdd_url(self):
root, source, output = self.make_source([
["MAIN", "标题", "SKU-A", "颜色分类", "尺码", "黑色", "M", "https://img.example/a.jpg", "https://mobile.pinduoduo.com/goods.html?goods_id=123456789&track=1", "店铺 A", "24948397488", "2026-08-19"],
["MAIN", "标题", "SKU-B", "尺碼", "顏色", "L", "白色", "https://img.example/a.jpg", "https://mobile.yangkeduo.com/goods.html?goods_id=987654321", "店铺 A", "24948397488", "2026-08-19"],
])
result = catalog.export_file(source, root, output)
self.assertEqual((result.rows, result.valid_pdd_rows), (2, 2))
with result.output.open(encoding="utf-8-sig", newline="") as handle:
exported = list(csv.DictReader(handle))
self.assertEqual(len(exported), 2)
self.assertEqual(exported[0]["pdd_goods_url"], "https://mobile.yangkeduo.com/goods.html?goods_id=123456789")
self.assertEqual((exported[0]["color"], exported[0]["size"], exported[0]["parse_ok"]), ("黑色", "M", "true"))
self.assertEqual((exported[1]["color"], exported[1]["size"]), ("白色", "L"))
self.assertEqual(exported[0]["source_file"], "pinduoduo 域名/sample.xlsx")
def test_无效_pdd_url_保留蝦皮字段但不创建关联(self):
root, source, output = self.make_source([
["MAIN", "标题", "SKU-A", "款式", "套餐", "甲", "乙", "https://img.example/a.jpg", "https://example.com/item", "店铺 A", "24948397488", ""],
])
result = catalog.export_file(source, root, output)
self.assertEqual((result.rows, result.valid_pdd_rows), (1, 0))
with result.output.open(encoding="utf-8-sig", newline="") as handle:
exported = next(csv.DictReader(handle))
self.assertEqual(exported["shopee_goods_id"], "24948397488")
self.assertEqual(exported["spec_raw"], "甲,乙")
self.assertEqual(exported["parse_ok"], "false")
self.assertEqual(exported["association_pdd_goods_id"], "")
self.assertEqual(exported["validation_code"], "PDD_URL_HOST_INVALID")
def test_输出目录不能位于输入目录内(self):
root, _, _ = self.make_source([])
args = catalog.build_parser().parse_args([str(root), "--output-dir", str(root / "csv")])
with self.assertRaisesRegex(catalog.CatalogExportError, "输出目录"):
catalog.run(args)
if __name__ == "__main__":
unittest.main()