Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Each generated endpoint module exposes four entrypoints:

| Module | Operation | Method · Path |
| --- | --- | --- |
| `api.auth` | `auth` | `POST /auth/token` — exchange API key for a short-lived JWT |
| `api.exchange` | `get_exchanges` | `GET /exchanges` |
| `api.exchange` | `get_instruments` | `GET /exchange/{exchangeId}/instruments` |
| `api.exchange` | `get_exchange_tickers_hour` | `GET /exchange/{exchangeId}/tickers/{base}/{quote}` |
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "qtsurfer-api-client"
version = "0.94.0"
version = "0.95.1"
description = "Auto-generated Python client for the QTSurfer API."
readme = "README.md"
license = "Apache-2.0"
Expand Down
1 change: 1 addition & 0 deletions src/qtsurfer/api/client/_generated/api/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Contains endpoint functions for accessing the API"""
174 changes: 174 additions & 0 deletions src/qtsurfer/api/client/_generated/api/auth/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
from http import HTTPStatus
from typing import Any, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.auth_token_error import AuthTokenError
from ...models.auth_token_response import AuthTokenResponse
from ...types import Response


def _get_kwargs() -> dict[str, Any]:

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/auth/token",
}

return _kwargs


def _parse_response(
*, client: AuthenticatedClient | Client, response: httpx.Response
) -> Any | AuthTokenError | AuthTokenResponse | None:
if response.status_code == 200:
response_200 = AuthTokenResponse.from_dict(response.json())

return response_200

if response.status_code == 401:
response_401 = AuthTokenError.from_dict(response.json())

return response_401

if response.status_code == 429:
response_429 = cast(Any, None)
return response_429

if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: AuthenticatedClient | Client, response: httpx.Response
) -> Response[Any | AuthTokenError | AuthTokenResponse]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: AuthenticatedClient,
) -> Response[Any | AuthTokenError | AuthTokenResponse]:
"""Exchange API key for a short-lived JWT

Exchanges a long-lived API key for a short-lived JWT used by every other
endpoint. This is the only endpoint that accepts an API key directly —
callers should obtain a JWT here, then send it as `Authorization: Bearer
<token>` to all other operations.

The returned JWT carries the caller's subscription `tier` as a claim and
expires after `expires_in` seconds. Callers should refresh the token
before expiry (or on a `401` response) by calling this endpoint again.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any | AuthTokenError | AuthTokenResponse]
"""

kwargs = _get_kwargs()

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: AuthenticatedClient,
) -> Any | AuthTokenError | AuthTokenResponse | None:
"""Exchange API key for a short-lived JWT

Exchanges a long-lived API key for a short-lived JWT used by every other
endpoint. This is the only endpoint that accepts an API key directly —
callers should obtain a JWT here, then send it as `Authorization: Bearer
<token>` to all other operations.

The returned JWT carries the caller's subscription `tier` as a claim and
expires after `expires_in` seconds. Callers should refresh the token
before expiry (or on a `401` response) by calling this endpoint again.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Any | AuthTokenError | AuthTokenResponse
"""

return sync_detailed(
client=client,
).parsed


async def asyncio_detailed(
*,
client: AuthenticatedClient,
) -> Response[Any | AuthTokenError | AuthTokenResponse]:
"""Exchange API key for a short-lived JWT

Exchanges a long-lived API key for a short-lived JWT used by every other
endpoint. This is the only endpoint that accepts an API key directly —
callers should obtain a JWT here, then send it as `Authorization: Bearer
<token>` to all other operations.

The returned JWT carries the caller's subscription `tier` as a claim and
expires after `expires_in` seconds. Callers should refresh the token
before expiry (or on a `401` response) by calling this endpoint again.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any | AuthTokenError | AuthTokenResponse]
"""

kwargs = _get_kwargs()

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: AuthenticatedClient,
) -> Any | AuthTokenError | AuthTokenResponse | None:
"""Exchange API key for a short-lived JWT

Exchanges a long-lived API key for a short-lived JWT used by every other
endpoint. This is the only endpoint that accepts an API key directly —
callers should obtain a JWT here, then send it as `Authorization: Bearer
<token>` to all other operations.

The returned JWT carries the caller's subscription `tier` as a claim and
expires after `expires_in` seconds. Callers should refresh the token
before expiry (or on a `401` response) by calling this endpoint again.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Any | AuthTokenError | AuthTokenResponse
"""

return (
await asyncio_detailed(
client=client,
)
).parsed
10 changes: 10 additions & 0 deletions src/qtsurfer/api/client/_generated/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""Contains all the data models used in inputs/outputs"""

from .accepted_job import AcceptedJob
from .auth_token_error import AuthTokenError
from .auth_token_error_code import AuthTokenErrorCode
from .auth_token_response import AuthTokenResponse
from .auth_token_response_tier import AuthTokenResponseTier
from .auth_token_response_token_type import AuthTokenResponseTokenType
from .backtest_job_result import BacktestJobResult
from .cancel_execution_response_200 import CancelExecutionResponse200
from .cancel_execution_response_200_status import CancelExecutionResponse200Status
Expand All @@ -24,6 +29,11 @@

__all__ = (
"AcceptedJob",
"AuthTokenError",
"AuthTokenErrorCode",
"AuthTokenResponse",
"AuthTokenResponseTier",
"AuthTokenResponseTokenType",
"BacktestJobResult",
"CancelExecutionResponse200",
"CancelExecutionResponse200Status",
Expand Down
72 changes: 72 additions & 0 deletions src/qtsurfer/api/client/_generated/models/auth_token_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from __future__ import annotations

from collections.abc import Mapping
from typing import Any, TypeVar

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..models.auth_token_error_code import AuthTokenErrorCode

T = TypeVar("T", bound="AuthTokenError")


@_attrs_define
class AuthTokenError:
"""Error envelope returned by `POST /auth/token` when the API key is rejected.

Attributes:
code (AuthTokenErrorCode): Machine-readable error reason.
message (str): Human-readable description of the failure.
"""

code: AuthTokenErrorCode
message: str
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
code = self.code.value

message = self.message

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"code": code,
"message": message,
}
)

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
code = AuthTokenErrorCode(d.pop("code"))

message = d.pop("message")

auth_token_error = cls(
code=code,
message=message,
)

auth_token_error.additional_properties = d
return auth_token_error

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties
10 changes: 10 additions & 0 deletions src/qtsurfer/api/client/_generated/models/auth_token_error_code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from enum import Enum


class AuthTokenErrorCode(str, Enum):
APIKEY_EXPIRED = "apikey_expired"
APIKEY_REVOKED = "apikey_revoked"
INVALID_APIKEY = "invalid_apikey"

def __str__(self) -> str:
return str(self.value)
Loading
Loading