Skip to content

model_registry

model_registry

Registry mapping API endpoint patterns to Pydantic model classes.

Uses regex matching to map actual endpoint URIs (with tags/IDs) to the correct response model. Returns None for unknown endpoints so the caller can fall back to dynamic model generation.

get_model_for_endpoint

get_model_for_endpoint(uri: str) -> dict[str, Any] | None

Look up the model class for an endpoint URI.

PARAMETER DESCRIPTION
uri

The API endpoint path (e.g., "/clans/%23ABC123")

TYPE: str

RETURNS DESCRIPTION
dict[str, Any] | None

Dict with "model" (the model class) and "paginated" (bool),

dict[str, Any] | None

or None if no matching model is found.

Source code in cocapi/model_registry.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
def get_model_for_endpoint(
    uri: str,
) -> dict[str, Any] | None:
    """
    Look up the model class for an endpoint URI.

    Args:
        uri: The API endpoint path (e.g., "/clans/%23ABC123")

    Returns:
        Dict with "model" (the model class) and "paginated" (bool),
        or None if no matching model is found.
    """
    if not SCHEMAS_AVAILABLE:
        return None

    for pattern, model_class, is_paginated in _ENDPOINT_PATTERNS:
        if pattern.match(uri):
            return {"model": model_class, "paginated": is_paginated}

    return None

resolve_response

resolve_response(response: dict[str, Any], uri: str) -> Any

Resolve an API response dict into a Pydantic model if a matching schema exists.

PARAMETER DESCRIPTION
response

The raw API response dict

TYPE: dict[str, Any]

uri

The endpoint URI used for the request

TYPE: str

RETURNS DESCRIPTION
Any

A Pydantic model instance for known endpoints, the original dict

Any

for error responses, or None if no matching model is found (signals

Any

the caller to use dynamic model fallback).

Source code in cocapi/model_registry.py
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def resolve_response(response: dict[str, Any], uri: str) -> Any:
    """
    Resolve an API response dict into a Pydantic model if a matching
    schema exists.

    Args:
        response: The raw API response dict
        uri: The endpoint URI used for the request

    Returns:
        A Pydantic model instance for known endpoints, the original dict
        for error responses, or None if no matching model is found (signals
        the caller to use dynamic model fallback).
    """
    if not SCHEMAS_AVAILABLE:
        return response

    if response.get("result") == "error":
        return response

    match = get_model_for_endpoint(uri)
    if match is None:
        return None  # Signal caller to use dynamic fallback

    model_class: type[BaseModel] = match["model"]
    is_paginated: bool = match["paginated"]

    try:
        if is_paginated:
            # Validate each item in the list
            items = response.get("items", [])
            validated_items = [model_class.model_validate(item) for item in items]
            # Keep paging as a plain dict so extract_after_cursor() can use .get()
            paging = response.get("paging")
            return {
                "items": validated_items,
                "paging": paging,
            }
        else:
            return model_class.model_validate(response)
    except Exception:
        return None  # Signal caller to use dynamic fallback