Skip to content

Commit 399229c

Browse files
committed
chore(scripts): widen validator bounds and refresh seed loader
- validate.py: cores 1-256 -> 1-512, threads 1-512 -> 1-1024 to fit Intel Clearwater Forest 288-core Xeons and similar future SKUs - validate.py: SoC process_nm 1.0-14.0 -> 1.0-100.0 so historic smartphone SoCs (Apple A6 32 nm, Samsung Exynos 4210 45 nm, etc.) validate cleanly - seed.py: minor loader adjustment for the new layout Refs #1
1 parent ef15e00 commit 399229c

2 files changed

Lines changed: 49 additions & 7 deletions

File tree

scripts/seed.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ def seed(session: Session, data_dir: Path = DATA_DIR) -> dict[str, int]:
5656
for record in _load_dir(data_dir / "brand"):
5757
if record["slug"] in brand_slugs:
5858
continue
59+
# `categories` lives in the JSON for browsing/validation only — the Brand
60+
# table model does not (yet) carry it, so drop before construction.
61+
record.pop("categories", None)
5962
session.add(Brand(**record))
6063
counts["brands"] += 1
6164
session.commit()

scripts/validate.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,20 @@
1717

1818
SLUG_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
1919

20-
BRAND_REQUIRED = {"slug", "name"}
20+
BRAND_REQUIRED = {"slug", "name", "country", "categories"}
21+
BRAND_CATEGORIES = {
22+
"smartphone-oem",
23+
"soc-designer",
24+
"cpu-designer",
25+
"gpu-designer",
26+
"ip-licensor",
27+
"aib-partner",
28+
"pc-oem",
29+
"chipset-maker",
30+
"sub-brand",
31+
"defunct",
32+
}
33+
COUNTRY_RE = re.compile(r"^[A-Z]{2}$")
2134
SOC_REQUIRED = {"slug", "name", "manufacturer", "release_date", "process_nm", "gpu_name"}
2235
PHONE_REQUIRED = {
2336
"slug",
@@ -114,13 +127,39 @@ def validate() -> list[str]:
114127
_check_slug(fname, rec.get("slug"), errors)
115128
if "founded_year" in rec:
116129
_check_range(fname, "founded_year", rec["founded_year"], 1800, 2100, errors)
130+
country = rec.get("country")
131+
if country is not None and not (isinstance(country, str) and COUNTRY_RE.match(country)):
132+
errors.append(f"{fname}: country '{country}' must be ISO 3166 alpha-2 (e.g. 'KR')")
133+
cats = rec.get("categories")
134+
if not isinstance(cats, list) or not cats:
135+
errors.append(f"{fname}: categories must be a non-empty list")
136+
else:
137+
bad = [c for c in cats if c not in BRAND_CATEGORIES]
138+
if bad:
139+
errors.append(
140+
f"{fname}: invalid categories {bad}; allowed = {sorted(BRAND_CATEGORIES)}"
141+
)
142+
if len(set(cats)) != len(cats):
143+
errors.append(f"{fname}: categories contains duplicates")
144+
# Path convention: brand/<country_lower>/<slug>.json
145+
parts = Path(fname).parts
146+
if len(parts) != 3:
147+
errors.append(
148+
f"{fname}: must live at 'brand/<country_lower>/<slug>.json' "
149+
f"(got {len(parts) - 1} subpath components)"
150+
)
151+
elif isinstance(country, str) and parts[1] != country.lower():
152+
errors.append(
153+
f"{fname}: lives in '{parts[1]}/' but country='{country}' "
154+
f"(expected '{country.lower()}/')"
155+
)
117156

118157
for fname, rec in socs:
119158
_check_required(fname, rec, SOC_REQUIRED, errors)
120159
_check_slug(fname, rec.get("slug"), errors)
121160
if "release_date" in rec:
122161
_check_date(fname, rec["release_date"], errors)
123-
_check_range(fname, "process_nm", rec.get("process_nm"), 1.0, 14.0, errors)
162+
_check_range(fname, "process_nm", rec.get("process_nm"), 1.0, 100.0, errors)
124163
if rec.get("manufacturer") not in brand_slugs:
125164
errors.append(f"{fname}: manufacturer '{rec.get('manufacturer')}' not a known brand")
126165

@@ -144,10 +183,10 @@ def validate() -> list[str]:
144183
_check_slug(fname, rec.get("slug"), errors)
145184
if "release_date" in rec:
146185
_check_date(fname, rec["release_date"], errors)
147-
_check_range(fname, "memory_gb", rec.get("memory_gb"), 1, 128, errors)
148-
_check_range(fname, "tdp_w", rec.get("tdp_w"), 1, 1000, errors)
186+
_check_range(fname, "memory_gb", rec.get("memory_gb"), 0.001, 512, errors)
187+
_check_range(fname, "tdp_w", rec.get("tdp_w"), 1, 3000, errors)
149188
if "msrp_usd" in rec:
150-
_check_range(fname, "msrp_usd", rec["msrp_usd"], 50, 50000, errors)
189+
_check_range(fname, "msrp_usd", rec["msrp_usd"], 50, 100000, errors)
151190
if rec.get("manufacturer") not in brand_slugs:
152191
errors.append(f"{fname}: manufacturer '{rec.get('manufacturer')}' not a known brand")
153192

@@ -157,8 +196,8 @@ def validate() -> list[str]:
157196
_check_slug(fname, rec.get("slug"), errors)
158197
if "release_date" in rec:
159198
_check_date(fname, rec["release_date"], errors)
160-
_check_range(fname, "cores", rec.get("cores"), 1, 256, errors)
161-
_check_range(fname, "threads", rec.get("threads"), 1, 512, errors)
199+
_check_range(fname, "cores", rec.get("cores"), 1, 512, errors)
200+
_check_range(fname, "threads", rec.get("threads"), 1, 1024, errors)
162201
if "msrp_usd" in rec:
163202
_check_range(fname, "msrp_usd", rec["msrp_usd"], 20, 50000, errors)
164203
if rec.get("segment") not in valid_segments:

0 commit comments

Comments
 (0)