sdkrouter 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sdkrouter/__init__.py +110 -0
- sdkrouter/_api/__init__.py +28 -0
- sdkrouter/_api/client.py +204 -0
- sdkrouter/_api/generated/__init__.py +21 -0
- sdkrouter/_api/generated/cdn/__init__.py +209 -0
- sdkrouter/_api/generated/cdn/cdn__api__cdn/__init__.py +7 -0
- sdkrouter/_api/generated/cdn/cdn__api__cdn/client.py +133 -0
- sdkrouter/_api/generated/cdn/cdn__api__cdn/models.py +163 -0
- sdkrouter/_api/generated/cdn/cdn__api__cdn/sync_client.py +132 -0
- sdkrouter/_api/generated/cdn/client.py +75 -0
- sdkrouter/_api/generated/cdn/logger.py +256 -0
- sdkrouter/_api/generated/cdn/pyproject.toml +55 -0
- sdkrouter/_api/generated/cdn/retry.py +272 -0
- sdkrouter/_api/generated/cdn/sync_client.py +58 -0
- sdkrouter/_api/generated/cleaner/__init__.py +212 -0
- sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/__init__.py +7 -0
- sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/client.py +83 -0
- sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/models.py +117 -0
- sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/sync_client.py +82 -0
- sdkrouter/_api/generated/cleaner/client.py +75 -0
- sdkrouter/_api/generated/cleaner/enums.py +55 -0
- sdkrouter/_api/generated/cleaner/logger.py +256 -0
- sdkrouter/_api/generated/cleaner/pyproject.toml +55 -0
- sdkrouter/_api/generated/cleaner/retry.py +272 -0
- sdkrouter/_api/generated/cleaner/sync_client.py +58 -0
- sdkrouter/_api/generated/keys/__init__.py +212 -0
- sdkrouter/_api/generated/keys/client.py +75 -0
- sdkrouter/_api/generated/keys/enums.py +64 -0
- sdkrouter/_api/generated/keys/keys__api__keys/__init__.py +7 -0
- sdkrouter/_api/generated/keys/keys__api__keys/client.py +150 -0
- sdkrouter/_api/generated/keys/keys__api__keys/models.py +152 -0
- sdkrouter/_api/generated/keys/keys__api__keys/sync_client.py +149 -0
- sdkrouter/_api/generated/keys/logger.py +256 -0
- sdkrouter/_api/generated/keys/pyproject.toml +55 -0
- sdkrouter/_api/generated/keys/retry.py +272 -0
- sdkrouter/_api/generated/keys/sync_client.py +58 -0
- sdkrouter/_api/generated/models/__init__.py +209 -0
- sdkrouter/_api/generated/models/client.py +75 -0
- sdkrouter/_api/generated/models/logger.py +256 -0
- sdkrouter/_api/generated/models/models__api__llm_models/__init__.py +7 -0
- sdkrouter/_api/generated/models/models__api__llm_models/client.py +99 -0
- sdkrouter/_api/generated/models/models__api__llm_models/models.py +206 -0
- sdkrouter/_api/generated/models/models__api__llm_models/sync_client.py +99 -0
- sdkrouter/_api/generated/models/pyproject.toml +55 -0
- sdkrouter/_api/generated/models/retry.py +272 -0
- sdkrouter/_api/generated/models/sync_client.py +58 -0
- sdkrouter/_api/generated/shortlinks/__init__.py +209 -0
- sdkrouter/_api/generated/shortlinks/client.py +75 -0
- sdkrouter/_api/generated/shortlinks/logger.py +256 -0
- sdkrouter/_api/generated/shortlinks/pyproject.toml +55 -0
- sdkrouter/_api/generated/shortlinks/retry.py +272 -0
- sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/__init__.py +7 -0
- sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/client.py +137 -0
- sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/models.py +153 -0
- sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/sync_client.py +136 -0
- sdkrouter/_api/generated/shortlinks/sync_client.py +58 -0
- sdkrouter/_api/generated/vision/__init__.py +212 -0
- sdkrouter/_api/generated/vision/client.py +75 -0
- sdkrouter/_api/generated/vision/enums.py +40 -0
- sdkrouter/_api/generated/vision/logger.py +256 -0
- sdkrouter/_api/generated/vision/pyproject.toml +55 -0
- sdkrouter/_api/generated/vision/retry.py +272 -0
- sdkrouter/_api/generated/vision/sync_client.py +58 -0
- sdkrouter/_api/generated/vision/vision__api__vision/__init__.py +7 -0
- sdkrouter/_api/generated/vision/vision__api__vision/client.py +65 -0
- sdkrouter/_api/generated/vision/vision__api__vision/models.py +138 -0
- sdkrouter/_api/generated/vision/vision__api__vision/sync_client.py +65 -0
- sdkrouter/_client.py +432 -0
- sdkrouter/_config.py +74 -0
- sdkrouter/_constants.py +21 -0
- sdkrouter/_internal/__init__.py +1 -0
- sdkrouter/_types/__init__.py +30 -0
- sdkrouter/_types/cdn.py +27 -0
- sdkrouter/_types/models.py +26 -0
- sdkrouter/_types/ocr.py +24 -0
- sdkrouter/_types/parsed.py +101 -0
- sdkrouter/_types/shortlinks.py +27 -0
- sdkrouter/_types/vision.py +29 -0
- sdkrouter/_version.py +3 -0
- sdkrouter/helpers/__init__.py +13 -0
- sdkrouter/helpers/formatting.py +15 -0
- sdkrouter/helpers/html.py +100 -0
- sdkrouter/helpers/json_cleaner.py +53 -0
- sdkrouter/tools/__init__.py +129 -0
- sdkrouter/tools/cdn.py +285 -0
- sdkrouter/tools/cleaner.py +186 -0
- sdkrouter/tools/keys.py +215 -0
- sdkrouter/tools/models.py +196 -0
- sdkrouter/tools/shortlinks.py +165 -0
- sdkrouter/tools/vision.py +173 -0
- sdkrouter/utils/__init__.py +27 -0
- sdkrouter/utils/parsing.py +109 -0
- sdkrouter/utils/tokens.py +375 -0
- sdkrouter-0.1.1.dist-info/METADATA +411 -0
- sdkrouter-0.1.1.dist-info/RECORD +96 -0
- sdkrouter-0.1.1.dist-info/WHEEL +4 -0
sdkrouter/__init__.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SDKRouter - Unified SDK for AI services with OpenAI compatibility.
|
|
3
|
+
|
|
4
|
+
Example:
|
|
5
|
+
```python
|
|
6
|
+
from sdkrouter import SDKRouter
|
|
7
|
+
|
|
8
|
+
# Initialize client
|
|
9
|
+
client = SDKRouter(api_key="your-api-key")
|
|
10
|
+
|
|
11
|
+
# OpenAI-compatible chat
|
|
12
|
+
response = client.chat.completions.create(
|
|
13
|
+
model="openai/gpt-4o",
|
|
14
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
15
|
+
)
|
|
16
|
+
print(response.choices[0].message.content)
|
|
17
|
+
|
|
18
|
+
# Vision analysis
|
|
19
|
+
result = client.vision.analyze(image_url="https://example.com/image.jpg")
|
|
20
|
+
print(result.description)
|
|
21
|
+
|
|
22
|
+
# CDN upload
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
file = client.cdn.upload(Path("image.png"), ttl="7d")
|
|
25
|
+
print(file.url)
|
|
26
|
+
```
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from ._version import __version__
|
|
30
|
+
from ._client import SDKRouter, AsyncSDKRouter
|
|
31
|
+
from ._config import SDKConfig, get_config, configure, reset_config
|
|
32
|
+
|
|
33
|
+
# API Client utilities
|
|
34
|
+
from ._api import HTTPClientFactory, BaseResource, AsyncBaseResource
|
|
35
|
+
|
|
36
|
+
# Types
|
|
37
|
+
from ._types.vision import VisionAnalyzeRequest, VisionAnalyzeResponse
|
|
38
|
+
from ._types.ocr import OCRRequest, OCRResponse
|
|
39
|
+
from ._types.cdn import CDNFile, CDNUploadRequest
|
|
40
|
+
from ._types.shortlinks import ShortLink, ShortLinkCreateRequest
|
|
41
|
+
from ._types.models import Model, ModelPricing
|
|
42
|
+
from ._types.parsed import ParsedChatCompletion, ParsedChoice, ParsedMessage
|
|
43
|
+
|
|
44
|
+
# Helpers (from archive)
|
|
45
|
+
from .helpers import json_to_toon, JsonCleaner, html_to_text, extract_links, extract_images
|
|
46
|
+
|
|
47
|
+
# Utilities
|
|
48
|
+
from .utils import (
|
|
49
|
+
TokenCounter,
|
|
50
|
+
count_tokens,
|
|
51
|
+
count_messages_tokens,
|
|
52
|
+
estimate_image_tokens,
|
|
53
|
+
get_optimal_detail_mode,
|
|
54
|
+
# Parsing utilities
|
|
55
|
+
ResponseFormatT,
|
|
56
|
+
to_strict_json_schema,
|
|
57
|
+
type_to_response_format,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
# Version
|
|
62
|
+
"__version__",
|
|
63
|
+
# Clients
|
|
64
|
+
"SDKRouter",
|
|
65
|
+
"AsyncSDKRouter",
|
|
66
|
+
# Configuration
|
|
67
|
+
"SDKConfig",
|
|
68
|
+
"get_config",
|
|
69
|
+
"configure",
|
|
70
|
+
"reset_config",
|
|
71
|
+
# API utilities
|
|
72
|
+
"HTTPClientFactory",
|
|
73
|
+
"BaseResource",
|
|
74
|
+
"AsyncBaseResource",
|
|
75
|
+
# Vision types
|
|
76
|
+
"VisionAnalyzeRequest",
|
|
77
|
+
"VisionAnalyzeResponse",
|
|
78
|
+
# OCR types
|
|
79
|
+
"OCRRequest",
|
|
80
|
+
"OCRResponse",
|
|
81
|
+
# CDN types
|
|
82
|
+
"CDNFile",
|
|
83
|
+
"CDNUploadRequest",
|
|
84
|
+
# Shortlinks types
|
|
85
|
+
"ShortLink",
|
|
86
|
+
"ShortLinkCreateRequest",
|
|
87
|
+
# Model types
|
|
88
|
+
"Model",
|
|
89
|
+
"ModelPricing",
|
|
90
|
+
# Parsed types (structured output)
|
|
91
|
+
"ParsedChatCompletion",
|
|
92
|
+
"ParsedChoice",
|
|
93
|
+
"ParsedMessage",
|
|
94
|
+
# Helpers
|
|
95
|
+
"json_to_toon",
|
|
96
|
+
"JsonCleaner",
|
|
97
|
+
"html_to_text",
|
|
98
|
+
"extract_links",
|
|
99
|
+
"extract_images",
|
|
100
|
+
# Token utilities
|
|
101
|
+
"TokenCounter",
|
|
102
|
+
"count_tokens",
|
|
103
|
+
"count_messages_tokens",
|
|
104
|
+
"estimate_image_tokens",
|
|
105
|
+
"get_optimal_detail_mode",
|
|
106
|
+
# Parsing utilities
|
|
107
|
+
"ResponseFormatT",
|
|
108
|
+
"to_strict_json_schema",
|
|
109
|
+
"type_to_response_format",
|
|
110
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SDKRouter API Client Utilities.
|
|
3
|
+
|
|
4
|
+
Provides base classes for building tool resources:
|
|
5
|
+
- HTTPClientFactory: Creates configured httpx clients
|
|
6
|
+
- BaseResource: Base class for sync tool resources
|
|
7
|
+
- AsyncBaseResource: Base class for async tool resources
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
>>> from sdkrouter._api import BaseResource, AsyncBaseResource
|
|
11
|
+
>>>
|
|
12
|
+
>>> class MyResource(BaseResource):
|
|
13
|
+
... def __init__(self, config):
|
|
14
|
+
... super().__init__(config)
|
|
15
|
+
... self._api = SyncMyAPI(self._http_client)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from .client import (
|
|
19
|
+
HTTPClientFactory,
|
|
20
|
+
BaseResource,
|
|
21
|
+
AsyncBaseResource,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"HTTPClientFactory",
|
|
26
|
+
"BaseResource",
|
|
27
|
+
"AsyncBaseResource",
|
|
28
|
+
]
|
sdkrouter/_api/client.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SDKRouter API Client Utilities.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- HTTPClientFactory: Creates configured httpx clients
|
|
6
|
+
- BaseResource: Base class for sync tool resources
|
|
7
|
+
- AsyncBaseResource: Base class for async tool resources
|
|
8
|
+
- Generated API clients (sync and async) for all tools
|
|
9
|
+
|
|
10
|
+
All tools inherit from base classes to ensure consistent
|
|
11
|
+
HTTP client configuration and authentication.
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
>>> from sdkrouter._api.client import BaseResource, SyncVisionVisionAPI
|
|
15
|
+
>>>
|
|
16
|
+
>>> class VisionResource(BaseResource):
|
|
17
|
+
... def __init__(self, config):
|
|
18
|
+
... super().__init__(config)
|
|
19
|
+
... self._api = SyncVisionVisionAPI(self._http_client)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from typing import TYPE_CHECKING
|
|
25
|
+
|
|
26
|
+
import httpx
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from .._config import SDKConfig
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# Generated API Clients (Async)
|
|
33
|
+
# ============================================================================
|
|
34
|
+
from .generated.vision.vision__api__vision import VisionVisionAPI
|
|
35
|
+
from .generated.cdn.cdn__api__cdn import CdnCdnAPI
|
|
36
|
+
from .generated.keys.keys__api__keys import KeysKeysAPI
|
|
37
|
+
from .generated.shortlinks.shortlinks__api__shortlinks import ShortlinksShortlinksAPI
|
|
38
|
+
from .generated.cleaner.cleaner__api__cleaner import CleanerCleanerAPI
|
|
39
|
+
from .generated.models.models__api__llm_models import ModelsLlmModelsAPI
|
|
40
|
+
|
|
41
|
+
# ============================================================================
|
|
42
|
+
# Generated API Clients (Sync)
|
|
43
|
+
# ============================================================================
|
|
44
|
+
from .generated.vision.vision__api__vision.sync_client import SyncVisionVisionAPI
|
|
45
|
+
from .generated.cdn.cdn__api__cdn.sync_client import SyncCdnCdnAPI
|
|
46
|
+
from .generated.keys.keys__api__keys.sync_client import SyncKeysKeysAPI
|
|
47
|
+
from .generated.shortlinks.shortlinks__api__shortlinks.sync_client import SyncShortlinksShortlinksAPI
|
|
48
|
+
from .generated.cleaner.cleaner__api__cleaner.sync_client import SyncCleanerCleanerAPI
|
|
49
|
+
from .generated.models.models__api__llm_models.sync_client import SyncModelsLlmModelsAPI
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class HTTPClientFactory:
|
|
53
|
+
"""
|
|
54
|
+
Factory for creating configured httpx clients.
|
|
55
|
+
|
|
56
|
+
Creates sync/async HTTP clients with:
|
|
57
|
+
- Base URL from config
|
|
58
|
+
- Bearer token authentication
|
|
59
|
+
- Configured timeout
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
>>> factory = HTTPClientFactory(sdk_config)
|
|
63
|
+
>>> sync_client = factory.create_sync_client()
|
|
64
|
+
>>> async_client = factory.create_async_client()
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(self, config: "SDKConfig"):
|
|
68
|
+
"""
|
|
69
|
+
Initialize factory with SDK configuration.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
config: SDKConfig with base_url, api_key, timeout
|
|
73
|
+
"""
|
|
74
|
+
self._config = config
|
|
75
|
+
|
|
76
|
+
def _get_headers(self) -> dict[str, str]:
|
|
77
|
+
"""Build request headers with auth token."""
|
|
78
|
+
return {"Authorization": f"Bearer {self._config.api_key}"}
|
|
79
|
+
|
|
80
|
+
def create_sync_client(self) -> httpx.Client:
|
|
81
|
+
"""
|
|
82
|
+
Create a synchronous HTTP client.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Configured httpx.Client with base_url, auth headers, timeout
|
|
86
|
+
"""
|
|
87
|
+
return httpx.Client(
|
|
88
|
+
base_url=self._config.base_url,
|
|
89
|
+
headers=self._get_headers(),
|
|
90
|
+
timeout=self._config.timeout,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def create_async_client(self) -> httpx.AsyncClient:
|
|
94
|
+
"""
|
|
95
|
+
Create an asynchronous HTTP client.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Configured httpx.AsyncClient with base_url, auth headers, timeout
|
|
99
|
+
"""
|
|
100
|
+
return httpx.AsyncClient(
|
|
101
|
+
base_url=self._config.base_url,
|
|
102
|
+
headers=self._get_headers(),
|
|
103
|
+
timeout=self._config.timeout,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class BaseResource:
|
|
108
|
+
"""
|
|
109
|
+
Base class for synchronous tool resources.
|
|
110
|
+
|
|
111
|
+
Provides:
|
|
112
|
+
- HTTP client creation via HTTPClientFactory
|
|
113
|
+
- Access to SDK config
|
|
114
|
+
- Common http_client property
|
|
115
|
+
|
|
116
|
+
Subclasses should initialize their generated API client in __init__:
|
|
117
|
+
|
|
118
|
+
class VisionResource(BaseResource):
|
|
119
|
+
def __init__(self, config: SDKConfig):
|
|
120
|
+
super().__init__(config)
|
|
121
|
+
self._api = SyncVisionVisionAPI(self._http_client)
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
def __init__(self, config: "SDKConfig"):
|
|
125
|
+
"""
|
|
126
|
+
Initialize resource with SDK configuration.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
config: SDKConfig with base_url, api_key, timeout
|
|
130
|
+
"""
|
|
131
|
+
self._config = config
|
|
132
|
+
self._factory = HTTPClientFactory(config)
|
|
133
|
+
self._http_client = self._factory.create_sync_client()
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def http_client(self) -> httpx.Client:
|
|
137
|
+
"""Access the underlying HTTP client for direct requests."""
|
|
138
|
+
return self._http_client
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def config(self) -> "SDKConfig":
|
|
142
|
+
"""Access the SDK configuration."""
|
|
143
|
+
return self._config
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class AsyncBaseResource:
|
|
147
|
+
"""
|
|
148
|
+
Base class for asynchronous tool resources.
|
|
149
|
+
|
|
150
|
+
Provides:
|
|
151
|
+
- HTTP client creation via HTTPClientFactory
|
|
152
|
+
- Access to SDK config
|
|
153
|
+
- Common http_client property
|
|
154
|
+
|
|
155
|
+
Subclasses should initialize their generated API client in __init__:
|
|
156
|
+
|
|
157
|
+
class AsyncVisionResource(AsyncBaseResource):
|
|
158
|
+
def __init__(self, config: SDKConfig):
|
|
159
|
+
super().__init__(config)
|
|
160
|
+
self._api = VisionVisionAPI(self._http_client)
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
def __init__(self, config: "SDKConfig"):
|
|
164
|
+
"""
|
|
165
|
+
Initialize resource with SDK configuration.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
config: SDKConfig with base_url, api_key, timeout
|
|
169
|
+
"""
|
|
170
|
+
self._config = config
|
|
171
|
+
self._factory = HTTPClientFactory(config)
|
|
172
|
+
self._http_client = self._factory.create_async_client()
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def http_client(self) -> httpx.AsyncClient:
|
|
176
|
+
"""Access the underlying HTTP client for direct requests."""
|
|
177
|
+
return self._http_client
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def config(self) -> "SDKConfig":
|
|
181
|
+
"""Access the SDK configuration."""
|
|
182
|
+
return self._config
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
__all__ = [
|
|
186
|
+
# Base classes
|
|
187
|
+
"HTTPClientFactory",
|
|
188
|
+
"BaseResource",
|
|
189
|
+
"AsyncBaseResource",
|
|
190
|
+
# Async clients
|
|
191
|
+
"VisionVisionAPI",
|
|
192
|
+
"CdnCdnAPI",
|
|
193
|
+
"KeysKeysAPI",
|
|
194
|
+
"ShortlinksShortlinksAPI",
|
|
195
|
+
"CleanerCleanerAPI",
|
|
196
|
+
"ModelsLlmModelsAPI",
|
|
197
|
+
# Sync clients
|
|
198
|
+
"SyncVisionVisionAPI",
|
|
199
|
+
"SyncCdnCdnAPI",
|
|
200
|
+
"SyncKeysKeysAPI",
|
|
201
|
+
"SyncShortlinksShortlinksAPI",
|
|
202
|
+
"SyncCleanerCleanerAPI",
|
|
203
|
+
"SyncModelsLlmModelsAPI",
|
|
204
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auto-generated OpenAPI clients for SDK.
|
|
3
|
+
|
|
4
|
+
DO NOT EDIT - Generated by: python manage.py generate_api_sdk
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from . import vision
|
|
8
|
+
from . import models
|
|
9
|
+
from . import cdn
|
|
10
|
+
from . import shortlinks
|
|
11
|
+
from . import keys
|
|
12
|
+
from . import cleaner
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"vision",
|
|
16
|
+
"models",
|
|
17
|
+
"cdn",
|
|
18
|
+
"shortlinks",
|
|
19
|
+
"keys",
|
|
20
|
+
"cleaner",
|
|
21
|
+
]
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Auto-generated by DjangoCFG - see CLAUDE.md
|
|
2
|
+
"""
|
|
3
|
+
SDKRouter API - API Client with JWT Management
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
>>> from api import API
|
|
7
|
+
>>>
|
|
8
|
+
>>> api = API('https://api.example.com')
|
|
9
|
+
>>>
|
|
10
|
+
>>> # Set JWT token
|
|
11
|
+
>>> api.set_token('your-jwt-token', 'refresh-token')
|
|
12
|
+
>>>
|
|
13
|
+
>>> # Use API
|
|
14
|
+
>>> async with api:
|
|
15
|
+
... posts = await api.posts.list()
|
|
16
|
+
... user = await api.users.retrieve(1)
|
|
17
|
+
>>>
|
|
18
|
+
>>> # Check authentication
|
|
19
|
+
>>> if api.is_authenticated():
|
|
20
|
+
... # ...
|
|
21
|
+
>>>
|
|
22
|
+
>>> # Get OpenAPI schema path
|
|
23
|
+
>>> schema_path = api.get_schema_path()
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import threading
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
import httpx
|
|
32
|
+
|
|
33
|
+
from .client import APIClient
|
|
34
|
+
from .logger import LoggerConfig
|
|
35
|
+
from .retry import RetryConfig
|
|
36
|
+
from .cdn__api__cdn import CdnCdnAPI
|
|
37
|
+
|
|
38
|
+
TOKEN_KEY = "auth_token"
|
|
39
|
+
REFRESH_TOKEN_KEY = "refresh_token"
|
|
40
|
+
|
|
41
|
+
# Auto-generated by DjangoCFG - see CLAUDE.md
|
|
42
|
+
class API:
|
|
43
|
+
"""
|
|
44
|
+
API Client wrapper with JWT token management.
|
|
45
|
+
|
|
46
|
+
This class provides:
|
|
47
|
+
- Thread-safe JWT token storage
|
|
48
|
+
- Automatic Authorization header injection
|
|
49
|
+
- Context manager support for async operations
|
|
50
|
+
- Optional retry and logging configuration
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
>>> api = API('https://api.example.com')
|
|
54
|
+
>>> api.set_token('jwt-token')
|
|
55
|
+
>>> async with api:
|
|
56
|
+
... users = await api.users.list()
|
|
57
|
+
>>>
|
|
58
|
+
>>> # With retry and logging
|
|
59
|
+
>>> api = API(
|
|
60
|
+
... 'https://api.example.com',
|
|
61
|
+
... retry_config=RetryConfig(max_attempts=5),
|
|
62
|
+
... logger_config=LoggerConfig(enabled=True)
|
|
63
|
+
... )
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
base_url: str,
|
|
69
|
+
logger_config: LoggerConfig | None = None,
|
|
70
|
+
retry_config: RetryConfig | None = None,
|
|
71
|
+
**kwargs: Any
|
|
72
|
+
):
|
|
73
|
+
"""
|
|
74
|
+
Initialize API client.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
base_url: Base API URL (e.g., 'https://api.example.com')
|
|
78
|
+
logger_config: Logger configuration (None to disable logging)
|
|
79
|
+
retry_config: Retry configuration (None to disable retry)
|
|
80
|
+
**kwargs: Additional httpx.AsyncClient kwargs
|
|
81
|
+
"""
|
|
82
|
+
self.base_url = base_url.rstrip('/')
|
|
83
|
+
self._kwargs = kwargs
|
|
84
|
+
self._logger_config = logger_config
|
|
85
|
+
self._retry_config = retry_config
|
|
86
|
+
self._token: str | None = None
|
|
87
|
+
self._refresh_token: str | None = None
|
|
88
|
+
self._lock = threading.Lock()
|
|
89
|
+
self._client: APIClient | None = None
|
|
90
|
+
self._init_clients()
|
|
91
|
+
|
|
92
|
+
def _init_clients(self) -> None:
|
|
93
|
+
"""Initialize API client with current token."""
|
|
94
|
+
# Create httpx client with auth header if token exists
|
|
95
|
+
headers = {}
|
|
96
|
+
if self._token:
|
|
97
|
+
headers['Authorization'] = f'Bearer {self._token}'
|
|
98
|
+
|
|
99
|
+
kwargs = {**self._kwargs}
|
|
100
|
+
if headers:
|
|
101
|
+
kwargs['headers'] = headers
|
|
102
|
+
|
|
103
|
+
# Create new APIClient
|
|
104
|
+
self._client = APIClient(
|
|
105
|
+
self.base_url,
|
|
106
|
+
logger_config=self._logger_config,
|
|
107
|
+
retry_config=self._retry_config,
|
|
108
|
+
**kwargs
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def cdn_cdn(self) -> CdnCdnAPI:
|
|
113
|
+
"""Access cdn endpoints."""
|
|
114
|
+
return self._client.cdn_cdn
|
|
115
|
+
|
|
116
|
+
def get_token(self) -> str | None:
|
|
117
|
+
"""Get current JWT token."""
|
|
118
|
+
with self._lock:
|
|
119
|
+
return self._token
|
|
120
|
+
|
|
121
|
+
def get_refresh_token(self) -> str | None:
|
|
122
|
+
"""Get current refresh token."""
|
|
123
|
+
with self._lock:
|
|
124
|
+
return self._refresh_token
|
|
125
|
+
|
|
126
|
+
def set_token(self, token: str, refresh_token: str | None = None) -> None:
|
|
127
|
+
"""
|
|
128
|
+
Set JWT token and refresh token.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
token: JWT access token
|
|
132
|
+
refresh_token: JWT refresh token (optional)
|
|
133
|
+
"""
|
|
134
|
+
with self._lock:
|
|
135
|
+
self._token = token
|
|
136
|
+
if refresh_token:
|
|
137
|
+
self._refresh_token = refresh_token
|
|
138
|
+
|
|
139
|
+
# Reinitialize clients with new token
|
|
140
|
+
self._init_clients()
|
|
141
|
+
|
|
142
|
+
def clear_tokens(self) -> None:
|
|
143
|
+
"""Clear all tokens."""
|
|
144
|
+
with self._lock:
|
|
145
|
+
self._token = None
|
|
146
|
+
self._refresh_token = None
|
|
147
|
+
|
|
148
|
+
# Reinitialize clients without token
|
|
149
|
+
self._init_clients()
|
|
150
|
+
|
|
151
|
+
def is_authenticated(self) -> bool:
|
|
152
|
+
"""Check if user is authenticated."""
|
|
153
|
+
return self.get_token() is not None
|
|
154
|
+
|
|
155
|
+
def set_base_url(self, url: str) -> None:
|
|
156
|
+
"""
|
|
157
|
+
Update base URL and reinitialize clients.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
url: New base URL
|
|
161
|
+
"""
|
|
162
|
+
self.base_url = url.rstrip('/')
|
|
163
|
+
self._init_clients()
|
|
164
|
+
|
|
165
|
+
def get_base_url(self) -> str:
|
|
166
|
+
"""Get current base URL."""
|
|
167
|
+
return self.base_url
|
|
168
|
+
|
|
169
|
+
def get_schema_path(self) -> str:
|
|
170
|
+
"""
|
|
171
|
+
Get OpenAPI schema path.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Path to the OpenAPI schema JSON file
|
|
175
|
+
|
|
176
|
+
Note:
|
|
177
|
+
The OpenAPI schema is available in the schema.json file.
|
|
178
|
+
You can load it dynamically using:
|
|
179
|
+
```python
|
|
180
|
+
import json
|
|
181
|
+
from pathlib import Path
|
|
182
|
+
|
|
183
|
+
schema_path = Path(__file__).parent / 'schema.json'
|
|
184
|
+
with open(schema_path) as f:
|
|
185
|
+
schema = json.load(f)
|
|
186
|
+
```
|
|
187
|
+
"""
|
|
188
|
+
return './schema.json'
|
|
189
|
+
|
|
190
|
+
async def __aenter__(self) -> 'API':
|
|
191
|
+
"""Async context manager entry."""
|
|
192
|
+
if self._client:
|
|
193
|
+
await self._client.__aenter__()
|
|
194
|
+
return self
|
|
195
|
+
|
|
196
|
+
async def __aexit__(self, *args: Any) -> None:
|
|
197
|
+
"""Async context manager exit."""
|
|
198
|
+
if self._client:
|
|
199
|
+
await self._client.__aexit__(*args)
|
|
200
|
+
|
|
201
|
+
async def close(self) -> None:
|
|
202
|
+
"""Close HTTP client."""
|
|
203
|
+
if self._client:
|
|
204
|
+
await self._client.close()
|
|
205
|
+
|
|
206
|
+
__all__ = [
|
|
207
|
+
"API",
|
|
208
|
+
"APIClient",
|
|
209
|
+
]
|