from __future__ import annotations import json import urllib.error import urllib.request from pathlib import Path ROOT = Path(__file__).resolve().parent.parent PROFILE = json.loads((ROOT / "profiles" / "mobile-development-notebook.json").read_text(encoding="utf-8")) FIXTURE = json.loads((ROOT / "fixtures" / "manual-demo.json").read_text(encoding="utf-8")) BASE = "http://127.0.0.1:8000" AS_OF = "2026-10-03T12:00:00Z" DEFINITIONS = [ {"key": "ram_gb", "value_type": "number", "canonical_unit": "GB", "minimum": 0, "description": "RAM in GB"}, {"key": "storage_gb", "value_type": "number", "canonical_unit": "GB", "minimum": 0, "description": "Storage in GB"}, {"key": "weight_kg", "value_type": "number", "canonical_unit": "kg", "minimum": 0, "description": "Weight in kg"}, {"key": "battery_score", "value_type": "number", "minimum": 0, "maximum": 100, "description": "Manual battery score"}, {"key": "display_score", "value_type": "number", "minimum": 0, "maximum": 100, "description": "Manual display score"}, {"key": "cpu_score", "value_type": "number", "minimum": 0, "maximum": 100, "description": "Manual CPU score"}, {"key": "ports", "value_type": "string_list", "description": "Ports"}, ] def request(method: str, path: str, body=None, expected=(200, 201, 409)): data = None if body is None else json.dumps(body, default=str).encode() req = urllib.request.Request( f"{BASE}{path}", data=data, method=method, headers={"Content-Type": "application/json"} if body is not None else {}, ) try: with urllib.request.urlopen(req) as response: payload = json.loads(response.read().decode()) if response.status not in expected: raise SystemExit(f"{method} {path} -> {response.status}: {payload}") return response.status, payload except urllib.error.HTTPError as exc: payload = json.loads(exc.read().decode()) if exc.code not in expected: raise SystemExit(f"{method} {path} -> {exc.code}: {payload}") from exc return exc.code, payload def main() -> None: for definition in DEFINITIONS: request("POST", "/api/v1/attribute-definitions", definition) request("POST", "/api/v1/profiles", PROFILE) product = FIXTURE["products"][0] request( "POST", "/api/v1/products", { "id": product["id"], "category": product["category"], "brand": product["brand"], "name": product["name"], "model": product.get("model"), }, ) for variant in product["variants"]: request( "POST", f"/api/v1/products/{product['id']}/variants", { "id": variant["id"], "name": variant["name"], "manufacturer_sku": variant.get("manufacturer_sku"), "identifiers": variant.get("identifiers") or {}, }, ) for attribute in variant["attributes"]: request("POST", f"/api/v1/variants/{variant['id']}/attributes", {**attribute, "source_id": "manual"}) for offer in FIXTURE["offers"]: request( "POST", f"/api/v1/variants/{offer['variant_id']}/offers", { "id": offer["id"], "source_id": "manual", "external_id": offer["external_id"], "seller": offer["seller"], "url": offer.get("url"), "market": offer["market"], "currency": offer["currency"], "condition": offer["condition"], }, ) for price in FIXTURE["prices"]: offer = next(item for item in FIXTURE["offers"] if item["external_id"] == price["external_offer_id"]) request( "POST", f"/api/v1/offers/{offer['id']}/prices", { "id": price["id"], "source_id": "manual", "external_observation_id": price["external_observation_id"], "observed_at": price["observed_at"], "item_price": price["item_price"], "shipping_price": price["shipping_price"], "currency": price["currency"], "availability": price["availability"], "raw_payload": price["raw_payload"], "confidence": price["confidence"], }, expected=(200, 201), ) cases = { "A": ("22222222-2222-4222-8222-222222222222", "33333333-3333-4333-8333-333333333333"), "B": ("22222222-2222-4222-8222-22222222222b", "33333333-3333-4333-8333-33333333333b"), "C": ("22222222-2222-4222-8222-22222222222c", "33333333-3333-4333-8333-33333333333c"), "D": ("22222222-2222-4222-8222-222222222222", "33333333-3333-4333-8333-33333333333d"), } for label, (variant_id, offer_id) in cases.items(): status, result = request( "POST", f"/api/v1/evaluate/{variant_id}", { "profile_id": "mobile-development-notebook", "profile_version": 1, "offer_id": offer_id, "as_of": AS_OF, }, expected=(201,), ) print( f"case {label}: {status} overall={result['overall_eligibility']} " f"product={result['product_score']} price={result['price_score']} " f"deal={result['deal_score']} class={result['classification']}" ) if __name__ == "__main__": main()