githubkit 0.11.0a2__py3-none-any.whl → 0.11.0a4__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.
- githubkit/compat.py +16 -2
- githubkit/core.py +72 -7
- githubkit/exception.py +24 -0
- githubkit/github.py +4 -2
- githubkit/graphql/__init__.py +13 -2
- githubkit/graphql/models.py +1 -0
- githubkit/typing.py +3 -3
- githubkit/utils.py +2 -17
- githubkit/versions/latest/__init__.py +8 -0
- githubkit/versions/rest.py +20 -6
- githubkit/versions/v2022_11_28/__init__.py +8 -0
- githubkit/versions/v2022_11_28/models/group_0002.py +2 -2
- githubkit/versions/v2022_11_28/models/group_0027.py +3 -5
- githubkit/versions/v2022_11_28/models/group_0041.py +1 -3
- githubkit/versions/v2022_11_28/models/group_0112.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0127.py +1 -0
- githubkit/versions/v2022_11_28/models/group_0131.py +2 -2
- githubkit/versions/v2022_11_28/models/group_0169.py +1 -3
- githubkit/versions/v2022_11_28/models/group_0190.py +5 -4
- githubkit/versions/v2022_11_28/models/group_0225.py +2 -1
- githubkit/versions/v2022_11_28/models/group_0227.py +7 -4
- githubkit/versions/v2022_11_28/models/group_0228.py +2 -2
- githubkit/versions/v2022_11_28/models/group_0240.py +1 -3
- githubkit/versions/v2022_11_28/models/group_0313.py +5 -4
- githubkit/versions/v2022_11_28/models/group_0314.py +5 -4
- githubkit/versions/v2022_11_28/models/group_0315.py +4 -3
- githubkit/versions/v2022_11_28/models/group_0824.py +1 -3
- githubkit/versions/v2022_11_28/models/group_0825.py +1 -3
- githubkit/versions/v2022_11_28/models/group_0838.py +4 -2
- githubkit/versions/v2022_11_28/models/group_0841.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0842.py +4 -2
- githubkit/versions/v2022_11_28/models/group_0845.py +2 -8
- githubkit/versions/v2022_11_28/models/group_0854.py +2 -1
- githubkit/versions/v2022_11_28/models/group_0855.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0856.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0858.py +2 -8
- githubkit/versions/v2022_11_28/models/group_0861.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0863.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0865.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0867.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0870.py +2 -8
- githubkit/versions/v2022_11_28/models/group_0887.py +3 -3
- githubkit/versions/v2022_11_28/models/group_0889.py +4 -2
- githubkit/versions/v2022_11_28/models/group_0892.py +5 -3
- githubkit/versions/v2022_11_28/models/group_0894.py +4 -2
- githubkit/versions/v2022_11_28/models/group_0913.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0921.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0937.py +4 -2
- githubkit/versions/v2022_11_28/models/group_0938.py +3 -2
- githubkit/versions/v2022_11_28/models/group_0939.py +4 -2
- githubkit/versions/v2022_11_28/models/group_0948.py +2 -8
- githubkit/versions/v2022_11_28/models/group_0972.py +16 -13
- githubkit/versions/v2022_11_28/models/group_0973.py +2 -5
- githubkit/versions/v2022_11_28/models/group_0974.py +2 -5
- githubkit/versions/v2022_11_28/models/group_0975.py +14 -17
- githubkit/versions/v2022_11_28/models/group_0976.py +2 -4
- githubkit/versions/v2022_11_28/models/group_0977.py +2 -4
- githubkit/versions/v2022_11_28/models/group_0982.py +8 -6
- githubkit/versions/v2022_11_28/models/group_0989.py +2 -8
- githubkit/versions/v2022_11_28/models/group_0997.py +2 -1
- githubkit/versions/v2022_11_28/models/group_0999.py +2 -8
- githubkit/versions/v2022_11_28/models/group_1004.py +4 -2
- githubkit/versions/v2022_11_28/models/group_1032.py +2 -1
- githubkit/versions/v2022_11_28/models/group_1033.py +2 -5
- githubkit/versions/v2022_11_28/models/group_1035.py +2 -1
- githubkit/versions/v2022_11_28/models/group_1036.py +2 -5
- githubkit/versions/v2022_11_28/models/group_1094.py +3 -7
- githubkit/versions/v2022_11_28/models/group_1114.py +2 -8
- githubkit/versions/v2022_11_28/models/group_1127.py +4 -3
- githubkit/versions/v2022_11_28/models/group_1134.py +3 -7
- githubkit/versions/v2022_11_28/rest/__init__.py +11 -1
- githubkit/versions/v2022_11_28/rest/actions.py +11 -1
- githubkit/versions/v2022_11_28/rest/activity.py +11 -1
- githubkit/versions/v2022_11_28/rest/apps.py +11 -1
- githubkit/versions/v2022_11_28/rest/billing.py +11 -1
- githubkit/versions/v2022_11_28/rest/checks.py +11 -1
- githubkit/versions/v2022_11_28/rest/classroom.py +11 -1
- githubkit/versions/v2022_11_28/rest/code_scanning.py +11 -1
- githubkit/versions/v2022_11_28/rest/codes_of_conduct.py +11 -1
- githubkit/versions/v2022_11_28/rest/codespaces.py +11 -1
- githubkit/versions/v2022_11_28/rest/copilot.py +11 -1
- githubkit/versions/v2022_11_28/rest/dependabot.py +11 -1
- githubkit/versions/v2022_11_28/rest/dependency_graph.py +11 -1
- githubkit/versions/v2022_11_28/rest/emojis.py +11 -1
- githubkit/versions/v2022_11_28/rest/gists.py +11 -1
- githubkit/versions/v2022_11_28/rest/git.py +11 -1
- githubkit/versions/v2022_11_28/rest/gitignore.py +11 -1
- githubkit/versions/v2022_11_28/rest/interactions.py +11 -1
- githubkit/versions/v2022_11_28/rest/issues.py +11 -1
- githubkit/versions/v2022_11_28/rest/licenses.py +11 -1
- githubkit/versions/v2022_11_28/rest/markdown.py +11 -1
- githubkit/versions/v2022_11_28/rest/meta.py +11 -1
- githubkit/versions/v2022_11_28/rest/migrations.py +11 -1
- githubkit/versions/v2022_11_28/rest/oidc.py +11 -1
- githubkit/versions/v2022_11_28/rest/orgs.py +11 -1
- githubkit/versions/v2022_11_28/rest/packages.py +11 -1
- githubkit/versions/v2022_11_28/rest/projects.py +11 -1
- githubkit/versions/v2022_11_28/rest/pulls.py +11 -1
- githubkit/versions/v2022_11_28/rest/rate_limit.py +11 -1
- githubkit/versions/v2022_11_28/rest/reactions.py +11 -1
- githubkit/versions/v2022_11_28/rest/repos.py +13 -1
- githubkit/versions/v2022_11_28/rest/search.py +11 -1
- githubkit/versions/v2022_11_28/rest/secret_scanning.py +11 -1
- githubkit/versions/v2022_11_28/rest/security_advisories.py +11 -1
- githubkit/versions/v2022_11_28/rest/teams.py +11 -1
- githubkit/versions/v2022_11_28/rest/users.py +11 -1
- githubkit/versions/v2022_11_28/types/group_0127.py +1 -0
- {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a4.dist-info}/METADATA +22 -6
- {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a4.dist-info}/RECORD +111 -109
- {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a4.dist-info}/LICENSE +0 -0
- {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a4.dist-info}/WHEEL +0 -0
githubkit/compat.py
CHANGED
|
@@ -29,8 +29,9 @@ if TYPE_CHECKING:
|
|
|
29
29
|
CVC = TypeVar("CVC", bound=CustomValidationClass)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
if PYDANTIC_V2:
|
|
32
|
+
if PYDANTIC_V2: # pragma: pydantic-v2
|
|
33
33
|
from pydantic_core import CoreSchema, core_schema
|
|
34
|
+
from pydantic_core import to_jsonable_python as to_jsonable_python
|
|
34
35
|
from pydantic import (
|
|
35
36
|
BaseModel,
|
|
36
37
|
ConfigDict,
|
|
@@ -80,7 +81,8 @@ if PYDANTIC_V2:
|
|
|
80
81
|
)
|
|
81
82
|
return class_
|
|
82
83
|
|
|
83
|
-
else:
|
|
84
|
+
else: # pragma: pydantic-v1
|
|
85
|
+
from pydantic.json import pydantic_encoder
|
|
84
86
|
from pydantic import Extra, BaseModel, parse_obj_as, parse_raw_as, root_validator
|
|
85
87
|
|
|
86
88
|
class GitHubModel(BaseModel):
|
|
@@ -97,6 +99,18 @@ else:
|
|
|
97
99
|
def type_validate_json(type_: Type[T], data: Any) -> T:
|
|
98
100
|
return parse_raw_as(type_, data)
|
|
99
101
|
|
|
102
|
+
def to_jsonable_python(obj: Any) -> Any:
|
|
103
|
+
if isinstance(obj, dict):
|
|
104
|
+
return {k: to_jsonable_python(v) for k, v in obj.items()}
|
|
105
|
+
|
|
106
|
+
if isinstance(obj, (list, tuple)):
|
|
107
|
+
return [to_jsonable_python(item) for item in obj]
|
|
108
|
+
|
|
109
|
+
if obj is None or isinstance(obj, (int, float, str, bool)):
|
|
110
|
+
return obj
|
|
111
|
+
|
|
112
|
+
return pydantic_encoder(obj)
|
|
113
|
+
|
|
100
114
|
def model_dump(model: BaseModel, by_alias: bool = True) -> Dict[str, Any]:
|
|
101
115
|
return model.dict(by_alias=by_alias)
|
|
102
116
|
|
githubkit/core.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from types import TracebackType
|
|
2
2
|
from contextvars import ContextVar
|
|
3
|
+
from datetime import datetime, timezone, timedelta
|
|
3
4
|
from contextlib import contextmanager, asynccontextmanager
|
|
4
5
|
from typing import (
|
|
5
6
|
Any,
|
|
@@ -20,9 +21,8 @@ import httpx
|
|
|
20
21
|
import hishel
|
|
21
22
|
|
|
22
23
|
from .response import Response
|
|
23
|
-
from .
|
|
24
|
+
from .compat import to_jsonable_python
|
|
24
25
|
from .config import Config, get_config
|
|
25
|
-
from .exception import RequestError, RequestFailed, RequestTimeout
|
|
26
26
|
from .auth import BaseAuthStrategy, TokenAuthStrategy, UnauthAuthStrategy
|
|
27
27
|
from .typing import (
|
|
28
28
|
URLTypes,
|
|
@@ -32,6 +32,13 @@ from .typing import (
|
|
|
32
32
|
RequestFiles,
|
|
33
33
|
QueryParamTypes,
|
|
34
34
|
)
|
|
35
|
+
from .exception import (
|
|
36
|
+
RequestError,
|
|
37
|
+
RequestFailed,
|
|
38
|
+
RequestTimeout,
|
|
39
|
+
PrimaryRateLimitExceeded,
|
|
40
|
+
SecondaryRateLimitExceeded,
|
|
41
|
+
)
|
|
35
42
|
|
|
36
43
|
T = TypeVar("T")
|
|
37
44
|
A = TypeVar("A", bound="BaseAuthStrategy")
|
|
@@ -265,7 +272,7 @@ class GitHubCore(Generic[A]):
|
|
|
265
272
|
content=content,
|
|
266
273
|
data=data,
|
|
267
274
|
files=files,
|
|
268
|
-
json=
|
|
275
|
+
json=to_jsonable_python(json),
|
|
269
276
|
headers=headers,
|
|
270
277
|
cookies=cookies,
|
|
271
278
|
)
|
|
@@ -297,7 +304,7 @@ class GitHubCore(Generic[A]):
|
|
|
297
304
|
content=content,
|
|
298
305
|
data=data,
|
|
299
306
|
files=files,
|
|
300
|
-
json=
|
|
307
|
+
json=to_jsonable_python(json),
|
|
301
308
|
headers=headers,
|
|
302
309
|
cookies=cookies,
|
|
303
310
|
)
|
|
@@ -316,15 +323,73 @@ class GitHubCore(Generic[A]):
|
|
|
316
323
|
if response.is_error:
|
|
317
324
|
error_models = error_models or {}
|
|
318
325
|
status_code = str(response.status_code)
|
|
326
|
+
|
|
319
327
|
error_model = error_models.get(
|
|
320
328
|
status_code,
|
|
321
329
|
error_models.get(
|
|
322
330
|
f"{status_code[:-2]}XX", error_models.get("default", Any)
|
|
323
331
|
),
|
|
324
332
|
)
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
333
|
+
resp = Response(response, error_model)
|
|
334
|
+
else:
|
|
335
|
+
resp = Response(response, response_model)
|
|
336
|
+
|
|
337
|
+
# only check rate limit when response is 403 or 429
|
|
338
|
+
if response.status_code in (403, 429):
|
|
339
|
+
self._check_rate_limit(resp)
|
|
340
|
+
|
|
341
|
+
if response.is_error:
|
|
342
|
+
raise RequestFailed(resp)
|
|
343
|
+
return resp
|
|
344
|
+
|
|
345
|
+
# check rate limit
|
|
346
|
+
def _check_rate_limit(self, response: Response) -> None:
|
|
347
|
+
# check rate limit exceeded
|
|
348
|
+
# https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api#exceeding-the-rate-limit
|
|
349
|
+
# https://docs.github.com/en/graphql/overview/rate-limits-and-node-limits-for-the-graphql-api#exceeding-the-rate-limit
|
|
350
|
+
# https://github.com/octokit/plugin-throttling.js/blob/135a0f556752a6c4c0ed3b2798bb58e228cd179a/src/index.ts#L134-L179
|
|
351
|
+
|
|
352
|
+
# Secondary rate limits
|
|
353
|
+
# the `retry-after` response header is present
|
|
354
|
+
if "retry-after" in response.headers:
|
|
355
|
+
raise SecondaryRateLimitExceeded(
|
|
356
|
+
response, self._extract_retry_after(response)
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
if (
|
|
360
|
+
"x-ratelimit-remaining" in response.headers
|
|
361
|
+
and response.headers["x-ratelimit-remaining"] == "0"
|
|
362
|
+
):
|
|
363
|
+
retry_after = self._extract_retry_after(response)
|
|
364
|
+
|
|
365
|
+
try:
|
|
366
|
+
error = response.json()
|
|
367
|
+
except Exception:
|
|
368
|
+
error = None
|
|
369
|
+
|
|
370
|
+
# Secondary rate limits
|
|
371
|
+
# error message indicates that you exceeded a secondary rate limit
|
|
372
|
+
if (
|
|
373
|
+
isinstance(error, dict)
|
|
374
|
+
and "message" in error
|
|
375
|
+
and "secondary rate" in error["message"]
|
|
376
|
+
):
|
|
377
|
+
raise SecondaryRateLimitExceeded(response, retry_after)
|
|
378
|
+
|
|
379
|
+
# Primary rate limits
|
|
380
|
+
raise PrimaryRateLimitExceeded(response, retry_after)
|
|
381
|
+
|
|
382
|
+
def _extract_retry_after(self, response: Response) -> timedelta:
|
|
383
|
+
if "retry-after" in response.headers:
|
|
384
|
+
return timedelta(seconds=int(response.headers["retry-after"]))
|
|
385
|
+
elif "x-ratelimit-reset" in response.headers:
|
|
386
|
+
retry_after = datetime.fromtimestamp(
|
|
387
|
+
int(response.headers["x-ratelimit-reset"]), tz=timezone.utc
|
|
388
|
+
) - datetime.now(tz=timezone.utc)
|
|
389
|
+
return max(retry_after, timedelta())
|
|
390
|
+
else:
|
|
391
|
+
# wait for at least one minute before retrying
|
|
392
|
+
return timedelta(seconds=60)
|
|
328
393
|
|
|
329
394
|
# sync request and check
|
|
330
395
|
def request(
|
githubkit/exception.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from datetime import timedelta
|
|
1
2
|
from typing import TYPE_CHECKING
|
|
2
3
|
|
|
3
4
|
import httpx
|
|
@@ -50,6 +51,29 @@ class RequestFailed(GitHubException):
|
|
|
50
51
|
)
|
|
51
52
|
|
|
52
53
|
|
|
54
|
+
class RateLimitExceeded(RequestFailed):
|
|
55
|
+
"""API request failed with rate limit exceeded"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, response: "Response", retry_after: timedelta):
|
|
58
|
+
super().__init__(response)
|
|
59
|
+
self.retry_after = retry_after
|
|
60
|
+
|
|
61
|
+
def __repr__(self) -> str:
|
|
62
|
+
return (
|
|
63
|
+
f"{self.__class__.__name__}(method={self.request.method}, "
|
|
64
|
+
f"url={self.request.url}, status_code={self.response.status_code}, "
|
|
65
|
+
f"retry_after={self.retry_after})"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class PrimaryRateLimitExceeded(RateLimitExceeded):
|
|
70
|
+
"""API request failed with primary rate limit exceeded"""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class SecondaryRateLimitExceeded(RateLimitExceeded):
|
|
74
|
+
"""API request failed with secondary rate limit exceeded"""
|
|
75
|
+
|
|
76
|
+
|
|
53
77
|
class GraphQLFailed(GitHubException):
|
|
54
78
|
"""GraphQL request with errors in response"""
|
|
55
79
|
|
githubkit/github.py
CHANGED
|
@@ -142,7 +142,8 @@ class GitHub(GitHubCore[A]):
|
|
|
142
142
|
json = build_graphql_request(query, variables)
|
|
143
143
|
|
|
144
144
|
return parse_graphql_response(
|
|
145
|
-
self
|
|
145
|
+
self,
|
|
146
|
+
self.request("POST", "/graphql", json=json, response_model=GraphQLResponse),
|
|
146
147
|
)
|
|
147
148
|
|
|
148
149
|
async def async_graphql(
|
|
@@ -151,9 +152,10 @@ class GitHub(GitHubCore[A]):
|
|
|
151
152
|
json = build_graphql_request(query, variables)
|
|
152
153
|
|
|
153
154
|
return parse_graphql_response(
|
|
155
|
+
self,
|
|
154
156
|
await self.arequest(
|
|
155
157
|
"POST", "/graphql", json=json, response_model=GraphQLResponse
|
|
156
|
-
)
|
|
158
|
+
),
|
|
157
159
|
)
|
|
158
160
|
|
|
159
161
|
# rest pagination
|
githubkit/graphql/__init__.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Any, Dict, Optional, cast
|
|
2
2
|
|
|
3
|
-
from githubkit.exception import GraphQLFailed
|
|
3
|
+
from githubkit.exception import GraphQLFailed, PrimaryRateLimitExceeded
|
|
4
4
|
|
|
5
5
|
from .models import GraphQLError as GraphQLError
|
|
6
6
|
from .models import SourceLocation as SourceLocation
|
|
7
7
|
from .models import GraphQLResponse as GraphQLResponse
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
+
from githubkit.core import GitHubCore
|
|
10
11
|
from githubkit.response import Response
|
|
11
12
|
|
|
12
13
|
|
|
@@ -19,8 +20,18 @@ def build_graphql_request(
|
|
|
19
20
|
return json
|
|
20
21
|
|
|
21
22
|
|
|
22
|
-
def parse_graphql_response(
|
|
23
|
+
def parse_graphql_response(
|
|
24
|
+
github: "GitHubCore", response: "Response[GraphQLResponse]"
|
|
25
|
+
) -> Dict[str, Any]:
|
|
23
26
|
response_data = response.parsed_data
|
|
24
27
|
if response_data.errors:
|
|
28
|
+
# check rate limit exceeded
|
|
29
|
+
# https://docs.github.com/en/graphql/overview/rate-limits-and-node-limits-for-the-graphql-api#exceeding-the-rate-limit
|
|
30
|
+
# x-ratelimit-remaining may not be 0, ignore it
|
|
31
|
+
# https://github.com/octokit/plugin-throttling.js/pull/636
|
|
32
|
+
if any(error.type == "RATE_LIMITED" for error in response_data.errors):
|
|
33
|
+
raise PrimaryRateLimitExceeded(
|
|
34
|
+
response, github._extract_retry_after(response)
|
|
35
|
+
)
|
|
25
36
|
raise GraphQLFailed(response_data)
|
|
26
37
|
return cast(Dict[str, Any], response_data.data)
|
githubkit/graphql/models.py
CHANGED
githubkit/typing.py
CHANGED
|
@@ -45,7 +45,7 @@ FileTypes: TypeAlias = Union[
|
|
|
45
45
|
]
|
|
46
46
|
RequestFiles: TypeAlias = Union[Dict[str, FileTypes], List[Tuple[str, FileTypes]]]
|
|
47
47
|
|
|
48
|
-
if PYDANTIC_V2:
|
|
48
|
+
if PYDANTIC_V2: # pragma: pydantic-v2
|
|
49
49
|
from pydantic import AfterValidator
|
|
50
50
|
from pydantic_core import PydanticCustomError
|
|
51
51
|
|
|
@@ -59,9 +59,9 @@ if PYDANTIC_V2:
|
|
|
59
59
|
AfterValidator(_validate_unique_list),
|
|
60
60
|
Field(json_schema_extra={"uniqueItems": True}),
|
|
61
61
|
]
|
|
62
|
-
else:
|
|
62
|
+
else: # pragma: pydantic-v1
|
|
63
63
|
UniqueList: TypeAlias = Annotated[List[H], Field(unique_items=True)] # type: ignore
|
|
64
64
|
|
|
65
65
|
# if the property is not required, we allow it to have the value null.
|
|
66
66
|
# See https://github.com/yanyongyu/githubkit/issues/47
|
|
67
|
-
Missing: TypeAlias =
|
|
67
|
+
Missing: TypeAlias = Union[Literal[UNSET], T, None]
|
githubkit/utils.py
CHANGED
|
@@ -3,11 +3,10 @@ from enum import Enum
|
|
|
3
3
|
from typing import Any, Dict, Type, Generic, Literal, TypeVar, final
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
|
-
from pydantic_core import to_jsonable_python
|
|
7
6
|
|
|
8
7
|
from .compat import PYDANTIC_V2, custom_validation, type_validate_python
|
|
9
8
|
|
|
10
|
-
if PYDANTIC_V2:
|
|
9
|
+
if PYDANTIC_V2: # pragma: pydantic-v2
|
|
11
10
|
from pydantic_core import core_schema
|
|
12
11
|
from pydantic import GetCoreSchemaHandler
|
|
13
12
|
|
|
@@ -69,20 +68,6 @@ def is_async(obj: Any) -> bool:
|
|
|
69
68
|
return inspect.iscoroutinefunction(func_)
|
|
70
69
|
|
|
71
70
|
|
|
72
|
-
# FIXME: remove pydantic-core dependency
|
|
73
|
-
def obj_to_jsonable(obj: Any) -> Any:
|
|
74
|
-
if isinstance(obj, dict):
|
|
75
|
-
return {k: obj_to_jsonable(v) for k, v in obj.items()}
|
|
76
|
-
|
|
77
|
-
if isinstance(obj, (list, tuple)):
|
|
78
|
-
return [obj_to_jsonable(item) for item in obj]
|
|
79
|
-
|
|
80
|
-
if obj is None or isinstance(obj, (int, float, str, bool)):
|
|
81
|
-
return obj
|
|
82
|
-
|
|
83
|
-
return to_jsonable_python(obj)
|
|
84
|
-
|
|
85
|
-
|
|
86
71
|
class TaggedUnion(Generic[T]):
|
|
87
72
|
__slots__ = ("type_", "discriminator", "tag")
|
|
88
73
|
|
|
@@ -94,7 +79,7 @@ class TaggedUnion(Generic[T]):
|
|
|
94
79
|
def _validate(self, value: Any) -> T:
|
|
95
80
|
return type_validate_python(self.type_, value)
|
|
96
81
|
|
|
97
|
-
if PYDANTIC_V2:
|
|
82
|
+
if PYDANTIC_V2: # pragma: pydantic-v2
|
|
98
83
|
|
|
99
84
|
def __get_pydantic_core_schema__(
|
|
100
85
|
self, _source_type: Any, _handler: "GetCoreSchemaHandler"
|
githubkit/versions/rest.py
CHANGED
|
@@ -8,6 +8,7 @@ See https://github.com/github/rest-api-description for more information.
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import importlib
|
|
11
|
+
from weakref import WeakKeyDictionary, ref
|
|
11
12
|
from typing import TYPE_CHECKING, Any, Dict, Literal, overload
|
|
12
13
|
|
|
13
14
|
from . import VERSIONS, VERSION_TYPE, LATEST_VERSION
|
|
@@ -27,7 +28,9 @@ else:
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class RestVersionSwitcher(_VersionProxy):
|
|
30
|
-
_cached_namespaces: Dict[VERSION_TYPE, Any] =
|
|
31
|
+
_cached_namespaces: "WeakKeyDictionary[GitHubCore, Dict[VERSION_TYPE, Any]]" = (
|
|
32
|
+
WeakKeyDictionary()
|
|
33
|
+
)
|
|
31
34
|
|
|
32
35
|
if not TYPE_CHECKING:
|
|
33
36
|
|
|
@@ -40,7 +43,16 @@ class RestVersionSwitcher(_VersionProxy):
|
|
|
40
43
|
return getattr(namespace, name)
|
|
41
44
|
|
|
42
45
|
def __init__(self, github: "GitHubCore"):
|
|
43
|
-
self.
|
|
46
|
+
self._github_ref = ref(github)
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def _github(self) -> "GitHubCore":
|
|
50
|
+
if g := self._github_ref():
|
|
51
|
+
return g
|
|
52
|
+
raise RuntimeError(
|
|
53
|
+
"GitHub client has already been collected. "
|
|
54
|
+
"Do not use the namespace after the client has been collected."
|
|
55
|
+
)
|
|
44
56
|
|
|
45
57
|
@overload
|
|
46
58
|
def __call__(self, version: Literal["2022-11-28"]) -> "V20221128RestNamespace":
|
|
@@ -51,9 +63,11 @@ class RestVersionSwitcher(_VersionProxy):
|
|
|
51
63
|
...
|
|
52
64
|
|
|
53
65
|
def __call__(self, version: VERSION_TYPE = LATEST_VERSION) -> Any:
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
g = self._github
|
|
67
|
+
cache = self._cached_namespaces.setdefault(g, {})
|
|
68
|
+
if version in cache:
|
|
69
|
+
return cache[version]
|
|
56
70
|
module = importlib.import_module(f".{VERSIONS[version]}.rest", __package__)
|
|
57
|
-
namespace = module.RestNamespace(
|
|
58
|
-
|
|
71
|
+
namespace = module.RestNamespace(g)
|
|
72
|
+
cache[version] = namespace
|
|
59
73
|
return namespace
|
|
@@ -56,8 +56,8 @@ class GlobalAdvisory(GitHubModel):
|
|
|
56
56
|
repository_advisory_url: Union[str, None] = Field(
|
|
57
57
|
description="The API URL for the repository advisory."
|
|
58
58
|
)
|
|
59
|
-
summary:
|
|
60
|
-
description="A short summary of the advisory."
|
|
59
|
+
summary: str = Field(
|
|
60
|
+
max_length=1024, description="A short summary of the advisory."
|
|
61
61
|
)
|
|
62
62
|
description: Union[Annotated[str, Field(max_length=65535)], None] = Field(
|
|
63
63
|
description="A detailed description of what the advisory entails."
|
|
@@ -33,8 +33,8 @@ class DependabotAlertSecurityAdvisory(GitHubModel):
|
|
|
33
33
|
cve_id: Union[str, None] = Field(
|
|
34
34
|
description="The unique CVE ID assigned to the advisory."
|
|
35
35
|
)
|
|
36
|
-
summary:
|
|
37
|
-
description="A short, plain text summary of the advisory."
|
|
36
|
+
summary: str = Field(
|
|
37
|
+
max_length=1024, description="A short, plain text summary of the advisory."
|
|
38
38
|
)
|
|
39
39
|
description: str = Field(
|
|
40
40
|
description="A long-form Markdown-supported description of the advisory."
|
|
@@ -74,9 +74,7 @@ class DependabotAlertSecurityAdvisoryPropCvss(GitHubModel):
|
|
|
74
74
|
Details for the advisory pertaining to the Common Vulnerability Scoring System.
|
|
75
75
|
"""
|
|
76
76
|
|
|
77
|
-
score:
|
|
78
|
-
description="The overall CVSS score of the advisory."
|
|
79
|
-
)
|
|
77
|
+
score: float = Field(le=10.0, description="The overall CVSS score of the advisory.")
|
|
80
78
|
vector_string: Union[str, None] = Field(
|
|
81
79
|
description="The full CVSS vector string for the advisory."
|
|
82
80
|
)
|
|
@@ -32,9 +32,7 @@ class GistComment(GitHubModel):
|
|
|
32
32
|
id: int = Field()
|
|
33
33
|
node_id: str = Field()
|
|
34
34
|
url: str = Field()
|
|
35
|
-
body:
|
|
36
|
-
description="The comment text."
|
|
37
|
-
)
|
|
35
|
+
body: str = Field(max_length=65535, description="The comment text.")
|
|
38
36
|
user: Union[None, SimpleUser] = Field()
|
|
39
37
|
created_at: datetime = Field()
|
|
40
38
|
updated_at: datetime = Field()
|
|
@@ -29,8 +29,9 @@ class RepositoryRulePullRequestPropParameters(GitHubModel):
|
|
|
29
29
|
require_last_push_approval: bool = Field(
|
|
30
30
|
description="Whether the most recent reviewable push must be approved by someone other than the person who pushed it."
|
|
31
31
|
)
|
|
32
|
-
required_approving_review_count:
|
|
33
|
-
|
|
32
|
+
required_approving_review_count: int = Field(
|
|
33
|
+
le=10.0,
|
|
34
|
+
description="The number of approving reviews that are required before a pull request can be merged.",
|
|
34
35
|
)
|
|
35
36
|
required_review_thread_resolution: bool = Field(
|
|
36
37
|
description="All conversations on code must be resolved before a pull request can be merged."
|
|
@@ -37,8 +37,8 @@ class RepositoryAdvisory(GitHubModel):
|
|
|
37
37
|
)
|
|
38
38
|
url: str = Field(description="The API URL for the advisory.")
|
|
39
39
|
html_url: str = Field(description="The URL for the advisory.")
|
|
40
|
-
summary:
|
|
41
|
-
description="A short summary of the advisory."
|
|
40
|
+
summary: str = Field(
|
|
41
|
+
max_length=1024, description="A short summary of the advisory."
|
|
42
42
|
)
|
|
43
43
|
description: Union[Annotated[str, Field(max_length=65535)], None] = Field(
|
|
44
44
|
description="A detailed description of what the advisory entails."
|
|
@@ -44,9 +44,7 @@ class ProtectedBranchPullRequestReview(GitHubModel):
|
|
|
44
44
|
)
|
|
45
45
|
dismiss_stale_reviews: bool = Field()
|
|
46
46
|
require_code_owner_reviews: bool = Field()
|
|
47
|
-
required_approving_review_count: Missing[
|
|
48
|
-
default=UNSET
|
|
49
|
-
)
|
|
47
|
+
required_approving_review_count: Missing[int] = Field(le=6.0, default=UNSET)
|
|
50
48
|
require_last_push_approval: Missing[bool] = Field(
|
|
51
49
|
default=UNSET,
|
|
52
50
|
description="Whether the most recent push must be approved by someone other than the person who pushed it.",
|
|
@@ -29,10 +29,11 @@ class CodeScanningAnalysis(GitHubModel):
|
|
|
29
29
|
ref: str = Field(
|
|
30
30
|
description="The Git reference, formatted as `refs/pull/<number>/merge`, `refs/pull/<number>/head`,\n`refs/heads/<branch name>` or simply `<branch name>`."
|
|
31
31
|
)
|
|
32
|
-
commit_sha:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
commit_sha: str = Field(
|
|
33
|
+
min_length=40,
|
|
34
|
+
max_length=40,
|
|
35
|
+
pattern="^[0-9a-fA-F]+$",
|
|
36
|
+
description="The SHA of the commit to which the analysis you are uploading relates.",
|
|
36
37
|
)
|
|
37
38
|
analysis_key: str = Field(
|
|
38
39
|
description="Identifies the configuration under which the analysis was executed. For example, in GitHub Actions this includes the workflow filename and job name."
|
|
@@ -25,7 +25,8 @@ from .group_0224 import Metadata
|
|
|
25
25
|
class Dependency(GitHubModel):
|
|
26
26
|
"""Dependency"""
|
|
27
27
|
|
|
28
|
-
package_url: Missing[
|
|
28
|
+
package_url: Missing[str] = Field(
|
|
29
|
+
pattern="^pkg",
|
|
29
30
|
default=UNSET,
|
|
30
31
|
description="Package-url (PURL) of dependency. See https://github.com/package-url/purl-spec for more details.",
|
|
31
32
|
)
|
|
@@ -32,11 +32,14 @@ class Snapshot(GitHubModel):
|
|
|
32
32
|
description="The version of the repository snapshot submission."
|
|
33
33
|
)
|
|
34
34
|
job: SnapshotPropJob = Field()
|
|
35
|
-
sha:
|
|
36
|
-
|
|
35
|
+
sha: str = Field(
|
|
36
|
+
min_length=40,
|
|
37
|
+
max_length=40,
|
|
38
|
+
description="The commit SHA associated with this dependency snapshot. Maximum length: 40 characters.",
|
|
37
39
|
)
|
|
38
|
-
ref:
|
|
39
|
-
|
|
40
|
+
ref: str = Field(
|
|
41
|
+
pattern="^refs/",
|
|
42
|
+
description="The repository branch that triggered this snapshot.",
|
|
40
43
|
)
|
|
41
44
|
detector: SnapshotPropDetector = Field(
|
|
42
45
|
description="A description of the detector used."
|
|
@@ -37,8 +37,8 @@ class DeploymentStatus(GitHubModel):
|
|
|
37
37
|
"error", "failure", "inactive", "pending", "success", "queued", "in_progress"
|
|
38
38
|
] = Field(description="The state of the status.")
|
|
39
39
|
creator: Union[None, SimpleUser] = Field()
|
|
40
|
-
description:
|
|
41
|
-
default="", description="A short description of the status."
|
|
40
|
+
description: str = Field(
|
|
41
|
+
max_length=140, default="", description="A short description of the status."
|
|
42
42
|
)
|
|
43
43
|
environment: Missing[str] = Field(
|
|
44
44
|
default=UNSET,
|
|
@@ -33,9 +33,7 @@ class GitRefPropObject(GitHubModel):
|
|
|
33
33
|
"""GitRefPropObject"""
|
|
34
34
|
|
|
35
35
|
type: str = Field()
|
|
36
|
-
sha:
|
|
37
|
-
description="SHA for the reference"
|
|
38
|
-
)
|
|
36
|
+
sha: str = Field(min_length=40, max_length=40, description="SHA for the reference")
|
|
39
37
|
url: str = Field()
|
|
40
38
|
|
|
41
39
|
|
|
@@ -23,11 +23,12 @@ from githubkit.compat import GitHubModel, model_rebuild
|
|
|
23
23
|
class RepositoryAdvisoryCreate(GitHubModel):
|
|
24
24
|
"""RepositoryAdvisoryCreate"""
|
|
25
25
|
|
|
26
|
-
summary:
|
|
27
|
-
description="A short summary of the advisory."
|
|
26
|
+
summary: str = Field(
|
|
27
|
+
max_length=1024, description="A short summary of the advisory."
|
|
28
28
|
)
|
|
29
|
-
description:
|
|
30
|
-
|
|
29
|
+
description: str = Field(
|
|
30
|
+
max_length=65535,
|
|
31
|
+
description="A detailed description of what the advisory impacts.",
|
|
31
32
|
)
|
|
32
33
|
cve_id: Missing[Union[str, None]] = Field(
|
|
33
34
|
default=UNSET, description="The Common Vulnerabilities and Exposures (CVE) ID."
|
|
@@ -23,11 +23,12 @@ from githubkit.compat import GitHubModel, model_rebuild
|
|
|
23
23
|
class PrivateVulnerabilityReportCreate(GitHubModel):
|
|
24
24
|
"""PrivateVulnerabilityReportCreate"""
|
|
25
25
|
|
|
26
|
-
summary:
|
|
27
|
-
description="A short summary of the advisory."
|
|
26
|
+
summary: str = Field(
|
|
27
|
+
max_length=1024, description="A short summary of the advisory."
|
|
28
28
|
)
|
|
29
|
-
description:
|
|
30
|
-
|
|
29
|
+
description: str = Field(
|
|
30
|
+
max_length=65535,
|
|
31
|
+
description="A detailed description of what the advisory impacts.",
|
|
31
32
|
)
|
|
32
33
|
vulnerabilities: Missing[
|
|
33
34
|
Union[List[PrivateVulnerabilityReportCreatePropVulnerabilitiesItems], None]
|
|
@@ -23,10 +23,11 @@ from githubkit.compat import GitHubModel, model_rebuild
|
|
|
23
23
|
class RepositoryAdvisoryUpdate(GitHubModel):
|
|
24
24
|
"""RepositoryAdvisoryUpdate"""
|
|
25
25
|
|
|
26
|
-
summary: Missing[
|
|
27
|
-
default=UNSET, description="A short summary of the advisory."
|
|
26
|
+
summary: Missing[str] = Field(
|
|
27
|
+
max_length=1024, default=UNSET, description="A short summary of the advisory."
|
|
28
28
|
)
|
|
29
|
-
description: Missing[
|
|
29
|
+
description: Missing[str] = Field(
|
|
30
|
+
max_length=65535,
|
|
30
31
|
default=UNSET,
|
|
31
32
|
description="A detailed description of what the advisory impacts.",
|
|
32
33
|
)
|
|
@@ -20,9 +20,7 @@ from githubkit.compat import GitHubModel, model_rebuild
|
|
|
20
20
|
class GistsGistIdCommentsPostBody(GitHubModel):
|
|
21
21
|
"""GistsGistIdCommentsPostBody"""
|
|
22
22
|
|
|
23
|
-
body:
|
|
24
|
-
description="The comment text."
|
|
25
|
-
)
|
|
23
|
+
body: str = Field(max_length=65535, description="The comment text.")
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
model_rebuild(GistsGistIdCommentsPostBody)
|
|
@@ -20,9 +20,7 @@ from githubkit.compat import GitHubModel, model_rebuild
|
|
|
20
20
|
class GistsGistIdCommentsCommentIdPatchBody(GitHubModel):
|
|
21
21
|
"""GistsGistIdCommentsCommentIdPatchBody"""
|
|
22
22
|
|
|
23
|
-
body:
|
|
24
|
-
description="The comment text."
|
|
25
|
-
)
|
|
23
|
+
body: str = Field(max_length=65535, description="The comment text.")
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
model_rebuild(GistsGistIdCommentsCommentIdPatchBody)
|