githubkit 0.11.0a2__py3-none-any.whl → 0.11.0a3__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 (51) hide show
  1. githubkit/compat.py +2 -2
  2. githubkit/core.py +69 -4
  3. githubkit/exception.py +24 -0
  4. githubkit/github.py +4 -2
  5. githubkit/graphql/__init__.py +13 -2
  6. githubkit/graphql/models.py +1 -0
  7. githubkit/typing.py +2 -2
  8. githubkit/utils.py +2 -2
  9. githubkit/versions/latest/__init__.py +8 -0
  10. githubkit/versions/rest.py +20 -6
  11. githubkit/versions/v2022_11_28/__init__.py +8 -0
  12. githubkit/versions/v2022_11_28/rest/__init__.py +11 -1
  13. githubkit/versions/v2022_11_28/rest/actions.py +11 -1
  14. githubkit/versions/v2022_11_28/rest/activity.py +11 -1
  15. githubkit/versions/v2022_11_28/rest/apps.py +11 -1
  16. githubkit/versions/v2022_11_28/rest/billing.py +11 -1
  17. githubkit/versions/v2022_11_28/rest/checks.py +11 -1
  18. githubkit/versions/v2022_11_28/rest/classroom.py +11 -1
  19. githubkit/versions/v2022_11_28/rest/code_scanning.py +11 -1
  20. githubkit/versions/v2022_11_28/rest/codes_of_conduct.py +11 -1
  21. githubkit/versions/v2022_11_28/rest/codespaces.py +11 -1
  22. githubkit/versions/v2022_11_28/rest/copilot.py +11 -1
  23. githubkit/versions/v2022_11_28/rest/dependabot.py +11 -1
  24. githubkit/versions/v2022_11_28/rest/dependency_graph.py +11 -1
  25. githubkit/versions/v2022_11_28/rest/emojis.py +11 -1
  26. githubkit/versions/v2022_11_28/rest/gists.py +11 -1
  27. githubkit/versions/v2022_11_28/rest/git.py +11 -1
  28. githubkit/versions/v2022_11_28/rest/gitignore.py +11 -1
  29. githubkit/versions/v2022_11_28/rest/interactions.py +11 -1
  30. githubkit/versions/v2022_11_28/rest/issues.py +11 -1
  31. githubkit/versions/v2022_11_28/rest/licenses.py +11 -1
  32. githubkit/versions/v2022_11_28/rest/markdown.py +11 -1
  33. githubkit/versions/v2022_11_28/rest/meta.py +11 -1
  34. githubkit/versions/v2022_11_28/rest/migrations.py +11 -1
  35. githubkit/versions/v2022_11_28/rest/oidc.py +11 -1
  36. githubkit/versions/v2022_11_28/rest/orgs.py +11 -1
  37. githubkit/versions/v2022_11_28/rest/packages.py +11 -1
  38. githubkit/versions/v2022_11_28/rest/projects.py +11 -1
  39. githubkit/versions/v2022_11_28/rest/pulls.py +11 -1
  40. githubkit/versions/v2022_11_28/rest/rate_limit.py +11 -1
  41. githubkit/versions/v2022_11_28/rest/reactions.py +11 -1
  42. githubkit/versions/v2022_11_28/rest/repos.py +11 -1
  43. githubkit/versions/v2022_11_28/rest/search.py +11 -1
  44. githubkit/versions/v2022_11_28/rest/secret_scanning.py +11 -1
  45. githubkit/versions/v2022_11_28/rest/security_advisories.py +11 -1
  46. githubkit/versions/v2022_11_28/rest/teams.py +11 -1
  47. githubkit/versions/v2022_11_28/rest/users.py +11 -1
  48. {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a3.dist-info}/METADATA +1 -1
  49. {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a3.dist-info}/RECORD +51 -49
  50. {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a3.dist-info}/LICENSE +0 -0
  51. {githubkit-0.11.0a2.dist-info → githubkit-0.11.0a3.dist-info}/WHEEL +0 -0
