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
122 changes: 43 additions & 79 deletions src/antfly/client.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
"""Main client interface for Antfly SDK."""

import base64
from typing import Any, Optional, cast

from httpx import Timeout

from antfly.client_generated import Client
from antfly.client_generated.api.api_table import (
batch,
from antfly.client_generated.api.table_management import (
create_table,
drop_table,
get_table,
list_tables,
)
from antfly.client_generated.api.data_operations import (
batch_write as batch,
lookup_key,
query_table,
)
from antfly.client_generated.client import AuthenticatedClient
from antfly.client_generated.models import (
Expand All @@ -21,9 +23,6 @@
CreateTableRequest,
CreateTableRequestIndexes,
Error,
QueryRequest,
QueryRequestFullTextSearch,
QueryResponses,
Table,
TableSchema,
TableStatus,
Expand All @@ -41,28 +40,57 @@ def __init__(
base_url: str,
username: Optional[str] = None,
password: Optional[str] = None,
api_key: Optional[tuple[str, str]] = None,
bearer_token: Optional[str] = None,
timeout: float = 30.0,
):
"""
Initialize Antfly client.

Supports three authentication methods (mutually exclusive):
- Basic auth: provide ``username`` and ``password``
- API key: provide ``api_key`` as ``(key_id, key_secret)``
- Bearer token: provide ``bearer_token``

Args:
base_url: Base URL of the Antfly server
username: Username for authentication (optional)
password: Password for authentication (optional)
username: Username for basic authentication (optional)
password: Password for basic authentication (optional)
api_key: Tuple of (key_id, key_secret) for API key authentication (optional)
bearer_token: Bearer token string for token authentication (optional)
timeout: Request timeout in seconds
"""
self.base_url = base_url.rstrip("/")

httpx_args: dict[str, Any] = {}
if username and password:
httpx_args["auth"] = (username, password)

self._client = Client(
base_url=self.base_url,
timeout=Timeout(timeout),
httpx_args=httpx_args,
)
if api_key is not None:
key_id, key_secret = api_key
encoded = base64.b64encode(f"{key_id}:{key_secret}".encode()).decode()
self._client = AuthenticatedClient(
base_url=self.base_url,
token=encoded,
prefix="ApiKey",
timeout=Timeout(timeout),
httpx_args=httpx_args,
)
elif bearer_token is not None:
self._client = AuthenticatedClient(
base_url=self.base_url,
token=bearer_token,
prefix="Bearer",
timeout=Timeout(timeout),
httpx_args=httpx_args,
)
else:
if username and password:
httpx_args["auth"] = (username, password)

self._client = Client(
base_url=self.base_url,
timeout=Timeout(timeout),
httpx_args=httpx_args,
)

# Table operations

Expand Down Expand Up @@ -171,70 +199,6 @@ def drop_table(self, name: str) -> None:
if response is None:
raise AntflyException(f"Failed to drop table '{name}'")

# Query operations

def query(
self,
table: Optional[str] = None,
full_text_search: Optional[dict[str, Any]] = None,
semantic_search: Optional[str] = None,
filter_prefix: Optional[str] = None,
limit: int = 10,
offset: int = 0,
**kwargs: Any,
) -> QueryResponses:
"""
Query a table or perform global query.

Args:
table: Table name (optional for global query)
full_text_search: Full-text search query
semantic_search: Semantic search query
filter_prefix: Key prefix filter
limit: Maximum number of results
offset: Number of results to skip
**kwargs: Additional query parameters

Returns:
Query result object

Raises:
AntflyException: If query fails
"""
request = QueryRequest(
table=table if table is not None else UNSET,
full_text_search=(
cast(QueryRequestFullTextSearch, full_text_search) if full_text_search is not None else UNSET
),
semantic_search=semantic_search if semantic_search is not None else UNSET,
filter_prefix=filter_prefix if filter_prefix is not None else UNSET,
limit=limit,
offset=offset,
**kwargs,
)

if table:
response = query_table.sync(
table_name=table,
client=cast(AuthenticatedClient, self._client),
body=request,
)
else:
# Use global query endpoint
from antfly.client_generated.api.api_table import global_query

response = global_query.sync(
client=cast(AuthenticatedClient, self._client),
body=request,
)

if isinstance(response, Error):
raise AntflyException(f"Query failed: {response.error}")
if response is None:
raise AntflyException("Query failed")

return response

def get(self, table: str, key: str) -> dict[str, Any]:
"""
Get a single record by key.
Expand Down
1 change: 1 addition & 0 deletions src/antfly/client_generated/api/api_key/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Contains endpoint functions for accessing the API"""
206 changes: 206 additions & 0 deletions src/antfly/client_generated/api/api_key/create_api_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.api_key_with_secret import ApiKeyWithSecret
from ...models.create_api_key_request import CreateApiKeyRequest
from ...models.error import Error
from ...types import Response


def _get_kwargs(
user_name: str,
*,
body: CreateApiKeyRequest,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": f"/users/{user_name}/api-keys",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[ApiKeyWithSecret, Error]]:
if response.status_code == 201:
response_201 = ApiKeyWithSecret.from_dict(response.json())

return response_201

if response.status_code == 400:
response_400 = Error.from_dict(response.json())

return response_400

if response.status_code == 403:
response_403 = Error.from_dict(response.json())

return response_403

if response.status_code == 404:
response_404 = Error.from_dict(response.json())

return response_404

if response.status_code == 500:
response_500 = Error.from_dict(response.json())

return response_500

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


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[ApiKeyWithSecret, Error]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
user_name: str,
*,
client: AuthenticatedClient,
body: CreateApiKeyRequest,
) -> Response[Union[ApiKeyWithSecret, Error]]:
"""Create a new API key

Creates a new API key for the specified user. The cleartext secret is returned only in this
response.

Args:
user_name (str): Example: johndoe.
body (CreateApiKeyRequest): Request to create a new API key.

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[Union[ApiKeyWithSecret, Error]]
"""

kwargs = _get_kwargs(
user_name=user_name,
body=body,
)

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

return _build_response(client=client, response=response)


def sync(
user_name: str,
*,
client: AuthenticatedClient,
body: CreateApiKeyRequest,
) -> Optional[Union[ApiKeyWithSecret, Error]]:
"""Create a new API key

Creates a new API key for the specified user. The cleartext secret is returned only in this
response.

Args:
user_name (str): Example: johndoe.
body (CreateApiKeyRequest): Request to create a new API key.

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:
Union[ApiKeyWithSecret, Error]
"""

return sync_detailed(
user_name=user_name,
client=client,
body=body,
).parsed


async def asyncio_detailed(
user_name: str,
*,
client: AuthenticatedClient,
body: CreateApiKeyRequest,
) -> Response[Union[ApiKeyWithSecret, Error]]:
"""Create a new API key

Creates a new API key for the specified user. The cleartext secret is returned only in this
response.

Args:
user_name (str): Example: johndoe.
body (CreateApiKeyRequest): Request to create a new API key.

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[Union[ApiKeyWithSecret, Error]]
"""

kwargs = _get_kwargs(
user_name=user_name,
body=body,
)

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

return _build_response(client=client, response=response)


async def asyncio(
user_name: str,
*,
client: AuthenticatedClient,
body: CreateApiKeyRequest,
) -> Optional[Union[ApiKeyWithSecret, Error]]:
"""Create a new API key

Creates a new API key for the specified user. The cleartext secret is returned only in this
response.

Args:
user_name (str): Example: johndoe.
body (CreateApiKeyRequest): Request to create a new API key.

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:
Union[ApiKeyWithSecret, Error]
"""

return (
await asyncio_detailed(
user_name=user_name,
client=client,
body=body,
)
).parsed
Loading
Loading