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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from .models import *
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CdnCdnAPI:
|
|
9
|
+
"""API endpoints for Cdn."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, client: httpx.AsyncClient):
|
|
12
|
+
"""Initialize sub-client with shared httpx client."""
|
|
13
|
+
self._client = client
|
|
14
|
+
|
|
15
|
+
async def list(self, page: int | None = None, page_size: int | None = None) -> list[PaginatedCDNFileListList]:
|
|
16
|
+
"""
|
|
17
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
18
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
19
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
20
|
+
/api/cdn/stats/ - Get storage statistics
|
|
21
|
+
"""
|
|
22
|
+
url = "/api/cdn/"
|
|
23
|
+
response = await self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None})
|
|
24
|
+
if not response.is_success:
|
|
25
|
+
try:
|
|
26
|
+
error_body = response.json()
|
|
27
|
+
except Exception:
|
|
28
|
+
error_body = response.text
|
|
29
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
30
|
+
return PaginatedCDNFileListList.model_validate(response.json())
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def create(self, data: CDNFileUploadRequest) -> CDNFileUpload:
|
|
34
|
+
"""
|
|
35
|
+
Upload a new file or download from URL.
|
|
36
|
+
"""
|
|
37
|
+
url = "/api/cdn/"
|
|
38
|
+
response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
39
|
+
if not response.is_success:
|
|
40
|
+
try:
|
|
41
|
+
error_body = response.json()
|
|
42
|
+
except Exception:
|
|
43
|
+
error_body = response.text
|
|
44
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
45
|
+
return CDNFileUpload.model_validate(response.json())
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def retrieve(self, uuid: str) -> CDNFileDetail:
|
|
49
|
+
"""
|
|
50
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
51
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
52
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
53
|
+
/api/cdn/stats/ - Get storage statistics
|
|
54
|
+
"""
|
|
55
|
+
url = f"/api/cdn/{uuid}/"
|
|
56
|
+
response = await self._client.get(url)
|
|
57
|
+
if not response.is_success:
|
|
58
|
+
try:
|
|
59
|
+
error_body = response.json()
|
|
60
|
+
except Exception:
|
|
61
|
+
error_body = response.text
|
|
62
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
63
|
+
return CDNFileDetail.model_validate(response.json())
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
async def update(self, uuid: str) -> CDNFileList:
|
|
67
|
+
"""
|
|
68
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
69
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
70
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
71
|
+
/api/cdn/stats/ - Get storage statistics
|
|
72
|
+
"""
|
|
73
|
+
url = f"/api/cdn/{uuid}/"
|
|
74
|
+
response = await self._client.put(url)
|
|
75
|
+
if not response.is_success:
|
|
76
|
+
try:
|
|
77
|
+
error_body = response.json()
|
|
78
|
+
except Exception:
|
|
79
|
+
error_body = response.text
|
|
80
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
81
|
+
return CDNFileList.model_validate(response.json())
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
async def partial_update(self, uuid: str) -> CDNFileList:
|
|
85
|
+
"""
|
|
86
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
87
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
88
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
89
|
+
/api/cdn/stats/ - Get storage statistics
|
|
90
|
+
"""
|
|
91
|
+
url = f"/api/cdn/{uuid}/"
|
|
92
|
+
response = await self._client.patch(url)
|
|
93
|
+
if not response.is_success:
|
|
94
|
+
try:
|
|
95
|
+
error_body = response.json()
|
|
96
|
+
except Exception:
|
|
97
|
+
error_body = response.text
|
|
98
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
99
|
+
return CDNFileList.model_validate(response.json())
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
async def destroy(self, uuid: str) -> None:
|
|
103
|
+
"""
|
|
104
|
+
Delete a file.
|
|
105
|
+
"""
|
|
106
|
+
url = f"/api/cdn/{uuid}/"
|
|
107
|
+
response = await self._client.delete(url)
|
|
108
|
+
if not response.is_success:
|
|
109
|
+
try:
|
|
110
|
+
error_body = response.json()
|
|
111
|
+
except Exception:
|
|
112
|
+
error_body = response.text
|
|
113
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
async def stats_retrieve(self) -> CDNStats:
|
|
118
|
+
"""
|
|
119
|
+
Get storage statistics
|
|
120
|
+
|
|
121
|
+
Get CDN storage statistics for the current user.
|
|
122
|
+
"""
|
|
123
|
+
url = "/api/cdn/stats/"
|
|
124
|
+
response = await self._client.get(url)
|
|
125
|
+
if not response.is_success:
|
|
126
|
+
try:
|
|
127
|
+
error_body = response.json()
|
|
128
|
+
except Exception:
|
|
129
|
+
error_body = response.text
|
|
130
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
131
|
+
return CDNStats.model_validate(response.json())
|
|
132
|
+
|
|
133
|
+
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Auto-generated by DjangoCFG - see CLAUDE.md
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CDNFileList(BaseModel):
|
|
11
|
+
"""
|
|
12
|
+
Serializer for listing CDN files.
|
|
13
|
+
|
|
14
|
+
Response model (includes read-only fields).
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
model_config = ConfigDict(
|
|
18
|
+
validate_assignment=True,
|
|
19
|
+
extra="allow",
|
|
20
|
+
frozen=False,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
id: Any = ...
|
|
24
|
+
uuid: Any = Field(description='Unique file identifier for URLs')
|
|
25
|
+
short_code: Any = Field(description='Short code for URLs')
|
|
26
|
+
filename: Any = Field(description='Original filename')
|
|
27
|
+
content_type: Any = Field(description='MIME type of the file')
|
|
28
|
+
size_bytes: int = Field(description='File size in bytes')
|
|
29
|
+
is_public: bool = Field(description='Whether file is publicly accessible')
|
|
30
|
+
is_expired: bool = ...
|
|
31
|
+
is_image: bool = ...
|
|
32
|
+
access_count: int = Field(description='Number of times the file was accessed')
|
|
33
|
+
expires_at: Any | None = Field(None, description='When the file expires (null = never)')
|
|
34
|
+
url: Any = ...
|
|
35
|
+
short_url: Any = ...
|
|
36
|
+
created_at: Any = ...
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class PaginatedCDNFileListList(BaseModel):
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
Response model (includes read-only fields).
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
model_config = ConfigDict(
|
|
47
|
+
validate_assignment=True,
|
|
48
|
+
extra="allow",
|
|
49
|
+
frozen=False,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
count: int = Field(description='Total number of items across all pages')
|
|
53
|
+
page: int = Field(description='Current page number (1-based)')
|
|
54
|
+
pages: int = Field(description='Total number of pages')
|
|
55
|
+
page_size: int = Field(description='Number of items per page')
|
|
56
|
+
has_next: bool = Field(description='Whether there is a next page')
|
|
57
|
+
has_previous: bool = Field(description='Whether there is a previous page')
|
|
58
|
+
next_page: int | None = Field(None, description='Next page number (null if no next page)')
|
|
59
|
+
previous_page: int | None = Field(None, description='Previous page number (null if no previous page)')
|
|
60
|
+
results: list[CDNFileList] = Field(description='Array of items for current page')
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class CDNFileUploadRequest(BaseModel):
|
|
65
|
+
"""
|
|
66
|
+
Serializer for file upload request. Supports two modes: - file: Direct file
|
|
67
|
+
upload - url: Server downloads from URL
|
|
68
|
+
|
|
69
|
+
Request model (no read-only fields).
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
model_config = ConfigDict(
|
|
73
|
+
validate_assignment=True,
|
|
74
|
+
extra="allow",
|
|
75
|
+
frozen=False,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
file: str | None = None
|
|
79
|
+
url: str | None = Field(None, description='URL to download file from (alternative to file upload)', min_length=1)
|
|
80
|
+
filename: str | None = Field(None, description='Filename (optional, extracted from URL if not provided)', min_length=1)
|
|
81
|
+
ttl: str | None = Field(None, description='TTL (e.g., 30d, 7d, 24h, 0=forever)', min_length=1)
|
|
82
|
+
is_public: bool | None = None
|
|
83
|
+
metadata: dict[str, Any] | None = None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class CDNFileUpload(BaseModel):
|
|
88
|
+
"""
|
|
89
|
+
Serializer for file upload request. Supports two modes: - file: Direct file
|
|
90
|
+
upload - url: Server downloads from URL
|
|
91
|
+
|
|
92
|
+
Response model (includes read-only fields).
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
model_config = ConfigDict(
|
|
96
|
+
validate_assignment=True,
|
|
97
|
+
extra="allow",
|
|
98
|
+
frozen=False,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
file: str | None = None
|
|
102
|
+
url: str | None = Field(None, description='URL to download file from (alternative to file upload)')
|
|
103
|
+
filename: str | None = Field(None, description='Filename (optional, extracted from URL if not provided)')
|
|
104
|
+
ttl: str | None = Field(None, description='TTL (e.g., 30d, 7d, 24h, 0=forever)')
|
|
105
|
+
is_public: bool | None = None
|
|
106
|
+
metadata: dict[str, Any] | None = None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class CDNFileDetail(BaseModel):
|
|
111
|
+
"""
|
|
112
|
+
Serializer for CDN file details.
|
|
113
|
+
|
|
114
|
+
Response model (includes read-only fields).
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
model_config = ConfigDict(
|
|
118
|
+
validate_assignment=True,
|
|
119
|
+
extra="allow",
|
|
120
|
+
frozen=False,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
id: Any = ...
|
|
124
|
+
uuid: Any = Field(description='Unique file identifier for URLs')
|
|
125
|
+
short_code: Any = Field(description='Short code for URLs')
|
|
126
|
+
filename: Any = Field(description='Original filename')
|
|
127
|
+
content_type: Any = Field(description='MIME type of the file')
|
|
128
|
+
size_bytes: int = Field(description='File size in bytes')
|
|
129
|
+
is_public: bool = Field(description='Whether file is publicly accessible')
|
|
130
|
+
is_expired: bool = ...
|
|
131
|
+
is_image: bool = ...
|
|
132
|
+
access_count: int = Field(description='Number of times the file was accessed')
|
|
133
|
+
expires_at: Any | None = Field(None, description='When the file expires (null = never)')
|
|
134
|
+
url: Any = ...
|
|
135
|
+
short_url: Any = ...
|
|
136
|
+
created_at: Any = ...
|
|
137
|
+
checksum_sha256: str = Field(description='SHA256 checksum for deduplication', max_length=64)
|
|
138
|
+
storage_backend: str | None = Field(None, description='Storage backend (local, s3, etc.)', max_length=50)
|
|
139
|
+
last_accessed_at: str | None = Field(None, description='Last time the file was accessed')
|
|
140
|
+
metadata: dict[str, Any] | None = Field(None, description='Additional file metadata')
|
|
141
|
+
updated_at: Any = ...
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class CDNStats(BaseModel):
|
|
146
|
+
"""
|
|
147
|
+
Serializer for CDN storage statistics.
|
|
148
|
+
|
|
149
|
+
Response model (includes read-only fields).
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
model_config = ConfigDict(
|
|
153
|
+
validate_assignment=True,
|
|
154
|
+
extra="allow",
|
|
155
|
+
frozen=False,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
total_files: int = Field(description='Total number of files')
|
|
159
|
+
total_size_bytes: int = Field(description='Total size in bytes')
|
|
160
|
+
total_access_count: int = Field(description='Total access count')
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from .models import *
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SyncCdnCdnAPI:
|
|
9
|
+
"""Synchronous API endpoints for Cdn."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, client: httpx.Client):
|
|
12
|
+
"""Initialize sync sub-client with shared httpx client."""
|
|
13
|
+
self._client = client
|
|
14
|
+
|
|
15
|
+
def list(self, page: int | None = None, page_size: int | None = None) -> list[PaginatedCDNFileListList]:
|
|
16
|
+
"""
|
|
17
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
18
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
19
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
20
|
+
/api/cdn/stats/ - Get storage statistics
|
|
21
|
+
"""
|
|
22
|
+
url = "/api/cdn/"
|
|
23
|
+
response = self._client.get(url, params={"page": page if page is not None else None, "page_size": page_size if page_size is not None else None})
|
|
24
|
+
if not response.is_success:
|
|
25
|
+
try:
|
|
26
|
+
error_body = response.json()
|
|
27
|
+
except Exception:
|
|
28
|
+
error_body = response.text
|
|
29
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
30
|
+
return PaginatedCDNFileListList.model_validate(response.json())
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create(self, data: CDNFileUploadRequest) -> CDNFileUpload:
|
|
34
|
+
"""
|
|
35
|
+
Upload a new file or download from URL.
|
|
36
|
+
"""
|
|
37
|
+
url = "/api/cdn/"
|
|
38
|
+
response = self._client.post(url, json=data.model_dump(exclude_unset=True))
|
|
39
|
+
if not response.is_success:
|
|
40
|
+
try:
|
|
41
|
+
error_body = response.json()
|
|
42
|
+
except Exception:
|
|
43
|
+
error_body = response.text
|
|
44
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
45
|
+
return CDNFileUpload.model_validate(response.json())
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def retrieve(self, uuid: str) -> CDNFileDetail:
|
|
49
|
+
"""
|
|
50
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
51
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
52
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
53
|
+
/api/cdn/stats/ - Get storage statistics
|
|
54
|
+
"""
|
|
55
|
+
url = f"/api/cdn/{uuid}/"
|
|
56
|
+
response = self._client.get(url)
|
|
57
|
+
if not response.is_success:
|
|
58
|
+
try:
|
|
59
|
+
error_body = response.json()
|
|
60
|
+
except Exception:
|
|
61
|
+
error_body = response.text
|
|
62
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
63
|
+
return CDNFileDetail.model_validate(response.json())
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def update(self, uuid: str) -> CDNFileList:
|
|
67
|
+
"""
|
|
68
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
69
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
70
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
71
|
+
/api/cdn/stats/ - Get storage statistics
|
|
72
|
+
"""
|
|
73
|
+
url = f"/api/cdn/{uuid}/"
|
|
74
|
+
response = self._client.put(url)
|
|
75
|
+
if not response.is_success:
|
|
76
|
+
try:
|
|
77
|
+
error_body = response.json()
|
|
78
|
+
except Exception:
|
|
79
|
+
error_body = response.text
|
|
80
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
81
|
+
return CDNFileList.model_validate(response.json())
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def partial_update(self, uuid: str) -> CDNFileList:
|
|
85
|
+
"""
|
|
86
|
+
ViewSet for CDN file management. Endpoints: - GET /api/cdn/ - List
|
|
87
|
+
user's files - POST /api/cdn/ - Upload a new file - GET /api/cdn/{uuid}/
|
|
88
|
+
- Get file details - DELETE /api/cdn/{uuid}/ - Delete file - GET
|
|
89
|
+
/api/cdn/stats/ - Get storage statistics
|
|
90
|
+
"""
|
|
91
|
+
url = f"/api/cdn/{uuid}/"
|
|
92
|
+
response = self._client.patch(url)
|
|
93
|
+
if not response.is_success:
|
|
94
|
+
try:
|
|
95
|
+
error_body = response.json()
|
|
96
|
+
except Exception:
|
|
97
|
+
error_body = response.text
|
|
98
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
99
|
+
return CDNFileList.model_validate(response.json())
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def destroy(self, uuid: str) -> None:
|
|
103
|
+
"""
|
|
104
|
+
Delete a file.
|
|
105
|
+
"""
|
|
106
|
+
url = f"/api/cdn/{uuid}/"
|
|
107
|
+
response = self._client.delete(url)
|
|
108
|
+
if not response.is_success:
|
|
109
|
+
try:
|
|
110
|
+
error_body = response.json()
|
|
111
|
+
except Exception:
|
|
112
|
+
error_body = response.text
|
|
113
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def stats_retrieve(self) -> CDNStats:
|
|
117
|
+
"""
|
|
118
|
+
Get storage statistics
|
|
119
|
+
|
|
120
|
+
Get CDN storage statistics for the current user.
|
|
121
|
+
"""
|
|
122
|
+
url = "/api/cdn/stats/"
|
|
123
|
+
response = self._client.get(url)
|
|
124
|
+
if not response.is_success:
|
|
125
|
+
try:
|
|
126
|
+
error_body = response.json()
|
|
127
|
+
except Exception:
|
|
128
|
+
error_body = response.text
|
|
129
|
+
raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
|
|
130
|
+
return CDNStats.model_validate(response.json())
|
|
131
|
+
|
|
132
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from .cdn__api__cdn import CdnCdnAPI
|
|
8
|
+
from .logger import APILogger, LoggerConfig
|
|
9
|
+
from .retry import RetryConfig, RetryAsyncClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class APIClient:
|
|
13
|
+
"""
|
|
14
|
+
Async API client for SDKRouter API.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
>>> async with APIClient(base_url='https://api.example.com') as client:
|
|
18
|
+
... users = await client.users.list()
|
|
19
|
+
... post = await client.posts.create(data=new_post)
|
|
20
|
+
>>>
|
|
21
|
+
>>> # With retry configuration
|
|
22
|
+
>>> retry_config = RetryConfig(max_attempts=5, min_wait=2.0)
|
|
23
|
+
>>> async with APIClient(base_url='https://api.example.com', retry_config=retry_config) as client:
|
|
24
|
+
... users = await client.users.list()
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
base_url: str,
|
|
30
|
+
logger_config: Optional[LoggerConfig] = None,
|
|
31
|
+
retry_config: Optional[RetryConfig] = None,
|
|
32
|
+
**kwargs: Any,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
Initialize API client.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
base_url: Base API URL (e.g., 'https://api.example.com')
|
|
39
|
+
logger_config: Logger configuration (None to disable logging)
|
|
40
|
+
retry_config: Retry configuration (None to disable retry)
|
|
41
|
+
**kwargs: Additional httpx.AsyncClient kwargs
|
|
42
|
+
"""
|
|
43
|
+
self.base_url = base_url.rstrip('/')
|
|
44
|
+
|
|
45
|
+
# Create HTTP client with or without retry
|
|
46
|
+
if retry_config is not None:
|
|
47
|
+
self._client = RetryAsyncClient(
|
|
48
|
+
base_url=self.base_url,
|
|
49
|
+
retry_config=retry_config,
|
|
50
|
+
**kwargs,
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
self._client = httpx.AsyncClient(
|
|
54
|
+
base_url=self.base_url,
|
|
55
|
+
**kwargs,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Initialize logger
|
|
59
|
+
self.logger: Optional[APILogger] = None
|
|
60
|
+
if logger_config is not None:
|
|
61
|
+
self.logger = APILogger(logger_config)
|
|
62
|
+
|
|
63
|
+
# Initialize sub-clients
|
|
64
|
+
self.cdn_cdn = CdnCdnAPI(self._client)
|
|
65
|
+
|
|
66
|
+
async def __aenter__(self) -> 'APIClient':
|
|
67
|
+
await self._client.__aenter__()
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
async def __aexit__(self, *args: Any) -> None:
|
|
71
|
+
await self._client.__aexit__(*args)
|
|
72
|
+
|
|
73
|
+
async def close(self) -> None:
|
|
74
|
+
"""Close HTTP client."""
|
|
75
|
+
await self._client.aclose()
|