gentic-sdk 0.1.0__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.
- gentic_sdk/__init__.py +4 -0
- gentic_sdk/client.py +116 -0
- gentic_sdk/exceptions.py +5 -0
- gentic_sdk/models.py +1490 -0
- gentic_sdk/resources/__init__.py +18 -0
- gentic_sdk/resources/account.py +37 -0
- gentic_sdk/resources/activity.py +15 -0
- gentic_sdk/resources/auth.py +34 -0
- gentic_sdk/resources/categories.py +15 -0
- gentic_sdk/resources/cli.py +13 -0
- gentic_sdk/resources/health.py +10 -0
- gentic_sdk/resources/library.py +40 -0
- gentic_sdk/resources/notifications.py +22 -0
- gentic_sdk/resources/oauth.py +16 -0
- gentic_sdk/resources/profiles.py +34 -0
- gentic_sdk/resources/projects.py +13 -0
- gentic_sdk/resources/recommend.py +22 -0
- gentic_sdk/resources/skills.py +100 -0
- gentic_sdk/resources/subscriptions.py +27 -0
- gentic_sdk-0.1.0.dist-info/METADATA +24 -0
- gentic_sdk-0.1.0.dist-info/RECORD +22 -0
- gentic_sdk-0.1.0.dist-info/WHEEL +4 -0
gentic_sdk/__init__.py
ADDED
gentic_sdk/client.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from functools import lru_cache
|
|
4
|
+
from typing import Any, TypeVar
|
|
5
|
+
from urllib.parse import quote
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
from pydantic import BaseModel, TypeAdapter
|
|
9
|
+
|
|
10
|
+
from gentic_sdk import models
|
|
11
|
+
from gentic_sdk.exceptions import GenticHubError
|
|
12
|
+
from gentic_sdk.resources.account import AccountApi
|
|
13
|
+
from gentic_sdk.resources.activity import ActivityApi
|
|
14
|
+
from gentic_sdk.resources.auth import AuthApi
|
|
15
|
+
from gentic_sdk.resources.categories import CategoriesApi
|
|
16
|
+
from gentic_sdk.resources.cli import CliApi
|
|
17
|
+
from gentic_sdk.resources.health import HealthApi
|
|
18
|
+
from gentic_sdk.resources.library import LibraryApi
|
|
19
|
+
from gentic_sdk.resources.oauth import OauthApi
|
|
20
|
+
from gentic_sdk.resources.notifications import NotificationsApi
|
|
21
|
+
from gentic_sdk.resources.profiles import ProfilesApi
|
|
22
|
+
from gentic_sdk.resources.projects import ProjectsApi
|
|
23
|
+
from gentic_sdk.resources.recommend import RecommendApi
|
|
24
|
+
from gentic_sdk.resources.skills import SkillsApi
|
|
25
|
+
from gentic_sdk.resources.subscriptions import SubscriptionsApi
|
|
26
|
+
|
|
27
|
+
Result = TypeVar("Result")
|
|
28
|
+
TokenSource = str | Callable[[], str | None]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@lru_cache
|
|
32
|
+
def adapter_for(result_type: Any) -> TypeAdapter[Any]:
|
|
33
|
+
return TypeAdapter(result_type)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class GenticHub:
|
|
37
|
+
def __init__(self, base_url: str, token: TokenSource | None = None, timeout: float = 30.0, http_client: httpx.Client | None = None) -> None:
|
|
38
|
+
self.token = token
|
|
39
|
+
self.http_client = http_client or httpx.Client(base_url=base_url.rstrip("/"), timeout=timeout)
|
|
40
|
+
self.health = HealthApi(self)
|
|
41
|
+
self.auth = AuthApi(self)
|
|
42
|
+
self.skills = SkillsApi(self)
|
|
43
|
+
self.categories = CategoriesApi(self)
|
|
44
|
+
self.cli = CliApi(self)
|
|
45
|
+
self.library = LibraryApi(self)
|
|
46
|
+
self.account = AccountApi(self)
|
|
47
|
+
self.activity = ActivityApi(self)
|
|
48
|
+
self.notifications = NotificationsApi(self)
|
|
49
|
+
self.profiles = ProfilesApi(self)
|
|
50
|
+
self.projects = ProjectsApi(self)
|
|
51
|
+
self.oauth = OauthApi(self)
|
|
52
|
+
self.subscriptions = SubscriptionsApi(self)
|
|
53
|
+
self.recommend = RecommendApi(self)
|
|
54
|
+
|
|
55
|
+
def __enter__(self) -> "GenticHub":
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
def __exit__(self, *_exception: object) -> None:
|
|
59
|
+
self.close()
|
|
60
|
+
|
|
61
|
+
def close(self) -> None:
|
|
62
|
+
self.http_client.close()
|
|
63
|
+
|
|
64
|
+
def sign_in(self, email: str, password: str) -> models.TokenResponse:
|
|
65
|
+
token = self.auth.token(models.TokenRequest(email=email, password=password))
|
|
66
|
+
if not isinstance(token, models.TokenResponse):
|
|
67
|
+
raise GenticHubError(500, "unexpected_answer")
|
|
68
|
+
self.token = token.access_token
|
|
69
|
+
return token
|
|
70
|
+
|
|
71
|
+
def sign_out(self) -> None:
|
|
72
|
+
self.auth.sign_out()
|
|
73
|
+
self.token = None
|
|
74
|
+
|
|
75
|
+
def request(
|
|
76
|
+
self,
|
|
77
|
+
method: str,
|
|
78
|
+
path: str,
|
|
79
|
+
result_type: type[Result] | Any = None,
|
|
80
|
+
*,
|
|
81
|
+
path_parameters: dict[str, Any] | None = None,
|
|
82
|
+
query: dict[str, Any] | None = None,
|
|
83
|
+
body: BaseModel | dict[str, Any] | None = None,
|
|
84
|
+
) -> Any:
|
|
85
|
+
headers = {"accept": "application/json"}
|
|
86
|
+
token = self.token() if callable(self.token) else self.token
|
|
87
|
+
if token:
|
|
88
|
+
headers["authorization"] = f"Bearer {token}"
|
|
89
|
+
filled_path = path.format(**{name: quote(str(value), safe="") for name, value in (path_parameters or {}).items()})
|
|
90
|
+
content = None
|
|
91
|
+
if body is not None:
|
|
92
|
+
headers["content-type"] = "application/json"
|
|
93
|
+
payload = body.model_dump(mode="json", exclude_unset=True) if isinstance(body, BaseModel) else body
|
|
94
|
+
content = json.dumps(payload)
|
|
95
|
+
response = self.http_client.request(
|
|
96
|
+
method,
|
|
97
|
+
filled_path,
|
|
98
|
+
params={name: value for name, value in (query or {}).items() if value is not None},
|
|
99
|
+
headers=headers,
|
|
100
|
+
content=content,
|
|
101
|
+
)
|
|
102
|
+
if response.is_error:
|
|
103
|
+
raise GenticHubError(response.status_code, self.error_detail(response))
|
|
104
|
+
if response.status_code == 204 or result_type is None:
|
|
105
|
+
return None
|
|
106
|
+
return adapter_for(result_type).validate_python(response.json())
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def error_detail(response: httpx.Response) -> str:
|
|
110
|
+
try:
|
|
111
|
+
detail = response.json().get("detail")
|
|
112
|
+
except (ValueError, AttributeError):
|
|
113
|
+
detail = None
|
|
114
|
+
if detail is None:
|
|
115
|
+
return response.reason_phrase
|
|
116
|
+
return detail if isinstance(detail, str) else json.dumps(detail)
|