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.
Files changed (96) hide show
  1. sdkrouter/__init__.py +110 -0
  2. sdkrouter/_api/__init__.py +28 -0
  3. sdkrouter/_api/client.py +204 -0
  4. sdkrouter/_api/generated/__init__.py +21 -0
  5. sdkrouter/_api/generated/cdn/__init__.py +209 -0
  6. sdkrouter/_api/generated/cdn/cdn__api__cdn/__init__.py +7 -0
  7. sdkrouter/_api/generated/cdn/cdn__api__cdn/client.py +133 -0
  8. sdkrouter/_api/generated/cdn/cdn__api__cdn/models.py +163 -0
  9. sdkrouter/_api/generated/cdn/cdn__api__cdn/sync_client.py +132 -0
  10. sdkrouter/_api/generated/cdn/client.py +75 -0
  11. sdkrouter/_api/generated/cdn/logger.py +256 -0
  12. sdkrouter/_api/generated/cdn/pyproject.toml +55 -0
  13. sdkrouter/_api/generated/cdn/retry.py +272 -0
  14. sdkrouter/_api/generated/cdn/sync_client.py +58 -0
  15. sdkrouter/_api/generated/cleaner/__init__.py +212 -0
  16. sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/__init__.py +7 -0
  17. sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/client.py +83 -0
  18. sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/models.py +117 -0
  19. sdkrouter/_api/generated/cleaner/cleaner__api__cleaner/sync_client.py +82 -0
  20. sdkrouter/_api/generated/cleaner/client.py +75 -0
  21. sdkrouter/_api/generated/cleaner/enums.py +55 -0
  22. sdkrouter/_api/generated/cleaner/logger.py +256 -0
  23. sdkrouter/_api/generated/cleaner/pyproject.toml +55 -0
  24. sdkrouter/_api/generated/cleaner/retry.py +272 -0
  25. sdkrouter/_api/generated/cleaner/sync_client.py +58 -0
  26. sdkrouter/_api/generated/keys/__init__.py +212 -0
  27. sdkrouter/_api/generated/keys/client.py +75 -0
  28. sdkrouter/_api/generated/keys/enums.py +64 -0
  29. sdkrouter/_api/generated/keys/keys__api__keys/__init__.py +7 -0
  30. sdkrouter/_api/generated/keys/keys__api__keys/client.py +150 -0
  31. sdkrouter/_api/generated/keys/keys__api__keys/models.py +152 -0
  32. sdkrouter/_api/generated/keys/keys__api__keys/sync_client.py +149 -0
  33. sdkrouter/_api/generated/keys/logger.py +256 -0
  34. sdkrouter/_api/generated/keys/pyproject.toml +55 -0
  35. sdkrouter/_api/generated/keys/retry.py +272 -0
  36. sdkrouter/_api/generated/keys/sync_client.py +58 -0
  37. sdkrouter/_api/generated/models/__init__.py +209 -0
  38. sdkrouter/_api/generated/models/client.py +75 -0
  39. sdkrouter/_api/generated/models/logger.py +256 -0
  40. sdkrouter/_api/generated/models/models__api__llm_models/__init__.py +7 -0
  41. sdkrouter/_api/generated/models/models__api__llm_models/client.py +99 -0
  42. sdkrouter/_api/generated/models/models__api__llm_models/models.py +206 -0
  43. sdkrouter/_api/generated/models/models__api__llm_models/sync_client.py +99 -0
  44. sdkrouter/_api/generated/models/pyproject.toml +55 -0
  45. sdkrouter/_api/generated/models/retry.py +272 -0
  46. sdkrouter/_api/generated/models/sync_client.py +58 -0
  47. sdkrouter/_api/generated/shortlinks/__init__.py +209 -0
  48. sdkrouter/_api/generated/shortlinks/client.py +75 -0
  49. sdkrouter/_api/generated/shortlinks/logger.py +256 -0
  50. sdkrouter/_api/generated/shortlinks/pyproject.toml +55 -0
  51. sdkrouter/_api/generated/shortlinks/retry.py +272 -0
  52. sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/__init__.py +7 -0
  53. sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/client.py +137 -0
  54. sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/models.py +153 -0
  55. sdkrouter/_api/generated/shortlinks/shortlinks__api__shortlinks/sync_client.py +136 -0
  56. sdkrouter/_api/generated/shortlinks/sync_client.py +58 -0
  57. sdkrouter/_api/generated/vision/__init__.py +212 -0
  58. sdkrouter/_api/generated/vision/client.py +75 -0
  59. sdkrouter/_api/generated/vision/enums.py +40 -0
  60. sdkrouter/_api/generated/vision/logger.py +256 -0
  61. sdkrouter/_api/generated/vision/pyproject.toml +55 -0
  62. sdkrouter/_api/generated/vision/retry.py +272 -0
  63. sdkrouter/_api/generated/vision/sync_client.py +58 -0
  64. sdkrouter/_api/generated/vision/vision__api__vision/__init__.py +7 -0
  65. sdkrouter/_api/generated/vision/vision__api__vision/client.py +65 -0
  66. sdkrouter/_api/generated/vision/vision__api__vision/models.py +138 -0
  67. sdkrouter/_api/generated/vision/vision__api__vision/sync_client.py +65 -0
  68. sdkrouter/_client.py +432 -0
  69. sdkrouter/_config.py +74 -0
  70. sdkrouter/_constants.py +21 -0
  71. sdkrouter/_internal/__init__.py +1 -0
  72. sdkrouter/_types/__init__.py +30 -0
  73. sdkrouter/_types/cdn.py +27 -0
  74. sdkrouter/_types/models.py +26 -0
  75. sdkrouter/_types/ocr.py +24 -0
  76. sdkrouter/_types/parsed.py +101 -0
  77. sdkrouter/_types/shortlinks.py +27 -0
  78. sdkrouter/_types/vision.py +29 -0
  79. sdkrouter/_version.py +3 -0
  80. sdkrouter/helpers/__init__.py +13 -0
  81. sdkrouter/helpers/formatting.py +15 -0
  82. sdkrouter/helpers/html.py +100 -0
  83. sdkrouter/helpers/json_cleaner.py +53 -0
  84. sdkrouter/tools/__init__.py +129 -0
  85. sdkrouter/tools/cdn.py +285 -0
  86. sdkrouter/tools/cleaner.py +186 -0
  87. sdkrouter/tools/keys.py +215 -0
  88. sdkrouter/tools/models.py +196 -0
  89. sdkrouter/tools/shortlinks.py +165 -0
  90. sdkrouter/tools/vision.py +173 -0
  91. sdkrouter/utils/__init__.py +27 -0
  92. sdkrouter/utils/parsing.py +109 -0
  93. sdkrouter/utils/tokens.py +375 -0
  94. sdkrouter-0.1.1.dist-info/METADATA +411 -0
  95. sdkrouter-0.1.1.dist-info/RECORD +96 -0
  96. sdkrouter-0.1.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,212 @@
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 .cleaner__api__cleaner import CleanerCleanerAPI
37
+ from . import enums
38
+ # NOTE: Individual enum imports commented out due to invalid Python syntax with dotted names
39
+ # from .enums import CleanRequestRequest.output_format, CleaningRequestDetail.status, CleaningRequestList.status
40
+
41
+ TOKEN_KEY = "auth_token"
42
+ REFRESH_TOKEN_KEY = "refresh_token"
43
+
44
+ # Auto-generated by DjangoCFG - see CLAUDE.md
45
+ class API:
46
+ """
47
+ API Client wrapper with JWT token management.
48
+
49
+ This class provides:
50
+ - Thread-safe JWT token storage
51
+ - Automatic Authorization header injection
52
+ - Context manager support for async operations
53
+ - Optional retry and logging configuration
54
+
55
+ Example:
56
+ >>> api = API('https://api.example.com')
57
+ >>> api.set_token('jwt-token')
58
+ >>> async with api:
59
+ ... users = await api.users.list()
60
+ >>>
61
+ >>> # With retry and logging
62
+ >>> api = API(
63
+ ... 'https://api.example.com',
64
+ ... retry_config=RetryConfig(max_attempts=5),
65
+ ... logger_config=LoggerConfig(enabled=True)
66
+ ... )
67
+ """
68
+
69
+ def __init__(
70
+ self,
71
+ base_url: str,
72
+ logger_config: LoggerConfig | None = None,
73
+ retry_config: RetryConfig | None = None,
74
+ **kwargs: Any
75
+ ):
76
+ """
77
+ Initialize API client.
78
+
79
+ Args:
80
+ base_url: Base API URL (e.g., 'https://api.example.com')
81
+ logger_config: Logger configuration (None to disable logging)
82
+ retry_config: Retry configuration (None to disable retry)
83
+ **kwargs: Additional httpx.AsyncClient kwargs
84
+ """
85
+ self.base_url = base_url.rstrip('/')
86
+ self._kwargs = kwargs
87
+ self._logger_config = logger_config
88
+ self._retry_config = retry_config
89
+ self._token: str | None = None
90
+ self._refresh_token: str | None = None
91
+ self._lock = threading.Lock()
92
+ self._client: APIClient | None = None
93
+ self._init_clients()
94
+
95
+ def _init_clients(self) -> None:
96
+ """Initialize API client with current token."""
97
+ # Create httpx client with auth header if token exists
98
+ headers = {}
99
+ if self._token:
100
+ headers['Authorization'] = f'Bearer {self._token}'
101
+
102
+ kwargs = {**self._kwargs}
103
+ if headers:
104
+ kwargs['headers'] = headers
105
+
106
+ # Create new APIClient
107
+ self._client = APIClient(
108
+ self.base_url,
109
+ logger_config=self._logger_config,
110
+ retry_config=self._retry_config,
111
+ **kwargs
112
+ )
113
+
114
+ @property
115
+ def cleaner_cleaner(self) -> CleanerCleanerAPI:
116
+ """Access cleaner endpoints."""
117
+ return self._client.cleaner_cleaner
118
+
119
+ def get_token(self) -> str | None:
120
+ """Get current JWT token."""
121
+ with self._lock:
122
+ return self._token
123
+
124
+ def get_refresh_token(self) -> str | None:
125
+ """Get current refresh token."""
126
+ with self._lock:
127
+ return self._refresh_token
128
+
129
+ def set_token(self, token: str, refresh_token: str | None = None) -> None:
130
+ """
131
+ Set JWT token and refresh token.
132
+
133
+ Args:
134
+ token: JWT access token
135
+ refresh_token: JWT refresh token (optional)
136
+ """
137
+ with self._lock:
138
+ self._token = token
139
+ if refresh_token:
140
+ self._refresh_token = refresh_token
141
+
142
+ # Reinitialize clients with new token
143
+ self._init_clients()
144
+
145
+ def clear_tokens(self) -> None:
146
+ """Clear all tokens."""
147
+ with self._lock:
148
+ self._token = None
149
+ self._refresh_token = None
150
+
151
+ # Reinitialize clients without token
152
+ self._init_clients()
153
+
154
+ def is_authenticated(self) -> bool:
155
+ """Check if user is authenticated."""
156
+ return self.get_token() is not None
157
+
158
+ def set_base_url(self, url: str) -> None:
159
+ """
160
+ Update base URL and reinitialize clients.
161
+
162
+ Args:
163
+ url: New base URL
164
+ """
165
+ self.base_url = url.rstrip('/')
166
+ self._init_clients()
167
+
168
+ def get_base_url(self) -> str:
169
+ """Get current base URL."""
170
+ return self.base_url
171
+
172
+ def get_schema_path(self) -> str:
173
+ """
174
+ Get OpenAPI schema path.
175
+
176
+ Returns:
177
+ Path to the OpenAPI schema JSON file
178
+
179
+ Note:
180
+ The OpenAPI schema is available in the schema.json file.
181
+ You can load it dynamically using:
182
+ ```python
183
+ import json
184
+ from pathlib import Path
185
+
186
+ schema_path = Path(__file__).parent / 'schema.json'
187
+ with open(schema_path) as f:
188
+ schema = json.load(f)
189
+ ```
190
+ """
191
+ return './schema.json'
192
+
193
+ async def __aenter__(self) -> 'API':
194
+ """Async context manager entry."""
195
+ if self._client:
196
+ await self._client.__aenter__()
197
+ return self
198
+
199
+ async def __aexit__(self, *args: Any) -> None:
200
+ """Async context manager exit."""
201
+ if self._client:
202
+ await self._client.__aexit__(*args)
203
+
204
+ async def close(self) -> None:
205
+ """Close HTTP client."""
206
+ if self._client:
207
+ await self._client.close()
208
+
209
+ __all__ = [
210
+ "API",
211
+ "APIClient",
212
+ ]
@@ -0,0 +1,7 @@
1
+ # Auto-generated by DjangoCFG - see CLAUDE.md
2
+ from .client import CleanerCleanerAPI
3
+ from .models import *
4
+
5
+ __all__ = [
6
+ "CleanerCleanerAPI",
7
+ ]
@@ -0,0 +1,83 @@
1
+ from __future__ import annotations
2
+
3
+ import httpx
4
+
5
+ from .models import *
6
+
7
+
8
+ class CleanerCleanerAPI:
9
+ """API endpoints for Cleaner."""
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) -> None:
16
+ """
17
+ List cleaning requests
18
+
19
+ List user's cleaning requests.
20
+ """
21
+ url = "/api/cleaner/"
22
+ response = await self._client.get(url)
23
+ if not response.is_success:
24
+ try:
25
+ error_body = response.json()
26
+ except Exception:
27
+ error_body = response.text
28
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
29
+ return None
30
+
31
+
32
+ async def retrieve(self, id: str) -> CleaningRequestDetail:
33
+ """
34
+ Get cleaning request details
35
+
36
+ Get cleaning request details.
37
+ """
38
+ url = f"/api/cleaner/{id}/"
39
+ response = await self._client.get(url)
40
+ if not response.is_success:
41
+ try:
42
+ error_body = response.json()
43
+ except Exception:
44
+ error_body = response.text
45
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
46
+ return CleaningRequestDetail.model_validate(response.json())
47
+
48
+
49
+ async def clean_create(self, data: CleanRequestRequest) -> CleanResponse:
50
+ """
51
+ Clean HTML file
52
+
53
+ Clean HTML file. Accepts multipart/form-data with HTML file. Returns
54
+ cleaned HTML with statistics.
55
+ """
56
+ url = "/api/cleaner/clean/"
57
+ response = await self._client.post(url, json=data.model_dump(exclude_unset=True))
58
+ if not response.is_success:
59
+ try:
60
+ error_body = response.json()
61
+ except Exception:
62
+ error_body = response.text
63
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
64
+ return CleanResponse.model_validate(response.json())
65
+
66
+
67
+ async def stats_retrieve(self) -> CleaningStats:
68
+ """
69
+ Get cleaning statistics
70
+
71
+ Get cleaning statistics.
72
+ """
73
+ url = "/api/cleaner/stats/"
74
+ response = await self._client.get(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 CleaningStats.model_validate(response.json())
82
+
83
+
@@ -0,0 +1,117 @@
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
+ from ..enums import CleanRequestRequestOutputFormat, CleaningRequestDetailStatus
10
+
11
+
12
+ class CleaningRequestDetail(BaseModel):
13
+ """
14
+ Detail serializer for cleaning request.
15
+
16
+ Response model (includes read-only fields).
17
+ """
18
+
19
+ model_config = ConfigDict(
20
+ validate_assignment=True,
21
+ extra="allow",
22
+ frozen=False,
23
+ )
24
+
25
+ uuid: Any = Field(description='Unique request identifier')
26
+ original_filename: Any = Field(description='Original filename')
27
+ original_size_bytes: int = Field(description='Original HTML size in bytes')
28
+ cleaned_html: Any = Field(description='Cleaned HTML content')
29
+ cleaned_size_bytes: int = Field(description='Cleaned HTML size in bytes')
30
+ output_format: Any = Field(description='Output format: html, markdown, aom, xtree')
31
+ config: dict[str, Any] = Field(description='CleanerConfig used for this request')
32
+ stats: dict[str, Any] = Field(description='Cleaning statistics (elements removed, etc.)')
33
+ status: CleaningRequestDetailStatus = Field(description='* `pending` - Pending\n* `processing` - Processing\n* `success` - Success\n* `error` - Error')
34
+ error_message: Any = Field(description='Error message if request failed')
35
+ duration_ms: int | None = Field(None, description='Processing duration in milliseconds')
36
+ compression_ratio: float = ...
37
+ size_reduction_percent: float = ...
38
+ created_at: Any = ...
39
+
40
+
41
+
42
+ class CleanRequestRequest(BaseModel):
43
+ """
44
+ Request serializer for HTML cleaning (multipart/form-data).
45
+
46
+ Request model (no read-only fields).
47
+ """
48
+
49
+ model_config = ConfigDict(
50
+ validate_assignment=True,
51
+ extra="allow",
52
+ frozen=False,
53
+ )
54
+
55
+ file: str = Field(description='HTML file to clean')
56
+ output_format: CleanRequestRequestOutputFormat | None = Field(None, description='* `html` - html\n* `markdown` - markdown\n* `aom` - aom\n* `xtree` - xtree')
57
+ max_tokens: int | None = Field(None, ge=100, le=100000)
58
+ remove_scripts: bool | None = None
59
+ remove_styles: bool | None = None
60
+ remove_comments: bool | None = None
61
+ remove_hidden: bool | None = None
62
+ filter_classes: bool | None = None
63
+ class_threshold: float | None = Field(None, ge=0.0, le=1.0)
64
+ try_hydration: bool | None = None
65
+ preserve_selectors: list[str] | None = None
66
+
67
+
68
+
69
+ class CleanResponse(BaseModel):
70
+ """
71
+ Response serializer for cleaned HTML.
72
+
73
+ Response model (includes read-only fields).
74
+ """
75
+
76
+ model_config = ConfigDict(
77
+ validate_assignment=True,
78
+ extra="allow",
79
+ frozen=False,
80
+ )
81
+
82
+ request_uuid: str = ...
83
+ cleaned_html: str = ...
84
+ original_size: int = ...
85
+ cleaned_size: int = ...
86
+ compression_ratio: float = ...
87
+ size_reduction_percent: float = ...
88
+ duration_ms: int = ...
89
+ output_format: str = ...
90
+ stats: dict[str, Any] = ...
91
+
92
+
93
+
94
+ class CleaningStats(BaseModel):
95
+ """
96
+ Statistics serializer.
97
+
98
+ Response model (includes read-only fields).
99
+ """
100
+
101
+ model_config = ConfigDict(
102
+ validate_assignment=True,
103
+ extra="allow",
104
+ frozen=False,
105
+ )
106
+
107
+ total_requests: int = ...
108
+ successful_requests: int = ...
109
+ failed_requests: int = ...
110
+ total_original_bytes: int | None = None
111
+ total_cleaned_bytes: int | None = None
112
+ avg_duration_ms: float | None = None
113
+ overall_compression_ratio: float | None = None
114
+ overall_size_reduction_percent: float | None = None
115
+
116
+
117
+
@@ -0,0 +1,82 @@
1
+ from __future__ import annotations
2
+
3
+ import httpx
4
+
5
+ from .models import *
6
+
7
+
8
+ class SyncCleanerCleanerAPI:
9
+ """Synchronous API endpoints for Cleaner."""
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) -> None:
16
+ """
17
+ List cleaning requests
18
+
19
+ List user's cleaning requests.
20
+ """
21
+ url = "/api/cleaner/"
22
+ response = self._client.get(url)
23
+ if not response.is_success:
24
+ try:
25
+ error_body = response.json()
26
+ except Exception:
27
+ error_body = response.text
28
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
29
+
30
+
31
+ def retrieve(self, id: str) -> CleaningRequestDetail:
32
+ """
33
+ Get cleaning request details
34
+
35
+ Get cleaning request details.
36
+ """
37
+ url = f"/api/cleaner/{id}/"
38
+ response = self._client.get(url)
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 CleaningRequestDetail.model_validate(response.json())
46
+
47
+
48
+ def clean_create(self, data: CleanRequestRequest) -> CleanResponse:
49
+ """
50
+ Clean HTML file
51
+
52
+ Clean HTML file. Accepts multipart/form-data with HTML file. Returns
53
+ cleaned HTML with statistics.
54
+ """
55
+ url = "/api/cleaner/clean/"
56
+ response = self._client.post(url, json=data.model_dump(exclude_unset=True))
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 CleanResponse.model_validate(response.json())
64
+
65
+
66
+ def stats_retrieve(self) -> CleaningStats:
67
+ """
68
+ Get cleaning statistics
69
+
70
+ Get cleaning statistics.
71
+ """
72
+ url = "/api/cleaner/stats/"
73
+ response = self._client.get(url)
74
+ if not response.is_success:
75
+ try:
76
+ error_body = response.json()
77
+ except Exception:
78
+ error_body = response.text
79
+ raise httpx.HTTPStatusError(f"{response.status_code}: {error_body}", request=response.request, response=response)
80
+ return CleaningStats.model_validate(response.json())
81
+
82
+
@@ -0,0 +1,75 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Optional
4
+
5
+ import httpx
6
+
7
+ from .cleaner__api__cleaner import CleanerCleanerAPI
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.cleaner_cleaner = CleanerCleanerAPI(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()
@@ -0,0 +1,55 @@
1
+ # Auto-generated by DjangoCFG - see CLAUDE.md
2
+ from enum import IntEnum, Enum
3
+
4
+ # Python 3.10 compatibility: StrEnum was added in Python 3.11
5
+ # Use str + Enum instead for backward compatibility
6
+ class StrEnum(str, Enum):
7
+ """String Enum for Python 3.10+ compatibility"""
8
+ pass
9
+
10
+
11
+ class CleanRequestRequestOutputFormat(StrEnum):
12
+ """
13
+ * `html` - html
14
+ * `markdown` - markdown
15
+ * `aom` - aom
16
+ * `xtree` - xtree
17
+ """
18
+
19
+ HTML = "html"
20
+ MARKDOWN = "markdown"
21
+ AOM = "aom"
22
+ XTREE = "xtree"
23
+
24
+
25
+
26
+ class CleaningRequestDetailStatus(StrEnum):
27
+ """
28
+ * `pending` - Pending
29
+ * `processing` - Processing
30
+ * `success` - Success
31
+ * `error` - Error
32
+ """
33
+
34
+ PENDING = "pending"
35
+ PROCESSING = "processing"
36
+ SUCCESS = "success"
37
+ ERROR = "error"
38
+
39
+
40
+
41
+ class CleaningRequestListStatus(StrEnum):
42
+ """
43
+ * `pending` - Pending
44
+ * `processing` - Processing
45
+ * `success` - Success
46
+ * `error` - Error
47
+ """
48
+
49
+ PENDING = "pending"
50
+ PROCESSING = "processing"
51
+ SUCCESS = "success"
52
+ ERROR = "error"
53
+
54
+
55
+