SPB Git forge
28commits 1branches 0releases
7.7 MBsize
maindefault branch
10 days agolast push
Python 66.3% TypeScript 22.7% JavaScript 8.6% HTML 1.4% CSS 0.7%
18.2 KB · 306 lines python
Raw Blame History
1"""Row → API shapes, exactly as documented in docs/API.md. Never invent values: missing inputs stay `null` / omitted."""2from __future__ import annotations34import json5from typing import Any6from urllib.parse import urlparse78from companyatlas.taxonomy import Metric, confidence_label910INT_METRICS = {Metric.OPEN_JOBS.value}11PCT_METRICS = {Metric.HIRING_MOMENTUM_7D.value, Metric.HIRING_MOMENTUM_30D.value, Metric.HIRING_MOMENTUM_90D.value}121314def _json(value: Any) -> Any:15    if isinstance(value, str):16        try:17            return json.loads(value)18        except ValueError:19            return value20    return value212223def _dict(value: Any) -> dict[str, Any]:24    v = _json(value)25    return v if isinstance(v, dict) else {}262728def _list(value: Any) -> list[Any]:29    v = _json(value)30    return list(v) if isinstance(v, list | tuple) else []313233def _float(value: Any, nd: int = 1) -> float | None:34    if value is None:35        return None36    try:37        return round(float(value), nd)38    except (TypeError, ValueError):39        return None404142def _int(value: Any) -> int | None:43    if value is None:44        return None45    try:46        return int(value)47    except (TypeError, ValueError):48        return None495051def metric_value(metric: str, value: Any) -> float | int | None:52    if value is None:53        return None54    if metric in INT_METRICS:55        return _int(value)56    return _float(value, 1)575859def metrics_map(raw: Any) -> dict[str, float | int]:60    out: dict[str, float | int] = {}61    for k, v in _dict(raw).items():62        mv = metric_value(k, v)63        if mv is not None:64            out[k] = mv65    return out666768# ------------------------------------------------------------------------------------------------ companies697071def company_ref(row: dict[str, Any], prefix: str = "company_") -> dict[str, Any]:72    return {"id": row.get("company_id") or row.get("id"), "slug": row.get(f"{prefix}slug"), "display_name": row.get(f"{prefix}display_name"),73            "canonical_domain": row.get(f"{prefix}domain") or row.get(f"{prefix}canonical_domain"), "country": row.get(f"{prefix}country"),74            "logo_url": row.get(f"{prefix}logo_url")}757677def company_ref_from_company(c: dict[str, Any]) -> dict[str, Any]:78    return {"id": c["id"], "slug": c["slug"], "display_name": c["display_name"], "canonical_domain": c["canonical_domain"],79            "country": c.get("country"), "logo_url": c.get("logo_url")}808182def company_card(row: dict[str, Any]) -> dict[str, Any]:83    stats = _dict(row.get("stats"))8485    def count(key: str, fallback: Any) -> int:86        v = stats.get(key)87        if isinstance(v, int | float) and not isinstance(v, bool):88            return int(v)89        return int(fallback or 0)9091    card: dict[str, Any] = {92        "id": row["id"], "slug": row["slug"], "display_name": row["display_name"], "legal_name": row.get("legal_name"),93        "canonical_domain": row["canonical_domain"], "website": row["website"], "description": row.get("description"),94        "industries": list(row.get("industries") or []), "industry_primary": row.get("industry_primary"), "country": row.get("country"),95        "hq_city": row.get("hq_city"), "hq_region": row.get("hq_region"), "public_company": bool(row.get("public_company")),96        "ticker": row.get("ticker"), "exchange": row.get("exchange"), "founded_year": row.get("founded_year"),97        "employees_band": row.get("employees_band"), "logo_url": row.get("logo_url"), "status": row.get("status"),98        "onboarding_status": row.get("onboarding_status"), "importance": _float(row.get("importance"), 3) or 0.0, "tier": int(row.get("tier") or 4),99        "metrics": metrics_map(row.get("metrics")),100        "counts": {"sensors": count("sensors", row.get("sensors")), "observations": count("observations", row.get("observations")),101                   "changes": count("changes", row.get("changes")), "events": count("events", row.get("events")),102                   "jobs_open": count("jobs_open", row.get("jobs_open"))},103        "last_event_at": row.get("last_event_at"), "last_observed_at": row.get("last_observed_at"),104    }105    if "sparkline" in row:106        card["sparkline"] = [round(float(x), 1) for x in (row.get("sparkline") or [])]107    profile = _dict(row.get("profile"))108    if profile:109        card["profile"] = profile                       # docs/API.md "Profile & facts" — present once the company has been enriched110    return card111112113def relationship(row: dict[str, Any]) -> dict[str, Any]:114    """`company_relationships` row joined with the target company (`slug`, `display_name` aliases)."""115    return {"kind": row["kind"], "company": {"slug": row["slug"], "display_name": row["display_name"]} if row.get("slug") else None,116            "to_name": row.get("to_name") or row.get("display_name"), "valid_from": row.get("valid_from"), "valid_to": row.get("valid_to"),117            "confidence": _float(row.get("confidence"), 3), "source_url": row.get("source_url"), "provenance": _dict(row.get("provenance")),118            "first_seen_at": row.get("first_seen_at"), "last_seen_at": row.get("last_seen_at")}119120121# ------------------------------------------------------------------------------------------------ events122123124def event(row: dict[str, Any], *, with_company: bool = True) -> dict[str, Any]:125    conf = float(row.get("confidence") or 0)126    out: dict[str, Any] = {127        "id": row["id"], "event_type": row["event_type"], "event_subtype": row["event_subtype"], "importance": _float(row.get("importance"), 3),128        "confidence": round(conf, 3), "confidence_label": row.get("confidence_label") or confidence_label(conf), "title": row["title"],129        "summary": row.get("summary"), "old_value": row.get("old_value"), "new_value": row.get("new_value"), "payload": _dict(row.get("payload")),130        "entities": _dict(row.get("entities")), "tags": list(row.get("tags") or []), "detected_at": row["detected_at"],131        "effective_at": row.get("effective_at"), "published_at": row.get("published_at"), "source_url": row.get("source_url"),132        "surface": row.get("surface"), "sensor_id": row.get("sensor_id"), "change_id": row.get("change_id"), "cluster_id": row.get("cluster_id"),133        "origin": row.get("origin") or "deterministic", "model_name": row.get("model_name"), "prompt_version": row.get("prompt_version"),134        "status": row.get("status") or "active",135    }136    if with_company:137        out["company"] = company_ref(row)138    if row.get("status") == "retracted":139        out["retracted_reason"] = row.get("retracted_reason")140    return out141142143def event_source(row: dict[str, Any]) -> dict[str, Any]:144    return {"source_url": row["source_url"], "surface": row.get("surface"), "detected_at": row["detected_at"], "kind": row.get("kind") or "primary",145            "sensor_id": row.get("sensor_id"), "snapshot_id": row.get("snapshot_id")}146147148# ------------------------------------------------------------------------------------------------ provenance149150151def sensor(row: dict[str, Any]) -> dict[str, Any]:152    return {"id": row["id"], "company_id": row["company_id"], "surface": row["surface"], "connector_id": row["connector_id"], "url": row["url"],153            "canonical_url": row["canonical_url"], "domain": row["domain"], "status": row["status"], "tier": (row.get("tier") or "D").strip(),154            "quality_score": _float(row.get("quality_score"), 1), "discovery_confidence": _float(row.get("discovery_confidence"), 3),155            "discovery_method": row.get("discovery_method"), "current_interval_s": int(row.get("current_interval_s") or 0),156            "next_run_at": row.get("next_run_at"), "last_run_at": row.get("last_run_at"), "last_success_at": row.get("last_success_at"),157            "last_change_at": row.get("last_change_at"), "last_status": row.get("last_status"), "last_failure_class": row.get("last_failure_class"),158            "consecutive_failures": int(row.get("consecutive_failures") or 0), "observation_count": int(row.get("observation_count") or 0),159            "snapshot_count": int(row.get("snapshot_count") or 0), "change_count": int(row.get("change_count") or 0),160            "meaningful_change_count": int(row.get("meaningful_change_count") or 0), "event_count": int(row.get("event_count") or 0),161            "created_at": row.get("created_at")}162163164def sensor_admin(row: dict[str, Any]) -> dict[str, Any]:165    out = sensor(row)166    out.update({"base_interval_s": row.get("base_interval_s"), "last_error": row.get("last_error"), "priority": _float(row.get("priority"), 3),167                "claimed_by": row.get("claimed_by"), "claimed_at": row.get("claimed_at"), "retired_at": row.get("retired_at"),168                "consecutive_unchanged": row.get("consecutive_unchanged"), "config": _dict(row.get("config")), "updated_at": row.get("updated_at")})169    return out170171172def snapshot(row: dict[str, Any]) -> dict[str, Any]:173    return {"id": row["id"], "sensor_id": row["sensor_id"], "company_id": row.get("company_id"), "version_no": int(row.get("version_no") or 1),174            "fetched_at": row["fetched_at"], "title": row.get("title"), "language": row.get("language"), "text_length": row.get("text_length"),175            "block_count": row.get("block_count"), "extracted_summary": _dict(row.get("extracted_summary")), "content_hash": row["content_hash"],176            "previous_snapshot_id": row.get("previous_snapshot_id"), "observation_id": row.get("observation_id"),177            "collection_method": row.get("collection_method"), "connector_version": row.get("connector_version")}178179180def change(row: dict[str, Any], *, with_diff: bool = False) -> dict[str, Any]:181    out: dict[str, Any] = {"id": row["id"], "sensor_id": row["sensor_id"], "surface": row["surface"], "company_id": row["company_id"],182                           "detected_at": row["detected_at"], "significance": _float(row.get("significance"), 3), "kind": row["kind"],183                           "blocks_added": int(row.get("blocks_added") or 0), "blocks_removed": int(row.get("blocks_removed") or 0),184                           "blocks_modified": int(row.get("blocks_modified") or 0), "blocks_moved": int(row.get("blocks_moved") or 0),185                           "text_delta_ratio": _float(row.get("text_delta_ratio"), 4), "similarity": _float(row.get("similarity"), 4),186                           "snapshot_before": row.get("snapshot_before"), "snapshot_after": row["snapshot_after"], "status": row.get("status"),187                           "diff_version": row.get("diff_version")}188    if with_diff:189        out["diff"] = _dict(row.get("diff"))190        out["structured_delta"] = _dict(row.get("structured_delta"))191    return out192193194# ------------------------------------------------------------------------------------------------ entities195196197def job(row: dict[str, Any]) -> dict[str, Any]:198    return {"id": row["id"], "title": row["title"], "department": row.get("department"), "location_text": row.get("location_text"),199            "city": row.get("city"), "country": row.get("country"), "remote": row.get("remote"), "employment_type": row.get("employment_type"),200            "seniority": row.get("seniority"), "url": row.get("url"), "posted_at": row.get("posted_at"), "first_seen_at": row["first_seen_at"],201            "last_seen_at": row["last_seen_at"], "removed_at": row.get("removed_at"), "status": row.get("status") or "open",202            "is_ai": bool(row.get("is_ai"))}203204205def person(row: dict[str, Any]) -> dict[str, Any]:206    source_url = row.get("source_url")207    host = (urlparse(source_url).hostname or "").lower() if source_url else ""208    return {"id": row["id"], "name": row["name"], "title": row.get("title"), "role_category": row.get("role_category"),209            "is_executive": bool(row.get("is_executive")), "first_seen_at": row["first_seen_at"], "last_seen_at": row["last_seen_at"],210            "removed_at": row.get("removed_at"), "status": row.get("status") or "listed", "source_url": source_url,211            "source": "wikidata" if host.endswith("wikidata.org") else "page"}212213214def product(row: dict[str, Any]) -> dict[str, Any]:215    return {"id": row["id"], "name": row["name"], "category": row.get("category"), "description": row.get("description"), "url": row.get("url"),216            "first_seen_at": row["first_seen_at"], "last_seen_at": row["last_seen_at"], "removed_at": row.get("removed_at"),217            "status": row.get("status") or "listed"}218219220def plan(row: dict[str, Any]) -> dict[str, Any]:221    return {"id": row["id"], "plan_name": row["plan_name"], "price": _float(row.get("price"), 2), "price_text": row.get("price_text"),222            "currency": row.get("currency"), "billing_period": row.get("billing_period"), "unit": row.get("unit"),223            "features": [str(x) for x in _list(row.get("features"))], "contact_sales": bool(row.get("contact_sales")),224            "version_no": int(row.get("version_no") or 1), "valid_from": row["valid_from"], "valid_to": row.get("valid_to"),225            "status": row.get("status") or "current", "source_url": row.get("source_url")}226227228def location(row: dict[str, Any]) -> dict[str, Any]:229    return {"id": row["id"], "kind": row.get("kind") or "office", "name": row.get("name"), "city": row.get("city"), "region": row.get("region"),230            "country": row.get("country"), "lat": row.get("lat"), "lon": row.get("lon"), "first_seen_at": row["first_seen_at"],231            "last_seen_at": row["last_seen_at"], "removed_at": row.get("removed_at"), "status": row.get("status") or "listed",232            "source_url": row.get("source_url")}233234235def news_item(row: dict[str, Any]) -> dict[str, Any]:236    return {"id": row["id"], "title": row["title"], "url": row["url"], "summary": row.get("summary"), "category": row.get("category"),237            "published_at": row.get("published_at"), "first_seen_at": row["first_seen_at"], "language": row.get("language")}238239240def metric_point(row: dict[str, Any]) -> dict[str, Any]:241    return {"day": row["day"], "value": _float(row.get("value"), 2), "confidence": _float(row.get("confidence"), 3)}242243244def signal(row: dict[str, Any]) -> dict[str, Any]:245    return {"id": row["id"], "company_id": row.get("company_id"), "scope": row.get("scope") or "company", "scope_key": row.get("scope_key"),246            "kind": row["kind"], "strength": _float(row.get("strength"), 3), "confidence": _float(row.get("confidence"), 3), "title": row["title"],247            "explanation": row.get("explanation"), "evidence": _dict(row.get("evidence")), "window_days": int(row.get("window_days") or 30),248            "detected_at": row["detected_at"], "expires_at": row.get("expires_at"), "status": row.get("status") or "active"}249250251# ------------------------------------------------------------------------------------------------ owner / admin252253254def alert(row: dict[str, Any]) -> dict[str, Any]:255    out = {"id": row["id"], "name": row["name"], "company_id": row.get("company_id"), "condition": _dict(row.get("condition")),256           "channel": row.get("channel") or "web", "target": row.get("target"), "enabled": bool(row.get("enabled", True)),257           "created_at": row["created_at"], "last_fired_at": row.get("last_fired_at")}258    if row.get("company_slug"):259        out["company"] = company_ref(row)260    return out261262263def alert_delivery(row: dict[str, Any]) -> dict[str, Any]:264    return {"id": row["id"], "alert_id": row["alert_id"], "alert_name": row.get("alert_name"), "event_id": row.get("event_id"),265            "event_title": row.get("event_title"), "delivered_at": row["delivered_at"], "channel": row["channel"], "status": row["status"],266            "detail": row.get("detail")}267268269def queue_job(row: dict[str, Any]) -> dict[str, Any]:270    return {"id": row["id"], "kind": row["kind"], "key": row["key"], "payload": _dict(row.get("payload")), "priority": _float(row.get("priority"), 3),271            "run_at": row["run_at"], "locked_at": row.get("locked_at"), "locked_by": row.get("locked_by"), "attempts": row.get("attempts"),272            "max_attempts": row.get("max_attempts"), "status": row["status"], "last_error": row.get("last_error"), "created_at": row["created_at"],273            "finished_at": row.get("finished_at")}274275276def llm_job(row: dict[str, Any]) -> dict[str, Any]:277    return {"id": row["id"], "kind": row["kind"], "ref_id": row["ref_id"], "company_id": row.get("company_id"), "model": row.get("model"),278            "prompt_version": row.get("prompt_version"), "status": row["status"], "attempts": row.get("attempts"),279            "request_tokens": row.get("request_tokens"), "response_tokens": row.get("response_tokens"), "latency_ms": row.get("latency_ms"),280            "result": _json(row.get("result")), "error": row.get("error"), "created_at": row["created_at"], "started_at": row.get("started_at"),281            "finished_at": row.get("finished_at")}282283284def failure(row: dict[str, Any]) -> dict[str, Any]:285    return {"id": row["id"], "sensor_id": row.get("sensor_id"), "company_id": row.get("company_id"), "at": row["at"],286            "failure_class": row["failure_class"], "status_code": row.get("status_code"), "message": row.get("message"), "url": row.get("url"),287            "company_slug": row.get("company_slug"), "surface": row.get("surface")}288289290def review(row: dict[str, Any]) -> dict[str, Any]:291    return {"id": row["id"], "kind": row["kind"], "ref_id": row.get("ref_id"), "company_id": row.get("company_id"), "payload": _dict(row.get("payload")),292            "status": row["status"], "resolution": row.get("resolution"), "created_at": row["created_at"], "resolved_at": row.get("resolved_at"),293            "company_slug": row.get("company_slug"), "company_display_name": row.get("company_display_name")}294295296def connector(row: dict[str, Any]) -> dict[str, Any]:297    return {"id": row["id"], "name": row["name"], "version": row["version"], "category": row["category"], "fetch_mode": row.get("fetch_mode"),298            "enabled": bool(row.get("enabled")), "default_interval_s": row.get("default_interval_s"),299            "supports_discovery": bool(row.get("supports_discovery")), "supports_incremental": bool(row.get("supports_incremental")),300            "stats": _dict(row.get("stats")), "created_at": row.get("created_at"), "updated_at": row.get("updated_at")}301302303__all__ = ["alert", "alert_delivery", "change", "company_card", "company_ref", "company_ref_from_company", "connector", "event", "event_source",304           "failure", "job", "llm_job", "location", "metric_point", "metric_value", "metrics_map", "news_item", "person", "plan", "product",305           "queue_job", "relationship", "review", "sensor", "sensor_admin", "signal", "snapshot"]306