githubkit/compat.py CHANGED
@@ -29,7 +29,7 @@ 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
34
  from pydantic import (
35
35
  BaseModel,
@@ -80,7 +80,7 @@ if PYDANTIC_V2:
80
80
  )
81
81
  return class_
82
82
 
83
- else:
83
+ else: # pragma: pydantic-v1
84
84
  from pydantic import Extra, BaseModel, parse_obj_as, parse_raw_as, root_validator
85
85
 
86
86
  class GitHubModel(BaseModel):
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,
@@ -22,7 +23,6 @@ import hishel
22
23
  from .response import Response
23
24
  from .utils import obj_to_jsonable
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")
@@ -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
- rep = Response(response, error_model)
326
- raise RequestFailed(rep)
327
- return Response(response, response_model)
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.request("POST", "/graphql", json=json, response_model=GraphQLResponse)
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
@@ -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(response: "Response[GraphQLResponse]") -> Dict[str, Any]:
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)
@@ -9,6 +9,7 @@ class SourceLocation(GitHubModel):
9
9
 
10
10
 
11
11
  class GraphQLError(GitHubModel):
12
+ type: str # https://github.com/octokit/graphql.js/pull/314
12
13
  message: str
13
14
  locations: Optional[List[SourceLocation]] = None
14
15
  path: Optional[List[Union[int, str]]] = None
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,7 +59,7 @@ 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.
githubkit/utils.py CHANGED
@@ -7,7 +7,7 @@ from pydantic_core import to_jsonable_python
7
7
 
8
8
  from .compat import PYDANTIC_V2, custom_validation, type_validate_python
9
9
 
10
- if PYDANTIC_V2:
10
+ if PYDANTIC_V2: # pragma: pydantic-v2
11
11
  from pydantic_core import core_schema
12
12
  from pydantic import GetCoreSchemaHandler
13
13
 
@@ -94,7 +94,7 @@ class TaggedUnion(Generic[T]):
94
94
  def _validate(self, value: Any) -> T:
95
95
  return type_validate_python(self.type_, value)
96
96
 
97
- if PYDANTIC_V2:
97
+ if PYDANTIC_V2: # pragma: pydantic-v2
98
98
 
