SDS API wrapper/testing for coder
| examples | ||
| sds_api_client | ||
| .env.example | ||
| .gitignore | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
SDS Managed API - Python Client Wrapper
Lightweight Python wrapper around the SDS Managed API with:
- SDSClient (Bearer auth)
- Retries, timeouts, SSL verify toggle
- OData helpers ($select, $expand, $orderby, $filter, $top, $skip, $count)
- Auto-login on 401 Unauthorized (token cached and only fetched when needed) to prevent constant manual logins or logins on every single call
Prerequisites
- Python 3.8+
- uv (recommended) → https://docs.astral.sh/uv/
- Install: curl -LsSf https://astral.sh/uv/install.sh | sh
Getting started (uv)
- Sync deps (creates .venv from pyproject.toml):
- uv sync
- Run the example (provide credentials):
- KEYCLOAK_MAIL="you@example.com" KEYCLOAK_PASSWORD="your-password"
uv run examples/list_tenants.py
- KEYCLOAK_MAIL="you@example.com" KEYCLOAK_PASSWORD="your-password"
Quick usage
import os
from sds_api_client import SDSClient
# Option A: Let the client auto-login on first 401 using credentials
client = SDSClient(
base_url=os.getenv("SDS_BASE_URL"),
auth_user=os.getenv("KEYCLOAK_MAIL"),
auth_password=os.getenv("KEYCLOAK_PASSWORD"),
)
rows = client.tenants.list(top=10)
print(rows)
# Option B: Explicit login (token applied to Authorization header)
client = SDSClient(base_url=os.getenv("SDS_BASE_URL"))
client.login_keycloak(
user=os.getenv("KEYCLOAK_MAIL"),
password=os.getenv("KEYCLOAK_PASSWORD"),
)
rows = client.tenants.list(top=10)
print(rows)
API error handling
from sds_api_client import APIError
try:
client.tenants.list(top=1)
except APIError as e:
print(e)
print(e.to_dict())
Auth details
- Auto-login on 401 Unauthorized: if a request returns 401 and
auth_user/auth_passwordare configured, the client will callKeycloakAuth/tokenusing form datauserandpassword, cache the returned token, and retry the original request once. The token is reused for subsequent calls and not regenerated unless another 401 is received. - Explicit login option remains available via
client.login_keycloak(user=..., password=..., path=..., extra=...). By default the client posts form data (Content-Type: application/x-www-form-urlencoded) toKeycloakAuth/tokenwith fieldsuserandpassword. It expects a JSON body containing atoken(or common fallbacks likeaccess_token).
Extending endpoints
Use TenantsEndpoint as a template under sds_api_client/endpoints/ and expose via a property on SDSClient.
Notes
- Default OData key paths like
/Tenants(1); set key_style="slash" for/Tenants/1.