import csv
import os
import stat
import subprocess
import textwrap
import unittest
from pathlib import Path
from tempfile import TemporaryDirectory
ROOT = Path(__file__).resolve().parents[1]
IMPORTINFO_HTML = textwrap.dedent(
"""
Search Results
| Run Date | Master BOL | House BOL | Voyage # |
Bill Type | Carrier Code | IMO # | Vessel Name |
Arrival Date | US Port | Foreign Port | Quantity |
Weight | Type of Service | Shipper | Consignee |
Notify Party | Commodity |
| 2026-05-01 | EGLV142653125618 | SNHBSHALAX264014 | 084E |
House Bill | SNHB | 9604081 | EVER LOGIC |
2026-05-01 | LOS ANGELES, CALIFORNIA | SHANGHAI CHINA (MAINLAND) |
42 PKG | 12,578 K | House to House |
TECH-FRONT (CHONGQING) COMPUTER CO | CEVA C/O VALVE CORPORATION |
CEVA C/O VALVE CORPORATION | GAME CONSOLE |
| 2026-04-28 | CMDUCHN3170474 | EXDO621128151 | 0XRAJ |
House Bill | EXDO | 9436379 | CMA CGM SAMSON |
2026-04-28 | SAVANNAH, GEORGIA | SHANGHAI CHINA (MAINLAND) |
15 PKG | 4,143 KG | Pier to Pier |
TECH-FRONT (CHONGQING) COMPUTER CO | PROMETHEAN INC. |
| CHROMEBOX HTS: |
"""
)
IMPORTGENIUS_HTML = textwrap.dedent(
"""
Ingram Micro C/o Valve Corporation
Updated: 2026-05-18
Importer Shipments
# Bill of Lading Product Importer Supplier Arrival Date Country of Origin Gross Weight KGS Quantity
1 SNHBSHACHI265020 GAME CONSOLE INGRAM MICRO C/O VALVE CORPORATION TECH-FRONT (CHONGQING) COMPUTER CO 2026-05-18 China 14353 Kgs 42 PKG
2 SNHBSHACHI264140 GAME CONSOLE INGRAM MICRO C/O VALVE CORPORATION TECH-FRONT (CHONGQING) COMPUTER CO 2026-05-18 China 14533 Kgs 42 PKG
3 SNHBSHACHI264031 GAME CONSOLE INGRAM MICRO C/O VALVE CORPORATION TECH-FRONT (CHONGQING) COMPUTER CO 2026-05-08 China 12615 Kgs 42 PKG
"""
)
IMPORTGENIUS_CEVA_VR_HTML = textwrap.dedent(
"""
CEVA C/o Valve Corporation
Updated: 2026-06-10
Importer Shipments
# Bill of Lading Product Importer Supplier Arrival Date Country of Origin Gross Weight KGS Quantity
1 SNHBSHACHI265173 VIRTUAL REALITY DEVICES CEVA C/O VALVE CORPORATION TECH-FRONT (CHONGQING) COMPUTER CO 2026-06-10 China 6374 Kgs 42 PKG
2 SNHBSHACHI265174 VIRTUAL REALITY DEVICES CEVA C/O VALVE CORPORATION TECH-FRONT (CHONGQING) COMPUTER CO 2026-06-10 China 6372 Kgs 42 PKG
"""
)
IMPORTGENIUS_VERTICAL_CEVA_VR_HTML = textwrap.dedent(
"""
CEVA C/o Valve Corporation
Importer Shipments
#
Bill of Lading
Product
Importer
Supplier
Arrival Date
Country of Origin
Gross Weight KGS
Quantity
1
SNHBSHACHI265173
VIRTUAL REALITY DEVICES
CEVA C/O VALVE CORPORATION
TECH-FRONT (CHONGQING) COMPUTER CO
2026-06-10
China
6374 Kgs
42 PKG
"""
)
IMPORTGENIUS_CEVA_NL_VR_HTML = textwrap.dedent(
"""
CEVA NL C/o Valve Corporation
Updated: 2026-06-10
Importer Shipments
# Bill of Lading Product Importer Supplier Arrival Date Country of Origin Gross Weight KGS Quantity
1 SNHBSHALAX265177 VIRTUAL REALITY DEVICES CEVA NL C/O VALVE CORPORATION TECH-FRONT (CHONGQING) COMPUTER CO 2026-06-10 China 6400 Kgs 42 PKG
"""
)
IMPORTGENIUS_VALVE_CONTROLLER_HTML = textwrap.dedent(
"""
Valve Corporation
Updated: 2026-06-10
Importer Shipments
# Bill of Lading Product Importer Supplier Arrival Date Country of Origin Gross Weight KGS Quantity
1 SNHBHKGLBG266011 WIRELESS PC CONTROLLER VALVE CORPORATION CHENG UEI PRECISION IND. CO LTD 2026-06-10 Hong Kong 9727 Kgs 30 PKG
4 DSVFMIL0341656 PNEUMATIC ACTUATOR VALVE 48 LLC L.P.S. SRL PER CONTO BIFFI ITALIA S 2026-05-16 Italy 1830 Kgs 1 CAS
5 SNHBHKGLBG265013 WIRELESS PC CONTROLLER VALVE CORPORATION CHENG UEI PRECISION IND. CO LTD 2026-05-12 Hong Kong 12970 Kgs 40 PKG
"""
)
def run_parser(args, reports):
return subprocess.run(
[
"python3",
str(ROOT / "scripts" / "parse_importinfo_shipments.py"),
*args,
"--report-dir",
str(reports),
],
cwd=ROOT,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
def read_rows(reports):
return list(
csv.DictReader(
(reports / "customs-shipments.tsv").read_text(encoding="utf-8").splitlines(),
delimiter="\t",
)
)
def write_executable(path, content):
path.write_text(textwrap.dedent(content).lstrip(), encoding="utf-8")
path.chmod(path.stat().st_mode | stat.S_IXUSR)
class CustomsShipmentParserTests(unittest.TestCase):
def test_extracts_relevant_importinfo_rows(self):
with TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
html = tmp_path / "ceva-valve.html"
html.write_text(IMPORTINFO_HTML, encoding="utf-8")
reports = tmp_path / "reports"
result = run_parser(["--input", f"ceva-valve={html}"], reports)
self.assertEqual("", result.stderr)
self.assertEqual(0, result.returncode)
rows = read_rows(reports)
self.assertEqual(1, len(rows))
self.assertEqual("SNHBSHALAX264014", rows[0]["house_bol"])
self.assertEqual("GAME CONSOLE", rows[0]["commodity"])
self.assertEqual("CEVA C/O VALVE CORPORATION", rows[0]["consignee"])
key_lines = (reports / "customs-shipments-key-lines.txt").read_text(
encoding="utf-8"
)
self.assertIn("2026-05-01", key_lines)
self.assertIn("SNHBSHALAX264014", key_lines)
self.assertIn("GAME CONSOLE", key_lines)
report = (reports / "customs-shipments.md").read_text(encoding="utf-8")
self.assertIn("## Newest Relevant Shipments", report)
self.assertIn("CEVA C/O VALVE CORPORATION", report)
self.assertIn("TECH-FRONT (CHONGQING) COMPUTER CO", report)
def test_preserves_distinct_same_day_bols(self):
with TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
html = tmp_path / "same-day.html"
html.write_text(
IMPORTINFO_HTML.replace(
"",
textwrap.dedent(
"""
| 2026-05-01 | EGLV142653125669 | SNHBSHALAX264015 | 084E |
House Bill | SNHB | 9604081 | EVER LOGIC |
2026-05-01 | LOS ANGELES, CALIFORNIA | SHANGHAI CHINA (MAINLAND) |
42 PKG | 12,596 K | House to House |
TECH-FRONT (CHONGQING) COMPUTER CO | CEVA C/O VALVE CORPORATION |
CEVA C/O VALVE CORPORATION | GAME CONSOLE |
"""
),
),
encoding="utf-8",
)
reports = tmp_path / "reports"
result = run_parser(["--input", f"ceva-valve={html}"], reports)
self.assertEqual(0, result.returncode)
rows = read_rows(reports)
self.assertEqual(
["SNHBSHALAX264014", "SNHBSHALAX264015"],
[row["house_bol"] for row in rows],
)
def test_ignores_later_unrelated_table_headers(self):
with TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
html = tmp_path / "extra-table.html"
html.write_text(
IMPORTINFO_HTML.replace(
"