99
99
  def __get_pydantic_core_schema__(
100
100
  self, _source_type: Any, _handler: "GetCoreSchemaHandler"
@@ -0,0 +1,8 @@
1
+ """DO NOT EDIT THIS FILE!
2
+
3
+ This file is automatically @generated by githubkit using the follow command:
4
+
5
+ python -m codegen && isort . && black .
6
+
7
+ See https://github.com/github/rest-api-description for more information.
8
+ """
@@ -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._github = github
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
- if version in self._cached_namespaces:
55
- return self._cached_namespaces[version]
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(self._github)
58
- self._cached_namespaces[version] = namespace
71
+ namespace = module.RestNamespace(g)
72
+ cache[version] = namespace
59
73
  return namespace
@@ -0,0 +1,8 @@
1
+ """DO NOT EDIT THIS FILE!
2
+
3
+ This file is automatically @generated by githubkit using the follow command:
4
+
5
+ python -m codegen && isort . && black .
6
+
7
+ See https://github.com/github/rest-api-description for more information.
8
+ """
@@ -7,6 +7,7 @@ python -m codegen && isort . && black .
7
7
  See https://github.com/github/rest-api-description for more information.
8
8
  """
9
9
 
10
+ from weakref import ref
10
11
  from typing import TYPE_CHECKING
11
12
  from functools import cached_property
12
13
 
@@ -52,7 +53,16 @@ if TYPE_CHECKING:
52
53
 
53
54
  class RestNamespace:
54
55
  def __init__(self, github: "GitHubCore"):
55
- self._github = github
56
+ self._github_ref = ref(github)
57
+
58
+ @property
59
+ def _github(self) -> "GitHubCore":
60
+ if g := self._github_ref():
61
+ return g
62
+ raise RuntimeError(
63
+ "GitHub client has already been collected. "
64
+ "Do not use this namespace after the client has been collected."
65
+ )
56
66
 
57
67
  @cached_property
58
68
  def meta(self) -> "MetaClient":
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -121,7 +122,16 @@ class ActionsClient:
121
122
  _REST_API_VERSION = "2022-11-28"
122
123
 
123
124
  def __init__(self, github: GitHubCore):
124
- self._github = github
125
+ self._github_ref = ref(github)
126
+
127
+ @property
128
+ def _github(self) -> GitHubCore:
129
+ if g := self._github_ref():
130
+ return g
131
+ raise RuntimeError(
132
+ "GitHub client has already been collected. "
133
+ "Do not use this client after the client has been collected."
134
+ )
125
135
 
126
136
  def get_actions_cache_usage_for_org(
127
137
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -54,7 +55,16 @@ class ActivityClient:
54
55
  _REST_API_VERSION = "2022-11-28"
55
56
 
56
57
  def __init__(self, github: GitHubCore):
57
- self._github = github
58
+ self._github_ref = ref(github)
59
+
60
+ @property
61
+ def _github(self) -> GitHubCore:
62
+ if g := self._github_ref():
63
+ return g
64
+ raise RuntimeError(
65
+ "GitHub client has already been collected. "
66
+ "Do not use this client after the client has been collected."
67
+ )
58
68
 
59
69
  def list_public_events(
60
70
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -62,7 +63,16 @@ class AppsClient:
62
63
  _REST_API_VERSION = "2022-11-28"
63
64
 
64
65
  def __init__(self, github: GitHubCore):
65
- self._github = github
66
+ self._github_ref = ref(github)
67
+
68
+ @property
69
+ def _github(self) -> GitHubCore:
70
+ if g := self._github_ref():
71
+ return g
72
+ raise RuntimeError(
73
+ "GitHub client has already been collected. "
74
+ "Do not use this client after the client has been collected."
75
+ )
66
76
 
67
77
  def get_authenticated(
68
78
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -30,7 +31,16 @@ class BillingClient:
30
31
  _REST_API_VERSION = "2022-11-28"
31
32
 
32
33
  def __init__(self, github: GitHubCore):
33
- self._github = github
34
+ self._github_ref = ref(github)
35
+
36
+ @property
37
+ def _github(self) -> GitHubCore:
38
+ if g := self._github_ref():
39
+ return g
40
+ raise RuntimeError(
41
+ "GitHub client has already been collected. "
42
+ "Do not use this client after the client has been collected."
43
+ )
34
44
 
35
45
  def get_github_actions_billing_org(
36
46
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -57,7 +58,16 @@ class ChecksClient:
57
58
  _REST_API_VERSION = "2022-11-28"
58
59
 
59
60
  def __init__(self, github: GitHubCore):
60
- self._github = github
61
+ self._github_ref = ref(github)
62
+
63
+ @property
64
+ def _github(self) -> GitHubCore:
65
+ if g := self._github_ref():
66
+ return g
67
+ raise RuntimeError(
68
+ "GitHub client has already been collected. "
69
+ "Do not use this client after the client has been collected."
70
+ )
61
71
 
62
72
  @overload
63
73
  def create(
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -41,7 +42,16 @@ class ClassroomClient:
41
42
  _REST_API_VERSION = "2022-11-28"
42
43
 
43
44
  def __init__(self, github: GitHubCore):
44
- self._github = github
45
+ self._github_ref = ref(github)
46
+
47
+ @property
48
+ def _github(self) -> GitHubCore:
49
+ if g := self._github_ref():
50
+ return g
51
+ raise RuntimeError(
52
+ "GitHub client has already been collected. "
53
+ "Do not use this client after the client has been collected."
54
+ )
45
55
 
46
56
  def get_an_assignment(
47
57
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -52,7 +53,16 @@ class CodeScanningClient:
52
53
  _REST_API_VERSION = "2022-11-28"
53
54
 
54
55
  def __init__(self, github: GitHubCore):
55
- self._github = github
56
+ self._github_ref = ref(github)
57
+
58
+ @property
59
+ def _github(self) -> GitHubCore:
60
+ if g := self._github_ref():
61
+ return g
62
+ raise RuntimeError(
63
+ "GitHub client has already been collected. "
64
+ "Do not use this client after the client has been collected."
65
+ )
56
66
 
57
67
  def list_alerts_for_org(
58
68
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -32,7 +33,16 @@ class CodesOfConductClient:
32
33
  _REST_API_VERSION = "2022-11-28"
33
34
 
34
35
  def __init__(self, github: GitHubCore):
35
- self._github = github
36
+ self._github_ref = ref(github)
37
+
38
+ @property
39
+ def _github(self) -> GitHubCore:
40
+ if g := self._github_ref():
41
+ return g
42
+ raise RuntimeError(
43
+ "GitHub client has already been collected. "
44
+ "Do not use this client after the client has been collected."
45
+ )
36
46
 
37
47
  def get_all_codes_of_conduct(
38
48
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -76,7 +77,16 @@ class CodespacesClient:
76
77
  _REST_API_VERSION = "2022-11-28"
77
78
 
78
79
  def __init__(self, github: GitHubCore):
79
- self._github = github
80
+ self._github_ref = ref(github)
81
+
82
+ @property
83
+ def _github(self) -> GitHubCore:
84
+ if g := self._github_ref():
85
+ return g
86
+ raise RuntimeError(
87
+ "GitHub client has already been collected. "
88
+ "Do not use this client after the client has been collected."
89
+ )
80
90
 
81
91
  def list_in_organization(
82
92
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -48,7 +49,16 @@ class CopilotClient:
48
49
  _REST_API_VERSION = "2022-11-28"
49
50
 
50
51
  def __init__(self, github: GitHubCore):
51
- self._github = github
52
+ self._github_ref = ref(github)
53
+
54
+ @property
55
+ def _github(self) -> GitHubCore:
56
+ if g := self._github_ref():
57
+ return g
58
+ raise RuntimeError(
59
+ "GitHub client has already been collected. "
60
+ "Do not use this client after the client has been collected."
61
+ )
52
62
 
53
63
  def get_copilot_organization_details(
54
64
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -50,7 +51,16 @@ class DependabotClient:
50
51
  _REST_API_VERSION = "2022-11-28"
51
52
 
52
53
  def __init__(self, github: GitHubCore):
53
- self._github = github
54
+ self._github_ref = ref(github)
55
+
56
+ @property
57
+ def _github(self) -> GitHubCore:
58
+ if g := self._github_ref():
59
+ return g
60
+ raise RuntimeError(
61
+ "GitHub client has already been collected. "
62
+ "Do not use this client after the client has been collected."
63
+ )
54
64
 
55
65
  def list_alerts_for_enterprise(
56
66
  self,
@@ -10,6 +10,7 @@ See https://github.com/github/rest-api-description for more information.
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ from weakref import ref
13
14
  from typing_extensions import Annotated
14
15
  from typing import TYPE_CHECKING, Dict, Literal, Optional, overload
15
16
 
@@ -46,7 +47,16 @@ class DependencyGraphClient:
46
47
  _REST_API_VERSION = "2022-11-28"
47
48
 
48
49
  def __init__(self, github: GitHubCore):
49
- self._github = github
50
+ self._github_ref = ref(github)
51
+
52
+ @property
53
+ def _github(self) -> GitHubCore:
54
+ if g := self._github_ref():
55
+ return g
56
+ raise RuntimeError(
57
+ "GitHub client has already been collected. "
58
+ "Do not use this client after the client has been collected."
59
+ )
50
60
 
51
61
  def diff_range(
52
62
  self,