gitcode-api 1.2.20__py3-none-any.whl → 1.3.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.
Files changed (43) hide show
  1. gitcode_api/__init__.py +8 -2
  2. gitcode_api/_base_client.py +7 -2
  3. gitcode_api/_exceptions.py +8 -0
  4. gitcode_api/exceptions.py +19 -0
  5. gitcode_api/llm/mcp.py +5 -5
  6. gitcode_api/models.py +205 -0
  7. gitcode_api/resources/__init__.py +1 -1
  8. gitcode_api/resources/_shared/__init__.py +18 -0
  9. gitcode_api/resources/_shared/base.py +129 -0
  10. gitcode_api/resources/{_shared.py → _shared/fetch_template.py} +133 -259
  11. gitcode_api/resources/account/__init__.py +17 -0
  12. gitcode_api/resources/account/oauth_resource_group.py +159 -0
  13. gitcode_api/resources/account/orgs_resource_group.py +422 -0
  14. gitcode_api/resources/account/search_resource_group.py +236 -0
  15. gitcode_api/resources/account/users_resource_group.py +249 -0
  16. gitcode_api/resources/collaboration/__init__.py +20 -0
  17. gitcode_api/resources/collaboration/_helpers.py +10 -0
  18. gitcode_api/resources/collaboration/issues_resource_group.py +855 -0
  19. gitcode_api/resources/collaboration/labels_resource_group.py +248 -0
  20. gitcode_api/resources/collaboration/members_resource_group.py +195 -0
  21. gitcode_api/resources/collaboration/milestones_resource_group.py +192 -0
  22. gitcode_api/resources/collaboration/pulls_resource_group.py +1300 -0
  23. gitcode_api/resources/misc/__init__.py +14 -0
  24. gitcode_api/resources/misc/releases_resource_group.py +445 -0
  25. gitcode_api/resources/misc/tags_resource_group.py +286 -0
  26. gitcode_api/resources/misc/webhooks_resource_group.py +192 -0
  27. gitcode_api/resources/repositories/__init__.py +17 -0
  28. gitcode_api/resources/repositories/branches_resource_group.py +151 -0
  29. gitcode_api/resources/repositories/commits_resource_group.py +333 -0
  30. gitcode_api/resources/repositories/repo_contents_resource_group.py +459 -0
  31. gitcode_api/resources/repositories/repos_resource_group.py +1279 -0
  32. gitcode_api/version.txt +1 -1
  33. {gitcode_api-1.2.20.dist-info → gitcode_api-1.3.0.dist-info}/METADATA +3 -3
  34. gitcode_api-1.3.0.dist-info/RECORD +52 -0
  35. gitcode_api/resources/account.py +0 -1086
  36. gitcode_api/resources/collaboration.py +0 -2818
  37. gitcode_api/resources/misc.py +0 -901
  38. gitcode_api/resources/repositories.py +0 -2197
  39. gitcode_api-1.2.20.dist-info/RECORD +0 -31
  40. {gitcode_api-1.2.20.dist-info → gitcode_api-1.3.0.dist-info}/WHEEL +0 -0
  41. {gitcode_api-1.2.20.dist-info → gitcode_api-1.3.0.dist-info}/entry_points.txt +0 -0
  42. {gitcode_api-1.2.20.dist-info → gitcode_api-1.3.0.dist-info}/licenses/LICENSE +0 -0
  43. {gitcode_api-1.2.20.dist-info → gitcode_api-1.3.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,855 @@
1
+ """AbstractIssuesResource, IssuesResource, and AsyncIssuesResource resource group."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import List, Optional, Union
5
+
6
+ from ..._models import (
7
+ Issue,
8
+ IssueComment,
9
+ IssueOperationLog,
10
+ Label,
11
+ PullRequest,
12
+ RepositoryGitCodeTemplate,
13
+ as_model,
14
+ )
15
+ from ...constants import GITCODE_ISSUE_TEMPLATE_PATH_RE
16
+ from .._shared import (
17
+ AsyncResource,
18
+ SyncResource,
19
+ get_gitcode_template_body_async,
20
+ get_gitcode_template_body_sync,
21
+ list_gitcode_template_rows_async,
22
+ list_gitcode_template_rows_sync,
23
+ )
24
+ from ._helpers import _comma_join
25
+
26
+ # mypy: disable-error-code=override
27
+ # pylint: disable=invalid-overridden-method,protected-access,redefined-builtin,duplicate-code
28
+
29
+
30
+ class AbstractIssuesResource(ABC):
31
+ """Interface for Issues resource endpoints."""
32
+
33
+ @abstractmethod
34
+ def list(
35
+ self,
36
+ *,
37
+ owner: Optional[str] = None,
38
+ repo: Optional[str] = None,
39
+ state: Optional[str] = None,
40
+ sort: Optional[str] = None,
41
+ direction: Optional[str] = None,
42
+ page: Optional[int] = None,
43
+ per_page: Optional[int] = None,
44
+ ) -> List[Issue]:
45
+ """List issues for a repository.
46
+
47
+ :param owner: Repository owner path. Uses the client default when omitted.
48
+ :param repo: Repository name. Uses the client default when omitted.
49
+ :param state: Issue state filter such as ``open`` or ``closed`` (see Issues API).
50
+ :param sort: Optional sort field.
51
+ :param direction: Optional sort direction.
52
+ :param page: Page number.
53
+ :param per_page: Page size.
54
+ :returns: Matching issues.
55
+ """
56
+
57
+ @abstractmethod
58
+ def get(self, *, number: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None) -> Issue:
59
+ """Get a single issue by number.
60
+
61
+ :param number: Repository-local issue number.
62
+ :param owner: Repository owner path. Uses the client default when omitted.
63
+ :param repo: Repository name. Uses the client default when omitted.
64
+ :returns: Issue details.
65
+ """
66
+
67
+ @abstractmethod
68
+ def create(
69
+ self,
70
+ *,
71
+ owner: str,
72
+ repo: Optional[str] = None,
73
+ title: str,
74
+ body: Optional[str] = None,
75
+ assignee: Optional[str] = None,
76
+ labels: Optional[List[str]] = None,
77
+ milestone: Union[int, str, None] = None,
78
+ security_hole: Optional[str] = None,
79
+ ) -> Issue:
80
+ """Create an issue for a repository.
81
+
82
+ :param owner: Repository owner path.
83
+ :param repo: Repository name. Uses the client default when omitted.
84
+ :param title: Issue title.
85
+ :param body: Optional issue description.
86
+ :param assignee: Optional assignee username.
87
+ :param labels: Optional label names.
88
+ :param milestone: Optional milestone identifier.
89
+ :param security_hole: Whether the issue is private; form field described in the Issues API (default public).
90
+ :returns: Created issue details.
91
+ """
92
+
93
+ @abstractmethod
94
+ def update(
95
+ self,
96
+ *,
97
+ number: Union[int, str],
98
+ owner: str,
99
+ repo: Optional[str] = None,
100
+ title: Optional[str] = None,
101
+ body: Optional[str] = None,
102
+ state: Optional[str] = None,
103
+ assignee: Optional[str] = None,
104
+ labels: Optional[List[str]] = None,
105
+ milestone: Union[int, str, None] = None,
106
+ security_hole: Optional[str] = None,
107
+ ) -> Issue:
108
+ """Update an existing issue.
109
+
110
+ :param number: Repository-local issue number.
111
+ :param owner: Repository owner path.
112
+ :param repo: Repository name. Uses the client default when omitted.
113
+ :param title: Updated issue title.
114
+ :param body: Updated issue description.
115
+ :param state: Updated state such as ``reopen`` or ``close``.
116
+ :param assignee: Updated assignee username.
117
+ :param labels: Replacement label names.
118
+ :param milestone: Updated milestone identifier.
119
+ :param security_hole: Whether the issue is private; form field described in the Issues API.
120
+ :returns: Updated issue details.
121
+ """
122
+
123
+ @abstractmethod
124
+ def list_comments(
125
+ self,
126
+ *,
127
+ number: Union[int, str],
128
+ owner: Optional[str] = None,
129
+ repo: Optional[str] = None,
130
+ page: Optional[int] = None,
131
+ per_page: Optional[int] = None,
132
+ ) -> List[IssueComment]:
133
+ """List comments for an issue.
134
+
135
+ :param number: Repository-local issue number.
136
+ :param owner: Repository owner path. Uses the client default when omitted.
137
+ :param repo: Repository path (name). Uses the client default when omitted.
138
+ :param page: Current page number (query).
139
+ :param per_page: Page size; maximum per REST API is typically 100.
140
+ :returns: Issue comments.
141
+ """
142
+
143
+ @abstractmethod
144
+ def create_comment(
145
+ self,
146
+ *,
147
+ number: Union[int, str],
148
+ body: str,
149
+ owner: Optional[str] = None,
150
+ repo: Optional[str] = None,
151
+ ) -> IssueComment:
152
+ """Create a comment on an issue.
153
+
154
+ :param number: Repository-local issue number.
155
+ :param body: Comment body text.
156
+ :param owner: Repository owner path. Uses the client default when omitted.
157
+ :param repo: Repository path. Uses the client default when omitted.
158
+ :returns: Created comment.
159
+ """
160
+
161
+ @abstractmethod
162
+ def get_comment(
163
+ self,
164
+ *,
165
+ comment_id: Union[int, str],
166
+ owner: Optional[str] = None,
167
+ repo: Optional[str] = None,
168
+ ) -> IssueComment:
169
+ """Get a single issue comment by identifier.
170
+
171
+ :param comment_id: Comment id from the API.
172
+ :param owner: Repository owner path. Uses the client default when omitted.
173
+ :param repo: Repository path. Uses the client default when omitted.
174
+ :returns: Issue comment.
175
+ """
176
+
177
+ @abstractmethod
178
+ def update_comment(
179
+ self,
180
+ *,
181
+ comment_id: Union[int, str],
182
+ body: str,
183
+ owner: Optional[str] = None,
184
+ repo: Optional[str] = None,
185
+ ) -> IssueComment:
186
+ """Update an issue comment.
187
+
188
+ :param comment_id: Comment id from the API.
189
+ :param body: Updated comment body.
190
+ :param owner: Repository owner path. Uses the client default when omitted.
191
+ :param repo: Repository path. Uses the client default when omitted.
192
+ :returns: Updated comment.
193
+ """
194
+
195
+ @abstractmethod
196
+ def delete_comment(
197
+ self, *, comment_id: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
198
+ ) -> None:
199
+ """Delete an issue comment.
200
+
201
+ :param comment_id: Comment id from the API.
202
+ :param owner: Repository owner path. Uses the client default when omitted.
203
+ :param repo: Repository path. Uses the client default when omitted.
204
+ """
205
+
206
+ @abstractmethod
207
+ def list_pull_requests(
208
+ self, *, number: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
209
+ ) -> List[PullRequest]:
210
+ """List pull requests associated with an issue.
211
+
212
+ :param number: Repository-local issue number.
213
+ :param owner: Repository owner path. Uses the client default when omitted.
214
+ :param repo: Repository path. Uses the client default when omitted.
215
+ :returns: Pull requests linked to the issue.
216
+ """
217
+
218
+ @abstractmethod
219
+ def add_labels(
220
+ self, *, number: Union[int, str], labels: List[str], owner: Optional[str] = None, repo: Optional[str] = None
221
+ ) -> List[Label]:
222
+ """Add labels to an issue.
223
+
224
+ :param number: Repository-local issue number.
225
+ :param labels: Label names to add (request body is a JSON array per REST API).
226
+ :param owner: Repository owner path. Uses the client default when omitted.
227
+ :param repo: Repository path. Uses the client default when omitted.
228
+ :returns: Labels on the issue after the operation.
229
+ """
230
+
231
+ @abstractmethod
232
+ def remove_label(
233
+ self, *, number: Union[int, str], name: str, owner: Optional[str] = None, repo: Optional[str] = None
234
+ ) -> None:
235
+ """Remove one label from an issue (REST path includes the label name).
236
+
237
+ :param number: Repository-local issue number.
238
+ :param name: Label name to remove.
239
+ :param owner: Repository owner path. Uses the client default when omitted.
240
+ :param repo: Repository path. Uses the client default when omitted.
241
+ """
242
+
243
+ @abstractmethod
244
+ def list_enterprise(self, *, enterprise: str, **params) -> List[Issue]:
245
+ """List enterprise issues visible to the caller.
246
+
247
+ :param enterprise: Enterprise path or login.
248
+ :param params: Additional query parameters accepted by ``GET .../enterprises/{enterprise}/issues``.
249
+ :returns: Enterprise-scoped issues.
250
+ """
251
+
252
+ @abstractmethod
253
+ def list_user(self, **params) -> List[Issue]:
254
+ """List issues for the authenticated user.
255
+
256
+ :param params: Query parameters for ``GET /user/issues`` (filters, pagination, etc.).
257
+ :returns: Issues assigned to or authored by the user, per API rules.
258
+ """
259
+
260
+ @abstractmethod
261
+ def list_org(self, *, org: str, **params) -> List[Issue]:
262
+ """List organization issues visible to the current user.
263
+
264
+ :param org: Organization path or login.
265
+ :param params: Query parameters for ``GET .../orgs/{org}/issues``.
266
+ :returns: Organization-scoped issues.
267
+ """
268
+
269
+ @abstractmethod
270
+ def get_enterprise_issue(self, *, enterprise: str, number: Union[int, str]) -> Issue:
271
+ """Get a specific enterprise issue.
272
+
273
+ :param enterprise: Enterprise path or login.
274
+ :param number: Enterprise issue id or number as accepted by the API path.
275
+ :returns: Issue payload.
276
+ """
277
+
278
+ @abstractmethod
279
+ def list_enterprise_comments(self, *, enterprise: str, number: Union[int, str], **params) -> List[IssueComment]:
280
+ """List comments for an enterprise issue.
281
+
282
+ :param enterprise: Enterprise path or login.
283
+ :param number: Enterprise issue identifier in the path.
284
+ :param params: Optional pagination or filter query parameters.
285
+ :returns: Comments on the enterprise issue.
286
+ """
287
+
288
+ @abstractmethod
289
+ def list_enterprise_labels(self, *, enterprise: str, issue_id: Union[int, str]) -> List[Label]:
290
+ """List labels attached to an enterprise issue.
291
+
292
+ :param enterprise: Enterprise path or login.
293
+ :param issue_id: Enterprise issue id in the path segment ``.../issues/{issue_id}/labels``.
294
+ :returns: Labels on the issue.
295
+ """
296
+
297
+ @abstractmethod
298
+ def list_operation_logs(
299
+ self, *, owner: str, number: Union[int, str], page: Optional[int] = None, per_page: Optional[int] = None
300
+ ) -> List[IssueOperationLog]:
301
+ """List operation (audit) logs for an issue.
302
+
303
+ :param owner: Repository owner path (path segment ``repos/{owner}/...`` for this endpoint).
304
+ :param number: Repository-local issue number.
305
+ :param page: Page number.
306
+ :param per_page: Page size.
307
+ :returns: Operation log entries.
308
+ """
309
+
310
+ @abstractmethod
311
+ def list_templates(
312
+ self,
313
+ *,
314
+ owner: Optional[str] = None,
315
+ repo: Optional[str] = None,
316
+ ) -> List[RepositoryGitCodeTemplate]:
317
+ """List active issue templates under ``.gitcode/`` for this repository.
318
+
319
+ Matches Markdown (``.md``, ``.markdown``) and YAML (``.yml`` / ``.yaml``) paths whose
320
+ names start with ``ISSUE_TEMPLATE`` under ``.gitcode/`` (case-insensitive), including
321
+ files inside localized directories such as ``.gitcode/ISSUE_TEMPLATE.en/``.
322
+
323
+ Resolution tries the repository, then the owner's ``.gitcode`` repository, then any
324
+ parent main and ``parent/.gitcode`` pairs discovered from forks (each candidate is
325
+ inspected with ``GET /repos/{owner}/{repo}``; when ``fork`` is true, its parent's repos
326
+ are appended, deduplicated, and visited in order). The first source with matching
327
+ templates wins.
328
+
329
+ Version 1.2.19: Now also supporting GitHub-mirrored repos with a ``.github/`` folder.
330
+
331
+ :param owner: Repository owner path. Uses the client default when omitted.
332
+ :param repo: Repository name. Uses the client default when omitted.
333
+ :returns: Template metadata entries (paths and SHAs); empty when none match.
334
+ """
335
+
336
+ @abstractmethod
337
+ def get_template(
338
+ self,
339
+ *,
340
+ path: str,
341
+ owner: Optional[str] = None,
342
+ repo: Optional[str] = None,
343
+ encoding: str = "utf-8",
344
+ **decoding_kwargs,
345
+ ) -> str:
346
+ """Load a single issue template file body from the default branch.
347
+
348
+ Uses the same resolution order as :meth:`list_templates`. The path must match the
349
+ active issue template naming convention (see GitCode ``.gitcode`` documentation).
350
+
351
+ :param path: Repository-relative path such as ``.gitcode/ISSUE_TEMPLATE_bug.md`` or
352
+ ``.gitcode/ISSUE_TEMPLATE/config.yml``.
353
+ :param owner: Repository owner path. Uses the client default when omitted.
354
+ :param repo: Repository name. Uses the client default when omitted.
355
+ :param encoding: Codec to use when decoding raw file bytes. Default ``utf-8``.
356
+ :param decoding_kwargs: Keyword arguments forwarded to :meth:`bytes.decode`, such as
357
+ ``errors`` (``"strict"``, ``"ignore"``, or ``"replace"``).
358
+ :returns: Decoded template file contents.
359
+ """
360
+
361
+
362
+ class IssuesResource(SyncResource, AbstractIssuesResource):
363
+ """Synchronous issue endpoints."""
364
+
365
+ def list(
366
+ self,
367
+ *,
368
+ owner: Optional[str] = None,
369
+ repo: Optional[str] = None,
370
+ state: Optional[str] = None,
371
+ sort: Optional[str] = None,
372
+ direction: Optional[str] = None,
373
+ page: Optional[int] = None,
374
+ per_page: Optional[int] = None,
375
+ ) -> List[Issue]:
376
+ return self._models(
377
+ "GET",
378
+ self._client._repo_path("issues", owner=owner, repo=repo),
379
+ Issue,
380
+ params={
381
+ "state": state,
382
+ "sort": sort,
383
+ "direction": direction,
384
+ "page": page,
385
+ "per_page": per_page,
386
+ },
387
+ )
388
+
389
+ def get(self, *, number: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None) -> Issue:
390
+ return self._model("GET", self._client._repo_path("issues", number, owner=owner, repo=repo), Issue)
391
+
392
+ def create(
393
+ self,
394
+ *,
395
+ owner: str,
396
+ repo: Optional[str] = None,
397
+ title: str,
398
+ body: Optional[str] = None,
399
+ assignee: Optional[str] = None,
400
+ labels: Optional[List[str]] = None,
401
+ milestone: Union[int, str, None] = None,
402
+ security_hole: Optional[str] = None,
403
+ ) -> Issue:
404
+ resolved_repo = repo or self._client.repo
405
+ return self._model(
406
+ "POST",
407
+ self._client._path("repos", owner, "issues"),
408
+ Issue,
409
+ json={
410
+ "repo": resolved_repo,
411
+ "title": title,
412
+ "body": body,
413
+ "assignee": assignee,
414
+ "labels": _comma_join(labels),
415
+ "milestone": milestone,
416
+ "security_hole": security_hole,
417
+ },
418
+ )
419
+
420
+ def update(
421
+ self,
422
+ *,
423
+ number: Union[int, str],
424
+ owner: str,
425
+ repo: Optional[str] = None,
426
+ title: Optional[str] = None,
427
+ body: Optional[str] = None,
428
+ state: Optional[str] = None,
429
+ assignee: Optional[str] = None,
430
+ labels: Optional[List[str]] = None,
431
+ milestone: Union[int, str, None] = None,
432
+ security_hole: Optional[str] = None,
433
+ ) -> Issue:
434
+ resolved_repo = repo or self._client.repo
435
+ return self._model(
436
+ "PATCH",
437
+ self._client._path("repos", owner, "issues", number),
438
+ Issue,
439
+ json={
440
+ "repo": resolved_repo,
441
+ "title": title,
442
+ "body": body,
443
+ "state": state,
444
+ "assignee": assignee,
445
+ "labels": _comma_join(labels),
446
+ "milestone": milestone,
447
+ "security_hole": security_hole,
448
+ },
449
+ )
450
+
451
+ def list_comments(
452
+ self,
453
+ *,
454
+ number: Union[int, str],
455
+ owner: Optional[str] = None,
456
+ repo: Optional[str] = None,
457
+ page: Optional[int] = None,
458
+ per_page: Optional[int] = None,
459
+ ) -> List[IssueComment]:
460
+ return self._models(
461
+ "GET",
462
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
463
+ IssueComment,
464
+ params={"page": page, "per_page": per_page},
465
+ )
466
+
467
+ def create_comment(
468
+ self,
469
+ *,
470
+ number: Union[int, str],
471
+ body: str,
472
+ owner: Optional[str] = None,
473
+ repo: Optional[str] = None,
474
+ ) -> IssueComment:
475
+ return self._model(
476
+ "POST",
477
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
478
+ IssueComment,
479
+ json={"body": body},
480
+ )
481
+
482
+ def get_comment(
483
+ self,
484
+ *,
485
+ comment_id: Union[int, str],
486
+ owner: Optional[str] = None,
487
+ repo: Optional[str] = None,
488
+ ) -> IssueComment:
489
+ return self._model(
490
+ "GET",
491
+ self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo),
492
+ IssueComment,
493
+ )
494
+
495
+ def update_comment(
496
+ self,
497
+ *,
498
+ comment_id: Union[int, str],
499
+ body: str,
500
+ owner: Optional[str] = None,
501
+ repo: Optional[str] = None,
502
+ ) -> IssueComment:
503
+ return self._model(
504
+ "PATCH",
505
+ self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo),
506
+ IssueComment,
507
+ json={"body": body},
508
+ )
509
+
510
+ def delete_comment(
511
+ self, *, comment_id: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
512
+ ) -> None:
513
+ self._request("DELETE", self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo))
514
+
515
+ def list_pull_requests(
516
+ self, *, number: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
517
+ ) -> List[PullRequest]:
518
+ return self._models(
519
+ "GET",
520
+ self._client._repo_path("issues", number, "pull_requests", owner=owner, repo=repo),
521
+ PullRequest,
522
+ )
523
+
524
+ def add_labels(
525
+ self, *, number: Union[int, str], labels: List[str], owner: Optional[str] = None, repo: Optional[str] = None
526
+ ) -> List[Label]:
527
+ return self._models(
528
+ "POST",
529
+ self._client._repo_path("issues", number, "labels", owner=owner, repo=repo),
530
+ Label,
531
+ json=labels,
532
+ )
533
+
534
+ def remove_label(
535
+ self, *, number: Union[int, str], name: str, owner: Optional[str] = None, repo: Optional[str] = None
536
+ ) -> None:
537
+ self._request("DELETE", self._client._repo_path("issues", number, "labels", name, owner=owner, repo=repo))
538
+
539
+ def list_enterprise(self, *, enterprise: str, **params) -> List[Issue]:
540
+ return self._models("GET", self._client._path("enterprises", enterprise, "issues"), Issue, params=params)
541
+
542
+ def list_user(self, **params) -> List[Issue]:
543
+ return self._models("GET", self._client._path("user", "issues"), Issue, params=params)
544
+
545
+ def list_org(self, *, org: str, **params) -> List[Issue]:
546
+ return self._models("GET", self._client._path("orgs", org, "issues"), Issue, params=params)
547
+
548
+ def get_enterprise_issue(self, *, enterprise: str, number: Union[int, str]) -> Issue:
549
+ return self._model("GET", self._client._path("enterprises", enterprise, "issues", number), Issue)
550
+
551
+ def list_enterprise_comments(self, *, enterprise: str, number: Union[int, str], **params) -> List[IssueComment]:
552
+ return self._models(
553
+ "GET",
554
+ self._client._path("enterprises", enterprise, "issues", number, "comments"),
555
+ IssueComment,
556
+ params=params,
557
+ )
558
+
559
+ def list_enterprise_labels(self, *, enterprise: str, issue_id: Union[int, str]) -> List[Label]:
560
+ return self._models("GET", self._client._path("enterprises", enterprise, "issues", issue_id, "labels"), Label)
561
+
562
+ def list_operation_logs(
563
+ self, *, owner: str, number: Union[int, str], page: Optional[int] = None, per_page: Optional[int] = None
564
+ ) -> List[IssueOperationLog]:
565
+ return self._models(
566
+ "GET",
567
+ self._client._path("repos", owner, "issues", number, "operate_logs"),
568
+ IssueOperationLog,
569
+ params={"page": page, "per_page": per_page},
570
+ )
571
+
572
+ def list_templates(
573
+ self,
574
+ *,
575
+ owner: Optional[str] = None,
576
+ repo: Optional[str] = None,
577
+ ) -> List[RepositoryGitCodeTemplate]:
578
+ resolved_owner, resolved_repo = self._client._resolve_repo_context(owner, repo)
579
+ rows = list_gitcode_template_rows_sync(
580
+ self._client, resolved_owner, resolved_repo, GITCODE_ISSUE_TEMPLATE_PATH_RE
581
+ )
582
+ return [
583
+ as_model(
584
+ {
585
+ "path": path,
586
+ "sha": sha,
587
+ "template_owner": template_owner,
588
+ "template_repo": template_repo,
589
+ },
590
+ RepositoryGitCodeTemplate,
591
+ )
592
+ for template_owner, template_repo, path, sha in rows
593
+ ]
594
+
595
+ def get_template(
596
+ self,
597
+ *,
598
+ path: str,
599
+ owner: Optional[str] = None,
600
+ repo: Optional[str] = None,
601
+ encoding: str = "utf-8",
602
+ **decoding_kwargs,
603
+ ) -> str:
604
+ resolved_owner, resolved_repo = self._client._resolve_repo_context(owner, repo)
605
+ return get_gitcode_template_body_sync(
606
+ self._client,
607
+ path,
608
+ GITCODE_ISSUE_TEMPLATE_PATH_RE,
609
+ resolved_owner,
610
+ resolved_repo,
611
+ encoding=encoding,
612
+ **decoding_kwargs,
613
+ )
614
+
615
+
616
+ class AsyncIssuesResource(AsyncResource, AbstractIssuesResource):
617
+ """Asynchronous issue endpoints.
618
+
619
+ Methods correspond one-to-one with :class:`IssuesResource`; signatures, JSON/query
620
+ payloads, and return types are the same. Refer to the synchronous class for full
621
+ parameter descriptions aligned with ``docs/rest_api`` (Issues API).
622
+ """
623
+
624
+ async def list(
625
+ self,
626
+ *,
627
+ owner: Optional[str] = None,
628
+ repo: Optional[str] = None,
629
+ state: Optional[str] = None,
630
+ sort: Optional[str] = None,
631
+ direction: Optional[str] = None,
632
+ page: Optional[int] = None,
633
+ per_page: Optional[int] = None,
634
+ ) -> List[Issue]:
635
+ return await self._models(
636
+ "GET",
637
+ self._client._repo_path("issues", owner=owner, repo=repo),
638
+ Issue,
639
+ params={
640
+ "state": state,
641
+ "sort": sort,
642
+ "direction": direction,
643
+ "page": page,
644
+ "per_page": per_page,
645
+ },
646
+ )
647
+
648
+ async def get(self, *, number: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None) -> Issue:
649
+ return await self._model("GET", self._client._repo_path("issues", number, owner=owner, repo=repo), Issue)
650
+
651
+ async def create(
652
+ self,
653
+ *,
654
+ owner: str,
655
+ repo: Optional[str] = None,
656
+ title: str,
657
+ body: Optional[str] = None,
658
+ assignee: Optional[str] = None,
659
+ labels: Optional[List[str]] = None,
660
+ milestone: Union[int, str, None] = None,
661
+ security_hole: Optional[str] = None,
662
+ ) -> Issue:
663
+ resolved_repo = repo or self._client.repo
664
+ return await self._model(
665
+ "POST",
666
+ self._client._path("repos", owner, "issues"),
667
+ Issue,
668
+ json={
669
+ "repo": resolved_repo,
670
+ "title": title,
671
+ "body": body,
672
+ "assignee": assignee,
673
+ "labels": _comma_join(labels),
674
+ "milestone": milestone,
675
+ "security_hole": security_hole,
676
+ },
677
+ )
678
+
679
+ async def update(
680
+ self,
681
+ *,
682
+ number: Union[int, str],
683
+ owner: str,
684
+ repo: Optional[str] = None,
685
+ title: Optional[str] = None,
686
+ body: Optional[str] = None,
687
+ state: Optional[str] = None,
688
+ assignee: Optional[str] = None,
689
+ labels: Optional[List[str]] = None,
690
+ milestone: Union[int, str, None] = None,
691
+ security_hole: Optional[str] = None,
692
+ ) -> Issue:
693
+ resolved_repo = repo or self._client.repo
694
+ return await self._model(
695
+ "PATCH",
696
+ self._client._path("repos", owner, "issues", number),
697
+ Issue,
698
+ json={
699
+ "repo": resolved_repo,
700
+ "title": title,
701
+ "body": body,
702
+ "state": state,
703
+ "assignee": assignee,
704
+ "labels": _comma_join(labels),
705
+ "milestone": milestone,
706
+ "security_hole": security_hole,
707
+ },
708
+ )
709
+
710
+ async def list_comments(
711
+ self,
712
+ *,
713
+ number: Union[int, str],
714
+ owner: Optional[str] = None,
715
+ repo: Optional[str] = None,
716
+ page: Optional[int] = None,
717
+ per_page: Optional[int] = None,
718
+ ) -> List[IssueComment]:
719
+ return await self._models(
720
+ "GET",
721
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
722
+ IssueComment,
723
+ params={"page": page, "per_page": per_page},
724
+ )
725
+
726
+ async def create_comment(
727
+ self, *, number: Union[int, str], body: str, owner: Optional[str] = None, repo: Optional[str] = None
728
+ ) -> IssueComment:
729
+ return await self._model(
730
+ "POST",
731
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
732
+ IssueComment,
733
+ json={"body": body},
734
+ )
735
+
736
+ async def get_comment(
737
+ self, *, comment_id: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
738
+ ) -> IssueComment:
739
+ return await self._model(
740
+ "GET", self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo), IssueComment
741
+ )
742
+
743
+ async def update_comment(
744
+ self, *, comment_id: Union[int, str], body: str, owner: Optional[str] = None, repo: Optional[str] = None
745
+ ) -> IssueComment:
746
+ return await self._model(
747
+ "PATCH",
748
+ self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo),
749
+ IssueComment,
750
+ json={"body": body},
751
+ )
752
+
753
+ async def delete_comment(
754
+ self, *, comment_id: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
755
+ ) -> None:
756
+ await self._request("DELETE", self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo))
757
+
758
+ async def list_pull_requests(
759
+ self, *, number: Union[int, str], owner: Optional[str] = None, repo: Optional[str] = None
760
+ ) -> List[PullRequest]:
761
+ return await self._models(
762
+ "GET", self._client._repo_path("issues", number, "pull_requests", owner=owner, repo=repo), PullRequest
763
+ )
764
+
765
+ async def add_labels(
766
+ self, *, number: Union[int, str], labels: List[str], owner: Optional[str] = None, repo: Optional[str] = None
767
+ ) -> List[Label]:
768
+ return await self._models(
769
+ "POST", self._client._repo_path("issues", number, "labels", owner=owner, repo=repo), Label, json=labels
770
+ )
771
+
772
+ async def remove_label(
773
+ self, *, number: Union[int, str], name: str, owner: Optional[str] = None, repo: Optional[str] = None
774
+ ) -> None:
775
+ await self._request("DELETE", self._client._repo_path("issues", number, "labels", name, owner=owner, repo=repo))
776
+
777
+ async def list_enterprise(self, *, enterprise: str, **params) -> List[Issue]:
778
+ return await self._models("GET", self._client._path("enterprises", enterprise, "issues"), Issue, params=params)
779
+
780
+ async def list_user(self, **params) -> List[Issue]:
781
+ return await self._models("GET", self._client._path("user", "issues"), Issue, params=params)
782
+
783
+ async def list_org(self, *, org: str, **params) -> List[Issue]:
784
+ return await self._models("GET", self._client._path("orgs", org, "issues"), Issue, params=params)
785
+
786
+ async def get_enterprise_issue(self, *, enterprise: str, number: Union[int, str]) -> Issue:
787
+ return await self._model("GET", self._client._path("enterprises", enterprise, "issues", number), Issue)
788
+
789
+ async def list_enterprise_comments(
790
+ self, *, enterprise: str, number: Union[int, str], **params
791
+ ) -> List[IssueComment]:
792
+ return await self._models(
793
+ "GET",
794
+ self._client._path("enterprises", enterprise, "issues", number, "comments"),
795
+ IssueComment,
796
+ params=params,
797
+ )
798
+
799
+ async def list_enterprise_labels(self, *, enterprise: str, issue_id: Union[int, str]) -> List[Label]:
800
+ return await self._models(
801
+ "GET", self._client._path("enterprises", enterprise, "issues", issue_id, "labels"), Label
802
+ )
803
+
804
+ async def list_operation_logs(
805
+ self, *, owner: str, number: Union[int, str], page: Optional[int] = None, per_page: Optional[int] = None
806
+ ) -> List[IssueOperationLog]:
807
+ return await self._models(
808
+ "GET",
809
+ self._client._path("repos", owner, "issues", number, "operate_logs"),
810
+ IssueOperationLog,
811
+ params={"page": page, "per_page": per_page},
812
+ )
813
+
814
+ async def list_templates(
815
+ self,
816
+ *,
817
+ owner: Optional[str] = None,
818
+ repo: Optional[str] = None,
819
+ ) -> List[RepositoryGitCodeTemplate]:
820
+ resolved_owner, resolved_repo = self._client._resolve_repo_context(owner, repo)
821
+ rows = await list_gitcode_template_rows_async(
822
+ self._client, resolved_owner, resolved_repo, GITCODE_ISSUE_TEMPLATE_PATH_RE
823
+ )
824
+ return [
825
+ as_model(
826
+ {
827
+ "path": path,
828
+ "sha": sha,
829
+ "template_owner": template_owner,
830
+ "template_repo": template_repo,
831
+ },
832
+ RepositoryGitCodeTemplate,
833
+ )
834
+ for template_owner, template_repo, path, sha in rows
835
+ ]
836
+
837
+ async def get_template(
838
+ self,
839
+ *,
840
+ path: str,
841
+ owner: Optional[str] = None,
842
+ repo: Optional[str] = None,
843
+ encoding: str = "utf-8",
844
+ **decoding_kwargs,
845
+ ) -> str:
846
+ resolved_owner, resolved_repo = self._client._resolve_repo_context(owner, repo)
847
+ return await get_gitcode_template_body_async(
848
+ self._client,
849
+ path,
850
+ GITCODE_ISSUE_TEMPLATE_PATH_RE,
851
+ resolved_owner,
852
+ resolved_repo,
853
+ encoding=encoding,
854
+ **decoding_kwargs,
855
+ )