google styled doc
This commit is contained in:
@@ -1,59 +1,36 @@
|
||||
"""
|
||||
openapi_first.client
|
||||
====================
|
||||
|
||||
OpenAPI-first HTTP client for contract-driven services.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
This module provides `OpenAPIClient`, a thin, strict HTTP client that
|
||||
derives all callable operations directly from an OpenAPI 3.x specification.
|
||||
|
||||
It is the client counterpart to `OpenAPIFirstApp`.
|
||||
|
||||
Core principles
|
||||
---------------
|
||||
- The OpenAPI specification is the single source of truth.
|
||||
- Each operationId becomes a callable Python method.
|
||||
- No implicit schema mutation or inference.
|
||||
- No code generation step.
|
||||
- Minimal abstraction over httpx.
|
||||
Notes:
|
||||
**Core Principles:**
|
||||
|
||||
What this module does
|
||||
---------------------
|
||||
- Parses an OpenAPI 3.x specification.
|
||||
- Dynamically creates one callable per operationId.
|
||||
- Enforces presence of:
|
||||
- servers
|
||||
- paths
|
||||
- operationId
|
||||
- Formats path parameters safely.
|
||||
- Handles JSON request bodies explicitly.
|
||||
- Returns raw `httpx.Response` objects.
|
||||
- The OpenAPI specification is the single source of truth
|
||||
- Each operationId becomes a callable Python method
|
||||
- No implicit schema mutation or inference
|
||||
- No code generation step
|
||||
- Minimal abstraction over httpx
|
||||
|
||||
What this module does NOT do
|
||||
----------------------------
|
||||
- It does not generate client code.
|
||||
- It does not validate request/response schemas.
|
||||
- It does not deserialize responses.
|
||||
- It does not retry requests.
|
||||
- It does not implement authentication helpers.
|
||||
- It does not assume non-2xx responses are failures.
|
||||
**Responsibilities:**
|
||||
|
||||
Intended usage
|
||||
--------------
|
||||
This client is designed for:
|
||||
- Parses an OpenAPI 3.x specification
|
||||
- Dynamically creates one callable per operationId
|
||||
- Enforces presence of servers, paths, and operationId
|
||||
- Formats path parameters safely
|
||||
- Handles JSON request bodies explicitly
|
||||
- Returns raw `httpx.Response` objects
|
||||
|
||||
- Service-to-service communication
|
||||
- Integration testing
|
||||
- Contract-driven internal SDK usage
|
||||
- Systems that want OpenAPI-first symmetry with `OpenAPIFirstApp`
|
||||
**Constraints:**
|
||||
|
||||
Design constraints
|
||||
------------------
|
||||
- Only the first server in the OpenAPI `servers` list is used if
|
||||
`base_url` is not explicitly provided.
|
||||
- Only explicitly declared request bodies are allowed.
|
||||
- `application/json` is handled natively; other media types are sent as raw content.
|
||||
- All responses are returned as-is.
|
||||
- This module intentionally does NOT: Generate client code, validate request/response schemas, deserialize responses, retry requests, implement authentication helpers, or assume non-2xx responses are failures.
|
||||
"""
|
||||
|
||||
from typing import Any, Callable, Dict, Optional
|
||||
@@ -65,73 +42,47 @@ from .errors import OpenAPIFirstError
|
||||
|
||||
|
||||
class OpenAPIClientError(OpenAPIFirstError):
|
||||
"""Raised when an OpenAPI client operation fails."""
|
||||
"""
|
||||
Raised when an OpenAPI client operation fails.
|
||||
"""
|
||||
|
||||
|
||||
class OpenAPIClient:
|
||||
"""
|
||||
OpenAPI-first HTTP client (httpx-based).
|
||||
|
||||
This client derives all callable methods directly from an OpenAPI 3.x
|
||||
specification. Each operationId becomes a method on the client
|
||||
instance.
|
||||
Notes:
|
||||
**Responsibilities:**
|
||||
|
||||
Design principles
|
||||
-----------------
|
||||
- One callable per operationId
|
||||
- Explicit parameters (path, query, headers, body)
|
||||
- No implicit schema inference or mutation
|
||||
- Returns raw httpx.Response objects
|
||||
- No response validation or deserialization
|
||||
- This client derives all callable methods directly from an OpenAPI 3.x specification. Each operationId becomes a method on the client instance.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
spec : dict
|
||||
Parsed OpenAPI 3.x specification.
|
||||
base_url : str | None
|
||||
Base URL of the target service. If omitted, the first entry
|
||||
in the OpenAPI `servers` list is used.
|
||||
client : httpx.Client | None
|
||||
Optional preconfigured httpx client instance.
|
||||
**Guarantees:**
|
||||
|
||||
Raises
|
||||
------
|
||||
OpenAPIClientError
|
||||
If:
|
||||
- No servers are defined and base_url is not provided
|
||||
- OpenAPI spec has no paths
|
||||
- An operation is missing operationId
|
||||
- Duplicate operationIds are detected
|
||||
- Required path parameters are missing
|
||||
- Required request body is missing
|
||||
- One callable per operationId
|
||||
- Explicit parameters (path, query, headers, body)
|
||||
- No implicit schema inference or mutation
|
||||
- Returns raw `httpx.Response` objects
|
||||
- No response validation or deserialization
|
||||
|
||||
Example
|
||||
-------
|
||||
```python
|
||||
from openapi_first import loader, client
|
||||
Example:
|
||||
```python
|
||||
from openapi_first import loader, client
|
||||
|
||||
spec = loader.load_openapi("openapi.yaml")
|
||||
spec = loader.load_openapi("openapi.yaml")
|
||||
|
||||
api = client.OpenAPIClient(
|
||||
spec=spec,
|
||||
base_url="http://localhost:8000",
|
||||
)
|
||||
api = client.OpenAPIClient(
|
||||
spec=spec,
|
||||
base_url="http://localhost:8000",
|
||||
)
|
||||
|
||||
# Call operationId: getUser
|
||||
response = api.getUser(
|
||||
path_params={"user_id": 123}
|
||||
)
|
||||
# Call operationId: getUser
|
||||
response = api.getUser(
|
||||
path_params={"user_id": 123}
|
||||
)
|
||||
|
||||
print(response.status_code)
|
||||
print(response.json())
|
||||
|
||||
# Call operationId: createUser
|
||||
response = api.createUser(
|
||||
body={"name": "Bob"}
|
||||
)
|
||||
|
||||
print(response.status_code)
|
||||
```
|
||||
print(response.status_code)
|
||||
print(response.json())
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
@@ -140,6 +91,21 @@ class OpenAPIClient:
|
||||
base_url: Optional[str] = None,
|
||||
client: Optional[httpx.Client] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Initialize the OpenAPI client.
|
||||
|
||||
Args:
|
||||
spec (dict[str, Any]):
|
||||
Parsed OpenAPI 3.x specification.
|
||||
base_url (str, optional):
|
||||
Base URL of the target service. If omitted, the first entry in the OpenAPI `servers` list is used.
|
||||
client (httpx.Client, optional):
|
||||
Optional preconfigured httpx client instance.
|
||||
|
||||
Raises:
|
||||
OpenAPIClientError:
|
||||
If no servers are defined, spec has no paths, operationIds are missing/duplicate, or required parameters are missing.
|
||||
"""
|
||||
self.spec = spec
|
||||
self.base_url = base_url or self._resolve_base_url(spec)
|
||||
self.client = client or httpx.Client(base_url=self.base_url)
|
||||
|
||||
Reference in New Issue
Block a user