gitcode-api 1.0.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.
@@ -0,0 +1,1451 @@
1
+ """Issue, pull request, label, milestone, and member resource groups."""
2
+
3
+ from typing import Any, List
4
+
5
+ from .._models import (
6
+ APIObject,
7
+ Issue,
8
+ IssueComment,
9
+ IssueOperationLog,
10
+ Label,
11
+ MergeResult,
12
+ MergeStatus,
13
+ Milestone,
14
+ PullRequest,
15
+ PullRequestComment,
16
+ PullRequestFile,
17
+ PullRequestReview,
18
+ PullRequestTest,
19
+ RepoMember,
20
+ RepoMemberPermission,
21
+ as_model,
22
+ )
23
+ from ._shared import AsyncResource, SyncResource
24
+
25
+
26
+ def _comma_join(values: List[str] | None) -> str | None:
27
+ """Join a list of strings into the comma-separated format used by the API."""
28
+ if not values:
29
+ return None
30
+ return ",".join(values)
31
+
32
+
33
+ class IssuesResource(SyncResource):
34
+ """Synchronous issue endpoints."""
35
+
36
+ def list(
37
+ self,
38
+ *,
39
+ owner: str | None = None,
40
+ repo: str | None = None,
41
+ state: str | None = None,
42
+ sort: str | None = None,
43
+ direction: str | None = None,
44
+ page: int | None = None,
45
+ per_page: int | None = None,
46
+ ) -> List[Issue]:
47
+ """List issues for a repository.
48
+
49
+ :param owner: Repository owner path. Uses the client default when omitted.
50
+ :param repo: Repository name. Uses the client default when omitted.
51
+ :param state: Optional issue state filter.
52
+ :param sort: Optional sort field.
53
+ :param direction: Optional sort direction.
54
+ :param page: Page number.
55
+ :param per_page: Page size.
56
+ :returns: Matching issues.
57
+ """
58
+ return self._models(
59
+ "GET",
60
+ self._client._repo_path("issues", owner=owner, repo=repo),
61
+ Issue,
62
+ params={
63
+ "state": state,
64
+ "sort": sort,
65
+ "direction": direction,
66
+ "page": page,
67
+ "per_page": per_page,
68
+ },
69
+ )
70
+
71
+ def get(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> Issue:
72
+ """Get a single issue by number.
73
+
74
+ :param number: Repository-local issue number.
75
+ :param owner: Repository owner path. Uses the client default when omitted.
76
+ :param repo: Repository name. Uses the client default when omitted.
77
+ :returns: Issue details.
78
+ """
79
+ return self._model("GET", self._client._repo_path("issues", number, owner=owner, repo=repo), Issue)
80
+
81
+ def create(
82
+ self,
83
+ *,
84
+ owner: str,
85
+ repo: str | None = None,
86
+ title: str,
87
+ body: str | None = None,
88
+ assignee: str | None = None,
89
+ labels: List[str] | None = None,
90
+ milestone: int | str | None = None,
91
+ security_hole: str | None = None,
92
+ ) -> Issue:
93
+ """Create an issue for a repository.
94
+
95
+ :param owner: Repository owner path.
96
+ :param repo: Repository name. Uses the client default when omitted.
97
+ :param title: Issue title.
98
+ :param body: Optional issue description.
99
+ :param assignee: Optional assignee username.
100
+ :param labels: Optional label names.
101
+ :param milestone: Optional milestone identifier.
102
+ :param security_hole: Optional private issue flag accepted by the API.
103
+ :returns: Created issue details.
104
+ """
105
+ resolved_repo = repo or self._client.repo
106
+ return self._model(
107
+ "POST",
108
+ self._client._path("repos", owner, "issues"),
109
+ Issue,
110
+ json={
111
+ "repo": resolved_repo,
112
+ "title": title,
113
+ "body": body,
114
+ "assignee": assignee,
115
+ "labels": _comma_join(labels),
116
+ "milestone": milestone,
117
+ "security_hole": security_hole,
118
+ },
119
+ )
120
+
121
+ def update(
122
+ self,
123
+ *,
124
+ number: int | str,
125
+ owner: str,
126
+ repo: str | None = None,
127
+ title: str | None = None,
128
+ body: str | None = None,
129
+ state: str | None = None,
130
+ assignee: str | None = None,
131
+ labels: List[str] | None = None,
132
+ milestone: int | str | None = None,
133
+ security_hole: str | None = None,
134
+ ) -> Issue:
135
+ """Update an existing issue.
136
+
137
+ :param number: Repository-local issue number.
138
+ :param owner: Repository owner path.
139
+ :param repo: Repository name. Uses the client default when omitted.
140
+ :param title: Updated issue title.
141
+ :param body: Updated issue description.
142
+ :param state: Updated state such as ``reopen`` or ``close``.
143
+ :param assignee: Updated assignee username.
144
+ :param labels: Replacement label names.
145
+ :param milestone: Updated milestone identifier.
146
+ :param security_hole: Optional private issue flag accepted by the API.
147
+ :returns: Updated issue details.
148
+ """
149
+ resolved_repo = repo or self._client.repo
150
+ return self._model(
151
+ "PATCH",
152
+ self._client._path("repos", owner, "issues", number),
153
+ Issue,
154
+ json={
155
+ "repo": resolved_repo,
156
+ "title": title,
157
+ "body": body,
158
+ "state": state,
159
+ "assignee": assignee,
160
+ "labels": _comma_join(labels),
161
+ "milestone": milestone,
162
+ "security_hole": security_hole,
163
+ },
164
+ )
165
+
166
+ def list_comments(
167
+ self,
168
+ *,
169
+ number: int | str,
170
+ owner: str | None = None,
171
+ repo: str | None = None,
172
+ page: int | None = None,
173
+ per_page: int | None = None,
174
+ ) -> List[IssueComment]:
175
+ """List comments for an issue."""
176
+ return self._models(
177
+ "GET",
178
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
179
+ IssueComment,
180
+ params={"page": page, "per_page": per_page},
181
+ )
182
+
183
+ def create_comment(
184
+ self,
185
+ *,
186
+ number: int | str,
187
+ body: str,
188
+ owner: str | None = None,
189
+ repo: str | None = None,
190
+ ) -> IssueComment:
191
+ """Create a comment on an issue."""
192
+ return self._model(
193
+ "POST",
194
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
195
+ IssueComment,
196
+ json={"body": body},
197
+ )
198
+
199
+ def get_comment(
200
+ self,
201
+ *,
202
+ comment_id: int | str,
203
+ owner: str | None = None,
204
+ repo: str | None = None,
205
+ ) -> IssueComment:
206
+ """Get a single issue comment by identifier."""
207
+ return self._model(
208
+ "GET",
209
+ self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo),
210
+ IssueComment,
211
+ )
212
+
213
+ def update_comment(
214
+ self,
215
+ *,
216
+ comment_id: int | str,
217
+ body: str,
218
+ owner: str | None = None,
219
+ repo: str | None = None,
220
+ ) -> IssueComment:
221
+ """Update an issue comment."""
222
+ return self._model(
223
+ "PATCH",
224
+ self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo),
225
+ IssueComment,
226
+ json={"body": body},
227
+ )
228
+
229
+ def delete_comment(self, *, comment_id: int | str, owner: str | None = None, repo: str | None = None) -> None:
230
+ """Delete an issue comment."""
231
+ self._request("DELETE", self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo))
232
+
233
+ def list_pull_requests(
234
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None
235
+ ) -> List[PullRequest]:
236
+ """List pull requests associated with an issue."""
237
+ return self._models(
238
+ "GET",
239
+ self._client._repo_path("issues", number, "pull_requests", owner=owner, repo=repo),
240
+ PullRequest,
241
+ )
242
+
243
+ def add_labels(
244
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
245
+ ) -> List[Label]:
246
+ """Add labels to an issue."""
247
+ return self._models(
248
+ "POST",
249
+ self._client._repo_path("issues", number, "labels", owner=owner, repo=repo),
250
+ Label,
251
+ json=labels,
252
+ )
253
+
254
+ def remove_label(self, *, number: int | str, name: str, owner: str | None = None, repo: str | None = None) -> None:
255
+ """Remove one or more labels from an issue."""
256
+ self._request("DELETE", self._client._repo_path("issues", number, "labels", name, owner=owner, repo=repo))
257
+
258
+ def list_enterprise(self, *, enterprise: str, **params: Any) -> List[Issue]:
259
+ """List enterprise issues visible to the caller."""
260
+ return self._models("GET", self._client._path("enterprises", enterprise, "issues"), Issue, params=params)
261
+
262
+ def list_user(self, **params: Any) -> List[Issue]:
263
+ """List issues for the authenticated user."""
264
+ return self._models("GET", self._client._path("user", "issues"), Issue, params=params)
265
+
266
+ def list_org(self, *, org: str, **params: Any) -> List[Issue]:
267
+ """List organization issues visible to the current user."""
268
+ return self._models("GET", self._client._path("orgs", org, "issues"), Issue, params=params)
269
+
270
+ def get_enterprise_issue(self, *, enterprise: str, number: int | str) -> Issue:
271
+ """Get a specific enterprise issue by global issue identifier."""
272
+ return self._model("GET", self._client._path("enterprises", enterprise, "issues", number), Issue)
273
+
274
+ def list_enterprise_comments(self, *, enterprise: str, number: int | str, **params: Any) -> List[IssueComment]:
275
+ """List comments for an enterprise issue."""
276
+ return self._models(
277
+ "GET",
278
+ self._client._path("enterprises", enterprise, "issues", number, "comments"),
279
+ IssueComment,
280
+ params=params,
281
+ )
282
+
283
+ def list_enterprise_labels(self, *, enterprise: str, issue_id: int | str) -> List[Label]:
284
+ """List labels attached to an enterprise issue."""
285
+ return self._models("GET", self._client._path("enterprises", enterprise, "issues", issue_id, "labels"), Label)
286
+
287
+ def list_operation_logs(
288
+ self, *, owner: str, number: int | str, page: int | None = None, per_page: int | None = None
289
+ ) -> List[IssueOperationLog]:
290
+ """List operation logs for an issue."""
291
+ return self._models(
292
+ "GET",
293
+ self._client._path("repos", owner, "issues", number, "operate_logs"),
294
+ IssueOperationLog,
295
+ params={"page": page, "per_page": per_page},
296
+ )
297
+
298
+
299
+ class PullsResource(SyncResource):
300
+ """Synchronous pull request endpoints."""
301
+
302
+ def list(
303
+ self,
304
+ *,
305
+ owner: str | None = None,
306
+ repo: str | None = None,
307
+ state: str | None = None,
308
+ sort: str | None = None,
309
+ direction: str | None = None,
310
+ page: int | None = None,
311
+ per_page: int | None = None,
312
+ **params: Any,
313
+ ) -> List[PullRequest] | APIObject:
314
+ """List pull requests for a repository."""
315
+ path = self._client._repo_path("pulls", owner=owner, repo=repo)
316
+ response = self._request(
317
+ "GET",
318
+ path,
319
+ params={
320
+ "state": state,
321
+ "sort": sort,
322
+ "direction": direction,
323
+ "page": page,
324
+ "per_page": per_page,
325
+ **params,
326
+ },
327
+ )
328
+ if isinstance(response, dict):
329
+ return as_model(response, APIObject)
330
+ return [as_model(item, PullRequest) for item in response]
331
+
332
+ def get(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> PullRequest:
333
+ """Get a single pull request."""
334
+ return self._model("GET", self._client._repo_path("pulls", number, owner=owner, repo=repo), PullRequest)
335
+
336
+ def create(
337
+ self,
338
+ *,
339
+ title: str,
340
+ head: str,
341
+ base: str,
342
+ owner: str | None = None,
343
+ repo: str | None = None,
344
+ body: str | None = None,
345
+ draft: bool | None = None,
346
+ assignees: List[str] | None = None,
347
+ testers: List[str] | None = None,
348
+ labels: List[str] | None = None,
349
+ milestone_number: int | None = None,
350
+ issue: str | None = None,
351
+ prune_source_branch: bool | None = None,
352
+ squash: bool | None = None,
353
+ squash_commit_message: str | None = None,
354
+ fork_path: str | None = None,
355
+ ) -> PullRequest:
356
+ """Create a pull request."""
357
+ return self._model(
358
+ "POST",
359
+ self._client._repo_path("pulls", owner=owner, repo=repo),
360
+ PullRequest,
361
+ json={
362
+ "title": title,
363
+ "head": head,
364
+ "base": base,
365
+ "body": body,
366
+ "draft": draft,
367
+ "assignees": _comma_join(assignees),
368
+ "testers": _comma_join(testers),
369
+ "labels": _comma_join(labels),
370
+ "milestone_number": milestone_number,
371
+ "issue": issue,
372
+ "prune_source_branch": prune_source_branch,
373
+ "squash": squash,
374
+ "squash_commit_message": squash_commit_message,
375
+ "fork_path": fork_path,
376
+ },
377
+ )
378
+
379
+ def update(
380
+ self,
381
+ *,
382
+ number: int | str,
383
+ owner: str | None = None,
384
+ repo: str | None = None,
385
+ title: str | None = None,
386
+ body: str | None = None,
387
+ state: str | None = None,
388
+ base: str | None = None,
389
+ labels: List[str] | None = None,
390
+ draft: bool | None = None,
391
+ ) -> PullRequest:
392
+ """Update a pull request."""
393
+ return self._model(
394
+ "PATCH",
395
+ self._client._repo_path("pulls", number, owner=owner, repo=repo),
396
+ PullRequest,
397
+ json={
398
+ "title": title,
399
+ "body": body,
400
+ "state": state,
401
+ "base": base,
402
+ "labels": _comma_join(labels),
403
+ "draft": draft,
404
+ },
405
+ )
406
+
407
+ def merge(
408
+ self,
409
+ *,
410
+ number: int | str,
411
+ owner: str | None = None,
412
+ repo: str | None = None,
413
+ merge_commit_message: str | None = None,
414
+ squash: bool | None = None,
415
+ ) -> MergeResult:
416
+ """Merge a pull request."""
417
+ return self._model(
418
+ "PUT",
419
+ self._client._repo_path("pulls", number, "merge", owner=owner, repo=repo),
420
+ MergeResult,
421
+ json={"merge_commit_message": merge_commit_message, "squash": squash},
422
+ )
423
+
424
+ def get_merge_status(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> MergeStatus:
425
+ """Get mergeability status for a pull request."""
426
+ return self._model(
427
+ "GET",
428
+ self._client._repo_path("pulls", number, "merge", owner=owner, repo=repo),
429
+ MergeStatus,
430
+ )
431
+
432
+ def list_commits(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> List[APIObject]:
433
+ """List commits included in a pull request."""
434
+ data = self._request("GET", self._client._repo_path("pulls", number, "commits", owner=owner, repo=repo))
435
+ return [as_model(item, APIObject) for item in data]
436
+
437
+ def list_files(
438
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None
439
+ ) -> List[PullRequestFile]:
440
+ """List files changed by a pull request."""
441
+ return self._models(
442
+ "GET",
443
+ self._client._repo_path("pulls", number, "files", owner=owner, repo=repo),
444
+ PullRequestFile,
445
+ )
446
+
447
+ def list_comments(
448
+ self,
449
+ *,
450
+ number: int | str,
451
+ owner: str | None = None,
452
+ repo: str | None = None,
453
+ page: int | None = None,
454
+ per_page: int | None = None,
455
+ ) -> List[PullRequestComment]:
456
+ """List comments on a pull request."""
457
+ return self._models(
458
+ "GET",
459
+ self._client._repo_path("pulls", number, "comments", owner=owner, repo=repo),
460
+ PullRequestComment,
461
+ params={"page": page, "per_page": per_page},
462
+ )
463
+
464
+ def create_comment(
465
+ self,
466
+ *,
467
+ number: int | str,
468
+ body: str,
469
+ owner: str | None = None,
470
+ repo: str | None = None,
471
+ commit_id: str | None = None,
472
+ path: str | None = None,
473
+ position: int | None = None,
474
+ ) -> PullRequestComment:
475
+ """Create a pull request comment."""
476
+ return self._model(
477
+ "POST",
478
+ self._client._repo_path("pulls", number, "comments", owner=owner, repo=repo),
479
+ PullRequestComment,
480
+ json={"body": body, "commit_id": commit_id, "path": path, "position": position},
481
+ )
482
+
483
+ def get_comment(
484
+ self,
485
+ *,
486
+ comment_id: int | str,
487
+ owner: str | None = None,
488
+ repo: str | None = None,
489
+ ) -> PullRequestComment:
490
+ """Get a single pull request comment."""
491
+ return self._model(
492
+ "GET",
493
+ self._client._repo_path("pulls", "comments", comment_id, owner=owner, repo=repo),
494
+ PullRequestComment,
495
+ )
496
+
497
+ def update_comment(
498
+ self,
499
+ *,
500
+ comment_id: int | str,
501
+ body: str,
502
+ owner: str | None = None,
503
+ repo: str | None = None,
504
+ ) -> PullRequestComment:
505
+ """Update a pull request comment."""
506
+ return self._model(
507
+ "PATCH",
508
+ self._client._repo_path("pulls", "comments", comment_id, owner=owner, repo=repo),
509
+ PullRequestComment,
510
+ json={"body": body},
511
+ )
512
+
513
+ def delete_comment(self, *, comment_id: int | str, owner: str | None = None, repo: str | None = None) -> None:
514
+ """Delete a pull request comment."""
515
+ self._request("DELETE", self._client._repo_path("pulls", "comments", comment_id, owner=owner, repo=repo))
516
+
517
+ def list_labels(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> List[Label]:
518
+ """List labels attached to a pull request."""
519
+ return self._models(
520
+ "GET",
521
+ self._client._repo_path("pulls", number, "labels", owner=owner, repo=repo),
522
+ Label,
523
+ )
524
+
525
+ def add_labels(
526
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
527
+ ) -> List[Label]:
528
+ """Add labels to a pull request."""
529
+ return self._models(
530
+ "POST",
531
+ self._client._repo_path("pulls", number, "labels", owner=owner, repo=repo),
532
+ Label,
533
+ json=labels,
534
+ )
535
+
536
+ def replace_labels(
537
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
538
+ ) -> List[Label]:
539
+ """Replace all labels on a pull request."""
540
+ return self._models(
541
+ "PUT",
542
+ self._client._repo_path("pulls", number, "labels", owner=owner, repo=repo),
543
+ Label,
544
+ json=labels,
545
+ )
546
+
547
+ def remove_label(self, *, number: int | str, label: str, owner: str | None = None, repo: str | None = None) -> None:
548
+ """Remove a label from a pull request."""
549
+ self._request("DELETE", self._client._repo_path("pulls", number, "labels", label, owner=owner, repo=repo))
550
+
551
+ def request_review(
552
+ self,
553
+ *,
554
+ number: int | str,
555
+ owner: str | None = None,
556
+ repo: str | None = None,
557
+ event: str,
558
+ body: str | None = None,
559
+ ) -> PullRequestReview:
560
+ """Submit a pull request review event."""
561
+ return self._model(
562
+ "POST",
563
+ self._client._repo_path("pulls", number, "review", owner=owner, repo=repo),
564
+ PullRequestReview,
565
+ json={"event": event, "body": body},
566
+ )
567
+
568
+ def list_operation_logs(
569
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None, **params: Any
570
+ ) -> List[APIObject]:
571
+ """List operation logs for a pull request."""
572
+ data = self._request(
573
+ "GET",
574
+ self._client._repo_path("pulls", number, "operate_logs", owner=owner, repo=repo),
575
+ params=params,
576
+ )
577
+ return [as_model(item, APIObject) for item in data]
578
+
579
+ def request_test(
580
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None, **payload: Any
581
+ ) -> PullRequestTest:
582
+ """Request testing for a pull request."""
583
+ return self._model(
584
+ "POST",
585
+ self._client._repo_path("pulls", number, "test", owner=owner, repo=repo),
586
+ PullRequestTest,
587
+ json=payload,
588
+ )
589
+
590
+ def update_testers(
591
+ self, *, number: int | str, testers: List[str], owner: str | None = None, repo: str | None = None
592
+ ) -> APIObject:
593
+ """Replace pull request testers."""
594
+ return self._model(
595
+ "PATCH",
596
+ self._client._repo_path("pulls", number, "testers", owner=owner, repo=repo),
597
+ APIObject,
598
+ json={"testers": _comma_join(testers)},
599
+ )
600
+
601
+ def add_testers(
602
+ self, *, number: int | str, testers: List[str], owner: str | None = None, repo: str | None = None
603
+ ) -> APIObject:
604
+ """Add testers to a pull request."""
605
+ return self._model(
606
+ "POST",
607
+ self._client._repo_path("pulls", number, "testers", owner=owner, repo=repo),
608
+ APIObject,
609
+ json={"testers": _comma_join(testers)},
610
+ )
611
+
612
+ def update_assignees(
613
+ self, *, number: int | str, assignees: List[str], owner: str | None = None, repo: str | None = None
614
+ ) -> APIObject:
615
+ """Replace pull request assignees."""
616
+ return self._model(
617
+ "PATCH",
618
+ self._client._repo_path("pulls", number, "assignees", owner=owner, repo=repo),
619
+ APIObject,
620
+ json={"assignees": _comma_join(assignees)},
621
+ )
622
+
623
+ def add_assignees(
624
+ self, *, number: int | str, assignees: List[str], owner: str | None = None, repo: str | None = None
625
+ ) -> APIObject:
626
+ """Add assignees to a pull request."""
627
+ return self._model(
628
+ "POST",
629
+ self._client._repo_path("pulls", number, "assignees", owner=owner, repo=repo),
630
+ APIObject,
631
+ json={"assignees": _comma_join(assignees)},
632
+ )
633
+
634
+ def remove_assignees(
635
+ self, *, number: int | str, assignees: List[str], owner: str | None = None, repo: str | None = None
636
+ ) -> None:
637
+ """Remove assignees from a pull request."""
638
+ self._request(
639
+ "DELETE",
640
+ self._client._repo_path("pulls", number, "assignees", owner=owner, repo=repo),
641
+ json={"assignees": _comma_join(assignees)},
642
+ )
643
+
644
+ def list_issues(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> List[Issue]:
645
+ """List issues linked to a pull request."""
646
+ return self._models("GET", self._client._repo_path("pulls", number, "issues", owner=owner, repo=repo), Issue)
647
+
648
+ def list_enterprise(self, *, enterprise: str, **params: Any) -> List[PullRequest]:
649
+ """List enterprise pull requests."""
650
+ return self._models(
651
+ "GET", self._client._path("enterprises", enterprise, "pull_requests"), PullRequest, params=params
652
+ )
653
+
654
+ def list_org(self, *, org: str, **params: Any) -> List[PullRequest]:
655
+ """List pull requests for an organization scope."""
656
+ return self._models("GET", self._client._path("org", org, "pull_requests"), PullRequest, params=params)
657
+
658
+ def list_issue_pull_requests(self, *, enterprise: str, number: int | str) -> List[PullRequest]:
659
+ """List pull requests associated with an enterprise issue."""
660
+ return self._models(
661
+ "GET",
662
+ self._client._path("enterprises", enterprise, "issues", number, "pull_requests"),
663
+ PullRequest,
664
+ )
665
+
666
+
667
+ class LabelsResource(SyncResource):
668
+ """Synchronous label endpoints."""
669
+
670
+ def list(self, *, owner: str | None = None, repo: str | None = None) -> List[Label]:
671
+ """List repository labels."""
672
+ return self._models("GET", self._client._repo_path("labels", owner=owner, repo=repo), Label)
673
+
674
+ def create(self, *, name: str, color: str, owner: str | None = None, repo: str | None = None) -> Label:
675
+ """Create a repository label."""
676
+ return self._model(
677
+ "POST",
678
+ self._client._repo_path("labels", owner=owner, repo=repo),
679
+ Label,
680
+ json={"name": name, "color": color},
681
+ )
682
+
683
+ def update(
684
+ self,
685
+ *,
686
+ original_name: str,
687
+ owner: str | None = None,
688
+ repo: str | None = None,
689
+ name: str | None = None,
690
+ color: str | None = None,
691
+ ) -> Label:
692
+ """Update a repository label."""
693
+ return self._model(
694
+ "PATCH",
695
+ self._client._repo_path("labels", original_name, owner=owner, repo=repo),
696
+ Label,
697
+ json={"name": name, "color": color},
698
+ )
699
+
700
+ def delete(self, *, name: str, owner: str | None = None, repo: str | None = None) -> None:
701
+ """Delete a repository label."""
702
+ self._request("DELETE", self._client._repo_path("labels", name, owner=owner, repo=repo))
703
+
704
+ def clear_issue_labels(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> None:
705
+ """Remove all labels from an issue."""
706
+ self._request("DELETE", self._client._repo_path("issues", number, "labels", owner=owner, repo=repo))
707
+
708
+ def replace_issue_labels(
709
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
710
+ ) -> List[Label]:
711
+ """Replace all labels on an issue."""
712
+ return self._models(
713
+ "PUT",
714
+ self._client._repo_path("issues", number, "labels", owner=owner, repo=repo),
715
+ Label,
716
+ json=labels,
717
+ )
718
+
719
+ def list_enterprise(
720
+ self,
721
+ *,
722
+ enterprise: str,
723
+ search: str | None = None,
724
+ direction: str | None = None,
725
+ page: int | None = None,
726
+ per_page: int | None = None,
727
+ api_version: str = "v5",
728
+ ) -> List[Label]:
729
+ """List labels for an enterprise, optionally using a different API version."""
730
+ if api_version == "v5":
731
+ path = self._client._path("enterprises", enterprise, "labels")
732
+ else:
733
+ host = self._client.base_url.split("/api/", maxsplit=1)[0]
734
+ path = f"{host}/api/{api_version}/enterprises/{self._client._encode_segment(enterprise)}/labels"
735
+ return self._models(
736
+ "GET",
737
+ path,
738
+ Label,
739
+ params={"search": search, "direction": direction, "page": page, "per_page": per_page},
740
+ )
741
+
742
+
743
+ class MilestonesResource(SyncResource):
744
+ """Synchronous milestone endpoints."""
745
+
746
+ def list(self, *, owner: str | None = None, repo: str | None = None, **params: Any) -> List[Milestone]:
747
+ """List milestones for a repository."""
748
+ return self._models(
749
+ "GET", self._client._repo_path("milestones", owner=owner, repo=repo), Milestone, params=params
750
+ )
751
+
752
+ def get(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> Milestone:
753
+ """Get a single milestone."""
754
+ return self._model("GET", self._client._repo_path("milestones", number, owner=owner, repo=repo), Milestone)
755
+
756
+ def create(
757
+ self,
758
+ *,
759
+ title: str,
760
+ due_on: str,
761
+ owner: str | None = None,
762
+ repo: str | None = None,
763
+ description: str | None = None,
764
+ ) -> Milestone:
765
+ """Create a milestone."""
766
+ return self._model(
767
+ "POST",
768
+ self._client._repo_path("milestones", owner=owner, repo=repo),
769
+ Milestone,
770
+ json={"title": title, "due_on": due_on, "description": description},
771
+ )
772
+
773
+ def update(
774
+ self,
775
+ *,
776
+ number: int | str,
777
+ title: str,
778
+ due_on: str,
779
+ owner: str | None = None,
780
+ repo: str | None = None,
781
+ description: str | None = None,
782
+ state: str | None = None,
783
+ ) -> Milestone:
784
+ """Update a milestone."""
785
+ return self._model(
786
+ "PATCH",
787
+ self._client._repo_path("milestones", number, owner=owner, repo=repo),
788
+ Milestone,
789
+ json={"title": title, "due_on": due_on, "description": description, "state": state},
790
+ )
791
+
792
+ def delete(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> None:
793
+ """Delete a milestone."""
794
+ self._request("DELETE", self._client._repo_path("milestones", number, owner=owner, repo=repo))
795
+
796
+
797
+ class MembersResource(SyncResource):
798
+ """Synchronous repository member endpoints."""
799
+
800
+ def add_or_update(
801
+ self, *, username: str, owner: str | None = None, repo: str | None = None, permission: str | None = None
802
+ ) -> RepoMember:
803
+ """Add or update repository member permissions."""
804
+ return self._model(
805
+ "PUT",
806
+ self._client._repo_path("collaborators", username, owner=owner, repo=repo),
807
+ RepoMember,
808
+ json={"permission": permission},
809
+ )
810
+
811
+ def remove(self, *, username: str, owner: str | None = None, repo: str | None = None) -> None:
812
+ """Remove a repository member."""
813
+ self._request("DELETE", self._client._repo_path("collaborators", username, owner=owner, repo=repo))
814
+
815
+ def list(
816
+ self, *, owner: str | None = None, repo: str | None = None, page: int | None = None, per_page: int | None = None
817
+ ) -> List[RepoMember]:
818
+ """List repository members."""
819
+ return self._models(
820
+ "GET",
821
+ self._client._repo_path("collaborators", owner=owner, repo=repo),
822
+ RepoMember,
823
+ params={"page": page, "per_page": per_page},
824
+ )
825
+
826
+ def get(self, *, username: str, owner: str | None = None, repo: str | None = None) -> APIObject:
827
+ """Check whether a user is a repository member."""
828
+ return self._model("GET", self._client._repo_path("collaborators", username, owner=owner, repo=repo), APIObject)
829
+
830
+ def get_permission(
831
+ self, *, username: str, owner: str | None = None, repo: str | None = None
832
+ ) -> RepoMemberPermission:
833
+ """Get repository member permissions."""
834
+ return self._model(
835
+ "GET",
836
+ self._client._repo_path("collaborators", username, "permission", owner=owner, repo=repo),
837
+ RepoMemberPermission,
838
+ )
839
+
840
+
841
+ class AsyncIssuesResource(AsyncResource):
842
+ """Asynchronous issue endpoints."""
843
+
844
+ async def list(self, *, owner: str | None = None, repo: str | None = None, **params: Any) -> List[Issue]:
845
+ return await self._models(
846
+ "GET", self._client._repo_path("issues", owner=owner, repo=repo), Issue, params=params
847
+ )
848
+
849
+ async def get(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> Issue:
850
+ return await self._model("GET", self._client._repo_path("issues", number, owner=owner, repo=repo), Issue)
851
+
852
+ async def create(
853
+ self,
854
+ *,
855
+ owner: str,
856
+ repo: str | None = None,
857
+ title: str,
858
+ body: str | None = None,
859
+ assignee: str | None = None,
860
+ labels: List[str] | None = None,
861
+ milestone: int | str | None = None,
862
+ security_hole: str | None = None,
863
+ ) -> Issue:
864
+ resolved_repo = repo or self._client.repo
865
+ return await self._model(
866
+ "POST",
867
+ self._client._path("repos", owner, "issues"),
868
+ Issue,
869
+ json={
870
+ "repo": resolved_repo,
871
+ "title": title,
872
+ "body": body,
873
+ "assignee": assignee,
874
+ "labels": _comma_join(labels),
875
+ "milestone": milestone,
876
+ "security_hole": security_hole,
877
+ },
878
+ )
879
+
880
+ async def update(
881
+ self,
882
+ *,
883
+ number: int | str,
884
+ owner: str,
885
+ repo: str | None = None,
886
+ title: str | None = None,
887
+ body: str | None = None,
888
+ state: str | None = None,
889
+ assignee: str | None = None,
890
+ labels: List[str] | None = None,
891
+ milestone: int | str | None = None,
892
+ security_hole: str | None = None,
893
+ ) -> Issue:
894
+ resolved_repo = repo or self._client.repo
895
+ return await self._model(
896
+ "PATCH",
897
+ self._client._path("repos", owner, "issues", number),
898
+ Issue,
899
+ json={
900
+ "repo": resolved_repo,
901
+ "title": title,
902
+ "body": body,
903
+ "state": state,
904
+ "assignee": assignee,
905
+ "labels": _comma_join(labels),
906
+ "milestone": milestone,
907
+ "security_hole": security_hole,
908
+ },
909
+ )
910
+
911
+ async def list_comments(
912
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None, **params: Any
913
+ ) -> List[IssueComment]:
914
+ return await self._models(
915
+ "GET",
916
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
917
+ IssueComment,
918
+ params=params,
919
+ )
920
+
921
+ async def create_comment(
922
+ self, *, number: int | str, body: str, owner: str | None = None, repo: str | None = None
923
+ ) -> IssueComment:
924
+ return await self._model(
925
+ "POST",
926
+ self._client._repo_path("issues", number, "comments", owner=owner, repo=repo),
927
+ IssueComment,
928
+ json={"body": body},
929
+ )
930
+
931
+ async def get_comment(
932
+ self, *, comment_id: int | str, owner: str | None = None, repo: str | None = None
933
+ ) -> IssueComment:
934
+ return await self._model(
935
+ "GET", self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo), IssueComment
936
+ )
937
+
938
+ async def update_comment(
939
+ self, *, comment_id: int | str, body: str, owner: str | None = None, repo: str | None = None
940
+ ) -> IssueComment:
941
+ return await self._model(
942
+ "PATCH",
943
+ self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo),
944
+ IssueComment,
945
+ json={"body": body},
946
+ )
947
+
948
+ async def delete_comment(self, *, comment_id: int | str, owner: str | None = None, repo: str | None = None) -> None:
949
+ await self._request("DELETE", self._client._repo_path("issues", "comments", comment_id, owner=owner, repo=repo))
950
+
951
+ async def list_pull_requests(
952
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None
953
+ ) -> List[PullRequest]:
954
+ return await self._models(
955
+ "GET", self._client._repo_path("issues", number, "pull_requests", owner=owner, repo=repo), PullRequest
956
+ )
957
+
958
+ async def add_labels(
959
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
960
+ ) -> List[Label]:
961
+ return await self._models(
962
+ "POST", self._client._repo_path("issues", number, "labels", owner=owner, repo=repo), Label, json=labels
963
+ )
964
+
965
+ async def remove_label(
966
+ self, *, number: int | str, name: str, owner: str | None = None, repo: str | None = None
967
+ ) -> None:
968
+ await self._request("DELETE", self._client._repo_path("issues", number, "labels", name, owner=owner, repo=repo))
969
+
970
+ async def list_enterprise(self, *, enterprise: str, **params: Any) -> List[Issue]:
971
+ return await self._models("GET", self._client._path("enterprises", enterprise, "issues"), Issue, params=params)
972
+
973
+ async def list_user(self, **params: Any) -> List[Issue]:
974
+ return await self._models("GET", self._client._path("user", "issues"), Issue, params=params)
975
+
976
+ async def list_org(self, *, org: str, **params: Any) -> List[Issue]:
977
+ return await self._models("GET", self._client._path("orgs", org, "issues"), Issue, params=params)
978
+
979
+ async def get_enterprise_issue(self, *, enterprise: str, number: int | str) -> Issue:
980
+ return await self._model("GET", self._client._path("enterprises", enterprise, "issues", number), Issue)
981
+
982
+ async def list_enterprise_comments(
983
+ self, *, enterprise: str, number: int | str, **params: Any
984
+ ) -> List[IssueComment]:
985
+ return await self._models(
986
+ "GET",
987
+ self._client._path("enterprises", enterprise, "issues", number, "comments"),
988
+ IssueComment,
989
+ params=params,
990
+ )
991
+
992
+ async def list_enterprise_labels(self, *, enterprise: str, issue_id: int | str) -> List[Label]:
993
+ return await self._models(
994
+ "GET", self._client._path("enterprises", enterprise, "issues", issue_id, "labels"), Label
995
+ )
996
+
997
+ async def list_operation_logs(self, *, owner: str, number: int | str, **params: Any) -> List[IssueOperationLog]:
998
+ return await self._models(
999
+ "GET",
1000
+ self._client._path("repos", owner, "issues", number, "operate_logs"),
1001
+ IssueOperationLog,
1002
+ params=params,
1003
+ )
1004
+
1005
+
1006
+ class AsyncPullsResource(AsyncResource):
1007
+ """Asynchronous pull request endpoints."""
1008
+
1009
+ async def list(
1010
+ self, *, owner: str | None = None, repo: str | None = None, **params: Any
1011
+ ) -> List[PullRequest] | APIObject:
1012
+ response = await self._request("GET", self._client._repo_path("pulls", owner=owner, repo=repo), params=params)
1013
+ if isinstance(response, dict):
1014
+ return as_model(response, APIObject)
1015
+ return [as_model(item, PullRequest) for item in response]
1016
+
1017
+ async def get(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> PullRequest:
1018
+ return await self._model("GET", self._client._repo_path("pulls", number, owner=owner, repo=repo), PullRequest)
1019
+
1020
+ async def create(
1021
+ self,
1022
+ *,
1023
+ title: str,
1024
+ head: str,
1025
+ base: str,
1026
+ owner: str | None = None,
1027
+ repo: str | None = None,
1028
+ body: str | None = None,
1029
+ draft: bool | None = None,
1030
+ assignees: List[str] | None = None,
1031
+ testers: List[str] | None = None,
1032
+ labels: List[str] | None = None,
1033
+ milestone_number: int | None = None,
1034
+ issue: str | None = None,
1035
+ prune_source_branch: bool | None = None,
1036
+ squash: bool | None = None,
1037
+ squash_commit_message: str | None = None,
1038
+ fork_path: str | None = None,
1039
+ ) -> PullRequest:
1040
+ return await self._model(
1041
+ "POST",
1042
+ self._client._repo_path("pulls", owner=owner, repo=repo),
1043
+ PullRequest,
1044
+ json={
1045
+ "title": title,
1046
+ "head": head,
1047
+ "base": base,
1048
+ "body": body,
1049
+ "draft": draft,
1050
+ "assignees": _comma_join(assignees),
1051
+ "testers": _comma_join(testers),
1052
+ "labels": _comma_join(labels),
1053
+ "milestone_number": milestone_number,
1054
+ "issue": issue,
1055
+ "prune_source_branch": prune_source_branch,
1056
+ "squash": squash,
1057
+ "squash_commit_message": squash_commit_message,
1058
+ "fork_path": fork_path,
1059
+ },
1060
+ )
1061
+
1062
+ async def update(
1063
+ self,
1064
+ *,
1065
+ number: int | str,
1066
+ owner: str | None = None,
1067
+ repo: str | None = None,
1068
+ title: str | None = None,
1069
+ body: str | None = None,
1070
+ state: str | None = None,
1071
+ base: str | None = None,
1072
+ labels: List[str] | None = None,
1073
+ draft: bool | None = None,
1074
+ ) -> PullRequest:
1075
+ return await self._model(
1076
+ "PATCH",
1077
+ self._client._repo_path("pulls", number, owner=owner, repo=repo),
1078
+ PullRequest,
1079
+ json={
1080
+ "title": title,
1081
+ "body": body,
1082
+ "state": state,
1083
+ "base": base,
1084
+ "labels": _comma_join(labels),
1085
+ "draft": draft,
1086
+ },
1087
+ )
1088
+
1089
+ async def merge(
1090
+ self,
1091
+ *,
1092
+ number: int | str,
1093
+ owner: str | None = None,
1094
+ repo: str | None = None,
1095
+ merge_commit_message: str | None = None,
1096
+ squash: bool | None = None,
1097
+ ) -> MergeResult:
1098
+ return await self._model(
1099
+ "PUT",
1100
+ self._client._repo_path("pulls", number, "merge", owner=owner, repo=repo),
1101
+ MergeResult,
1102
+ json={"merge_commit_message": merge_commit_message, "squash": squash},
1103
+ )
1104
+
1105
+ async def get_merge_status(
1106
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None
1107
+ ) -> MergeStatus:
1108
+ return await self._model(
1109
+ "GET", self._client._repo_path("pulls", number, "merge", owner=owner, repo=repo), MergeStatus
1110
+ )
1111
+
1112
+ async def list_commits(
1113
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None
1114
+ ) -> List[APIObject]:
1115
+ data = await self._request("GET", self._client._repo_path("pulls", number, "commits", owner=owner, repo=repo))
1116
+ return [as_model(item, APIObject) for item in data]
1117
+
1118
+ async def list_files(
1119
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None
1120
+ ) -> List[PullRequestFile]:
1121
+ return await self._models(
1122
+ "GET", self._client._repo_path("pulls", number, "files", owner=owner, repo=repo), PullRequestFile
1123
+ )
1124
+
1125
+ async def list_comments(
1126
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None, **params: Any
1127
+ ) -> List[PullRequestComment]:
1128
+ return await self._models(
1129
+ "GET",
1130
+ self._client._repo_path("pulls", number, "comments", owner=owner, repo=repo),
1131
+ PullRequestComment,
1132
+ params=params,
1133
+ )
1134
+
1135
+ async def create_comment(
1136
+ self,
1137
+ *,
1138
+ number: int | str,
1139
+ body: str,
1140
+ owner: str | None = None,
1141
+ repo: str | None = None,
1142
+ commit_id: str | None = None,
1143
+ path: str | None = None,
1144
+ position: int | None = None,
1145
+ ) -> PullRequestComment:
1146
+ return await self._model(
1147
+ "POST",
1148
+ self._client._repo_path("pulls", number, "comments", owner=owner, repo=repo),
1149
+ PullRequestComment,
1150
+ json={"body": body, "commit_id": commit_id, "path": path, "position": position},
1151
+ )
1152
+
1153
+ async def get_comment(
1154
+ self, *, comment_id: int | str, owner: str | None = None, repo: str | None = None
1155
+ ) -> PullRequestComment:
1156
+ return await self._model(
1157
+ "GET", self._client._repo_path("pulls", "comments", comment_id, owner=owner, repo=repo), PullRequestComment
1158
+ )
1159
+
1160
+ async def update_comment(
1161
+ self, *, comment_id: int | str, body: str, owner: str | None = None, repo: str | None = None
1162
+ ) -> PullRequestComment:
1163
+ return await self._model(
1164
+ "PATCH",
1165
+ self._client._repo_path("pulls", "comments", comment_id, owner=owner, repo=repo),
1166
+ PullRequestComment,
1167
+ json={"body": body},
1168
+ )
1169
+
1170
+ async def delete_comment(self, *, comment_id: int | str, owner: str | None = None, repo: str | None = None) -> None:
1171
+ await self._request("DELETE", self._client._repo_path("pulls", "comments", comment_id, owner=owner, repo=repo))
1172
+
1173
+ async def list_labels(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> List[Label]:
1174
+ return await self._models(
1175
+ "GET", self._client._repo_path("pulls", number, "labels", owner=owner, repo=repo), Label
1176
+ )
1177
+
1178
+ async def add_labels(
1179
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
1180
+ ) -> List[Label]:
1181
+ return await self._models(
1182
+ "POST", self._client._repo_path("pulls", number, "labels", owner=owner, repo=repo), Label, json=labels
1183
+ )
1184
+
1185
+ async def replace_labels(
1186
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
1187
+ ) -> List[Label]:
1188
+ return await self._models(
1189
+ "PUT", self._client._repo_path("pulls", number, "labels", owner=owner, repo=repo), Label, json=labels
1190
+ )
1191
+
1192
+ async def remove_label(
1193
+ self, *, number: int | str, label: str, owner: str | None = None, repo: str | None = None
1194
+ ) -> None:
1195
+ await self._request("DELETE", self._client._repo_path("pulls", number, "labels", label, owner=owner, repo=repo))
1196
+
1197
+ async def request_review(
1198
+ self,
1199
+ *,
1200
+ number: int | str,
1201
+ owner: str | None = None,
1202
+ repo: str | None = None,
1203
+ event: str,
1204
+ body: str | None = None,
1205
+ ) -> PullRequestReview:
1206
+ return await self._model(
1207
+ "POST",
1208
+ self._client._repo_path("pulls", number, "review", owner=owner, repo=repo),
1209
+ PullRequestReview,
1210
+ json={"event": event, "body": body},
1211
+ )
1212
+
1213
+ async def list_operation_logs(
1214
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None, **params: Any
1215
+ ) -> List[APIObject]:
1216
+ data = await self._request(
1217
+ "GET", self._client._repo_path("pulls", number, "operate_logs", owner=owner, repo=repo), params=params
1218
+ )
1219
+ return [as_model(item, APIObject) for item in data]
1220
+
1221
+ async def request_test(
1222
+ self, *, number: int | str, owner: str | None = None, repo: str | None = None, **payload: Any
1223
+ ) -> PullRequestTest:
1224
+ return await self._model(
1225
+ "POST",
1226
+ self._client._repo_path("pulls", number, "test", owner=owner, repo=repo),
1227
+ PullRequestTest,
1228
+ json=payload,
1229
+ )
1230
+
1231
+ async def update_testers(
1232
+ self, *, number: int | str, testers: List[str], owner: str | None = None, repo: str | None = None
1233
+ ) -> APIObject:
1234
+ return await self._model(
1235
+ "PATCH",
1236
+ self._client._repo_path("pulls", number, "testers", owner=owner, repo=repo),
1237
+ APIObject,
1238
+ json={"testers": _comma_join(testers)},
1239
+ )
1240
+
1241
+ async def add_testers(
1242
+ self, *, number: int | str, testers: List[str], owner: str | None = None, repo: str | None = None
1243
+ ) -> APIObject:
1244
+ return await self._model(
1245
+ "POST",
1246
+ self._client._repo_path("pulls", number, "testers", owner=owner, repo=repo),
1247
+ APIObject,
1248
+ json={"testers": _comma_join(testers)},
1249
+ )
1250
+
1251
+ async def update_assignees(
1252
+ self, *, number: int | str, assignees: List[str], owner: str | None = None, repo: str | None = None
1253
+ ) -> APIObject:
1254
+ return await self._model(
1255
+ "PATCH",
1256
+ self._client._repo_path("pulls", number, "assignees", owner=owner, repo=repo),
1257
+ APIObject,
1258
+ json={"assignees": _comma_join(assignees)},
1259
+ )
1260
+
1261
+ async def add_assignees(
1262
+ self, *, number: int | str, assignees: List[str], owner: str | None = None, repo: str | None = None
1263
+ ) -> APIObject:
1264
+ return await self._model(
1265
+ "POST",
1266
+ self._client._repo_path("pulls", number, "assignees", owner=owner, repo=repo),
1267
+ APIObject,
1268
+ json={"assignees": _comma_join(assignees)},
1269
+ )
1270
+
1271
+ async def remove_assignees(
1272
+ self, *, number: int | str, assignees: List[str], owner: str | None = None, repo: str | None = None
1273
+ ) -> None:
1274
+ await self._request(
1275
+ "DELETE",
1276
+ self._client._repo_path("pulls", number, "assignees", owner=owner, repo=repo),
1277
+ json={"assignees": _comma_join(assignees)},
1278
+ )
1279
+
1280
+ async def list_issues(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> List[Issue]:
1281
+ return await self._models(
1282
+ "GET", self._client._repo_path("pulls", number, "issues", owner=owner, repo=repo), Issue
1283
+ )
1284
+
1285
+ async def list_enterprise(self, *, enterprise: str, **params: Any) -> List[PullRequest]:
1286
+ return await self._models(
1287
+ "GET", self._client._path("enterprises", enterprise, "pull_requests"), PullRequest, params=params
1288
+ )
1289
+
1290
+ async def list_org(self, *, org: str, **params: Any) -> List[PullRequest]:
1291
+ return await self._models("GET", self._client._path("org", org, "pull_requests"), PullRequest, params=params)
1292
+
1293
+ async def list_issue_pull_requests(self, *, enterprise: str, number: int | str) -> List[PullRequest]:
1294
+ return await self._models(
1295
+ "GET", self._client._path("enterprises", enterprise, "issues", number, "pull_requests"), PullRequest
1296
+ )
1297
+
1298
+
1299
+ class AsyncLabelsResource(AsyncResource):
1300
+ """Asynchronous label endpoints."""
1301
+
1302
+ async def list(self, *, owner: str | None = None, repo: str | None = None) -> List[Label]:
1303
+ return await self._models("GET", self._client._repo_path("labels", owner=owner, repo=repo), Label)
1304
+
1305
+ async def create(self, *, name: str, color: str, owner: str | None = None, repo: str | None = None) -> Label:
1306
+ return await self._model(
1307
+ "POST",
1308
+ self._client._repo_path("labels", owner=owner, repo=repo),
1309
+ Label,
1310
+ json={"name": name, "color": color},
1311
+ )
1312
+
1313
+ async def update(
1314
+ self,
1315
+ *,
1316
+ original_name: str,
1317
+ owner: str | None = None,
1318
+ repo: str | None = None,
1319
+ name: str | None = None,
1320
+ color: str | None = None,
1321
+ ) -> Label:
1322
+ return await self._model(
1323
+ "PATCH",
1324
+ self._client._repo_path("labels", original_name, owner=owner, repo=repo),
1325
+ Label,
1326
+ json={"name": name, "color": color},
1327
+ )
1328
+
1329
+ async def delete(self, *, name: str, owner: str | None = None, repo: str | None = None) -> None:
1330
+ await self._request("DELETE", self._client._repo_path("labels", name, owner=owner, repo=repo))
1331
+
1332
+ async def clear_issue_labels(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> None:
1333
+ await self._request("DELETE", self._client._repo_path("issues", number, "labels", owner=owner, repo=repo))
1334
+
1335
+ async def replace_issue_labels(
1336
+ self, *, number: int | str, labels: List[str], owner: str | None = None, repo: str | None = None
1337
+ ) -> List[Label]:
1338
+ return await self._models(
1339
+ "PUT", self._client._repo_path("issues", number, "labels", owner=owner, repo=repo), Label, json=labels
1340
+ )
1341
+
1342
+ async def list_enterprise(
1343
+ self,
1344
+ *,
1345
+ enterprise: str,
1346
+ search: str | None = None,
1347
+ direction: str | None = None,
1348
+ page: int | None = None,
1349
+ per_page: int | None = None,
1350
+ api_version: str = "v5",
1351
+ ) -> List[Label]:
1352
+ if api_version == "v5":
1353
+ path = self._client._path("enterprises", enterprise, "labels")
1354
+ else:
1355
+ host = self._client.base_url.split("/api/", maxsplit=1)[0]
1356
+ path = f"{host}/api/{api_version}/enterprises/{self._client._encode_segment(enterprise)}/labels"
1357
+ return await self._models(
1358
+ "GET", path, Label, params={"search": search, "direction": direction, "page": page, "per_page": per_page}
1359
+ )
1360
+
1361
+
1362
+ class AsyncMilestonesResource(AsyncResource):
1363
+ """Asynchronous milestone endpoints."""
1364
+
1365
+ async def list(self, *, owner: str | None = None, repo: str | None = None, **params: Any) -> List[Milestone]:
1366
+ return await self._models(
1367
+ "GET", self._client._repo_path("milestones", owner=owner, repo=repo), Milestone, params=params
1368
+ )
1369
+
1370
+ async def get(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> Milestone:
1371
+ return await self._model(
1372
+ "GET", self._client._repo_path("milestones", number, owner=owner, repo=repo), Milestone
1373
+ )
1374
+
1375
+ async def create(
1376
+ self,
1377
+ *,
1378
+ title: str,
1379
+ due_on: str,
1380
+ owner: str | None = None,
1381
+ repo: str | None = None,
1382
+ description: str | None = None,
1383
+ ) -> Milestone:
1384
+ return await self._model(
1385
+ "POST",
1386
+ self._client._repo_path("milestones", owner=owner, repo=repo),
1387
+ Milestone,
1388
+ json={"title": title, "due_on": due_on, "description": description},
1389
+ )
1390
+
1391
+ async def update(
1392
+ self,
1393
+ *,
1394
+ number: int | str,
1395
+ title: str,
1396
+ due_on: str,
1397
+ owner: str | None = None,
1398
+ repo: str | None = None,
1399
+ description: str | None = None,
1400
+ state: str | None = None,
1401
+ ) -> Milestone:
1402
+ return await self._model(
1403
+ "PATCH",
1404
+ self._client._repo_path("milestones", number, owner=owner, repo=repo),
1405
+ Milestone,
1406
+ json={"title": title, "due_on": due_on, "description": description, "state": state},
1407
+ )
1408
+
1409
+ async def delete(self, *, number: int | str, owner: str | None = None, repo: str | None = None) -> None:
1410
+ await self._request("DELETE", self._client._repo_path("milestones", number, owner=owner, repo=repo))
1411
+
1412
+
1413
+ class AsyncMembersResource(AsyncResource):
1414
+ """Asynchronous repository member endpoints."""
1415
+
1416
+ async def add_or_update(
1417
+ self, *, username: str, owner: str | None = None, repo: str | None = None, permission: str | None = None
1418
+ ) -> RepoMember:
1419
+ return await self._model(
1420
+ "PUT",
1421
+ self._client._repo_path("collaborators", username, owner=owner, repo=repo),
1422
+ RepoMember,
1423
+ json={"permission": permission},
1424
+ )
1425
+
1426
+ async def remove(self, *, username: str, owner: str | None = None, repo: str | None = None) -> None:
1427
+ await self._request("DELETE", self._client._repo_path("collaborators", username, owner=owner, repo=repo))
1428
+
1429
+ async def list(
1430
+ self, *, owner: str | None = None, repo: str | None = None, page: int | None = None, per_page: int | None = None
1431
+ ) -> List[RepoMember]:
1432
+ return await self._models(
1433
+ "GET",
1434
+ self._client._repo_path("collaborators", owner=owner, repo=repo),
1435
+ RepoMember,
1436
+ params={"page": page, "per_page": per_page},
1437
+ )
1438
+
1439
+ async def get(self, *, username: str, owner: str | None = None, repo: str | None = None) -> APIObject:
1440
+ return await self._model(
1441
+ "GET", self._client._repo_path("collaborators", username, owner=owner, repo=repo), APIObject
1442
+ )
1443
+
1444
+ async def get_permission(
1445
+ self, *, username: str, owner: str | None = None, repo: str | None = None
1446
+ ) -> RepoMemberPermission:
1447
+ return await self._model(
1448
+ "GET",
1449
+ self._client._repo_path("collaborators", username, "permission", owner=owner, repo=repo),
1450
+ RepoMemberPermission,
1451
+ )