SuperRealCo commited on
Commit
7608ac0
·
verified ·
1 Parent(s): b495482

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. venv/lib/python3.10/site-packages/PyGithub-2.6.1.dist-info/COPYING +674 -0
  2. venv/lib/python3.10/site-packages/PyGithub-2.6.1.dist-info/COPYING.LESSER +165 -0
  3. venv/lib/python3.10/site-packages/github/AccessToken.py +158 -0
  4. venv/lib/python3.10/site-packages/github/AdvisoryBase.py +157 -0
  5. venv/lib/python3.10/site-packages/github/AdvisoryCredit.py +126 -0
  6. venv/lib/python3.10/site-packages/github/AdvisoryCreditDetailed.py +104 -0
  7. venv/lib/python3.10/site-packages/github/AdvisoryVulnerability.py +190 -0
  8. venv/lib/python3.10/site-packages/github/AdvisoryVulnerabilityPackage.py +91 -0
  9. venv/lib/python3.10/site-packages/github/AppAuthentication.py +57 -0
  10. venv/lib/python3.10/site-packages/github/ApplicationOAuth.py +198 -0
  11. venv/lib/python3.10/site-packages/github/Artifact.py +172 -0
  12. venv/lib/python3.10/site-packages/github/Auth.py +551 -0
  13. venv/lib/python3.10/site-packages/github/AuthenticatedUser.py +1167 -0
  14. venv/lib/python3.10/site-packages/github/Authorization.py +191 -0
  15. venv/lib/python3.10/site-packages/github/AuthorizationApplication.py +69 -0
  16. venv/lib/python3.10/site-packages/github/Autolink.py +92 -0
  17. venv/lib/python3.10/site-packages/github/Branch.py +657 -0
  18. venv/lib/python3.10/site-packages/github/BranchProtection.py +219 -0
  19. venv/lib/python3.10/site-packages/github/CVSS.py +80 -0
  20. venv/lib/python3.10/site-packages/github/CWE.py +72 -0
  21. venv/lib/python3.10/site-packages/github/CheckRun.py +298 -0
  22. venv/lib/python3.10/site-packages/github/CheckRunAnnotation.py +123 -0
  23. venv/lib/python3.10/site-packages/github/CheckRunOutput.py +95 -0
  24. venv/lib/python3.10/site-packages/github/CheckSuite.py +313 -0
  25. venv/lib/python3.10/site-packages/github/Clones.py +95 -0
  26. venv/lib/python3.10/site-packages/github/CodeScanAlert.py +160 -0
  27. venv/lib/python3.10/site-packages/github/PullRequestMergeStatus.py +81 -0
  28. venv/lib/python3.10/site-packages/github/RateLimit.py +166 -0
  29. venv/lib/python3.10/site-packages/github/Reaction.py +113 -0
  30. venv/lib/python3.10/site-packages/github/RepoCodeSecurityConfig.py +87 -0
  31. venv/lib/python3.10/site-packages/github/Repository.py +0 -0
  32. venv/lib/python3.10/site-packages/github/RepositoryAdvisory.py +424 -0
  33. venv/lib/python3.10/site-packages/github/RepositoryDiscussion.py +213 -0
  34. venv/lib/python3.10/site-packages/github/RepositoryDiscussionCategory.py +142 -0
  35. venv/lib/python3.10/site-packages/github/RepositoryDiscussionComment.py +149 -0
  36. venv/lib/python3.10/site-packages/github/RepositoryKey.py +152 -0
  37. venv/lib/python3.10/site-packages/github/RepositoryPreferences.py +80 -0
  38. venv/lib/python3.10/site-packages/github/Requester.py +1317 -0
  39. venv/lib/python3.10/site-packages/github/RequiredPullRequestReviews.py +146 -0
  40. venv/lib/python3.10/site-packages/github/RequiredStatusChecks.py +92 -0
  41. venv/lib/python3.10/site-packages/github/Secret.py +124 -0
  42. venv/lib/python3.10/site-packages/github/SecurityAndAnalysis.py +141 -0
  43. venv/lib/python3.10/site-packages/github/SecurityAndAnalysisFeature.py +70 -0
  44. venv/lib/python3.10/site-packages/github/SelfHostedActionsRunner.py +113 -0
  45. venv/lib/python3.10/site-packages/github/SourceImport.py +255 -0
  46. venv/lib/python3.10/site-packages/github/Stargazer.py +87 -0
  47. venv/lib/python3.10/site-packages/github/StatsCodeFrequency.py +79 -0
  48. venv/lib/python3.10/site-packages/github/StatsCommitActivity.py +82 -0
  49. venv/lib/python3.10/site-packages/github/StatsContributor.py +124 -0
  50. venv/lib/python3.10/site-packages/github/StatsParticipation.py +76 -0
venv/lib/python3.10/site-packages/PyGithub-2.6.1.dist-info/COPYING ADDED
@@ -0,0 +1,674 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ When we speak of free software, we are referring to freedom, not
23
+ price. Our General Public Licenses are designed to make sure that you
24
+ have the freedom to distribute copies of free software (and charge for
25
+ them if you wish), that you receive source code or can get it if you
26
+ want it, that you can change the software or use pieces of it in new
27
+ free programs, and that you know you can do these things.
28
+
29
+ To protect your rights, we need to prevent others from denying you
30
+ these rights or asking you to surrender the rights. Therefore, you have
31
+ certain responsibilities if you distribute copies of the software, or if
32
+ you modify it: responsibilities to respect the freedom of others.
33
+
34
+ For example, if you distribute copies of such a program, whether
35
+ gratis or for a fee, you must pass on to the recipients the same
36
+ freedoms that you received. You must make sure that they, too, receive
37
+ or can get the source code. And you must show them these terms so they
38
+ know their rights.
39
+
40
+ Developers that use the GNU GPL protect your rights with two steps:
41
+ (1) assert copyright on the software, and (2) offer you this License
42
+ giving you legal permission to copy, distribute and/or modify it.
43
+
44
+ For the developers' and authors' protection, the GPL clearly explains
45
+ that there is no warranty for this free software. For both users' and
46
+ authors' sake, the GPL requires that modified versions be marked as
47
+ changed, so that their problems will not be attributed erroneously to
48
+ authors of previous versions.
49
+
50
+ Some devices are designed to deny users access to install or run
51
+ modified versions of the software inside them, although the manufacturer
52
+ can do so. This is fundamentally incompatible with the aim of
53
+ protecting users' freedom to change the software. The systematic
54
+ pattern of such abuse occurs in the area of products for individuals to
55
+ use, which is precisely where it is most unacceptable. Therefore, we
56
+ have designed this version of the GPL to prohibit the practice for those
57
+ products. If such problems arise substantially in other domains, we
58
+ stand ready to extend this provision to those domains in future versions
59
+ of the GPL, as needed to protect the freedom of users.
60
+
61
+ Finally, every program is threatened constantly by software patents.
62
+ States should not allow patents to restrict development and use of
63
+ software on general-purpose computers, but in those that do, we wish to
64
+ avoid the special danger that patents applied to a free program could
65
+ make it effectively proprietary. To prevent this, the GPL assures that
66
+ patents cannot be used to render the program non-free.
67
+
68
+ The precise terms and conditions for copying, distribution and
69
+ modification follow.
70
+
71
+ TERMS AND CONDITIONS
72
+
73
+ 0. Definitions.
74
+
75
+ "This License" refers to version 3 of the GNU General Public License.
76
+
77
+ "Copyright" also means copyright-like laws that apply to other kinds of
78
+ works, such as semiconductor masks.
79
+
80
+ "The Program" refers to any copyrightable work licensed under this
81
+ License. Each licensee is addressed as "you". "Licensees" and
82
+ "recipients" may be individuals or organizations.
83
+
84
+ To "modify" a work means to copy from or adapt all or part of the work
85
+ in a fashion requiring copyright permission, other than the making of an
86
+ exact copy. The resulting work is called a "modified version" of the
87
+ earlier work or a work "based on" the earlier work.
88
+
89
+ A "covered work" means either the unmodified Program or a work based
90
+ on the Program.
91
+
92
+ To "propagate" a work means to do anything with it that, without
93
+ permission, would make you directly or secondarily liable for
94
+ infringement under applicable copyright law, except executing it on a
95
+ computer or modifying a private copy. Propagation includes copying,
96
+ distribution (with or without modification), making available to the
97
+ public, and in some countries other activities as well.
98
+
99
+ To "convey" a work means any kind of propagation that enables other
100
+ parties to make or receive copies. Mere interaction with a user through
101
+ a computer network, with no transfer of a copy, is not conveying.
102
+
103
+ An interactive user interface displays "Appropriate Legal Notices"
104
+ to the extent that it includes a convenient and prominently visible
105
+ feature that (1) displays an appropriate copyright notice, and (2)
106
+ tells the user that there is no warranty for the work (except to the
107
+ extent that warranties are provided), that licensees may convey the
108
+ work under this License, and how to view a copy of this License. If
109
+ the interface presents a list of user commands or options, such as a
110
+ menu, a prominent item in the list meets this criterion.
111
+
112
+ 1. Source Code.
113
+
114
+ The "source code" for a work means the preferred form of the work
115
+ for making modifications to it. "Object code" means any non-source
116
+ form of a work.
117
+
118
+ A "Standard Interface" means an interface that either is an official
119
+ standard defined by a recognized standards body, or, in the case of
120
+ interfaces specified for a particular programming language, one that
121
+ is widely used among developers working in that language.
122
+
123
+ The "System Libraries" of an executable work include anything, other
124
+ than the work as a whole, that (a) is included in the normal form of
125
+ packaging a Major Component, but which is not part of that Major
126
+ Component, and (b) serves only to enable use of the work with that
127
+ Major Component, or to implement a Standard Interface for which an
128
+ implementation is available to the public in source code form. A
129
+ "Major Component", in this context, means a major essential component
130
+ (kernel, window system, and so on) of the specific operating system
131
+ (if any) on which the executable work runs, or a compiler used to
132
+ produce the work, or an object code interpreter used to run it.
133
+
134
+ The "Corresponding Source" for a work in object code form means all
135
+ the source code needed to generate, install, and (for an executable
136
+ work) run the object code and to modify the work, including scripts to
137
+ control those activities. However, it does not include the work's
138
+ System Libraries, or general-purpose tools or generally available free
139
+ programs which are used unmodified in performing those activities but
140
+ which are not part of the work. For example, Corresponding Source
141
+ includes interface definition files associated with source files for
142
+ the work, and the source code for shared libraries and dynamically
143
+ linked subprograms that the work is specifically designed to require,
144
+ such as by intimate data communication or control flow between those
145
+ subprograms and other parts of the work.
146
+
147
+ The Corresponding Source need not include anything that users
148
+ can regenerate automatically from other parts of the Corresponding
149
+ Source.
150
+
151
+ The Corresponding Source for a work in source code form is that
152
+ same work.
153
+
154
+ 2. Basic Permissions.
155
+
156
+ All rights granted under this License are granted for the term of
157
+ copyright on the Program, and are irrevocable provided the stated
158
+ conditions are met. This License explicitly affirms your unlimited
159
+ permission to run the unmodified Program. The output from running a
160
+ covered work is covered by this License only if the output, given its
161
+ content, constitutes a covered work. This License acknowledges your
162
+ rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+ You may make, run and propagate covered works that you do not
165
+ convey, without conditions so long as your license otherwise remains
166
+ in force. You may convey covered works to others for the sole purpose
167
+ of having them make modifications exclusively for you, or provide you
168
+ with facilities for running those works, provided that you comply with
169
+ the terms of this License in conveying all material for which you do
170
+ not control copyright. Those thus making or running the covered works
171
+ for you must do so exclusively on your behalf, under your direction
172
+ and control, on terms that prohibit them from making any copies of
173
+ your copyrighted material outside their relationship with you.
174
+
175
+ Conveying under any other circumstances is permitted solely under
176
+ the conditions stated below. Sublicensing is not allowed; section 10
177
+ makes it unnecessary.
178
+
179
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+ No covered work shall be deemed part of an effective technological
182
+ measure under any applicable law fulfilling obligations under article
183
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+ similar laws prohibiting or restricting circumvention of such
185
+ measures.
186
+
187
+ When you convey a covered work, you waive any legal power to forbid
188
+ circumvention of technological measures to the extent such circumvention
189
+ is effected by exercising rights under this License with respect to
190
+ the covered work, and you disclaim any intention to limit operation or
191
+ modification of the work as a means of enforcing, against the work's
192
+ users, your or third parties' legal rights to forbid circumvention of
193
+ technological measures.
194
+
195
+ 4. Conveying Verbatim Copies.
196
+
197
+ You may convey verbatim copies of the Program's source code as you
198
+ receive it, in any medium, provided that you conspicuously and
199
+ appropriately publish on each copy an appropriate copyright notice;
200
+ keep intact all notices stating that this License and any
201
+ non-permissive terms added in accord with section 7 apply to the code;
202
+ keep intact all notices of the absence of any warranty; and give all
203
+ recipients a copy of this License along with the Program.
204
+
205
+ You may charge any price or no price for each copy that you convey,
206
+ and you may offer support or warranty protection for a fee.
207
+
208
+ 5. Conveying Modified Source Versions.
209
+
210
+ You may convey a work based on the Program, or the modifications to
211
+ produce it from the Program, in the form of source code under the
212
+ terms of section 4, provided that you also meet all of these conditions:
213
+
214
+ a) The work must carry prominent notices stating that you modified
215
+ it, and giving a relevant date.
216
+
217
+ b) The work must carry prominent notices stating that it is
218
+ released under this License and any conditions added under section
219
+ 7. This requirement modifies the requirement in section 4 to
220
+ "keep intact all notices".
221
+
222
+ c) You must license the entire work, as a whole, under this
223
+ License to anyone who comes into possession of a copy. This
224
+ License will therefore apply, along with any applicable section 7
225
+ additional terms, to the whole of the work, and all its parts,
226
+ regardless of how they are packaged. This License gives no
227
+ permission to license the work in any other way, but it does not
228
+ invalidate such permission if you have separately received it.
229
+
230
+ d) If the work has interactive user interfaces, each must display
231
+ Appropriate Legal Notices; however, if the Program has interactive
232
+ interfaces that do not display Appropriate Legal Notices, your
233
+ work need not make them do so.
234
+
235
+ A compilation of a covered work with other separate and independent
236
+ works, which are not by their nature extensions of the covered work,
237
+ and which are not combined with it such as to form a larger program,
238
+ in or on a volume of a storage or distribution medium, is called an
239
+ "aggregate" if the compilation and its resulting copyright are not
240
+ used to limit the access or legal rights of the compilation's users
241
+ beyond what the individual works permit. Inclusion of a covered work
242
+ in an aggregate does not cause this License to apply to the other
243
+ parts of the aggregate.
244
+
245
+ 6. Conveying Non-Source Forms.
246
+
247
+ You may convey a covered work in object code form under the terms
248
+ of sections 4 and 5, provided that you also convey the
249
+ machine-readable Corresponding Source under the terms of this License,
250
+ in one of these ways:
251
+
252
+ a) Convey the object code in, or embodied in, a physical product
253
+ (including a physical distribution medium), accompanied by the
254
+ Corresponding Source fixed on a durable physical medium
255
+ customarily used for software interchange.
256
+
257
+ b) Convey the object code in, or embodied in, a physical product
258
+ (including a physical distribution medium), accompanied by a
259
+ written offer, valid for at least three years and valid for as
260
+ long as you offer spare parts or customer support for that product
261
+ model, to give anyone who possesses the object code either (1) a
262
+ copy of the Corresponding Source for all the software in the
263
+ product that is covered by this License, on a durable physical
264
+ medium customarily used for software interchange, for a price no
265
+ more than your reasonable cost of physically performing this
266
+ conveying of source, or (2) access to copy the
267
+ Corresponding Source from a network server at no charge.
268
+
269
+ c) Convey individual copies of the object code with a copy of the
270
+ written offer to provide the Corresponding Source. This
271
+ alternative is allowed only occasionally and noncommercially, and
272
+ only if you received the object code with such an offer, in accord
273
+ with subsection 6b.
274
+
275
+ d) Convey the object code by offering access from a designated
276
+ place (gratis or for a charge), and offer equivalent access to the
277
+ Corresponding Source in the same way through the same place at no
278
+ further charge. You need not require recipients to copy the
279
+ Corresponding Source along with the object code. If the place to
280
+ copy the object code is a network server, the Corresponding Source
281
+ may be on a different server (operated by you or a third party)
282
+ that supports equivalent copying facilities, provided you maintain
283
+ clear directions next to the object code saying where to find the
284
+ Corresponding Source. Regardless of what server hosts the
285
+ Corresponding Source, you remain obligated to ensure that it is
286
+ available for as long as needed to satisfy these requirements.
287
+
288
+ e) Convey the object code using peer-to-peer transmission, provided
289
+ you inform other peers where the object code and Corresponding
290
+ Source of the work are being offered to the general public at no
291
+ charge under subsection 6d.
292
+
293
+ A separable portion of the object code, whose source code is excluded
294
+ from the Corresponding Source as a System Library, need not be
295
+ included in conveying the object code work.
296
+
297
+ A "User Product" is either (1) a "consumer product", which means any
298
+ tangible personal property which is normally used for personal, family,
299
+ or household purposes, or (2) anything designed or sold for incorporation
300
+ into a dwelling. In determining whether a product is a consumer product,
301
+ doubtful cases shall be resolved in favor of coverage. For a particular
302
+ product received by a particular user, "normally used" refers to a
303
+ typical or common use of that class of product, regardless of the status
304
+ of the particular user or of the way in which the particular user
305
+ actually uses, or expects or is expected to use, the product. A product
306
+ is a consumer product regardless of whether the product has substantial
307
+ commercial, industrial or non-consumer uses, unless such uses represent
308
+ the only significant mode of use of the product.
309
+
310
+ "Installation Information" for a User Product means any methods,
311
+ procedures, authorization keys, or other information required to install
312
+ and execute modified versions of a covered work in that User Product from
313
+ a modified version of its Corresponding Source. The information must
314
+ suffice to ensure that the continued functioning of the modified object
315
+ code is in no case prevented or interfered with solely because
316
+ modification has been made.
317
+
318
+ If you convey an object code work under this section in, or with, or
319
+ specifically for use in, a User Product, and the conveying occurs as
320
+ part of a transaction in which the right of possession and use of the
321
+ User Product is transferred to the recipient in perpetuity or for a
322
+ fixed term (regardless of how the transaction is characterized), the
323
+ Corresponding Source conveyed under this section must be accompanied
324
+ by the Installation Information. But this requirement does not apply
325
+ if neither you nor any third party retains the ability to install
326
+ modified object code on the User Product (for example, the work has
327
+ been installed in ROM).
328
+
329
+ The requirement to provide Installation Information does not include a
330
+ requirement to continue to provide support service, warranty, or updates
331
+ for a work that has been modified or installed by the recipient, or for
332
+ the User Product in which it has been modified or installed. Access to a
333
+ network may be denied when the modification itself materially and
334
+ adversely affects the operation of the network or violates the rules and
335
+ protocols for communication across the network.
336
+
337
+ Corresponding Source conveyed, and Installation Information provided,
338
+ in accord with this section must be in a format that is publicly
339
+ documented (and with an implementation available to the public in
340
+ source code form), and must require no special password or key for
341
+ unpacking, reading or copying.
342
+
343
+ 7. Additional Terms.
344
+
345
+ "Additional permissions" are terms that supplement the terms of this
346
+ License by making exceptions from one or more of its conditions.
347
+ Additional permissions that are applicable to the entire Program shall
348
+ be treated as though they were included in this License, to the extent
349
+ that they are valid under applicable law. If additional permissions
350
+ apply only to part of the Program, that part may be used separately
351
+ under those permissions, but the entire Program remains governed by
352
+ this License without regard to the additional permissions.
353
+
354
+ When you convey a copy of a covered work, you may at your option
355
+ remove any additional permissions from that copy, or from any part of
356
+ it. (Additional permissions may be written to require their own
357
+ removal in certain cases when you modify the work.) You may place
358
+ additional permissions on material, added by you to a covered work,
359
+ for which you have or can give appropriate copyright permission.
360
+
361
+ Notwithstanding any other provision of this License, for material you
362
+ add to a covered work, you may (if authorized by the copyright holders of
363
+ that material) supplement the terms of this License with terms:
364
+
365
+ a) Disclaiming warranty or limiting liability differently from the
366
+ terms of sections 15 and 16 of this License; or
367
+
368
+ b) Requiring preservation of specified reasonable legal notices or
369
+ author attributions in that material or in the Appropriate Legal
370
+ Notices displayed by works containing it; or
371
+
372
+ c) Prohibiting misrepresentation of the origin of that material, or
373
+ requiring that modified versions of such material be marked in
374
+ reasonable ways as different from the original version; or
375
+
376
+ d) Limiting the use for publicity purposes of names of licensors or
377
+ authors of the material; or
378
+
379
+ e) Declining to grant rights under trademark law for use of some
380
+ trade names, trademarks, or service marks; or
381
+
382
+ f) Requiring indemnification of licensors and authors of that
383
+ material by anyone who conveys the material (or modified versions of
384
+ it) with contractual assumptions of liability to the recipient, for
385
+ any liability that these contractual assumptions directly impose on
386
+ those licensors and authors.
387
+
388
+ All other non-permissive additional terms are considered "further
389
+ restrictions" within the meaning of section 10. If the Program as you
390
+ received it, or any part of it, contains a notice stating that it is
391
+ governed by this License along with a term that is a further
392
+ restriction, you may remove that term. If a license document contains
393
+ a further restriction but permits relicensing or conveying under this
394
+ License, you may add to a covered work material governed by the terms
395
+ of that license document, provided that the further restriction does
396
+ not survive such relicensing or conveying.
397
+
398
+ If you add terms to a covered work in accord with this section, you
399
+ must place, in the relevant source files, a statement of the
400
+ additional terms that apply to those files, or a notice indicating
401
+ where to find the applicable terms.
402
+
403
+ Additional terms, permissive or non-permissive, may be stated in the
404
+ form of a separately written license, or stated as exceptions;
405
+ the above requirements apply either way.
406
+
407
+ 8. Termination.
408
+
409
+ You may not propagate or modify a covered work except as expressly
410
+ provided under this License. Any attempt otherwise to propagate or
411
+ modify it is void, and will automatically terminate your rights under
412
+ this License (including any patent licenses granted under the third
413
+ paragraph of section 11).
414
+
415
+ However, if you cease all violation of this License, then your
416
+ license from a particular copyright holder is reinstated (a)
417
+ provisionally, unless and until the copyright holder explicitly and
418
+ finally terminates your license, and (b) permanently, if the copyright
419
+ holder fails to notify you of the violation by some reasonable means
420
+ prior to 60 days after the cessation.
421
+
422
+ Moreover, your license from a particular copyright holder is
423
+ reinstated permanently if the copyright holder notifies you of the
424
+ violation by some reasonable means, this is the first time you have
425
+ received notice of violation of this License (for any work) from that
426
+ copyright holder, and you cure the violation prior to 30 days after
427
+ your receipt of the notice.
428
+
429
+ Termination of your rights under this section does not terminate the
430
+ licenses of parties who have received copies or rights from you under
431
+ this License. If your rights have been terminated and not permanently
432
+ reinstated, you do not qualify to receive new licenses for the same
433
+ material under section 10.
434
+
435
+ 9. Acceptance Not Required for Having Copies.
436
+
437
+ You are not required to accept this License in order to receive or
438
+ run a copy of the Program. Ancillary propagation of a covered work
439
+ occurring solely as a consequence of using peer-to-peer transmission
440
+ to receive a copy likewise does not require acceptance. However,
441
+ nothing other than this License grants you permission to propagate or
442
+ modify any covered work. These actions infringe copyright if you do
443
+ not accept this License. Therefore, by modifying or propagating a
444
+ covered work, you indicate your acceptance of this License to do so.
445
+
446
+ 10. Automatic Licensing of Downstream Recipients.
447
+
448
+ Each time you convey a covered work, the recipient automatically
449
+ receives a license from the original licensors, to run, modify and
450
+ propagate that work, subject to this License. You are not responsible
451
+ for enforcing compliance by third parties with this License.
452
+
453
+ An "entity transaction" is a transaction transferring control of an
454
+ organization, or substantially all assets of one, or subdividing an
455
+ organization, or merging organizations. If propagation of a covered
456
+ work results from an entity transaction, each party to that
457
+ transaction who receives a copy of the work also receives whatever
458
+ licenses to the work the party's predecessor in interest had or could
459
+ give under the previous paragraph, plus a right to possession of the
460
+ Corresponding Source of the work from the predecessor in interest, if
461
+ the predecessor has it or can get it with reasonable efforts.
462
+
463
+ You may not impose any further restrictions on the exercise of the
464
+ rights granted or affirmed under this License. For example, you may
465
+ not impose a license fee, royalty, or other charge for exercise of
466
+ rights granted under this License, and you may not initiate litigation
467
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
468
+ any patent claim is infringed by making, using, selling, offering for
469
+ sale, or importing the Program or any portion of it.
470
+
471
+ 11. Patents.
472
+
473
+ A "contributor" is a copyright holder who authorizes use under this
474
+ License of the Program or a work on which the Program is based. The
475
+ work thus licensed is called the contributor's "contributor version".
476
+
477
+ A contributor's "essential patent claims" are all patent claims
478
+ owned or controlled by the contributor, whether already acquired or
479
+ hereafter acquired, that would be infringed by some manner, permitted
480
+ by this License, of making, using, or selling its contributor version,
481
+ but do not include claims that would be infringed only as a
482
+ consequence of further modification of the contributor version. For
483
+ purposes of this definition, "control" includes the right to grant
484
+ patent sublicenses in a manner consistent with the requirements of
485
+ this License.
486
+
487
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+ patent license under the contributor's essential patent claims, to
489
+ make, use, sell, offer for sale, import and otherwise run, modify and
490
+ propagate the contents of its contributor version.
491
+
492
+ In the following three paragraphs, a "patent license" is any express
493
+ agreement or commitment, however denominated, not to enforce a patent
494
+ (such as an express permission to practice a patent or covenant not to
495
+ sue for patent infringement). To "grant" such a patent license to a
496
+ party means to make such an agreement or commitment not to enforce a
497
+ patent against the party.
498
+
499
+ If you convey a covered work, knowingly relying on a patent license,
500
+ and the Corresponding Source of the work is not available for anyone
501
+ to copy, free of charge and under the terms of this License, through a
502
+ publicly available network server or other readily accessible means,
503
+ then you must either (1) cause the Corresponding Source to be so
504
+ available, or (2) arrange to deprive yourself of the benefit of the
505
+ patent license for this particular work, or (3) arrange, in a manner
506
+ consistent with the requirements of this License, to extend the patent
507
+ license to downstream recipients. "Knowingly relying" means you have
508
+ actual knowledge that, but for the patent license, your conveying the
509
+ covered work in a country, or your recipient's use of the covered work
510
+ in a country, would infringe one or more identifiable patents in that
511
+ country that you have reason to believe are valid.
512
+
513
+ If, pursuant to or in connection with a single transaction or
514
+ arrangement, you convey, or propagate by procuring conveyance of, a
515
+ covered work, and grant a patent license to some of the parties
516
+ receiving the covered work authorizing them to use, propagate, modify
517
+ or convey a specific copy of the covered work, then the patent license
518
+ you grant is automatically extended to all recipients of the covered
519
+ work and works based on it.
520
+
521
+ A patent license is "discriminatory" if it does not include within
522
+ the scope of its coverage, prohibits the exercise of, or is
523
+ conditioned on the non-exercise of one or more of the rights that are
524
+ specifically granted under this License. You may not convey a covered
525
+ work if you are a party to an arrangement with a third party that is
526
+ in the business of distributing software, under which you make payment
527
+ to the third party based on the extent of your activity of conveying
528
+ the work, and under which the third party grants, to any of the
529
+ parties who would receive the covered work from you, a discriminatory
530
+ patent license (a) in connection with copies of the covered work
531
+ conveyed by you (or copies made from those copies), or (b) primarily
532
+ for and in connection with specific products or compilations that
533
+ contain the covered work, unless you entered into that arrangement,
534
+ or that patent license was granted, prior to 28 March 2007.
535
+
536
+ Nothing in this License shall be construed as excluding or limiting
537
+ any implied license or other defenses to infringement that may
538
+ otherwise be available to you under applicable patent law.
539
+
540
+ 12. No Surrender of Others' Freedom.
541
+
542
+ If conditions are imposed on you (whether by court order, agreement or
543
+ otherwise) that contradict the conditions of this License, they do not
544
+ excuse you from the conditions of this License. If you cannot convey a
545
+ covered work so as to satisfy simultaneously your obligations under this
546
+ License and any other pertinent obligations, then as a consequence you may
547
+ not convey it at all. For example, if you agree to terms that obligate you
548
+ to collect a royalty for further conveying from those to whom you convey
549
+ the Program, the only way you could satisfy both those terms and this
550
+ License would be to refrain entirely from conveying the Program.
551
+
552
+ 13. Use with the GNU Affero General Public License.
553
+
554
+ Notwithstanding any other provision of this License, you have
555
+ permission to link or combine any covered work with a work licensed
556
+ under version 3 of the GNU Affero General Public License into a single
557
+ combined work, and to convey the resulting work. The terms of this
558
+ License will continue to apply to the part which is the covered work,
559
+ but the special requirements of the GNU Affero General Public License,
560
+ section 13, concerning interaction through a network will apply to the
561
+ combination as such.
562
+
563
+ 14. Revised Versions of this License.
564
+
565
+ The Free Software Foundation may publish revised and/or new versions of
566
+ the GNU General Public License from time to time. Such new versions will
567
+ be similar in spirit to the present version, but may differ in detail to
568
+ address new problems or concerns.
569
+
570
+ Each version is given a distinguishing version number. If the
571
+ Program specifies that a certain numbered version of the GNU General
572
+ Public License "or any later version" applies to it, you have the
573
+ option of following the terms and conditions either of that numbered
574
+ version or of any later version published by the Free Software
575
+ Foundation. If the Program does not specify a version number of the
576
+ GNU General Public License, you may choose any version ever published
577
+ by the Free Software Foundation.
578
+
579
+ If the Program specifies that a proxy can decide which future
580
+ versions of the GNU General Public License can be used, that proxy's
581
+ public statement of acceptance of a version permanently authorizes you
582
+ to choose that version for the Program.
583
+
584
+ Later license versions may give you additional or different
585
+ permissions. However, no additional obligations are imposed on any
586
+ author or copyright holder as a result of your choosing to follow a
587
+ later version.
588
+
589
+ 15. Disclaimer of Warranty.
590
+
591
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+ 16. Limitation of Liability.
601
+
602
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+ SUCH DAMAGES.
611
+
612
+ 17. Interpretation of Sections 15 and 16.
613
+
614
+ If the disclaimer of warranty and limitation of liability provided
615
+ above cannot be given local legal effect according to their terms,
616
+ reviewing courts shall apply local law that most closely approximates
617
+ an absolute waiver of all civil liability in connection with the
618
+ Program, unless a warranty or assumption of liability accompanies a
619
+ copy of the Program in return for a fee.
620
+
621
+ END OF TERMS AND CONDITIONS
622
+
623
+ How to Apply These Terms to Your New Programs
624
+
625
+ If you develop a new program, and you want it to be of the greatest
626
+ possible use to the public, the best way to achieve this is to make it
627
+ free software which everyone can redistribute and change under these terms.
628
+
629
+ To do so, attach the following notices to the program. It is safest
630
+ to attach them to the start of each source file to most effectively
631
+ state the exclusion of warranty; and each file should have at least
632
+ the "copyright" line and a pointer to where the full notice is found.
633
+
634
+ <one line to give the program's name and a brief idea of what it does.>
635
+ Copyright (C) <year> <name of author>
636
+
637
+ This program is free software: you can redistribute it and/or modify
638
+ it under the terms of the GNU General Public License as published by
639
+ the Free Software Foundation, either version 3 of the License, or
640
+ (at your option) any later version.
641
+
642
+ This program is distributed in the hope that it will be useful,
643
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645
+ GNU General Public License for more details.
646
+
647
+ You should have received a copy of the GNU General Public License
648
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
649
+
650
+ Also add information on how to contact you by electronic and paper mail.
651
+
652
+ If the program does terminal interaction, make it output a short
653
+ notice like this when it starts in an interactive mode:
654
+
655
+ <program> Copyright (C) <year> <name of author>
656
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+ This is free software, and you are welcome to redistribute it
658
+ under certain conditions; type `show c' for details.
659
+
660
+ The hypothetical commands `show w' and `show c' should show the appropriate
661
+ parts of the General Public License. Of course, your program's commands
662
+ might be different; for a GUI interface, you would use an "about box".
663
+
664
+ You should also get your employer (if you work as a programmer) or school,
665
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+ For more information on this, and how to apply and follow the GNU GPL, see
667
+ <http://www.gnu.org/licenses/>.
668
+
669
+ The GNU General Public License does not permit incorporating your program
670
+ into proprietary programs. If your program is a subroutine library, you
671
+ may consider it more useful to permit linking proprietary applications with
672
+ the library. If this is what you want to do, use the GNU Lesser General
673
+ Public License instead of this License. But first, please read
674
+ <http://www.gnu.org/philosophy/why-not-lgpl.html>.
venv/lib/python3.10/site-packages/PyGithub-2.6.1.dist-info/COPYING.LESSER ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
venv/lib/python3.10/site-packages/github/AccessToken.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
6
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
8
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
9
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
10
+ # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
11
+ # Copyright 2019 Nick Campbell <nicholas.j.campbell@gmail.com> #
12
+ # Copyright 2019 Rigas Papathanasopoulos <rigaspapas@gmail.com> #
13
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2022 Liuyang Wan <tsfdye@gmail.com> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2023 chantra <chantra@users.noreply.github.com> #
21
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from __future__ import annotations
42
+
43
+ from datetime import datetime, timedelta, timezone
44
+ from typing import Any
45
+
46
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
47
+
48
+
49
+ class AccessToken(NonCompletableGithubObject):
50
+ """
51
+ This class represents access tokens.
52
+ """
53
+
54
+ _created: datetime
55
+
56
+ def _initAttributes(self) -> None:
57
+ self._expires_in: Attribute[int | None] = NotSet
58
+ self._refresh_expires_in: Attribute[int | None] = NotSet
59
+ self._refresh_token: Attribute[str] = NotSet
60
+ self._scope: Attribute[str] = NotSet
61
+ self._token: Attribute[str] = NotSet
62
+ self._type: Attribute[str] = NotSet
63
+
64
+ def __repr__(self) -> str:
65
+ return self.get__repr__(
66
+ {
67
+ "token": f"{self.token[:5]}...",
68
+ "scope": self.scope,
69
+ "type": self.type,
70
+ "expires_in": self.expires_in,
71
+ "refresh_token": (f"{self.refresh_token[:5]}..." if self.refresh_token else None),
72
+ "refresh_token_expires_in": self.refresh_expires_in,
73
+ }
74
+ )
75
+
76
+ @property
77
+ def created(self) -> datetime:
78
+ """
79
+ :type: datetime
80
+ """
81
+ return self._created
82
+
83
+ @property
84
+ def expires_at(self) -> datetime | None:
85
+ """
86
+ :type: Optional[datetime]
87
+ """
88
+ seconds = self.expires_in
89
+ if seconds is not None:
90
+ return self._created + timedelta(seconds=seconds)
91
+ return None
92
+
93
+ @property
94
+ def expires_in(self) -> int | None:
95
+ """
96
+ :type: Optional[int]
97
+ """
98
+ return self._expires_in.value
99
+
100
+ @property
101
+ def refresh_expires_at(self) -> datetime | None:
102
+ """
103
+ :type: Optional[datetime]
104
+ """
105
+ seconds = self.refresh_expires_in
106
+ if seconds is not None:
107
+ return self._created + timedelta(seconds=seconds)
108
+ return None
109
+
110
+ @property
111
+ def refresh_expires_in(self) -> int | None:
112
+ """
113
+ :type: Optional[int]
114
+ """
115
+ return self._refresh_expires_in.value
116
+
117
+ @property
118
+ def refresh_token(self) -> str | None:
119
+ """
120
+ :type: Optional[string]
121
+ """
122
+ return self._refresh_token.value
123
+
124
+ @property
125
+ def scope(self) -> str:
126
+ """
127
+ :type: string
128
+ """
129
+ return self._scope.value
130
+
131
+ @property
132
+ def token(self) -> str:
133
+ """
134
+ :type: string
135
+ """
136
+ return self._token.value
137
+
138
+ @property
139
+ def type(self) -> str:
140
+ """
141
+ :type: string
142
+ """
143
+ return self._type.value
144
+
145
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
146
+ self._created = datetime.now(timezone.utc)
147
+ if "access_token" in attributes: # pragma no branch
148
+ self._token = self._makeStringAttribute(attributes["access_token"])
149
+ if "expires_in" in attributes: # pragma no branch
150
+ self._expires_in = self._makeIntAttribute(attributes["expires_in"])
151
+ if "refresh_token" in attributes: # pragma no branch
152
+ self._refresh_token = self._makeStringAttribute(attributes["refresh_token"])
153
+ if "refresh_token_expires_in" in attributes: # pragma no branch
154
+ self._refresh_expires_in = self._makeIntAttribute(attributes["refresh_token_expires_in"])
155
+ if "scope" in attributes: # pragma no branch
156
+ self._scope = self._makeStringAttribute(attributes["scope"])
157
+ if "token_type" in attributes: # pragma no branch
158
+ self._type = self._makeStringAttribute(attributes["token_type"])
venv/lib/python3.10/site-packages/github/AdvisoryBase.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
4
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
5
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
6
+ # Copyright 2024 Thomas Cooper <coopernetes@proton.me> #
7
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
8
+ # #
9
+ # This file is part of PyGithub. #
10
+ # http://pygithub.readthedocs.io/ #
11
+ # #
12
+ # PyGithub is free software: you can redistribute it and/or modify it under #
13
+ # the terms of the GNU Lesser General Public License as published by the Free #
14
+ # Software Foundation, either version 3 of the License, or (at your option) #
15
+ # any later version. #
16
+ # #
17
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
18
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
19
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
20
+ # details. #
21
+ # #
22
+ # You should have received a copy of the GNU Lesser General Public License #
23
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
24
+ # #
25
+ ################################################################################
26
+
27
+ from __future__ import annotations
28
+
29
+ from datetime import datetime
30
+ from typing import Any
31
+
32
+ from github.CVSS import CVSS
33
+ from github.CWE import CWE
34
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
35
+
36
+
37
+ class AdvisoryBase(NonCompletableGithubObject):
38
+ """
39
+ This class represents the shared attributes between GlobalAdvisory, RepositoryAdvisory and DependabotAdvisory
40
+ https://docs.github.com/en/rest/security-advisories/global-advisories
41
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
42
+ https://docs.github.com/en/rest/dependabot/alerts
43
+ """
44
+
45
+ def _initAttributes(self) -> None:
46
+ self._cve_id: Attribute[str] = NotSet
47
+ self._cvss: Attribute[CVSS] = NotSet
48
+ self._cvss_severities: Attribute[dict[str, Any]] = NotSet
49
+ self._cwes: Attribute[list[CWE]] = NotSet
50
+ self._description: Attribute[str] = NotSet
51
+ self._ghsa_id: Attribute[str] = NotSet
52
+ self._html_url: Attribute[str] = NotSet
53
+ self._identifiers: Attribute[list[dict]] = NotSet
54
+ self._published_at: Attribute[datetime] = NotSet
55
+ self._severity: Attribute[str] = NotSet
56
+ self._summary: Attribute[str] = NotSet
57
+ self._updated_at: Attribute[datetime] = NotSet
58
+ self._url: Attribute[str] = NotSet
59
+ self._withdrawn_at: Attribute[datetime] = NotSet
60
+
61
+ def __repr__(self) -> str:
62
+ return self.get__repr__({"ghsa_id": self.ghsa_id, "summary": self.summary})
63
+
64
+ @property
65
+ def cve_id(self) -> str:
66
+ return self._cve_id.value
67
+
68
+ @property
69
+ def cvss(self) -> CVSS:
70
+ return self._cvss.value
71
+
72
+ @property
73
+ def cvss_severities(self) -> dict[str, Any]:
74
+ return self._cvss_severities.value
75
+
76
+ @property
77
+ def cwes(self) -> list[CWE]:
78
+ return self._cwes.value
79
+
80
+ @property
81
+ def description(self) -> str:
82
+ return self._description.value
83
+
84
+ @property
85
+ def ghsa_id(self) -> str:
86
+ return self._ghsa_id.value
87
+
88
+ @property
89
+ def html_url(self) -> str:
90
+ return self._html_url.value
91
+
92
+ @property
93
+ def identifiers(self) -> list[dict]:
94
+ return self._identifiers.value
95
+
96
+ @property
97
+ def published_at(self) -> datetime:
98
+ return self._published_at.value
99
+
100
+ @property
101
+ def severity(self) -> str:
102
+ return self._severity.value
103
+
104
+ @property
105
+ def summary(self) -> str:
106
+ return self._summary.value
107
+
108
+ @property
109
+ def updated_at(self) -> datetime:
110
+ return self._updated_at.value
111
+
112
+ @property
113
+ def url(self) -> str:
114
+ return self._url.value
115
+
116
+ @property
117
+ def withdrawn_at(self) -> datetime:
118
+ return self._withdrawn_at.value
119
+
120
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
121
+ if "cve_id" in attributes: # pragma no branch
122
+ self._cve_id = self._makeStringAttribute(attributes["cve_id"])
123
+ if "cvss" in attributes: # pragma no branch
124
+ self._cvss = self._makeClassAttribute(CVSS, attributes["cvss"])
125
+ if "cvss_severities" in attributes: # pragma no branch
126
+ self._cvss_severities = self._makeDictAttribute(attributes["cvss_severities"])
127
+ if "cwes" in attributes: # pragma no branch
128
+ self._cwes = self._makeListOfClassesAttribute(CWE, attributes["cwes"])
129
+ if "description" in attributes: # pragma no branch
130
+ self._description = self._makeStringAttribute(attributes["description"])
131
+ if "ghsa_id" in attributes: # pragma no branch
132
+ self._ghsa_id = self._makeStringAttribute(attributes["ghsa_id"])
133
+ if "html_url" in attributes: # pragma no branch
134
+ self._html_url = self._makeStringAttribute(attributes["html_url"])
135
+ if "identifiers" in attributes: # pragma no branch
136
+ self._identifiers = self._makeListOfDictsAttribute(attributes["identifiers"])
137
+ if "published_at" in attributes: # pragma no branch
138
+ assert attributes["published_at"] is None or isinstance(attributes["published_at"], str), attributes[
139
+ "published_at"
140
+ ]
141
+ self._published_at = self._makeDatetimeAttribute(attributes["published_at"])
142
+ if "severity" in attributes: # pragma no branch
143
+ self._severity = self._makeStringAttribute(attributes["severity"])
144
+ if "summary" in attributes: # pragma no branch
145
+ self._summary = self._makeStringAttribute(attributes["summary"])
146
+ if "updated_at" in attributes: # pragma no branch
147
+ assert attributes["updated_at"] is None or isinstance(attributes["updated_at"], str), attributes[
148
+ "updated_at"
149
+ ]
150
+ self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
151
+ if "url" in attributes: # pragma no branch
152
+ self._url = self._makeStringAttribute(attributes["url"])
153
+ if "withdrawn_at" in attributes: # pragma no branch
154
+ assert attributes["withdrawn_at"] is None or isinstance(attributes["withdrawn_at"], str), attributes[
155
+ "withdrawn_at"
156
+ ]
157
+ self._withdrawn_at = self._makeDatetimeAttribute(attributes["withdrawn_at"])
venv/lib/python3.10/site-packages/github/AdvisoryCredit.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
4
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
5
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
6
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
7
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
8
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
9
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
10
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
11
+ # #
12
+ # This file is part of PyGithub. #
13
+ # http://pygithub.readthedocs.io/ #
14
+ # #
15
+ # PyGithub is free software: you can redistribute it and/or modify it under #
16
+ # the terms of the GNU Lesser General Public License as published by the Free #
17
+ # Software Foundation, either version 3 of the License, or (at your option) #
18
+ # any later version. #
19
+ # #
20
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
22
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
23
+ # details. #
24
+ # #
25
+ # You should have received a copy of the GNU Lesser General Public License #
26
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
27
+ # #
28
+ ################################################################################
29
+
30
+ from __future__ import annotations
31
+
32
+ from typing import Any, Union
33
+
34
+ from typing_extensions import TypedDict
35
+
36
+ import github.NamedUser
37
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
38
+
39
+
40
+ class SimpleCredit(TypedDict):
41
+ """
42
+ A simple credit for a security advisory.
43
+ """
44
+
45
+ login: str | github.NamedUser.NamedUser
46
+ type: str
47
+
48
+
49
+ Credit = Union[SimpleCredit, "AdvisoryCredit"]
50
+
51
+
52
+ class AdvisoryCredit(NonCompletableGithubObject):
53
+ """
54
+ This class represents a credit that is assigned to a SecurityAdvisory.
55
+
56
+ The reference can be found here
57
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
58
+
59
+ The OpenAPI schema can be found at
60
+ - /components/schemas/repository-advisory/properties/credits/items
61
+
62
+ """
63
+
64
+ def _initAttributes(self) -> None:
65
+ self._login: Attribute[str] = NotSet
66
+ self._type: Attribute[str] = NotSet
67
+
68
+ def __repr__(self) -> str:
69
+ return self.get__repr__(
70
+ {
71
+ "login": self.login,
72
+ "type": self.type,
73
+ }
74
+ )
75
+
76
+ @property
77
+ def login(self) -> str:
78
+ """
79
+ :type: string
80
+ """
81
+ return self._login.value
82
+
83
+ @property
84
+ def type(self) -> str:
85
+ """
86
+ :type: string
87
+ """
88
+ return self._type.value
89
+
90
+ @staticmethod
91
+ def _validate_credit(credit: Credit) -> None:
92
+ assert isinstance(credit, (dict, AdvisoryCredit)), credit
93
+ if isinstance(credit, dict):
94
+ assert "login" in credit, credit
95
+ assert "type" in credit, credit
96
+ assert isinstance(credit["login"], (str, github.NamedUser.NamedUser)), credit["login"]
97
+ assert isinstance(credit["type"], str), credit["type"]
98
+ else:
99
+ assert isinstance(credit.login, str), credit.login
100
+ assert isinstance(credit.type, str), credit.type
101
+
102
+ @staticmethod
103
+ def _to_github_dict(credit: Credit) -> SimpleCredit:
104
+ assert isinstance(credit, (dict, AdvisoryCredit)), credit
105
+ if isinstance(credit, dict):
106
+ assert "login" in credit, credit
107
+ assert "type" in credit, credit
108
+ assert isinstance(credit["login"], (str, github.NamedUser.NamedUser)), credit["login"]
109
+ login = credit["login"]
110
+ if isinstance(login, github.NamedUser.NamedUser):
111
+ login = login.login
112
+ return {
113
+ "login": login,
114
+ "type": credit["type"],
115
+ }
116
+ else:
117
+ return {
118
+ "login": credit.login,
119
+ "type": credit.type,
120
+ }
121
+
122
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
123
+ if "login" in attributes: # pragma no branch
124
+ self._login = self._makeStringAttribute(attributes["login"])
125
+ if "type" in attributes: # pragma no branch
126
+ self._type = self._makeStringAttribute(attributes["type"])
venv/lib/python3.10/site-packages/github/AdvisoryCreditDetailed.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
6
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
8
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
9
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
10
+ # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
11
+ # Copyright 2019 Nick Campbell <nicholas.j.campbell@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
18
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
19
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
20
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
21
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
22
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
23
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
24
+ # #
25
+ # This file is part of PyGithub. #
26
+ # http://pygithub.readthedocs.io/ #
27
+ # #
28
+ # PyGithub is free software: you can redistribute it and/or modify it under #
29
+ # the terms of the GNU Lesser General Public License as published by the Free #
30
+ # Software Foundation, either version 3 of the License, or (at your option) #
31
+ # any later version. #
32
+ # #
33
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
34
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
35
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
36
+ # details. #
37
+ # #
38
+ # You should have received a copy of the GNU Lesser General Public License #
39
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
40
+ # #
41
+ ################################################################################
42
+
43
+ from __future__ import annotations
44
+
45
+ from typing import Any
46
+
47
+ import github.NamedUser
48
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
49
+
50
+
51
+ class AdvisoryCreditDetailed(NonCompletableGithubObject):
52
+ """
53
+ This class represents a credit that is assigned to a SecurityAdvisory.
54
+
55
+ The reference can be found here
56
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
57
+
58
+ The OpenAPI schema can be found at
59
+ - /components/schemas/global-advisory/properties/credits/items
60
+ - /components/schemas/repository-advisory-credit
61
+
62
+ """
63
+
64
+ def _initAttributes(self) -> None:
65
+ self._state: Attribute[str] = NotSet
66
+ self._type: Attribute[str] = NotSet
67
+ self._user: Attribute[github.NamedUser.NamedUser] = NotSet
68
+
69
+ def __repr__(self) -> str:
70
+ return self.get__repr__(
71
+ {
72
+ "user": self.user,
73
+ "type": self.type,
74
+ }
75
+ )
76
+
77
+ @property
78
+ def state(self) -> str:
79
+ """
80
+ :type: string
81
+ """
82
+ return self._state.value
83
+
84
+ @property
85
+ def type(self) -> str:
86
+ """
87
+ :type: string
88
+ """
89
+ return self._type.value
90
+
91
+ @property
92
+ def user(self) -> github.NamedUser.NamedUser:
93
+ """
94
+ :type: :class:`github.NamedUser.NamedUser`
95
+ """
96
+ return self._user.value
97
+
98
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
99
+ if "state" in attributes: # pragma no branch
100
+ self._state = self._makeStringAttribute(attributes["state"])
101
+ if "type" in attributes: # pragma no branch
102
+ self._type = self._makeStringAttribute(attributes["type"])
103
+ if "user" in attributes: # pragma no branch
104
+ self._user = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["user"])
venv/lib/python3.10/site-packages/github/AdvisoryVulnerability.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
4
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
5
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
6
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
7
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
8
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
9
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
10
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
11
+ # #
12
+ # This file is part of PyGithub. #
13
+ # http://pygithub.readthedocs.io/ #
14
+ # #
15
+ # PyGithub is free software: you can redistribute it and/or modify it under #
16
+ # the terms of the GNU Lesser General Public License as published by the Free #
17
+ # Software Foundation, either version 3 of the License, or (at your option) #
18
+ # any later version. #
19
+ # #
20
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
22
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
23
+ # details. #
24
+ # #
25
+ # You should have received a copy of the GNU Lesser General Public License #
26
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
27
+ # #
28
+ ################################################################################
29
+
30
+ from __future__ import annotations
31
+
32
+ from typing import TYPE_CHECKING, Any, Union
33
+
34
+ from typing_extensions import TypedDict
35
+
36
+ import github.AdvisoryVulnerabilityPackage
37
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
38
+
39
+ if TYPE_CHECKING:
40
+ from github.AdvisoryVulnerabilityPackage import AdvisoryVulnerabilityPackage
41
+
42
+
43
+ class SimpleAdvisoryVulnerabilityPackage(TypedDict):
44
+ """
45
+ A simple package in an advisory.
46
+ """
47
+
48
+ ecosystem: str
49
+ name: str | None
50
+
51
+
52
+ class SimpleAdvisoryVulnerability(TypedDict):
53
+ """
54
+ A simple vulnerability in a security advisory.
55
+ """
56
+
57
+ package: SimpleAdvisoryVulnerabilityPackage
58
+ patched_versions: str | None
59
+ vulnerable_functions: list[str] | None
60
+ vulnerable_version_range: str | None
61
+
62
+
63
+ AdvisoryVulnerabilityInput = Union[SimpleAdvisoryVulnerability, "AdvisoryVulnerability"]
64
+
65
+
66
+ class AdvisoryVulnerability(NonCompletableGithubObject):
67
+ """
68
+ This class represents a package that is vulnerable to a parent SecurityAdvisory.
69
+
70
+ The reference can be found here
71
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
72
+
73
+ The OpenAPI schema can be found at
74
+ - /components/schemas/repository-advisory-vulnerability
75
+ - /components/schemas/vulnerability
76
+
77
+ """
78
+
79
+ def _initAttributes(self) -> None:
80
+ self._first_patched_version: Attribute[str] = NotSet
81
+ self._package: Attribute[AdvisoryVulnerabilityPackage] = NotSet
82
+ self._patched_versions: Attribute[str] = NotSet
83
+ self._vulnerable_functions: Attribute[list[str]] = NotSet
84
+ self._vulnerable_version_range: Attribute[str] = NotSet
85
+
86
+ def __repr__(self) -> str:
87
+ return self.get__repr__({"package": self.package})
88
+
89
+ @property
90
+ def first_patched_version(self) -> str:
91
+ return self._first_patched_version.value
92
+
93
+ @property
94
+ def package(
95
+ self,
96
+ ) -> AdvisoryVulnerabilityPackage:
97
+ """
98
+ :type: :class:`github.AdvisoryVulnerability.AdvisoryVulnerability`
99
+ """
100
+ return self._package.value
101
+
102
+ @property
103
+ def patched_versions(self) -> str:
104
+ """
105
+ :type: string
106
+ """
107
+ return self._patched_versions.value
108
+
109
+ @property
110
+ def vulnerable_functions(self) -> list[str] | None:
111
+ """
112
+ :type: list of string
113
+ """
114
+ return self._vulnerable_functions.value
115
+
116
+ @property
117
+ def vulnerable_version_range(self) -> str | None:
118
+ """
119
+ :type: string
120
+ """
121
+ return self._vulnerable_version_range.value
122
+
123
+ @classmethod
124
+ def _validate_vulnerability(cls, vulnerability: AdvisoryVulnerabilityInput) -> None:
125
+ assert isinstance(vulnerability, (dict, cls)), vulnerability
126
+ if isinstance(vulnerability, dict):
127
+ assert "package" in vulnerability, vulnerability
128
+ package: SimpleAdvisoryVulnerabilityPackage = vulnerability["package"]
129
+ assert isinstance(package, dict), package
130
+ assert "ecosystem" in package, package
131
+ assert isinstance(package["ecosystem"], str), package
132
+ assert "name" in package, package
133
+ assert isinstance(package["name"], (str, type(None))), package
134
+ assert "patched_versions" in vulnerability, vulnerability
135
+ assert isinstance(vulnerability["patched_versions"], (str, type(None))), vulnerability
136
+ assert "vulnerable_functions" in vulnerability, vulnerability
137
+ assert isinstance(vulnerability["vulnerable_functions"], (list, type(None))), vulnerability
138
+ assert "vulnerable_functions" in vulnerability, vulnerability
139
+ assert (
140
+ all(isinstance(vf, str) for vf in vulnerability["vulnerable_functions"])
141
+ if vulnerability["vulnerable_functions"] is not None
142
+ else True
143
+ ), vulnerability
144
+ assert "vulnerable_version_range" in vulnerability, vulnerability
145
+ assert isinstance(vulnerability["vulnerable_version_range"], (str, type(None))), vulnerability
146
+
147
+ else:
148
+ assert (
149
+ vulnerability.package is github.AdvisoryVulnerabilityPackage.AdvisoryVulnerabilityPackage
150
+ ), vulnerability
151
+
152
+ @staticmethod
153
+ def _to_github_dict(
154
+ vulnerability: AdvisoryVulnerabilityInput,
155
+ ) -> SimpleAdvisoryVulnerability:
156
+ if isinstance(vulnerability, dict):
157
+ vulnerability_package: SimpleAdvisoryVulnerabilityPackage = vulnerability["package"]
158
+ return {
159
+ "package": {
160
+ "ecosystem": vulnerability_package["ecosystem"],
161
+ "name": vulnerability_package["name"],
162
+ },
163
+ "patched_versions": vulnerability["patched_versions"],
164
+ "vulnerable_functions": vulnerability["vulnerable_functions"],
165
+ "vulnerable_version_range": vulnerability["vulnerable_version_range"],
166
+ }
167
+ return {
168
+ "package": {
169
+ "ecosystem": vulnerability.package.ecosystem,
170
+ "name": vulnerability.package.name,
171
+ },
172
+ "patched_versions": vulnerability.patched_versions,
173
+ "vulnerable_functions": vulnerability.vulnerable_functions,
174
+ "vulnerable_version_range": vulnerability.vulnerable_version_range,
175
+ }
176
+
177
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
178
+ if "first_patched_version" in attributes: # pragma no branch
179
+ self._first_patched_version = self._makeStringAttribute(attributes["first_patched_version"])
180
+ if "package" in attributes: # pragma no branch
181
+ self._package = self._makeClassAttribute(
182
+ github.AdvisoryVulnerabilityPackage.AdvisoryVulnerabilityPackage,
183
+ attributes["package"],
184
+ )
185
+ if "patched_versions" in attributes: # pragma no branch
186
+ self._patched_versions = self._makeStringAttribute(attributes["patched_versions"])
187
+ if "vulnerable_functions" in attributes: # pragma no branch
188
+ self._vulnerable_functions = self._makeListOfStringsAttribute(attributes["vulnerable_functions"])
189
+ if "vulnerable_version_range" in attributes: # pragma no branch
190
+ self._vulnerable_version_range = self._makeStringAttribute(attributes["vulnerable_version_range"])
venv/lib/python3.10/site-packages/github/AdvisoryVulnerabilityPackage.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
19
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
20
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
21
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
22
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
23
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
24
+ # Copyright 2024 Thomas Cooper <coopernetes@proton.me> #
25
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
26
+ # #
27
+ # This file is part of PyGithub. #
28
+ # http://pygithub.readthedocs.io/ #
29
+ # #
30
+ # PyGithub is free software: you can redistribute it and/or modify it under #
31
+ # the terms of the GNU Lesser General Public License as published by the Free #
32
+ # Software Foundation, either version 3 of the License, or (at your option) #
33
+ # any later version. #
34
+ # #
35
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
36
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
37
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
38
+ # details. #
39
+ # #
40
+ # You should have received a copy of the GNU Lesser General Public License #
41
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
42
+ # #
43
+ ################################################################################
44
+
45
+ from __future__ import annotations
46
+
47
+ from typing import Any
48
+
49
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
50
+
51
+
52
+ class AdvisoryVulnerabilityPackage(NonCompletableGithubObject):
53
+ """
54
+ This class represents an identifier for a package that is vulnerable to a parent SecurityAdvisory.
55
+
56
+ The reference can be found here
57
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
58
+
59
+ The OpenAPI schema can be found at
60
+ - /components/schemas/dependabot-alert-package
61
+ - /components/schemas/repository-advisory-vulnerability/properties/package
62
+ - /components/schemas/vulnerability/properties/package
63
+
64
+ """
65
+
66
+ def _initAttributes(self) -> None:
67
+ self._ecosystem: Attribute[str] = NotSet
68
+ self._name: Attribute[str | None] = NotSet
69
+
70
+ def __repr__(self) -> str:
71
+ return self.get__repr__({"name": self.name})
72
+
73
+ @property
74
+ def ecosystem(self) -> str:
75
+ """
76
+ :type: string
77
+ """
78
+ return self._ecosystem.value
79
+
80
+ @property
81
+ def name(self) -> str | None:
82
+ """
83
+ :type: string or None
84
+ """
85
+ return self._name.value
86
+
87
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
88
+ if "ecosystem" in attributes: # pragma no branch
89
+ self._ecosystem = self._makeStringAttribute(attributes["ecosystem"])
90
+ if "name" in attributes: # pragma no branch
91
+ self._name = self._makeStringAttribute(attributes["name"])
venv/lib/python3.10/site-packages/github/AppAuthentication.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
6
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
8
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
9
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
10
+ # Copyright 2019 TechnicalPirate <35609336+TechnicalPirate@users.noreply.github.com>#
11
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
12
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
14
+ # Copyright 2023 Denis Blanchette <dblanchette@coveo.com> #
15
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
16
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
17
+ # #
18
+ # This file is part of PyGithub. #
19
+ # http://pygithub.readthedocs.io/ #
20
+ # #
21
+ # PyGithub is free software: you can redistribute it and/or modify it under #
22
+ # the terms of the GNU Lesser General Public License as published by the Free #
23
+ # Software Foundation, either version 3 of the License, or (at your option) #
24
+ # any later version. #
25
+ # #
26
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
27
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
28
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
29
+ # details. #
30
+ # #
31
+ # You should have received a copy of the GNU Lesser General Public License #
32
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
33
+ # #
34
+ ################################################################################
35
+
36
+
37
+ from typing import Dict, Optional, Union
38
+
39
+ import deprecated
40
+
41
+ from github.Auth import AppAuth, AppInstallationAuth
42
+
43
+
44
+ @deprecated.deprecated("Use github.Auth.AppInstallationAuth instead")
45
+ class AppAuthentication(AppInstallationAuth):
46
+ def __init__(
47
+ self,
48
+ app_id: Union[int, str],
49
+ private_key: str,
50
+ installation_id: int,
51
+ token_permissions: Optional[Dict[str, str]] = None,
52
+ ):
53
+ super().__init__(
54
+ app_auth=AppAuth(app_id, private_key),
55
+ installation_id=installation_id,
56
+ token_permissions=token_permissions,
57
+ )
venv/lib/python3.10/site-packages/github/ApplicationOAuth.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2019 Rigas Papathanasopoulos <rigaspapas@gmail.com> #
4
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
5
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
6
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
7
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
8
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
9
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
10
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
11
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
12
+ # #
13
+ # This file is part of PyGithub. #
14
+ # http://pygithub.readthedocs.io/ #
15
+ # #
16
+ # PyGithub is free software: you can redistribute it and/or modify it under #
17
+ # the terms of the GNU Lesser General Public License as published by the Free #
18
+ # Software Foundation, either version 3 of the License, or (at your option) #
19
+ # any later version. #
20
+ # #
21
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
22
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
23
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
24
+ # details. #
25
+ # #
26
+ # You should have received a copy of the GNU Lesser General Public License #
27
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
28
+ # #
29
+ ################################################################################
30
+
31
+ from __future__ import annotations
32
+
33
+ import urllib.parse
34
+ from typing import TYPE_CHECKING, Any
35
+
36
+ import github.AccessToken
37
+ import github.Auth
38
+ from github.Consts import DEFAULT_BASE_URL, DEFAULT_OAUTH_URL
39
+ from github.GithubException import BadCredentialsException, GithubException
40
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
41
+ from github.Requester import Requester
42
+
43
+ if TYPE_CHECKING:
44
+ from github.AccessToken import AccessToken
45
+ from github.Auth import AppUserAuth
46
+
47
+
48
+ class ApplicationOAuth(NonCompletableGithubObject):
49
+ """
50
+ This class is used for identifying and authorizing users for Github Apps.
51
+
52
+ The reference can be found at
53
+ https://docs.github.com/en/developers/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps
54
+
55
+ """
56
+
57
+ def _initAttributes(self) -> None:
58
+ self._client_id: Attribute[str] = NotSet
59
+ self._client_secret: Attribute[str] = NotSet
60
+
61
+ def __init__(
62
+ self,
63
+ requester: Requester,
64
+ headers: dict[str, Any],
65
+ attributes: Any,
66
+ ) -> None:
67
+ # this object requires a request without authentication
68
+ requester = requester.withAuth(auth=None)
69
+ super().__init__(requester, headers, attributes)
70
+
71
+ def __repr__(self) -> str:
72
+ return self.get__repr__({"client_id": self._client_id.value})
73
+
74
+ @property
75
+ def client_id(self) -> str:
76
+ return self._client_id.value
77
+
78
+ @property
79
+ def client_secret(self) -> str:
80
+ return self._client_secret.value
81
+
82
+ def get_oauth_url(self, path: str) -> str:
83
+ if not path.startswith("/"):
84
+ path = f"/{path}"
85
+
86
+ if self._requester.base_url == DEFAULT_BASE_URL:
87
+ base_url = DEFAULT_OAUTH_URL
88
+ else:
89
+ base_url = f"{self._requester.scheme}://{self._requester.hostname_and_port}/login/oauth"
90
+ return f"{base_url}{path}"
91
+
92
+ def get_login_url(
93
+ self,
94
+ redirect_uri: str | None = None,
95
+ state: str | None = None,
96
+ login: str | None = None,
97
+ ) -> str:
98
+ """
99
+ Return the URL you need to redirect a user to in order to authorize your App.
100
+ """
101
+ parameters = {"client_id": self.client_id}
102
+ if redirect_uri is not None:
103
+ assert isinstance(redirect_uri, str), redirect_uri
104
+ parameters["redirect_uri"] = redirect_uri
105
+ if state is not None:
106
+ assert isinstance(state, str), state
107
+ parameters["state"] = state
108
+ if login is not None:
109
+ assert isinstance(login, str), login
110
+ parameters["login"] = login
111
+
112
+ query = urllib.parse.urlencode(parameters)
113
+
114
+ return self.get_oauth_url(f"/authorize?{query}")
115
+
116
+ def get_access_token(self, code: str, state: str | None = None) -> AccessToken:
117
+ """
118
+ :calls: `POST /login/oauth/access_token <https://docs.github.com/en/developers/apps/identifying-and-authorizing-users-for-github-apps>`_
119
+ """
120
+ assert isinstance(code, str), code
121
+ post_parameters = {
122
+ "code": code,
123
+ "client_id": self.client_id,
124
+ "client_secret": self.client_secret,
125
+ }
126
+
127
+ if state is not None:
128
+ post_parameters["state"] = state
129
+
130
+ headers, data = self._checkError(
131
+ *self._requester.requestJsonAndCheck(
132
+ "POST",
133
+ self.get_oauth_url("/access_token"),
134
+ headers={"Accept": "application/json"},
135
+ input=post_parameters,
136
+ )
137
+ )
138
+
139
+ return github.AccessToken.AccessToken(
140
+ requester=self._requester,
141
+ headers=headers,
142
+ attributes=data,
143
+ )
144
+
145
+ def get_app_user_auth(self, token: AccessToken) -> AppUserAuth:
146
+ return github.Auth.AppUserAuth(
147
+ client_id=self.client_id,
148
+ client_secret=self.client_secret,
149
+ token=token.token,
150
+ token_type=token.type,
151
+ expires_at=token.expires_at,
152
+ refresh_token=token.refresh_token,
153
+ refresh_expires_at=token.refresh_expires_at,
154
+ requester=self._requester,
155
+ )
156
+
157
+ def refresh_access_token(self, refresh_token: str) -> AccessToken:
158
+ """
159
+ :calls: `POST /login/oauth/access_token <https://docs.github.com/en/developers/apps/identifying-and-authorizing-users-for-github-apps>`_
160
+ :param refresh_token: string
161
+ """
162
+ assert isinstance(refresh_token, str)
163
+ post_parameters = {
164
+ "client_id": self.client_id,
165
+ "client_secret": self.client_secret,
166
+ "grant_type": "refresh_token",
167
+ "refresh_token": refresh_token,
168
+ }
169
+
170
+ headers, data = self._checkError(
171
+ *self._requester.requestJsonAndCheck(
172
+ "POST",
173
+ self.get_oauth_url("/access_token"),
174
+ headers={"Accept": "application/json"},
175
+ input=post_parameters,
176
+ )
177
+ )
178
+
179
+ return github.AccessToken.AccessToken(
180
+ requester=self._requester,
181
+ headers=headers,
182
+ attributes=data,
183
+ )
184
+
185
+ @staticmethod
186
+ def _checkError(headers: dict[str, Any], data: Any) -> tuple[dict[str, Any], Any]:
187
+ if isinstance(data, dict) and "error" in data:
188
+ if data["error"] == "bad_verification_code":
189
+ raise BadCredentialsException(200, data, headers)
190
+ raise GithubException(200, data, headers)
191
+
192
+ return headers, data
193
+
194
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
195
+ if "client_id" in attributes: # pragma no branch
196
+ self._client_id = self._makeStringAttribute(attributes["client_id"])
197
+ if "client_secret" in attributes: # pragma no branch
198
+ self._client_secret = self._makeStringAttribute(attributes["client_secret"])
venv/lib/python3.10/site-packages/github/Artifact.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2015 Matt Babineau <mbabineau@dataxu.com> #
9
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
10
+ # Copyright 2016 Martijn Koster <mak-github@greenhills.co.uk> #
11
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
12
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
13
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
14
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
16
+ # Copyright 2020 Colby Gallup <colbygallup@gmail.com> #
17
+ # Copyright 2020 Mahesh Raju <coder@mahesh.net> #
18
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
19
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
20
+ # Copyright 2022 Aleksei Fedotov <lexa@cfotr.com> #
21
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
22
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
23
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
24
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
25
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
26
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
27
+ # #
28
+ # This file is part of PyGithub. #
29
+ # http://pygithub.readthedocs.io/ #
30
+ # #
31
+ # PyGithub is free software: you can redistribute it and/or modify it under #
32
+ # the terms of the GNU Lesser General Public License as published by the Free #
33
+ # Software Foundation, either version 3 of the License, or (at your option) #
34
+ # any later version. #
35
+ # #
36
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
37
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
38
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
39
+ # details. #
40
+ # #
41
+ # You should have received a copy of the GNU Lesser General Public License #
42
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
43
+ # #
44
+ ################################################################################
45
+
46
+ from __future__ import annotations
47
+
48
+ from datetime import datetime
49
+ from typing import TYPE_CHECKING, Any
50
+
51
+ import github.WorkflowRun
52
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
53
+
54
+ if TYPE_CHECKING:
55
+ from github.WorkflowRun import WorkflowRun
56
+
57
+
58
+ class Artifact(NonCompletableGithubObject):
59
+ """
60
+ This class represents an Artifact of Github Run.
61
+
62
+ The OpenAPI schema can be found at
63
+ - /components/schemas/artifact
64
+
65
+ """
66
+
67
+ def _initAttributes(self) -> None:
68
+ self._archive_download_url: Attribute[str] = NotSet
69
+ self._created_at: Attribute[datetime] = NotSet
70
+ self._expired: Attribute[bool] = NotSet
71
+ self._expires_at: Attribute[datetime] = NotSet
72
+ self._head_sha: Attribute[str] = NotSet
73
+ self._id: Attribute[int] = NotSet
74
+ self._name: Attribute[str] = NotSet
75
+ self._node_id: Attribute[str] = NotSet
76
+ self._size_in_bytes: Attribute[int] = NotSet
77
+ self._updated_at: Attribute[datetime] = NotSet
78
+ self._url: Attribute[str] = NotSet
79
+ self._workflow_run: Attribute[WorkflowRun] = NotSet
80
+
81
+ def __repr__(self) -> str:
82
+ return self.get__repr__({"name": self._name.value, "id": self._id.value})
83
+
84
+ @property
85
+ def archive_download_url(self) -> str:
86
+ return self._archive_download_url.value
87
+
88
+ @property
89
+ def created_at(self) -> datetime:
90
+ return self._created_at.value
91
+
92
+ @property
93
+ def expired(self) -> bool:
94
+ return self._expired.value
95
+
96
+ @property
97
+ def expires_at(self) -> datetime:
98
+ return self._expires_at.value
99
+
100
+ @property
101
+ def head_sha(self) -> str:
102
+ return self._head_sha.value
103
+
104
+ @property
105
+ def id(self) -> int:
106
+ return self._id.value
107
+
108
+ @property
109
+ def name(self) -> str:
110
+ return self._name.value
111
+
112
+ @property
113
+ def node_id(self) -> str:
114
+ return self._node_id.value
115
+
116
+ @property
117
+ def size_in_bytes(self) -> int:
118
+ return self._size_in_bytes.value
119
+
120
+ @property
121
+ def updated_at(self) -> datetime:
122
+ return self._updated_at.value
123
+
124
+ @property
125
+ def url(self) -> str:
126
+ return self._url.value
127
+
128
+ @property
129
+ def workflow_run(self) -> WorkflowRun:
130
+ return self._workflow_run.value
131
+
132
+ def delete(self) -> bool:
133
+ """
134
+ :calls: `DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id} <https://docs.github.com/en/rest/actions/artifacts#delete-an-artifact>`_
135
+ """
136
+ status, headers, data = self._requester.requestBlob("DELETE", self.url)
137
+ return status == 204
138
+
139
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
140
+ if "archive_download_url" in attributes: # pragma no branch
141
+ self._archive_download_url = self._makeStringAttribute(attributes["archive_download_url"])
142
+ if "created_at" in attributes: # pragma no branch
143
+ assert attributes["created_at"] is None or isinstance(attributes["created_at"], (str,)), attributes[
144
+ "created_at"
145
+ ]
146
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
147
+ if "expired" in attributes: # pragma no branch
148
+ self._expired = self._makeBoolAttribute(attributes["expired"])
149
+ if "expires_at" in attributes: # pragma no branch
150
+ assert attributes["expires_at"] is None or isinstance(attributes["expires_at"], (str,)), attributes[
151
+ "expires_at"
152
+ ]
153
+ self._expires_at = self._makeDatetimeAttribute(attributes["expires_at"])
154
+ if "head_sha" in attributes: # pragma no branch
155
+ self._head_sha = self._makeStringAttribute(attributes["head_sha"])
156
+ if "id" in attributes: # pragma no branch
157
+ self._id = self._makeIntAttribute(attributes["id"])
158
+ if "name" in attributes: # pragma no branch
159
+ self._name = self._makeStringAttribute(attributes["name"])
160
+ if "node_id" in attributes: # pragma no branch
161
+ self._node_id = self._makeStringAttribute(attributes["node_id"])
162
+ if "size_in_bytes" in attributes: # pragma no branch
163
+ self._size_in_bytes = self._makeIntAttribute(attributes["size_in_bytes"])
164
+ if "updated_at" in attributes: # pragma no branch
165
+ assert attributes["updated_at"] is None or isinstance(attributes["updated_at"], (str,)), attributes[
166
+ "updated_at"
167
+ ]
168
+ self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
169
+ if "url" in attributes: # pragma no branch
170
+ self._url = self._makeStringAttribute(attributes["url"])
171
+ if "workflow_run" in attributes: # pragma no branch
172
+ self._workflow_run = self._makeClassAttribute(github.WorkflowRun.WorkflowRun, attributes["workflow_run"])
venv/lib/python3.10/site-packages/github/Auth.py ADDED
@@ -0,0 +1,551 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
4
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
5
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
6
+ # Copyright 2023 chantra <chantra@users.noreply.github.com> #
7
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
8
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
9
+ # Copyright 2024 Jonathan Kliem <jonathan.kliem@gmail.com> #
10
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
11
+ # #
12
+ # This file is part of PyGithub. #
13
+ # http://pygithub.readthedocs.io/ #
14
+ # #
15
+ # PyGithub is free software: you can redistribute it and/or modify it under #
16
+ # the terms of the GNU Lesser General Public License as published by the Free #
17
+ # Software Foundation, either version 3 of the License, or (at your option) #
18
+ # any later version. #
19
+ # #
20
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
22
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
23
+ # details. #
24
+ # #
25
+ # You should have received a copy of the GNU Lesser General Public License #
26
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
27
+ # #
28
+ ################################################################################
29
+
30
+ import abc
31
+ import base64
32
+ import time
33
+ from abc import ABC
34
+ from datetime import datetime, timedelta, timezone
35
+ from typing import TYPE_CHECKING, Callable, Dict, Optional, Union
36
+
37
+ import jwt
38
+ from requests import utils
39
+
40
+ from github import Consts
41
+ from github.InstallationAuthorization import InstallationAuthorization
42
+ from github.Requester import Requester, WithRequester
43
+
44
+ if TYPE_CHECKING:
45
+ from github.GithubIntegration import GithubIntegration
46
+
47
+ PrivateKeyGenerator = Callable[[], Union[str, bytes]]
48
+ DictSignFunction = Callable[[dict], Union[str, bytes]]
49
+
50
+ # For App authentication, time remaining before token expiration to request a new one
51
+ ACCESS_TOKEN_REFRESH_THRESHOLD_SECONDS = 20
52
+ TOKEN_REFRESH_THRESHOLD_TIMEDELTA = timedelta(seconds=ACCESS_TOKEN_REFRESH_THRESHOLD_SECONDS)
53
+
54
+
55
+ # add new implementations of github.Auth.Auth to docs/utilities.rst
56
+ class Auth(abc.ABC):
57
+ """
58
+ This class is the base class of all authentication methods for Requester.
59
+ """
60
+
61
+ @property
62
+ @abc.abstractmethod
63
+ def token_type(self) -> str:
64
+ """
65
+ The type of the auth token as used in the HTTP Authorization header, e.g. Bearer or Basic.
66
+
67
+ :return: token type
68
+
69
+ """
70
+
71
+ @property
72
+ @abc.abstractmethod
73
+ def token(self) -> str:
74
+ """
75
+ The auth token as used in the HTTP Authorization header.
76
+
77
+ :return: token
78
+
79
+ """
80
+
81
+ def authentication(self, headers: dict) -> None:
82
+ """
83
+ Add authorization to the headers.
84
+ """
85
+ headers["Authorization"] = f"{self.token_type} {self.token}"
86
+
87
+ def mask_authentication(self, headers: dict) -> None:
88
+ """
89
+ Mask header, e.g. for logging.
90
+ """
91
+ headers["Authorization"] = self._masked_token
92
+
93
+ @property
94
+ def _masked_token(self) -> str:
95
+ return "(unknown auth removed)"
96
+
97
+
98
+ class HTTPBasicAuth(Auth, abc.ABC):
99
+ @property
100
+ @abc.abstractmethod
101
+ def username(self) -> str:
102
+ """
103
+ The username.
104
+ """
105
+
106
+ @property
107
+ @abc.abstractmethod
108
+ def password(self) -> str:
109
+ """
110
+ The password.
111
+ """
112
+
113
+ @property
114
+ def token_type(self) -> str:
115
+ return "Basic"
116
+
117
+ @property
118
+ def token(self) -> str:
119
+ return base64.b64encode(f"{self.username}:{self.password}".encode()).decode("utf-8").replace("\n", "")
120
+
121
+ @property
122
+ def _masked_token(self) -> str:
123
+ return "Basic (login and password removed)"
124
+
125
+
126
+ class Login(HTTPBasicAuth):
127
+ """
128
+ This class is used to authenticate with login and password.
129
+ """
130
+
131
+ def __init__(self, login: str, password: str):
132
+ assert isinstance(login, str)
133
+ assert len(login) > 0
134
+ assert isinstance(password, str)
135
+ assert len(password) > 0
136
+
137
+ self._login = login
138
+ self._password = password
139
+
140
+ @property
141
+ def login(self) -> str:
142
+ return self._login
143
+
144
+ @property
145
+ def username(self) -> str:
146
+ return self.login
147
+
148
+ @property
149
+ def password(self) -> str:
150
+ return self._password
151
+
152
+
153
+ class Token(Auth):
154
+ """
155
+ This class is used to authenticate with a single constant token.
156
+ """
157
+
158
+ def __init__(self, token: str):
159
+ assert isinstance(token, str)
160
+ assert len(token) > 0
161
+ self._token = token
162
+
163
+ @property
164
+ def token_type(self) -> str:
165
+ return "token"
166
+
167
+ @property
168
+ def token(self) -> str:
169
+ return self._token
170
+
171
+ @property
172
+ def _masked_token(self) -> str:
173
+ return "token (oauth token removed)"
174
+
175
+
176
+ class JWT(Auth, ABC):
177
+ """
178
+ This class is the base class to authenticate with a JSON Web Token (JWT).
179
+
180
+ https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app
181
+
182
+ """
183
+
184
+ @property
185
+ def token_type(self) -> str:
186
+ return "Bearer"
187
+
188
+
189
+ class JwtSigner:
190
+ def __init__(self, private_key_or_func: Union[str, PrivateKeyGenerator], jwt_algorithm: str):
191
+ self._private_key_or_func = private_key_or_func
192
+ self._jwt_algorithm = jwt_algorithm
193
+
194
+ def jwt_sign(self, payload: dict) -> Union[str, bytes]:
195
+ if callable(self._private_key_or_func):
196
+ private_key = self._private_key_or_func()
197
+ else:
198
+ private_key = self._private_key_or_func
199
+ return jwt.encode(payload, key=private_key, algorithm=self._jwt_algorithm)
200
+
201
+
202
+ class AppAuth(JWT):
203
+ """
204
+ This class is used to authenticate as a GitHub App.
205
+
206
+ https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app
207
+
208
+ """
209
+
210
+ @staticmethod
211
+ def create_jwt_sign(private_key_or_func: Union[str, PrivateKeyGenerator], jwt_algorithm: str) -> DictSignFunction:
212
+ return JwtSigner(private_key_or_func, jwt_algorithm).jwt_sign
213
+
214
+ # v3: move * above private_key
215
+ def __init__(
216
+ self,
217
+ app_id: Union[int, str],
218
+ private_key: Optional[Union[str, PrivateKeyGenerator]] = None,
219
+ *,
220
+ sign_func: Optional[DictSignFunction] = None,
221
+ jwt_expiry: int = Consts.DEFAULT_JWT_EXPIRY,
222
+ jwt_issued_at: int = Consts.DEFAULT_JWT_ISSUED_AT,
223
+ ):
224
+ assert isinstance(app_id, (int, str)), app_id
225
+ if isinstance(app_id, str):
226
+ assert len(app_id) > 0, "app_id must not be empty"
227
+ assert private_key is not None or sign_func is not None, "either private_key or sign_func must be given"
228
+ assert private_key is None or sign_func is None, "private_key or sign_func cannot both be given"
229
+ if private_key is not None:
230
+ assert isinstance(private_key, str) or callable(private_key)
231
+ if isinstance(private_key, str):
232
+ assert len(private_key) > 0, "private_key must not be empty"
233
+ sign_func = AppAuth.create_jwt_sign(private_key, Consts.DEFAULT_JWT_ALGORITHM)
234
+ assert isinstance(jwt_expiry, int), jwt_expiry
235
+ assert Consts.MIN_JWT_EXPIRY <= jwt_expiry <= Consts.MAX_JWT_EXPIRY, jwt_expiry
236
+
237
+ self._app_id = app_id
238
+ self._sign_func = sign_func
239
+ self._jwt_expiry = jwt_expiry
240
+ self._jwt_issued_at = jwt_issued_at
241
+
242
+ @property
243
+ def app_id(self) -> Union[int, str]:
244
+ return self._app_id
245
+
246
+ @property
247
+ def token(self) -> str:
248
+ return self.create_jwt()
249
+
250
+ def get_installation_auth(
251
+ self,
252
+ installation_id: int,
253
+ token_permissions: Optional[Dict[str, str]] = None,
254
+ requester: Optional[Requester] = None,
255
+ ) -> "AppInstallationAuth":
256
+ """
257
+ Creates a github.Auth.AppInstallationAuth instance for an installation.
258
+
259
+ :param installation_id: installation id
260
+ :param token_permissions: optional permissions
261
+ :param requester: optional requester with app authentication
262
+ :return:
263
+
264
+ """
265
+ return AppInstallationAuth(self, installation_id, token_permissions, requester)
266
+
267
+ def create_jwt(self, expiration: Optional[int] = None) -> str:
268
+ """
269
+ Create a signed JWT
270
+ https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app
271
+
272
+ :return string: jwt
273
+ """
274
+ if expiration is not None:
275
+ assert isinstance(expiration, int), expiration
276
+ assert Consts.MIN_JWT_EXPIRY <= expiration <= Consts.MAX_JWT_EXPIRY, expiration
277
+
278
+ now = int(time.time())
279
+ payload = {
280
+ "iat": now + self._jwt_issued_at,
281
+ "exp": now + (expiration if expiration is not None else self._jwt_expiry),
282
+ "iss": self._app_id,
283
+ }
284
+ assert self._sign_func is not None
285
+ encrypted = self._sign_func(payload)
286
+
287
+ if isinstance(encrypted, bytes):
288
+ return encrypted.decode("utf-8")
289
+ return encrypted
290
+
291
+
292
+ class AppAuthToken(JWT):
293
+ """
294
+ This class is used to authenticate as a GitHub App with a single constant JWT.
295
+
296
+ https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app
297
+
298
+ """
299
+
300
+ def __init__(self, token: str):
301
+ assert isinstance(token, str)
302
+ assert len(token) > 0
303
+ self._token = token
304
+
305
+ @property
306
+ def token(self) -> str:
307
+ return self._token
308
+
309
+
310
+ class AppInstallationAuth(Auth, WithRequester["AppInstallationAuth"]):
311
+ """
312
+ This class is used to authenticate as a GitHub App Installation.
313
+
314
+ https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation
315
+
316
+ """
317
+
318
+ # used to fetch live access token when calling self.token
319
+ __integration: Optional["GithubIntegration"] = None
320
+ __installation_authorization: Optional[InstallationAuthorization] = None
321
+
322
+ def __init__(
323
+ self,
324
+ app_auth: AppAuth,
325
+ installation_id: int,
326
+ token_permissions: Optional[Dict[str, str]] = None,
327
+ requester: Optional[Requester] = None,
328
+ ):
329
+ super().__init__()
330
+
331
+ assert isinstance(app_auth, AppAuth), app_auth
332
+ assert isinstance(installation_id, int), installation_id
333
+ assert token_permissions is None or isinstance(token_permissions, dict), token_permissions
334
+ assert requester is None or isinstance(requester, Requester), requester
335
+
336
+ self._app_auth = app_auth
337
+ self._installation_id = installation_id
338
+ self._token_permissions = token_permissions
339
+
340
+ if requester is not None:
341
+ self.withRequester(requester)
342
+
343
+ def withRequester(self, requester: Requester) -> "AppInstallationAuth":
344
+ assert isinstance(requester, Requester), requester
345
+ super().withRequester(requester.withAuth(self._app_auth))
346
+
347
+ # imported here to avoid circular import
348
+ from github.GithubIntegration import GithubIntegration
349
+
350
+ self.__integration = GithubIntegration(**self.requester.kwargs)
351
+
352
+ return self
353
+
354
+ @property
355
+ def app_id(self) -> Union[int, str]:
356
+ return self._app_auth.app_id
357
+
358
+ @property
359
+ def installation_id(self) -> int:
360
+ return self._installation_id
361
+
362
+ @property
363
+ def token_permissions(self) -> Optional[Dict[str, str]]:
364
+ return self._token_permissions
365
+
366
+ @property
367
+ def token_type(self) -> str:
368
+ return "token"
369
+
370
+ @property
371
+ def token(self) -> str:
372
+ if self.__installation_authorization is None or self._is_expired:
373
+ self.__installation_authorization = self._get_installation_authorization()
374
+ return self.__installation_authorization.token
375
+
376
+ @property
377
+ def _is_expired(self) -> bool:
378
+ assert self.__installation_authorization is not None
379
+ token_expires_at = self.__installation_authorization.expires_at - TOKEN_REFRESH_THRESHOLD_TIMEDELTA
380
+ return token_expires_at < datetime.now(timezone.utc)
381
+
382
+ def _get_installation_authorization(self) -> InstallationAuthorization:
383
+ assert self.__integration is not None, "Method withRequester(Requester) must be called first"
384
+ return self.__integration.get_access_token(
385
+ self._installation_id,
386
+ permissions=self._token_permissions,
387
+ )
388
+
389
+ @property
390
+ def _masked_token(self) -> str:
391
+ return "token (oauth token removed)"
392
+
393
+
394
+ class AppUserAuth(Auth, WithRequester["AppUserAuth"]):
395
+ """
396
+ This class is used to authenticate as a GitHub App on behalf of a user.
397
+
398
+ https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-with-a-github-app-on-behalf-of-a-user
399
+
400
+ """
401
+
402
+ _client_id: str
403
+ _client_secret: str
404
+ _token: str
405
+ _type: str
406
+ _scope: Optional[str]
407
+ _expires_at: Optional[datetime]
408
+ _refresh_token: Optional[str]
409
+ _refresh_expires_at: Optional[datetime]
410
+
411
+ # imported here to avoid circular import
412
+ from github.ApplicationOAuth import ApplicationOAuth
413
+
414
+ __app: ApplicationOAuth
415
+
416
+ def __init__(
417
+ self,
418
+ client_id: str,
419
+ client_secret: str,
420
+ token: str,
421
+ token_type: Optional[str] = None,
422
+ expires_at: Optional[datetime] = None,
423
+ refresh_token: Optional[str] = None,
424
+ refresh_expires_at: Optional[datetime] = None,
425
+ requester: Optional[Requester] = None,
426
+ ) -> None:
427
+ super().__init__()
428
+
429
+ assert isinstance(client_id, str) and len(client_id) > 0
430
+ assert isinstance(client_secret, str) and len(client_secret) > 0
431
+ assert isinstance(token, str) and len(token) > 0
432
+ assert token_type is None or isinstance(token_type, str) and len(token_type) > 0, token_type
433
+ assert expires_at is None or isinstance(expires_at, datetime), expires_at
434
+ assert refresh_token is None or isinstance(refresh_token, str) and len(refresh_token) > 0
435
+ assert refresh_expires_at is None or isinstance(refresh_expires_at, datetime), refresh_expires_at
436
+ assert requester is None or isinstance(requester, Requester), requester
437
+
438
+ self._client_id = client_id
439
+ self._client_secret = client_secret
440
+ self._token = token
441
+ self._type = token_type or "bearer"
442
+ self._expires_at = expires_at
443
+ self._refresh_token = refresh_token
444
+ self._refresh_expires_at = refresh_expires_at
445
+
446
+ if requester is not None:
447
+ self.withRequester(requester)
448
+
449
+ @property
450
+ def token_type(self) -> str:
451
+ return self._type
452
+
453
+ @property
454
+ def token(self) -> str:
455
+ if self._is_expired:
456
+ self._refresh()
457
+ return self._token
458
+
459
+ def withRequester(self, requester: Requester) -> "AppUserAuth":
460
+ assert isinstance(requester, Requester), requester
461
+ super().withRequester(requester.withAuth(None))
462
+
463
+ # imported here to avoid circular import
464
+ from github.ApplicationOAuth import ApplicationOAuth
465
+
466
+ self.__app = ApplicationOAuth(
467
+ # take requester given to super().withRequester, not given to this method
468
+ super().requester,
469
+ headers={},
470
+ attributes={
471
+ "client_id": self._client_id,
472
+ "client_secret": self._client_secret,
473
+ },
474
+ )
475
+
476
+ return self
477
+
478
+ @property
479
+ def _is_expired(self) -> bool:
480
+ return self._expires_at is not None and self._expires_at < datetime.now(timezone.utc)
481
+
482
+ def _refresh(self) -> None:
483
+ if self._refresh_token is None:
484
+ raise RuntimeError("Cannot refresh expired token because no refresh token has been provided")
485
+ if self._refresh_expires_at is not None and self._refresh_expires_at < datetime.now(timezone.utc):
486
+ raise RuntimeError("Cannot refresh expired token because refresh token also expired")
487
+
488
+ # refresh token
489
+ token = self.__app.refresh_access_token(self._refresh_token)
490
+
491
+ # update this auth
492
+ self._token = token.token
493
+ self._type = token.type
494
+ self._scope = token.scope
495
+ self._expires_at = token.expires_at
496
+ self._refresh_token = token.refresh_token
497
+ self._refresh_expires_at = token.refresh_expires_at
498
+
499
+ @property
500
+ def expires_at(self) -> Optional[datetime]:
501
+ return self._expires_at
502
+
503
+ @property
504
+ def refresh_token(self) -> Optional[str]:
505
+ return self._refresh_token
506
+
507
+ @property
508
+ def refresh_expires_at(self) -> Optional[datetime]:
509
+ return self._refresh_expires_at
510
+
511
+ @property
512
+ def _masked_token(self) -> str:
513
+ return "Bearer (jwt removed)"
514
+
515
+
516
+ class NetrcAuth(HTTPBasicAuth, WithRequester["NetrcAuth"]):
517
+ """
518
+ This class is used to authenticate via .netrc.
519
+ """
520
+
521
+ def __init__(self) -> None:
522
+ super().__init__()
523
+
524
+ self._login: Optional[str] = None
525
+ self._password: Optional[str] = None
526
+
527
+ @property
528
+ def username(self) -> str:
529
+ return self.login
530
+
531
+ @property
532
+ def login(self) -> str:
533
+ assert self._login is not None, "Method withRequester(Requester) must be called first"
534
+ return self._login
535
+
536
+ @property
537
+ def password(self) -> str:
538
+ assert self._password is not None, "Method withRequester(Requester) must be called first"
539
+ return self._password
540
+
541
+ def withRequester(self, requester: Requester) -> "NetrcAuth":
542
+ assert isinstance(requester, Requester), requester
543
+ super().withRequester(requester)
544
+
545
+ auth = utils.get_netrc_auth(requester.base_url, raise_errors=True)
546
+ if auth is None:
547
+ raise RuntimeError(f"Could not get credentials from netrc for host {requester.hostname}")
548
+
549
+ self._login, self._password = auth
550
+
551
+ return self
venv/lib/python3.10/site-packages/github/AuthenticatedUser.py ADDED
@@ -0,0 +1,1167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Steve English <steve.english@navetas.com> #
4
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
5
+ # Copyright 2012 Zearin <zearin@gonk.net> #
6
+ # Copyright 2013 AKFish <akfish@gmail.com> #
7
+ # Copyright 2013 Cameron White <cawhite@pdx.edu> #
8
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
9
+ # Copyright 2013 poulp <mathieu.nerv@gmail.com> #
10
+ # Copyright 2014 Tomas Radej <tradej@redhat.com> #
11
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
12
+ # Copyright 2016 E. Dunham <github@edunham.net> #
13
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
14
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
15
+ # Copyright 2017 Balázs Rostás <rostas.balazs@gmail.com> #
16
+ # Copyright 2017 Jannis Gebauer <ja.geb@me.com> #
17
+ # Copyright 2017 Simon <spam@esemi.ru> #
18
+ # Copyright 2018 Alice GIRARD <bouhahah@gmail.com> #
19
+ # Copyright 2018 Bruce Richardson <itsbruce@workshy.org> #
20
+ # Copyright 2018 Riccardo Pittau <elfosardo@users.noreply.github.com> #
21
+ # Copyright 2018 Shubham Singh <41840111+singh811@users.noreply.github.com> #
22
+ # Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
23
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
24
+ # Copyright 2018 bryanhuntesl <31992054+bryanhuntesl@users.noreply.github.com> #
25
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
26
+ # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
27
+ # Copyright 2019 Jamie van Brunschot <j.brunschot@coolblue.nl> #
28
+ # Copyright 2019 Jon Dufresne <jon.dufresne@gmail.com> #
29
+ # Copyright 2019 Pavan Kunisetty <nagapavan@users.noreply.github.com> #
30
+ # Copyright 2019 Rigas Papathanasopoulos <rigaspapas@gmail.com> #
31
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
32
+ # Copyright 2019 Surya Teja <94suryateja@gmail.com> #
33
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
34
+ # Copyright 2020 Anuj Bansal <bansalanuj1996@gmail.com> #
35
+ # Copyright 2020 Glenn McDonald <testworksau@users.noreply.github.com> #
36
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
37
+ # Copyright 2021 MeggyCal <MeggyCal@users.noreply.github.com> #
38
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
39
+ # Copyright 2021 Yuya Nakamura <yuyan7sh@gmail.com> #
40
+ # Copyright 2021 sshekdar-VMware <87147229+sshekdar-VMware@users.noreply.github.com>#
41
+ # Copyright 2021 秋葉 <ambiguous404@gmail.com> #
42
+ # Copyright 2022 KimSia Sim <245021+simkimsia@users.noreply.github.com> #
43
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
44
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
45
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
46
+ # Copyright 2023 Kevin Grandjean <Muscaw@users.noreply.github.com> #
47
+ # Copyright 2023 Mark Amery <markamery@btinternet.com> #
48
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
49
+ # Copyright 2023 chantra <chantra@users.noreply.github.com> #
50
+ # Copyright 2024 Chris Wells <ping@cwlls.com> #
51
+ # Copyright 2024 Eduardo Ramírez <edu.rh90@gmail.com> #
52
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
53
+ # Copyright 2024 Oskar Jansson <56458534+janssonoskar@users.noreply.github.com>#
54
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
55
+ # #
56
+ # This file is part of PyGithub. #
57
+ # http://pygithub.readthedocs.io/ #
58
+ # #
59
+ # PyGithub is free software: you can redistribute it and/or modify it under #
60
+ # the terms of the GNU Lesser General Public License as published by the Free #
61
+ # Software Foundation, either version 3 of the License, or (at your option) #
62
+ # any later version. #
63
+ # #
64
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
65
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
66
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
67
+ # details. #
68
+ # #
69
+ # You should have received a copy of the GNU Lesser General Public License #
70
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
71
+ # #
72
+ ################################################################################
73
+
74
+ from __future__ import annotations
75
+
76
+ import urllib.parse
77
+ from datetime import datetime, timezone
78
+ from typing import TYPE_CHECKING, Any, NamedTuple
79
+
80
+ import github.Authorization
81
+ import github.Event
82
+ import github.Gist
83
+ import github.GithubObject
84
+ import github.Invitation
85
+ import github.Issue
86
+ import github.Membership
87
+ import github.Migration
88
+ import github.NamedUser
89
+ import github.Notification
90
+ import github.Organization
91
+ import github.Plan
92
+ import github.Repository
93
+ import github.UserKey
94
+ from github import Consts
95
+ from github.GithubObject import (
96
+ Attribute,
97
+ CompletableGithubObject,
98
+ NotSet,
99
+ Opt,
100
+ is_defined,
101
+ is_optional,
102
+ is_optional_list,
103
+ is_undefined,
104
+ )
105
+ from github.PaginatedList import PaginatedList
106
+
107
+ if TYPE_CHECKING:
108
+ from github.Authorization import Authorization
109
+ from github.Event import Event
110
+ from github.Gist import Gist
111
+ from github.InputFileContent import InputFileContent
112
+ from github.Installation import Installation
113
+ from github.Invitation import Invitation
114
+ from github.Issue import Issue
115
+ from github.Label import Label
116
+ from github.Membership import Membership
117
+ from github.Migration import Migration
118
+ from github.NamedUser import NamedUser
119
+ from github.Notification import Notification
120
+ from github.Organization import Organization
121
+ from github.Plan import Plan
122
+ from github.Project import Project
123
+ from github.Repository import Repository
124
+ from github.Team import Team
125
+ from github.UserKey import UserKey
126
+
127
+
128
+ class EmailData(NamedTuple):
129
+ email: str
130
+ primary: bool
131
+ verified: bool
132
+ visibility: str
133
+
134
+
135
+ class AuthenticatedUser(CompletableGithubObject):
136
+ """
137
+ This class represents AuthenticatedUsers as returned by https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
138
+
139
+ An AuthenticatedUser object can be created by calling ``get_user()`` on a Github object.
140
+ """
141
+
142
+ def _initAttributes(self) -> None:
143
+ self._avatar_url: Attribute[str] = NotSet
144
+ self._bio: Attribute[str] = NotSet
145
+ self._blog: Attribute[str] = NotSet
146
+ self._collaborators: Attribute[int] = NotSet
147
+ self._company: Attribute[str] = NotSet
148
+ self._created_at: Attribute[datetime] = NotSet
149
+ self._disk_usage: Attribute[int] = NotSet
150
+ self._email: Attribute[str] = NotSet
151
+ self._events_url: Attribute[str] = NotSet
152
+ self._followers: Attribute[int] = NotSet
153
+ self._followers_url: Attribute[str] = NotSet
154
+ self._following: Attribute[int] = NotSet
155
+ self._following_url: Attribute[str] = NotSet
156
+ self._gists_url: Attribute[str] = NotSet
157
+ self._gravatar_id: Attribute[str] = NotSet
158
+ self._hireable: Attribute[bool] = NotSet
159
+ self._html_url: Attribute[str] = NotSet
160
+ self._id: Attribute[int] = NotSet
161
+ self._location: Attribute[str] = NotSet
162
+ self._login: Attribute[str] = NotSet
163
+ self._name: Attribute[str] = NotSet
164
+ self._node_id: Attribute[str] = NotSet
165
+ self._organizations_url: Attribute[str] = NotSet
166
+ self._owned_private_repos: Attribute[int] = NotSet
167
+ self._plan: Attribute[github.Plan.Plan] = NotSet
168
+ self._private_gists: Attribute[int] = NotSet
169
+ self._public_gists: Attribute[int] = NotSet
170
+ self._public_repos: Attribute[int] = NotSet
171
+ self._received_events_url: Attribute[str] = NotSet
172
+ self._repos_url: Attribute[str] = NotSet
173
+ self._site_admin: Attribute[bool] = NotSet
174
+ self._starred_url: Attribute[str] = NotSet
175
+ self._subscriptions_url: Attribute[str] = NotSet
176
+ self._total_private_repos: Attribute[int] = NotSet
177
+ self._two_factor_authentication: Attribute[bool] = NotSet
178
+ self._type: Attribute[str] = NotSet
179
+ self._updated_at: Attribute[datetime] = NotSet
180
+ self._url: Attribute[str] = NotSet
181
+
182
+ def __repr__(self) -> str:
183
+ return self.get__repr__({"login": self._login.value})
184
+
185
+ @property
186
+ def avatar_url(self) -> str:
187
+ self._completeIfNotSet(self._avatar_url)
188
+ return self._avatar_url.value
189
+
190
+ @property
191
+ def bio(self) -> str:
192
+ self._completeIfNotSet(self._bio)
193
+ return self._bio.value
194
+
195
+ @property
196
+ def blog(self) -> str:
197
+ self._completeIfNotSet(self._blog)
198
+ return self._blog.value
199
+
200
+ @property
201
+ def collaborators(self) -> int:
202
+ self._completeIfNotSet(self._collaborators)
203
+ return self._collaborators.value
204
+
205
+ @property
206
+ def company(self) -> str:
207
+ self._completeIfNotSet(self._company)
208
+ return self._company.value
209
+
210
+ @property
211
+ def created_at(self) -> datetime:
212
+ self._completeIfNotSet(self._created_at)
213
+ return self._created_at.value
214
+
215
+ @property
216
+ def disk_usage(self) -> int:
217
+ self._completeIfNotSet(self._disk_usage)
218
+ return self._disk_usage.value
219
+
220
+ @property
221
+ def email(self) -> str:
222
+ self._completeIfNotSet(self._email)
223
+ return self._email.value
224
+
225
+ @property
226
+ def events_url(self) -> str:
227
+ self._completeIfNotSet(self._events_url)
228
+ return self._events_url.value
229
+
230
+ @property
231
+ def followers(self) -> int:
232
+ self._completeIfNotSet(self._followers)
233
+ return self._followers.value
234
+
235
+ @property
236
+ def followers_url(self) -> str:
237
+ self._completeIfNotSet(self._followers_url)
238
+ return self._followers_url.value
239
+
240
+ @property
241
+ def following(self) -> int:
242
+ self._completeIfNotSet(self._following)
243
+ return self._following.value
244
+
245
+ @property
246
+ def following_url(self) -> str:
247
+ self._completeIfNotSet(self._following_url)
248
+ return self._following_url.value
249
+
250
+ @property
251
+ def gists_url(self) -> str:
252
+ self._completeIfNotSet(self._gists_url)
253
+ return self._gists_url.value
254
+
255
+ @property
256
+ def gravatar_id(self) -> str:
257
+ self._completeIfNotSet(self._gravatar_id)
258
+ return self._gravatar_id.value
259
+
260
+ @property
261
+ def hireable(self) -> bool:
262
+ self._completeIfNotSet(self._hireable)
263
+ return self._hireable.value
264
+
265
+ @property
266
+ def html_url(self) -> str:
267
+ self._completeIfNotSet(self._html_url)
268
+ return self._html_url.value
269
+
270
+ @property
271
+ def id(self) -> int:
272
+ self._completeIfNotSet(self._id)
273
+ return self._id.value
274
+
275
+ @property
276
+ def location(self) -> str:
277
+ self._completeIfNotSet(self._location)
278
+ return self._location.value
279
+
280
+ @property
281
+ def login(self) -> str:
282
+ self._completeIfNotSet(self._login)
283
+ return self._login.value
284
+
285
+ @property
286
+ def name(self) -> str:
287
+ self._completeIfNotSet(self._name)
288
+ return self._name.value
289
+
290
+ @property
291
+ def node_id(self) -> str:
292
+ self._completeIfNotSet(self._node_id)
293
+ return self._node_id.value
294
+
295
+ @property
296
+ def organizations_url(self) -> str:
297
+ self._completeIfNotSet(self._organizations_url)
298
+ return self._organizations_url.value
299
+
300
+ @property
301
+ def owned_private_repos(self) -> int:
302
+ self._completeIfNotSet(self._owned_private_repos)
303
+ return self._owned_private_repos.value
304
+
305
+ @property
306
+ def plan(self) -> Plan:
307
+ self._completeIfNotSet(self._plan)
308
+ return self._plan.value
309
+
310
+ @property
311
+ def private_gists(self) -> int:
312
+ self._completeIfNotSet(self._private_gists)
313
+ return self._private_gists.value
314
+
315
+ @property
316
+ def public_gists(self) -> int:
317
+ self._completeIfNotSet(self._public_gists)
318
+ return self._public_gists.value
319
+
320
+ @property
321
+ def public_repos(self) -> int:
322
+ self._completeIfNotSet(self._public_repos)
323
+ return self._public_repos.value
324
+
325
+ @property
326
+ def received_events_url(self) -> str:
327
+ self._completeIfNotSet(self._received_events_url)
328
+ return self._received_events_url.value
329
+
330
+ @property
331
+ def repos_url(self) -> str:
332
+ self._completeIfNotSet(self._repos_url)
333
+ return self._repos_url.value
334
+
335
+ @property
336
+ def site_admin(self) -> bool:
337
+ self._completeIfNotSet(self._site_admin)
338
+ return self._site_admin.value
339
+
340
+ @property
341
+ def starred_url(self) -> str:
342
+ self._completeIfNotSet(self._starred_url)
343
+ return self._starred_url.value
344
+
345
+ @property
346
+ def subscriptions_url(self) -> str:
347
+ self._completeIfNotSet(self._subscriptions_url)
348
+ return self._subscriptions_url.value
349
+
350
+ @property
351
+ def total_private_repos(self) -> int:
352
+ self._completeIfNotSet(self._total_private_repos)
353
+ return self._total_private_repos.value
354
+
355
+ @property
356
+ def two_factor_authentication(self) -> bool:
357
+ self._completeIfNotSet(self._two_factor_authentication)
358
+ return self._two_factor_authentication.value
359
+
360
+ @property
361
+ def type(self) -> str:
362
+ self._completeIfNotSet(self._type)
363
+ return self._type.value
364
+
365
+ @property
366
+ def updated_at(self) -> datetime:
367
+ self._completeIfNotSet(self._updated_at)
368
+ return self._updated_at.value
369
+
370
+ @property
371
+ def url(self) -> str:
372
+ self._completeIfNotSet(self._url)
373
+ return self._url.value
374
+
375
+ def add_to_emails(self, *emails: str) -> None:
376
+ """
377
+ :calls: `POST /user/emails <http://docs.github.com/en/rest/reference/users#emails>`_
378
+ """
379
+ assert all(isinstance(element, str) for element in emails), emails
380
+ post_parameters = {"emails": emails}
381
+ headers, data = self._requester.requestJsonAndCheck("POST", "/user/emails", input=post_parameters)
382
+
383
+ def add_to_following(self, following: NamedUser) -> None:
384
+ """
385
+ :calls: `PUT /user/following/{user} <http://docs.github.com/en/rest/reference/users#followers>`_
386
+ """
387
+ assert isinstance(following, github.NamedUser.NamedUser), following
388
+ headers, data = self._requester.requestJsonAndCheck("PUT", f"/user/following/{following._identity}")
389
+
390
+ def add_to_starred(self, starred: Repository) -> None:
391
+ """
392
+ :calls: `PUT /user/starred/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#starring>`_
393
+ """
394
+ assert isinstance(starred, github.Repository.Repository), starred
395
+ headers, data = self._requester.requestJsonAndCheck("PUT", f"/user/starred/{starred._identity}")
396
+
397
+ def add_to_subscriptions(self, subscription: Repository) -> None:
398
+ """
399
+ :calls: `PUT /user/subscriptions/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#watching>`_
400
+ """
401
+ assert isinstance(subscription, github.Repository.Repository), subscription
402
+ headers, data = self._requester.requestJsonAndCheck("PUT", f"/user/subscriptions/{subscription._identity}")
403
+
404
+ def add_to_watched(self, watched: Repository) -> None:
405
+ """
406
+ :calls: `PUT /repos/{owner}/{repo}/subscription <http://docs.github.com/en/rest/reference/activity#watching>`_
407
+ """
408
+ assert isinstance(watched, github.Repository.Repository), watched
409
+ headers, data = self._requester.requestJsonAndCheck(
410
+ "PUT",
411
+ f"/repos/{watched._identity}/subscription",
412
+ input={"subscribed": True},
413
+ )
414
+
415
+ def create_authorization(
416
+ self,
417
+ scopes: Opt[list[str]] = NotSet,
418
+ note: Opt[str] = NotSet,
419
+ note_url: Opt[str] = NotSet,
420
+ client_id: Opt[str] = NotSet,
421
+ client_secret: Opt[str] = NotSet,
422
+ onetime_password: str | None = None,
423
+ ) -> Authorization:
424
+ """
425
+ :calls: `POST /authorizations <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
426
+ """
427
+ assert is_optional_list(scopes, str), scopes
428
+ assert is_optional(note, str), note
429
+ assert is_optional(note_url, str), note_url
430
+ assert is_optional(client_id, str), client_id
431
+ assert is_optional(client_secret, str), client_secret
432
+ assert onetime_password is None or isinstance(onetime_password, str), onetime_password
433
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items(
434
+ {
435
+ "scopes": scopes,
436
+ "note": note,
437
+ "note_url": note_url,
438
+ "client_id": client_id,
439
+ "client_secret": client_secret,
440
+ }
441
+ )
442
+
443
+ if onetime_password is not None:
444
+ request_header = {Consts.headerOTP: onetime_password} # pragma no cover (Should be covered)
445
+ else:
446
+ request_header = None
447
+ headers, data = self._requester.requestJsonAndCheck(
448
+ "POST",
449
+ "/authorizations",
450
+ input=post_parameters,
451
+ headers=request_header,
452
+ )
453
+ return github.Authorization.Authorization(self._requester, headers, data, completed=True)
454
+
455
+ @staticmethod
456
+ def create_fork(
457
+ repo: Repository,
458
+ name: Opt[str] = NotSet,
459
+ default_branch_only: Opt[bool] = NotSet,
460
+ ) -> Repository:
461
+ """
462
+ :calls: `POST /repos/{owner}/{repo}/forks <http://docs.github.com/en/rest/reference/repos#forks>`_
463
+ """
464
+ assert isinstance(repo, github.Repository.Repository), repo
465
+ return repo.create_fork(
466
+ organization=github.GithubObject.NotSet,
467
+ name=name,
468
+ default_branch_only=default_branch_only,
469
+ )
470
+
471
+ def create_repo_from_template(
472
+ self,
473
+ name: str,
474
+ repo: Repository,
475
+ description: Opt[str] = NotSet,
476
+ include_all_branches: Opt[bool] = NotSet,
477
+ private: Opt[bool] = NotSet,
478
+ ) -> Repository:
479
+ """
480
+ :calls: `POST /repos/{template_owner}/{template_repo}/generate <https://docs.github.com/en/rest/reference/repos#create-a-repository-using-a-template>`_
481
+ """
482
+ assert isinstance(name, str), name
483
+ assert isinstance(repo, github.Repository.Repository), repo
484
+ assert is_optional(description, str), description
485
+ assert is_optional(include_all_branches, bool), include_all_branches
486
+ assert is_optional(private, bool), private
487
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items(
488
+ {
489
+ "name": name,
490
+ "owner": self.login,
491
+ "description": description,
492
+ "include_all_branches": include_all_branches,
493
+ "private": private,
494
+ }
495
+ )
496
+
497
+ headers, data = self._requester.requestJsonAndCheck(
498
+ "POST",
499
+ f"/repos/{repo.owner.login}/{repo.name}/generate",
500
+ input=post_parameters,
501
+ headers={"Accept": "application/vnd.github.v3+json"},
502
+ )
503
+ return github.Repository.Repository(self._requester, headers, data, completed=True)
504
+
505
+ def create_gist(
506
+ self,
507
+ public: bool,
508
+ files: dict[str, InputFileContent],
509
+ description: Opt[str] = NotSet,
510
+ ) -> Gist:
511
+ """
512
+ :calls: `POST /gists <http://docs.github.com/en/rest/reference/gists>`_
513
+ """
514
+ assert isinstance(public, bool), public
515
+ assert all(isinstance(element, github.InputFileContent) for element in files.values()), files
516
+ assert is_undefined(description) or isinstance(description, str), description
517
+ post_parameters = {
518
+ "public": public,
519
+ "files": {key: value._identity for key, value in files.items()},
520
+ }
521
+ if is_defined(description):
522
+ post_parameters["description"] = description
523
+ headers, data = self._requester.requestJsonAndCheck("POST", "/gists", input=post_parameters)
524
+ return github.Gist.Gist(self._requester, headers, data, completed=True)
525
+
526
+ def create_key(self, title: str, key: str) -> UserKey:
527
+ """
528
+ :calls: `POST /user/keys <http://docs.github.com/en/rest/reference/users#git-ssh-keys>`_
529
+ :param title: string
530
+ :param key: string
531
+ :rtype: :class:`github.UserKey.UserKey`
532
+ """
533
+ assert isinstance(title, str), title
534
+ assert isinstance(key, str), key
535
+ post_parameters = {
536
+ "title": title,
537
+ "key": key,
538
+ }
539
+ headers, data = self._requester.requestJsonAndCheck("POST", "/user/keys", input=post_parameters)
540
+ return github.UserKey.UserKey(self._requester, headers, data, completed=True)
541
+
542
+ def create_project(self, name: str, body: Opt[str] = NotSet) -> Project:
543
+ """
544
+ :calls: `POST /user/projects <https://docs.github.com/en/rest/reference/projects#create-a-user-project>`_
545
+ :param name: string
546
+ :param body: string
547
+ :rtype: :class:`github.Project.Project`
548
+ """
549
+ assert isinstance(name, str), name
550
+ assert is_undefined(body) or isinstance(body, str), body
551
+ post_parameters = {
552
+ "name": name,
553
+ "body": body,
554
+ }
555
+ headers, data = self._requester.requestJsonAndCheck(
556
+ "POST",
557
+ "/user/projects",
558
+ input=post_parameters,
559
+ headers={"Accept": Consts.mediaTypeProjectsPreview},
560
+ )
561
+ return github.Project.Project(self._requester, headers, data, completed=True)
562
+
563
+ def create_repo(
564
+ self,
565
+ name: str,
566
+ description: Opt[str] = NotSet,
567
+ homepage: Opt[str] = NotSet,
568
+ private: Opt[bool] = NotSet,
569
+ has_issues: Opt[bool] = NotSet,
570
+ has_wiki: Opt[bool] = NotSet,
571
+ has_downloads: Opt[bool] = NotSet,
572
+ has_projects: Opt[bool] = NotSet,
573
+ has_discussions: Opt[bool] = NotSet,
574
+ auto_init: Opt[bool] = NotSet,
575
+ license_template: Opt[str] = NotSet,
576
+ gitignore_template: Opt[str] = NotSet,
577
+ allow_squash_merge: Opt[bool] = NotSet,
578
+ allow_merge_commit: Opt[bool] = NotSet,
579
+ allow_rebase_merge: Opt[bool] = NotSet,
580
+ delete_branch_on_merge: Opt[bool] = NotSet,
581
+ ) -> Repository:
582
+ """
583
+ :calls: `POST /user/repos <http://docs.github.com/en/rest/reference/repos>`_
584
+ """
585
+ assert isinstance(name, str), name
586
+ assert is_optional(description, str), description
587
+ assert is_optional(homepage, str), homepage
588
+ assert is_optional(private, bool), private
589
+ assert is_optional(has_issues, bool), has_issues
590
+ assert is_optional(has_wiki, bool), has_wiki
591
+ assert is_optional(has_downloads, bool), has_downloads
592
+ assert is_optional(has_projects, bool), has_projects
593
+ assert is_optional(has_discussions, bool), has_discussions
594
+ assert is_optional(auto_init, bool), auto_init
595
+ assert is_optional(license_template, str), license_template
596
+ assert is_optional(gitignore_template, str), gitignore_template
597
+ assert is_optional(allow_squash_merge, bool), allow_squash_merge
598
+ assert is_optional(allow_merge_commit, bool), allow_merge_commit
599
+ assert is_optional(allow_rebase_merge, bool), allow_rebase_merge
600
+ assert is_optional(delete_branch_on_merge, bool), delete_branch_on_merge
601
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items(
602
+ {
603
+ "name": name,
604
+ "description": description,
605
+ "homepage": homepage,
606
+ "private": private,
607
+ "has_issues": has_issues,
608
+ "has_wiki": has_wiki,
609
+ "has_downloads": has_downloads,
610
+ "has_projects": has_projects,
611
+ "has_discussions": has_discussions,
612
+ "auto_init": auto_init,
613
+ "license_template": license_template,
614
+ "gitignore_template": gitignore_template,
615
+ "allow_squash_merge": allow_squash_merge,
616
+ "allow_merge_commit": allow_merge_commit,
617
+ "allow_rebase_merge": allow_rebase_merge,
618
+ "delete_branch_on_merge": delete_branch_on_merge,
619
+ }
620
+ )
621
+
622
+ headers, data = self._requester.requestJsonAndCheck("POST", "/user/repos", input=post_parameters)
623
+ return github.Repository.Repository(self._requester, headers, data, completed=True)
624
+
625
+ def edit(
626
+ self,
627
+ name: Opt[str] = NotSet,
628
+ email: Opt[str] = NotSet,
629
+ blog: Opt[str] = NotSet,
630
+ company: Opt[str] = NotSet,
631
+ location: Opt[str] = NotSet,
632
+ hireable: Opt[bool] = NotSet,
633
+ bio: Opt[str] = NotSet,
634
+ ) -> None:
635
+ """
636
+ :calls: `PATCH /user <http://docs.github.com/en/rest/reference/users>`_
637
+ """
638
+ assert is_optional(name, str), name
639
+ assert is_optional(email, str), email
640
+ assert is_optional(blog, str), blog
641
+ assert is_optional(company, str), company
642
+ assert is_optional(location, str), location
643
+ assert is_optional(hireable, bool), hireable
644
+ assert is_optional(bio, str), bio
645
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items(
646
+ {
647
+ "name": name,
648
+ "email": email,
649
+ "blog": blog,
650
+ "company": company,
651
+ "location": location,
652
+ "hireable": hireable,
653
+ "bio": bio,
654
+ }
655
+ )
656
+
657
+ headers, data = self._requester.requestJsonAndCheck("PATCH", "/user", input=post_parameters)
658
+ self._useAttributes(data)
659
+
660
+ def get_authorization(self, id: int) -> Authorization:
661
+ """
662
+ :calls: `GET /authorizations/{id} <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
663
+ """
664
+ assert isinstance(id, int), id
665
+ headers, data = self._requester.requestJsonAndCheck("GET", f"/authorizations/{id}")
666
+ return github.Authorization.Authorization(self._requester, headers, data, completed=True)
667
+
668
+ def get_authorizations(self) -> PaginatedList[Authorization]:
669
+ """
670
+ :calls: `GET /authorizations <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
671
+ """
672
+ return PaginatedList(github.Authorization.Authorization, self._requester, "/authorizations", None)
673
+
674
+ def get_emails(self) -> list[EmailData]:
675
+ """
676
+ :calls: `GET /user/emails <http://docs.github.com/en/rest/reference/users#emails>`_
677
+ """
678
+ headers, data = self._requester.requestJsonAndCheck("GET", "/user/emails")
679
+ return [EmailData(**item) for item in data]
680
+
681
+ def get_events(self) -> PaginatedList[Event]:
682
+ """
683
+ :calls: `GET /events <http://docs.github.com/en/rest/reference/activity#events>`_
684
+ """
685
+ return PaginatedList(github.Event.Event, self._requester, "/events", None)
686
+
687
+ def get_followers(self) -> PaginatedList[NamedUser]:
688
+ """
689
+ :calls: `GET /user/followers <http://docs.github.com/en/rest/reference/users#followers>`_
690
+ """
691
+ return PaginatedList(github.NamedUser.NamedUser, self._requester, "/user/followers", None)
692
+
693
+ def get_following(self) -> PaginatedList[NamedUser]:
694
+ """
695
+ :calls: `GET /user/following <http://docs.github.com/en/rest/reference/users#followers>`_
696
+ """
697
+ return PaginatedList(github.NamedUser.NamedUser, self._requester, "/user/following", None)
698
+
699
+ def get_gists(self, since: Opt[datetime] = NotSet) -> PaginatedList[Gist]:
700
+ """
701
+ :calls: `GET /gists <http://docs.github.com/en/rest/reference/gists>`_
702
+ :param since: datetime format YYYY-MM-DDTHH:MM:SSZ
703
+ :rtype: :class:`PaginatedList` of :class:`github.Gist.Gist`
704
+ """
705
+ assert is_optional(since, datetime), since
706
+ url_parameters: dict[str, Any] = {}
707
+ if is_defined(since):
708
+ url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
709
+ return PaginatedList(github.Gist.Gist, self._requester, "/gists", url_parameters)
710
+
711
+ def get_issues(
712
+ self,
713
+ filter: Opt[str] = NotSet,
714
+ state: Opt[str] = NotSet,
715
+ labels: Opt[list[Label]] = NotSet,
716
+ sort: Opt[str] = NotSet,
717
+ direction: Opt[str] = NotSet,
718
+ since: Opt[datetime] = NotSet,
719
+ ) -> PaginatedList[Issue]:
720
+ """
721
+ :calls: `GET /issues <http://docs.github.com/en/rest/reference/issues>`_
722
+ """
723
+ assert is_optional(filter, str), filter
724
+ assert is_optional(state, str), state
725
+ assert is_optional_list(labels, github.Label.Label), labels
726
+ assert is_optional(sort, str), sort
727
+ assert is_optional(direction, str), direction
728
+ assert is_optional(since, datetime), since
729
+ url_parameters: dict[str, Any] = {}
730
+ if is_defined(filter):
731
+ url_parameters["filter"] = filter
732
+ if is_defined(state):
733
+ url_parameters["state"] = state
734
+ if is_defined(labels):
735
+ url_parameters["labels"] = ",".join(label.name for label in labels)
736
+ if is_defined(sort):
737
+ url_parameters["sort"] = sort
738
+ if is_defined(direction):
739
+ url_parameters["direction"] = direction
740
+ if is_defined(since):
741
+ url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
742
+ return PaginatedList(github.Issue.Issue, self._requester, "/issues", url_parameters)
743
+
744
+ def get_user_issues(
745
+ self,
746
+ filter: Opt[str] = NotSet,
747
+ state: Opt[str] = NotSet,
748
+ labels: Opt[list[Label]] = NotSet,
749
+ sort: Opt[str] = NotSet,
750
+ direction: Opt[str] = NotSet,
751
+ since: Opt[datetime] = NotSet,
752
+ ) -> PaginatedList[Issue]:
753
+ """
754
+ :calls: `GET /user/issues <http://docs.github.com/en/rest/reference/issues>`_
755
+ """
756
+ assert is_optional(filter, str), filter
757
+ assert is_optional(state, str), state
758
+ assert is_optional_list(labels, github.Label.Label), labels
759
+ assert is_optional(sort, str), sort
760
+ assert is_optional(direction, str), direction
761
+ assert is_optional(since, datetime), since
762
+ url_parameters: dict[str, Any] = {}
763
+ if is_defined(filter):
764
+ url_parameters["filter"] = filter
765
+ if is_defined(state):
766
+ url_parameters["state"] = state
767
+ if is_defined(labels):
768
+ url_parameters["labels"] = ",".join(label.name for label in labels)
769
+ if is_defined(sort):
770
+ url_parameters["sort"] = sort
771
+ if is_defined(direction):
772
+ url_parameters["direction"] = direction
773
+ if is_defined(since):
774
+ url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
775
+ return PaginatedList(github.Issue.Issue, self._requester, "/user/issues", url_parameters)
776
+
777
+ def get_key(self, id: int) -> UserKey:
778
+ """
779
+ :calls: `GET /user/keys/{id} <http://docs.github.com/en/rest/reference/users#git-ssh-keys>`_
780
+ """
781
+ assert isinstance(id, int), id
782
+ headers, data = self._requester.requestJsonAndCheck("GET", f"/user/keys/{id}")
783
+ return github.UserKey.UserKey(self._requester, headers, data, completed=True)
784
+
785
+ def get_keys(self) -> PaginatedList[UserKey]:
786
+ """
787
+ :calls: `GET /user/keys <http://docs.github.com/en/rest/reference/users#git-ssh-keys>`_
788
+ """
789
+ return PaginatedList(github.UserKey.UserKey, self._requester, "/user/keys", None)
790
+
791
+ def get_notification(self, id: str) -> Notification:
792
+ """
793
+ :calls: `GET /notifications/threads/{id} <http://docs.github.com/en/rest/reference/activity#notifications>`_
794
+ """
795
+
796
+ assert isinstance(id, str), id
797
+ headers, data = self._requester.requestJsonAndCheck("GET", f"/notifications/threads/{id}")
798
+ return github.Notification.Notification(self._requester, headers, data, completed=True)
799
+
800
+ def get_notifications(
801
+ self,
802
+ all: Opt[bool] = NotSet,
803
+ participating: Opt[bool] = NotSet,
804
+ since: Opt[datetime] = NotSet,
805
+ before: Opt[datetime] = NotSet,
806
+ ) -> PaginatedList[Notification]:
807
+ """
808
+ :calls: `GET /notifications <http://docs.github.com/en/rest/reference/activity#notifications>`_
809
+ """
810
+
811
+ assert is_optional(all, bool), all
812
+ assert is_optional(participating, bool), participating
813
+ assert is_optional(since, datetime), since
814
+ assert is_optional(before, datetime), before
815
+
816
+ params: dict[str, Any] = {}
817
+ if is_defined(all):
818
+ # convert True, False to true, false for api parameters
819
+ params["all"] = "true" if all else "false"
820
+ if is_defined(participating):
821
+ # convert True, False to true, false for api parameters
822
+ params["participating"] = "true" if participating else "false"
823
+ if is_defined(since):
824
+ params["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
825
+ if is_defined(before):
826
+ params["before"] = before.strftime("%Y-%m-%dT%H:%M:%SZ")
827
+
828
+ return PaginatedList(github.Notification.Notification, self._requester, "/notifications", params)
829
+
830
+ def get_organization_events(self, org: Organization) -> PaginatedList[Event]:
831
+ """
832
+ :calls: `GET /users/{user}/events/orgs/{org} <http://docs.github.com/en/rest/reference/activity#events>`_
833
+ """
834
+ assert isinstance(org, github.Organization.Organization), org
835
+ return PaginatedList(
836
+ github.Event.Event,
837
+ self._requester,
838
+ f"/users/{self.login}/events/orgs/{org.login}",
839
+ None,
840
+ )
841
+
842
+ def get_orgs(self) -> PaginatedList[Organization]:
843
+ """
844
+ :calls: `GET /user/orgs <http://docs.github.com/en/rest/reference/orgs>`_
845
+ """
846
+ return PaginatedList(github.Organization.Organization, self._requester, "/user/orgs", None)
847
+
848
+ def get_repo(self, name: str) -> Repository:
849
+ """
850
+ :calls: `GET /repos/{owner}/{repo} <http://docs.github.com/en/rest/reference/repos>`_
851
+ """
852
+ assert isinstance(name, str), name
853
+ name = urllib.parse.quote(name)
854
+ headers, data = self._requester.requestJsonAndCheck("GET", f"/repos/{self.login}/{name}")
855
+ return github.Repository.Repository(self._requester, headers, data, completed=True)
856
+
857
+ def get_repos(
858
+ self,
859
+ visibility: Opt[str] = NotSet,
860
+ affiliation: Opt[str] = NotSet,
861
+ type: Opt[str] = NotSet,
862
+ sort: Opt[str] = NotSet,
863
+ direction: Opt[str] = NotSet,
864
+ ) -> PaginatedList[Repository]:
865
+ """
866
+ :calls: `GET /user/repos <http://docs.github.com/en/rest/reference/repos>`_
867
+ """
868
+ assert is_optional(visibility, str), visibility
869
+ assert is_optional(affiliation, str), affiliation
870
+ assert is_optional(type, str), type
871
+ assert is_optional(sort, str), sort
872
+ assert is_optional(direction, str), direction
873
+ url_parameters = NotSet.remove_unset_items(
874
+ {
875
+ "visibility": visibility,
876
+ "affiliation": affiliation,
877
+ "type": type,
878
+ "sort": sort,
879
+ "direction": direction,
880
+ }
881
+ )
882
+ return PaginatedList(github.Repository.Repository, self._requester, "/user/repos", url_parameters)
883
+
884
+ def get_starred(self) -> PaginatedList[Repository]:
885
+ """
886
+ :calls: `GET /user/starred <http://docs.github.com/en/rest/reference/activity#starring>`_
887
+ """
888
+ return PaginatedList(github.Repository.Repository, self._requester, "/user/starred", None)
889
+
890
+ def get_starred_gists(self) -> PaginatedList[Gist]:
891
+ """
892
+ :calls: `GET /gists/starred <http://docs.github.com/en/rest/reference/gists>`_
893
+ """
894
+ return PaginatedList(github.Gist.Gist, self._requester, "/gists/starred", None)
895
+
896
+ def get_subscriptions(self) -> PaginatedList[Repository]:
897
+ """
898
+ :calls: `GET /user/subscriptions <http://docs.github.com/en/rest/reference/activity#watching>`_
899
+ """
900
+ return PaginatedList(github.Repository.Repository, self._requester, "/user/subscriptions", None)
901
+
902
+ def get_teams(self) -> PaginatedList[Team]:
903
+ """
904
+ :calls: `GET /user/teams <http://docs.github.com/en/rest/reference/teams>`_
905
+ """
906
+ return PaginatedList(github.Team.Team, self._requester, "/user/teams", None)
907
+
908
+ def get_watched(self) -> PaginatedList[Repository]:
909
+ """
910
+ :calls: `GET /user/subscriptions <http://docs.github.com/en/rest/reference/activity#watching>`_
911
+ """
912
+ return PaginatedList(github.Repository.Repository, self._requester, "/user/subscriptions", None)
913
+
914
+ def get_installations(self) -> PaginatedList[Installation]:
915
+ """
916
+ :calls: `GET /user/installations <http://docs.github.com/en/rest/reference/apps>`_
917
+ """
918
+ return PaginatedList(
919
+ github.Installation.Installation,
920
+ self._requester,
921
+ "/user/installations",
922
+ None,
923
+ headers={"Accept": Consts.mediaTypeIntegrationPreview},
924
+ list_item="installations",
925
+ )
926
+
927
+ def has_in_following(self, following: NamedUser) -> bool:
928
+ """
929
+ :calls: `GET /user/following/{user} <http://docs.github.com/en/rest/reference/users#followers>`_
930
+ """
931
+ assert isinstance(following, github.NamedUser.NamedUser), following
932
+ status, headers, data = self._requester.requestJson("GET", f"/user/following/{following._identity}")
933
+ return status == 204
934
+
935
+ def has_in_starred(self, starred: Repository) -> bool:
936
+ """
937
+ :calls: `GET /user/starred/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#starring>`_
938
+ """
939
+ assert isinstance(starred, github.Repository.Repository), starred
940
+ status, headers, data = self._requester.requestJson("GET", f"/user/starred/{starred._identity}")
941
+ return status == 204
942
+
943
+ def has_in_subscriptions(self, subscription: Repository) -> bool:
944
+ """
945
+ :calls: `GET /user/subscriptions/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#watching>`_
946
+ """
947
+ assert isinstance(subscription, github.Repository.Repository), subscription
948
+ status, headers, data = self._requester.requestJson("GET", f"/user/subscriptions/{subscription._identity}")
949
+ return status == 204
950
+
951
+ def has_in_watched(self, watched: Repository) -> bool:
952
+ """
953
+ :calls: `GET /repos/{owner}/{repo}/subscription <http://docs.github.com/en/rest/reference/activity#watching>`_
954
+ """
955
+ assert isinstance(watched, github.Repository.Repository), watched
956
+ status, headers, data = self._requester.requestJson("GET", f"/repos/{watched._identity}/subscription")
957
+ return status == 200
958
+
959
+ def mark_notifications_as_read(self, last_read_at: datetime | None = None) -> None:
960
+ """
961
+ :calls: `PUT /notifications <https://docs.github.com/en/rest/reference/activity#notifications>`_
962
+ """
963
+ if last_read_at is None:
964
+ last_read_at = datetime.now(timezone.utc)
965
+ assert isinstance(last_read_at, datetime)
966
+ put_parameters = {"last_read_at": last_read_at.strftime("%Y-%m-%dT%H:%M:%SZ")}
967
+
968
+ headers, data = self._requester.requestJsonAndCheck("PUT", "/notifications", input=put_parameters)
969
+
970
+ def remove_from_emails(self, *emails: str) -> None:
971
+ """
972
+ :calls: `DELETE /user/emails <http://docs.github.com/en/rest/reference/users#emails>`_
973
+ """
974
+ assert all(isinstance(element, str) for element in emails), emails
975
+ post_parameters = {"emails": emails}
976
+ headers, data = self._requester.requestJsonAndCheck("DELETE", "/user/emails", input=post_parameters)
977
+
978
+ def remove_from_following(self, following: NamedUser) -> None:
979
+ """
980
+ :calls: `DELETE /user/following/{user} <http://docs.github.com/en/rest/reference/users#followers>`_
981
+ """
982
+ assert isinstance(following, github.NamedUser.NamedUser), following
983
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"/user/following/{following._identity}")
984
+
985
+ def remove_from_starred(self, starred: Repository) -> None:
986
+ """
987
+ :calls: `DELETE /user/starred/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#starring>`_
988
+ """
989
+ assert isinstance(starred, github.Repository.Repository), starred
990
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"/user/starred/{starred._identity}")
991
+
992
+ def remove_from_subscriptions(self, subscription: Repository) -> None:
993
+ """
994
+ :calls: `DELETE /user/subscriptions/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#watching>`_
995
+ """
996
+ assert isinstance(subscription, github.Repository.Repository), subscription
997
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"/user/subscriptions/{subscription._identity}")
998
+
999
+ def remove_from_watched(self, watched: Repository) -> None:
1000
+ """
1001
+ :calls: `DELETE /repos/{owner}/{repo}/subscription <http://docs.github.com/en/rest/reference/activity#watching>`_
1002
+ """
1003
+ assert isinstance(watched, github.Repository.Repository), watched
1004
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"/repos/{watched._identity}/subscription")
1005
+
1006
+ def accept_invitation(self, invitation: Invitation | int) -> None:
1007
+ """
1008
+ :calls: `PATCH /user/repository_invitations/{invitation_id} <https://docs.github.com/en/rest/reference/repos/invitations#>`_
1009
+ """
1010
+ assert isinstance(invitation, github.Invitation.Invitation) or isinstance(invitation, int)
1011
+
1012
+ if isinstance(invitation, github.Invitation.Invitation):
1013
+ invitation = invitation.id
1014
+
1015
+ headers, data = self._requester.requestJsonAndCheck(
1016
+ "PATCH", f"/user/repository_invitations/{invitation}", input={}
1017
+ )
1018
+
1019
+ def get_invitations(self) -> PaginatedList[Invitation]:
1020
+ """
1021
+ :calls: `GET /user/repository_invitations <https://docs.github.com/en/rest/reference/repos#invitations>`_
1022
+ """
1023
+ return PaginatedList(
1024
+ github.Invitation.Invitation,
1025
+ self._requester,
1026
+ "/user/repository_invitations",
1027
+ None,
1028
+ )
1029
+
1030
+ def create_migration(
1031
+ self,
1032
+ repos: list[Repository] | tuple[Repository],
1033
+ lock_repositories: Opt[bool] = NotSet,
1034
+ exclude_attachments: Opt[bool] = NotSet,
1035
+ ) -> Migration:
1036
+ """
1037
+ :calls: `POST /user/migrations <https://docs.github.com/en/rest/reference/migrations>`_
1038
+ """
1039
+ assert isinstance(repos, (list, tuple)), repos
1040
+ assert all(isinstance(repo, str) for repo in repos), repos
1041
+ assert is_optional(lock_repositories, bool), lock_repositories
1042
+ assert is_optional(exclude_attachments, bool), exclude_attachments
1043
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items(
1044
+ {
1045
+ "repositories": repos,
1046
+ "lock_repositories": lock_repositories,
1047
+ "exclude_attachments": exclude_attachments,
1048
+ }
1049
+ )
1050
+
1051
+ headers, data = self._requester.requestJsonAndCheck(
1052
+ "POST",
1053
+ "/user/migrations",
1054
+ input=post_parameters,
1055
+ headers={"Accept": Consts.mediaTypeMigrationPreview},
1056
+ )
1057
+ return github.Migration.Migration(self._requester, headers, data, completed=True)
1058
+
1059
+ def get_migrations(self) -> PaginatedList[Migration]:
1060
+ """
1061
+ :calls: `GET /user/migrations <https://docs.github.com/en/rest/reference/migrations>`_
1062
+ """
1063
+ return PaginatedList(
1064
+ github.Migration.Migration,
1065
+ self._requester,
1066
+ "/user/migrations",
1067
+ None,
1068
+ headers={"Accept": Consts.mediaTypeMigrationPreview},
1069
+ )
1070
+
1071
+ def get_organization_memberships(self) -> PaginatedList[Membership]:
1072
+ """
1073
+ :calls: `GET /user/memberships/orgs/ <https://docs.github.com/en/rest/orgs/members#list-organization-memberships-for-the-authenticated-user>`_
1074
+ """
1075
+ return PaginatedList(
1076
+ github.Membership.Membership,
1077
+ self._requester,
1078
+ "/user/memberships/orgs",
1079
+ None,
1080
+ )
1081
+
1082
+ def get_organization_membership(self, org: str) -> Membership:
1083
+ """
1084
+ :calls: `GET /user/memberships/orgs/{org} <https://docs.github.com/en/rest/reference/orgs#get-an-organization-membership-for-the-authenticated-user>`_
1085
+ """
1086
+ assert isinstance(org, str)
1087
+ org = urllib.parse.quote(org)
1088
+ headers, data = self._requester.requestJsonAndCheck("GET", f"/user/memberships/orgs/{org}")
1089
+ return github.Membership.Membership(self._requester, headers, data, completed=True)
1090
+
1091
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
1092
+ if "avatar_url" in attributes: # pragma no branch
1093
+ self._avatar_url = self._makeStringAttribute(attributes["avatar_url"])
1094
+ if "bio" in attributes: # pragma no branch
1095
+ self._bio = self._makeStringAttribute(attributes["bio"])
1096
+ if "blog" in attributes: # pragma no branch
1097
+ self._blog = self._makeStringAttribute(attributes["blog"])
1098
+ if "collaborators" in attributes: # pragma no branch
1099
+ self._collaborators = self._makeIntAttribute(attributes["collaborators"])
1100
+ if "company" in attributes: # pragma no branch
1101
+ self._company = self._makeStringAttribute(attributes["company"])
1102
+ if "created_at" in attributes: # pragma no branch
1103
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
1104
+ if "disk_usage" in attributes: # pragma no branch
1105
+ self._disk_usage = self._makeIntAttribute(attributes["disk_usage"])
1106
+ if "email" in attributes: # pragma no branch
1107
+ self._email = self._makeStringAttribute(attributes["email"])
1108
+ if "events_url" in attributes: # pragma no branch
1109
+ self._events_url = self._makeStringAttribute(attributes["events_url"])
1110
+ if "followers" in attributes: # pragma no branch
1111
+ self._followers = self._makeIntAttribute(attributes["followers"])
1112
+ if "followers_url" in attributes: # pragma no branch
1113
+ self._followers_url = self._makeStringAttribute(attributes["followers_url"])
1114
+ if "following" in attributes: # pragma no branch
1115
+ self._following = self._makeIntAttribute(attributes["following"])
1116
+ if "following_url" in attributes: # pragma no branch
1117
+ self._following_url = self._makeStringAttribute(attributes["following_url"])
1118
+ if "gists_url" in attributes: # pragma no branch
1119
+ self._gists_url = self._makeStringAttribute(attributes["gists_url"])
1120
+ if "gravatar_id" in attributes: # pragma no branch
1121
+ self._gravatar_id = self._makeStringAttribute(attributes["gravatar_id"])
1122
+ if "hireable" in attributes: # pragma no branch
1123
+ self._hireable = self._makeBoolAttribute(attributes["hireable"])
1124
+ if "html_url" in attributes: # pragma no branch
1125
+ self._html_url = self._makeStringAttribute(attributes["html_url"])
1126
+ if "id" in attributes: # pragma no branch
1127
+ self._id = self._makeIntAttribute(attributes["id"])
1128
+ if "location" in attributes: # pragma no branch
1129
+ self._location = self._makeStringAttribute(attributes["location"])
1130
+ if "login" in attributes: # pragma no branch
1131
+ self._login = self._makeStringAttribute(attributes["login"])
1132
+ if "name" in attributes: # pragma no branch
1133
+ self._name = self._makeStringAttribute(attributes["name"])
1134
+ if "node_id" in attributes: # pragma no branch
1135
+ self._node_id = self._makeStringAttribute(attributes["node_id"])
1136
+ if "organizations_url" in attributes: # pragma no branch
1137
+ self._organizations_url = self._makeStringAttribute(attributes["organizations_url"])
1138
+ if "owned_private_repos" in attributes: # pragma no branch
1139
+ self._owned_private_repos = self._makeIntAttribute(attributes["owned_private_repos"])
1140
+ if "plan" in attributes: # pragma no branch
1141
+ self._plan = self._makeClassAttribute(github.Plan.Plan, attributes["plan"])
1142
+ if "private_gists" in attributes: # pragma no branch
1143
+ self._private_gists = self._makeIntAttribute(attributes["private_gists"])
1144
+ if "public_gists" in attributes: # pragma no branch
1145
+ self._public_gists = self._makeIntAttribute(attributes["public_gists"])
1146
+ if "public_repos" in attributes: # pragma no branch
1147
+ self._public_repos = self._makeIntAttribute(attributes["public_repos"])
1148
+ if "received_events_url" in attributes: # pragma no branch
1149
+ self._received_events_url = self._makeStringAttribute(attributes["received_events_url"])
1150
+ if "repos_url" in attributes: # pragma no branch
1151
+ self._repos_url = self._makeStringAttribute(attributes["repos_url"])
1152
+ if "site_admin" in attributes: # pragma no branch
1153
+ self._site_admin = self._makeBoolAttribute(attributes["site_admin"])
1154
+ if "starred_url" in attributes: # pragma no branch
1155
+ self._starred_url = self._makeStringAttribute(attributes["starred_url"])
1156
+ if "subscriptions_url" in attributes: # pragma no branch
1157
+ self._subscriptions_url = self._makeStringAttribute(attributes["subscriptions_url"])
1158
+ if "total_private_repos" in attributes: # pragma no branch
1159
+ self._total_private_repos = self._makeIntAttribute(attributes["total_private_repos"])
1160
+ if "two_factor_authentication" in attributes:
1161
+ self._two_factor_authentication = self._makeBoolAttribute(attributes["two_factor_authentication"])
1162
+ if "type" in attributes: # pragma no branch
1163
+ self._type = self._makeStringAttribute(attributes["type"])
1164
+ if "updated_at" in attributes: # pragma no branch
1165
+ self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
1166
+ if "url" in attributes: # pragma no branch
1167
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/Authorization.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # #
22
+ # This file is part of PyGithub. #
23
+ # http://pygithub.readthedocs.io/ #
24
+ # #
25
+ # PyGithub is free software: you can redistribute it and/or modify it under #
26
+ # the terms of the GNU Lesser General Public License as published by the Free #
27
+ # Software Foundation, either version 3 of the License, or (at your option) #
28
+ # any later version. #
29
+ # #
30
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
31
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
32
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
33
+ # details. #
34
+ # #
35
+ # You should have received a copy of the GNU Lesser General Public License #
36
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
37
+ # #
38
+ ################################################################################
39
+
40
+ from __future__ import annotations
41
+
42
+ from datetime import datetime
43
+ from typing import TYPE_CHECKING, Any
44
+
45
+ import github.AuthorizationApplication
46
+ import github.GithubObject
47
+ from github.GithubObject import Attribute, NotSet, Opt, _NotSetType
48
+
49
+ if TYPE_CHECKING:
50
+ from github.AuthorizationApplication import AuthorizationApplication
51
+
52
+
53
+ class Authorization(github.GithubObject.CompletableGithubObject):
54
+ """
55
+ This class represents Authorizations.
56
+
57
+ The reference can be found here
58
+ https://docs.github.com/en/enterprise-server@3.0/rest/reference/oauth-authorizations
59
+
60
+ """
61
+
62
+ def _initAttributes(self) -> None:
63
+ self._app: Attribute[AuthorizationApplication] = NotSet
64
+ self._created_at: Attribute[datetime] = NotSet
65
+ self._id: Attribute[int] = NotSet
66
+ self._note: Attribute[str | None] = NotSet
67
+ self._note_url: Attribute[str | None] = NotSet
68
+ self._scopes: Attribute[str] = NotSet
69
+ self._token: Attribute[str] = NotSet
70
+ self._updated_at: Attribute[datetime] = NotSet
71
+ self._url: Attribute[str] = NotSet
72
+
73
+ def __repr__(self) -> str:
74
+ return self.get__repr__({"scopes": self._scopes.value})
75
+
76
+ @property
77
+ def app(self) -> AuthorizationApplication:
78
+ self._completeIfNotSet(self._app)
79
+ return self._app.value
80
+
81
+ @property
82
+ def created_at(self) -> datetime:
83
+ """
84
+ :type: datetime.datetime
85
+ """
86
+ self._completeIfNotSet(self._created_at)
87
+ return self._created_at.value
88
+
89
+ @property
90
+ def id(self) -> int:
91
+ self._completeIfNotSet(self._id)
92
+ return self._id.value
93
+
94
+ @property
95
+ def note(self) -> str | None:
96
+ self._completeIfNotSet(self._note)
97
+ return self._note.value
98
+
99
+ @property
100
+ def note_url(self) -> str | None:
101
+ self._completeIfNotSet(self._note_url)
102
+ return self._note_url.value
103
+
104
+ @property
105
+ def scopes(self) -> str:
106
+ self._completeIfNotSet(self._scopes)
107
+ return self._scopes.value
108
+
109
+ @property
110
+ def token(self) -> str:
111
+ self._completeIfNotSet(self._token)
112
+ return self._token.value
113
+
114
+ @property
115
+ def updated_at(self) -> datetime:
116
+ self._completeIfNotSet(self._updated_at)
117
+ return self._updated_at.value
118
+
119
+ @property
120
+ def url(self) -> str:
121
+ self._completeIfNotSet(self._url)
122
+ return self._url.value
123
+
124
+ def delete(self) -> None:
125
+ """
126
+ :calls: `DELETE /authorizations/{id} <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
127
+ """
128
+ headers, data = self._requester.requestJsonAndCheck("DELETE", self.url)
129
+
130
+ def edit(
131
+ self,
132
+ scopes: Opt[list[str]] = NotSet,
133
+ add_scopes: Opt[list[str]] = NotSet,
134
+ remove_scopes: Opt[list[str]] = NotSet,
135
+ note: Opt[str] = NotSet,
136
+ note_url: Opt[str] = NotSet,
137
+ ) -> None:
138
+ """
139
+ :calls: `PATCH /authorizations/{id} <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
140
+ :param scopes: list of string
141
+ :param add_scopes: list of string
142
+ :param remove_scopes: list of string
143
+ :param note: string
144
+ :param note_url: string
145
+ :rtype: None
146
+ """
147
+ assert isinstance(scopes, _NotSetType) or all(isinstance(element, str) for element in scopes), scopes
148
+ assert isinstance(add_scopes, _NotSetType) or all(
149
+ isinstance(element, str) for element in add_scopes
150
+ ), add_scopes
151
+ assert isinstance(remove_scopes, _NotSetType) or all(
152
+ isinstance(element, str) for element in remove_scopes
153
+ ), remove_scopes
154
+ assert isinstance(note, (_NotSetType, str)), note
155
+ assert isinstance(note_url, (_NotSetType, str)), note_url
156
+
157
+ post_parameters = NotSet.remove_unset_items(
158
+ {
159
+ "scopes": scopes,
160
+ "add_scopes": add_scopes,
161
+ "remove_scopes": remove_scopes,
162
+ "note": note,
163
+ "note_url": note_url,
164
+ }
165
+ )
166
+
167
+ headers, data = self._requester.requestJsonAndCheck("PATCH", self.url, input=post_parameters)
168
+ self._useAttributes(data)
169
+
170
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
171
+ if "app" in attributes: # pragma no branch
172
+ self._app = self._makeClassAttribute(
173
+ github.AuthorizationApplication.AuthorizationApplication,
174
+ attributes["app"],
175
+ )
176
+ if "created_at" in attributes: # pragma no branch
177
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
178
+ if "id" in attributes: # pragma no branch
179
+ self._id = self._makeIntAttribute(attributes["id"])
180
+ if "note" in attributes: # pragma no branch
181
+ self._note = self._makeStringAttribute(attributes["note"])
182
+ if "note_url" in attributes: # pragma no branch
183
+ self._note_url = self._makeStringAttribute(attributes["note_url"])
184
+ if "scopes" in attributes: # pragma no branch
185
+ self._scopes = self._makeListOfStringsAttribute(attributes["scopes"])
186
+ if "token" in attributes: # pragma no branch
187
+ self._token = self._makeStringAttribute(attributes["token"])
188
+ if "updated_at" in attributes: # pragma no branch
189
+ self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
190
+ if "url" in attributes: # pragma no branch
191
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/AuthorizationApplication.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
16
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
17
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
19
+ # #
20
+ # This file is part of PyGithub. #
21
+ # http://pygithub.readthedocs.io/ #
22
+ # #
23
+ # PyGithub is free software: you can redistribute it and/or modify it under #
24
+ # the terms of the GNU Lesser General Public License as published by the Free #
25
+ # Software Foundation, either version 3 of the License, or (at your option) #
26
+ # any later version. #
27
+ # #
28
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
29
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
30
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
31
+ # details. #
32
+ # #
33
+ # You should have received a copy of the GNU Lesser General Public License #
34
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
35
+ # #
36
+ ################################################################################
37
+
38
+ from typing import Any, Dict
39
+
40
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
41
+
42
+
43
+ class AuthorizationApplication(CompletableGithubObject):
44
+ """
45
+ This class represents AuthorizationApplications.
46
+ """
47
+
48
+ def _initAttributes(self) -> None:
49
+ self._name: Attribute[str] = NotSet
50
+ self._url: Attribute[str] = NotSet
51
+
52
+ def __repr__(self) -> str:
53
+ return self.get__repr__({"name": self._name.value})
54
+
55
+ @property
56
+ def name(self) -> str:
57
+ self._completeIfNotSet(self._name)
58
+ return self._name.value
59
+
60
+ @property
61
+ def url(self) -> str:
62
+ self._completeIfNotSet(self._url)
63
+ return self._url.value
64
+
65
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
66
+ if "name" in attributes: # pragma no branch
67
+ self._name = self._makeStringAttribute(attributes["name"])
68
+ if "url" in attributes: # pragma no branch
69
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/Autolink.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
6
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
8
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
9
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
10
+ # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
11
+ # Copyright 2019 Nick Campbell <nicholas.j.campbell@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2022 Marco Köpcke <hello@parakoopa.de> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Oskar Jansson <56458534+janssonoskar@users.noreply.github.com>#
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from typing import Any, Dict
43
+
44
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
45
+
46
+
47
+ class Autolink(NonCompletableGithubObject):
48
+ """
49
+ This class represents Repository autolinks.
50
+
51
+ The reference can be found here
52
+ https://docs.github.com/en/rest/repos/autolinks?apiVersion=2022-11-28
53
+
54
+ The OpenAPI schema can be found at
55
+ - /components/schemas/autolink
56
+
57
+ """
58
+
59
+ def _initAttributes(self) -> None:
60
+ self._id: Attribute[int] = NotSet
61
+ self._is_alphanumeric: Attribute[bool] = NotSet
62
+ self._key_prefix: Attribute[str] = NotSet
63
+ self._url_template: Attribute[str] = NotSet
64
+
65
+ def __repr__(self) -> str:
66
+ return self.get__repr__({"id": self._id.value})
67
+
68
+ @property
69
+ def id(self) -> int:
70
+ return self._id.value
71
+
72
+ @property
73
+ def is_alphanumeric(self) -> bool:
74
+ return self._is_alphanumeric.value
75
+
76
+ @property
77
+ def key_prefix(self) -> str:
78
+ return self._key_prefix.value
79
+
80
+ @property
81
+ def url_template(self) -> str:
82
+ return self._url_template.value
83
+
84
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
85
+ if "id" in attributes: # pragma no branch
86
+ self._id = self._makeIntAttribute(attributes["id"])
87
+ if "is_alphanumeric" in attributes: # pragma no branch
88
+ self._is_alphanumeric = self._makeBoolAttribute(attributes["is_alphanumeric"])
89
+ if "key_prefix" in attributes: # pragma no branch
90
+ self._key_prefix = self._makeStringAttribute(attributes["key_prefix"])
91
+ if "url_template" in attributes: # pragma no branch
92
+ self._url_template = self._makeStringAttribute(attributes["url_template"])
venv/lib/python3.10/site-packages/github/Branch.py ADDED
@@ -0,0 +1,657 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2013 martinqt <m.ki2@laposte.net> #
8
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
9
+ # Copyright 2015 Kyle Hornberg <khornberg@users.noreply.github.com> #
10
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
11
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
12
+ # Copyright 2018 Alice GIRARD <bouhahah@gmail.com> #
13
+ # Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
16
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
18
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
19
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
20
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
21
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
22
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
23
+ # Copyright 2023 Juan Manuel "Kang" Pérez <kangcoding@gmail.com> #
24
+ # Copyright 2023 Kevin Grandjean <Muscaw@users.noreply.github.com> #
25
+ # Copyright 2023 Paul Luna <paulluna0215@gmail.com> #
26
+ # Copyright 2023 Thomas Devoogdt <thomas@devoogdt.com> #
27
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
28
+ # Copyright 2023 terenho <33275803+terenho@users.noreply.github.com> #
29
+ # Copyright 2024 Benjamin K <53038537+treee111@users.noreply.github.com> #
30
+ # Copyright 2024 Benjamin K. <53038537+treee111@users.noreply.github.com> #
31
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
32
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
33
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
34
+ # #
35
+ # This file is part of PyGithub. #
36
+ # http://pygithub.readthedocs.io/ #
37
+ # #
38
+ # PyGithub is free software: you can redistribute it and/or modify it under #
39
+ # the terms of the GNU Lesser General Public License as published by the Free #
40
+ # Software Foundation, either version 3 of the License, or (at your option) #
41
+ # any later version. #
42
+ # #
43
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
44
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
45
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
46
+ # details. #
47
+ # #
48
+ # You should have received a copy of the GNU Lesser General Public License #
49
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
50
+ # #
51
+ ################################################################################
52
+
53
+ from __future__ import annotations
54
+
55
+ from typing import TYPE_CHECKING, Any
56
+
57
+ import github.BranchProtection
58
+ import github.Commit
59
+ import github.RequiredPullRequestReviews
60
+ import github.RequiredStatusChecks
61
+ from github import Consts
62
+ from github.GithubObject import (
63
+ Attribute,
64
+ NonCompletableGithubObject,
65
+ NotSet,
66
+ Opt,
67
+ is_defined,
68
+ is_optional,
69
+ is_optional_list,
70
+ is_undefined,
71
+ )
72
+
73
+ if TYPE_CHECKING:
74
+ from github.BranchProtection import BranchProtection
75
+ from github.Commit import Commit
76
+ from github.NamedUser import NamedUser
77
+ from github.PaginatedList import PaginatedList
78
+ from github.RequiredPullRequestReviews import RequiredPullRequestReviews
79
+ from github.RequiredStatusChecks import RequiredStatusChecks
80
+ from github.Team import Team
81
+
82
+
83
+ class Branch(NonCompletableGithubObject):
84
+ """
85
+ This class represents Branches.
86
+
87
+ The reference can be found here
88
+ https://docs.github.com/en/rest/reference/repos#branches
89
+
90
+ The OpenAPI schema can be found at
91
+ - /components/schemas/branch-short
92
+ - /components/schemas/branch-with-protection
93
+ - /components/schemas/short-branch
94
+
95
+ """
96
+
97
+ def _initAttributes(self) -> None:
98
+ self.__links: Attribute[dict[str, Any]] = NotSet
99
+ self._commit: Attribute[Commit] = github.GithubObject.NotSet
100
+ self._name: Attribute[str] = github.GithubObject.NotSet
101
+ self._pattern: Attribute[str] = NotSet
102
+ self._protected: Attribute[bool] = github.GithubObject.NotSet
103
+ self._protection: Attribute[BranchProtection] = NotSet
104
+ self._protection_url: Attribute[str] = github.GithubObject.NotSet
105
+ self._required_approving_review_count: Attribute[int] = NotSet
106
+
107
+ def __repr__(self) -> str:
108
+ return self.get__repr__({"name": self._name.value})
109
+
110
+ @property
111
+ def _links(self) -> dict[str, Any]:
112
+ return self.__links.value
113
+
114
+ @property
115
+ def commit(self) -> Commit:
116
+ return self._commit.value
117
+
118
+ @property
119
+ def name(self) -> str:
120
+ return self._name.value
121
+
122
+ @property
123
+ def pattern(self) -> str:
124
+ return self._pattern.value
125
+
126
+ @property
127
+ def protected(self) -> bool:
128
+ return self._protected.value
129
+
130
+ @property
131
+ def protection(self) -> BranchProtection:
132
+ if is_undefined(self._protection):
133
+ return self.get_protection()
134
+ return self._protection.value
135
+
136
+ @property
137
+ def protection_url(self) -> str:
138
+ return self._protection_url.value
139
+
140
+ @property
141
+ def required_approving_review_count(self) -> int:
142
+ return self._required_approving_review_count.value
143
+
144
+ def get_protection(self) -> BranchProtection:
145
+ """
146
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection <https://docs.github.com/en/rest/reference/repos#branches>`_
147
+ """
148
+ headers, data = self._requester.requestJsonAndCheck(
149
+ "GET",
150
+ self.protection_url,
151
+ headers={"Accept": Consts.mediaTypeRequireMultipleApprovingReviews},
152
+ )
153
+ return github.BranchProtection.BranchProtection(self._requester, headers, data, completed=True)
154
+
155
+ def edit_protection(
156
+ self,
157
+ strict: Opt[bool] = NotSet,
158
+ contexts: Opt[list[str]] = NotSet,
159
+ enforce_admins: Opt[bool] = NotSet,
160
+ dismissal_users: Opt[list[str]] = NotSet,
161
+ dismissal_teams: Opt[list[str]] = NotSet,
162
+ dismissal_apps: Opt[list[str]] = NotSet,
163
+ dismiss_stale_reviews: Opt[bool] = NotSet,
164
+ require_code_owner_reviews: Opt[bool] = NotSet,
165
+ required_approving_review_count: Opt[int] = NotSet,
166
+ user_push_restrictions: Opt[list[str]] = NotSet,
167
+ team_push_restrictions: Opt[list[str]] = NotSet,
168
+ app_push_restrictions: Opt[list[str]] = NotSet,
169
+ required_linear_history: Opt[bool] = NotSet,
170
+ allow_force_pushes: Opt[bool] = NotSet,
171
+ required_conversation_resolution: Opt[bool] = NotSet,
172
+ lock_branch: Opt[bool] = NotSet,
173
+ allow_fork_syncing: Opt[bool] = NotSet,
174
+ users_bypass_pull_request_allowances: Opt[list[str]] = NotSet,
175
+ teams_bypass_pull_request_allowances: Opt[list[str]] = NotSet,
176
+ apps_bypass_pull_request_allowances: Opt[list[str]] = NotSet,
177
+ block_creations: Opt[bool] = NotSet,
178
+ require_last_push_approval: Opt[bool] = NotSet,
179
+ allow_deletions: Opt[bool] = NotSet,
180
+ checks: Opt[list[str | tuple[str, int]]] = NotSet,
181
+ ) -> BranchProtection:
182
+ """
183
+ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection <https://docs.github.com/en/rest/reference/repos#get-branch-protection>`_
184
+
185
+ NOTE: The GitHub API groups strict and contexts together, both must
186
+ be submitted. Take care to pass both as arguments even if only one is
187
+ changing. Use edit_required_status_checks() to avoid this.
188
+ """
189
+ assert is_optional(strict, bool), strict
190
+ assert is_optional_list(contexts, str), contexts
191
+ assert is_optional(enforce_admins, bool), enforce_admins
192
+ assert is_optional_list(dismissal_users, str), dismissal_users
193
+ assert is_optional_list(dismissal_teams, str), dismissal_teams
194
+ assert is_optional_list(dismissal_apps, str), dismissal_apps
195
+ assert is_optional(dismiss_stale_reviews, bool), dismiss_stale_reviews
196
+ assert is_optional(require_code_owner_reviews, bool), require_code_owner_reviews
197
+ assert is_optional(required_approving_review_count, int), required_approving_review_count
198
+ assert is_optional(required_linear_history, bool), required_linear_history
199
+ assert is_optional(allow_force_pushes, bool), allow_force_pushes
200
+ assert is_optional(required_conversation_resolution, bool), required_conversation_resolution
201
+ assert is_optional(lock_branch, bool), lock_branch
202
+ assert is_optional(allow_fork_syncing, bool), allow_fork_syncing
203
+ assert is_optional_list(users_bypass_pull_request_allowances, str), users_bypass_pull_request_allowances
204
+ assert is_optional_list(teams_bypass_pull_request_allowances, str), teams_bypass_pull_request_allowances
205
+ assert is_optional_list(apps_bypass_pull_request_allowances, str), apps_bypass_pull_request_allowances
206
+ assert is_optional(require_last_push_approval, bool), require_last_push_approval
207
+ assert is_optional(allow_deletions, bool), allow_deletions
208
+ assert is_optional_list(checks, (str, tuple)), checks
209
+ if is_defined(checks):
210
+ assert all(not isinstance(check, tuple) or list(map(type, check)) == [str, int] for check in checks), checks
211
+
212
+ post_parameters: dict[str, Any] = {}
213
+ if is_defined(strict) or is_defined(contexts) or is_defined(checks):
214
+ if is_undefined(strict):
215
+ strict = False
216
+
217
+ checks_parameters = []
218
+ if is_defined(checks):
219
+ checks_parameters = [
220
+ {"context": check[0], "app_id": check[1]} if isinstance(check, tuple) else {"context": check}
221
+ for check in checks
222
+ ]
223
+ elif is_defined(contexts):
224
+ checks_parameters = [{"context": context} for context in contexts]
225
+
226
+ post_parameters["required_status_checks"] = {
227
+ "strict": strict,
228
+ "checks": checks_parameters,
229
+ }
230
+ else:
231
+ post_parameters["required_status_checks"] = None
232
+
233
+ if is_defined(enforce_admins):
234
+ post_parameters["enforce_admins"] = enforce_admins
235
+ else:
236
+ post_parameters["enforce_admins"] = None
237
+
238
+ if (
239
+ is_defined(dismissal_users)
240
+ or is_defined(dismissal_teams)
241
+ or is_defined(dismissal_apps)
242
+ or is_defined(dismiss_stale_reviews)
243
+ or is_defined(require_code_owner_reviews)
244
+ or is_defined(required_approving_review_count)
245
+ or is_defined(users_bypass_pull_request_allowances)
246
+ or is_defined(teams_bypass_pull_request_allowances)
247
+ or is_defined(apps_bypass_pull_request_allowances)
248
+ or is_defined(require_last_push_approval)
249
+ ):
250
+ post_parameters["required_pull_request_reviews"] = {}
251
+ if is_defined(dismiss_stale_reviews):
252
+ post_parameters["required_pull_request_reviews"]["dismiss_stale_reviews"] = dismiss_stale_reviews
253
+ if is_defined(require_code_owner_reviews):
254
+ post_parameters["required_pull_request_reviews"][
255
+ "require_code_owner_reviews"
256
+ ] = require_code_owner_reviews
257
+ if is_defined(required_approving_review_count):
258
+ post_parameters["required_pull_request_reviews"][
259
+ "required_approving_review_count"
260
+ ] = required_approving_review_count
261
+ if is_defined(require_last_push_approval):
262
+ post_parameters["required_pull_request_reviews"][
263
+ "require_last_push_approval"
264
+ ] = require_last_push_approval
265
+
266
+ dismissal_restrictions = {}
267
+ if is_defined(dismissal_users):
268
+ dismissal_restrictions["users"] = dismissal_users
269
+ if is_defined(dismissal_teams):
270
+ dismissal_restrictions["teams"] = dismissal_teams
271
+ if is_defined(dismissal_apps):
272
+ dismissal_restrictions["apps"] = dismissal_apps
273
+
274
+ if dismissal_restrictions:
275
+ post_parameters["required_pull_request_reviews"]["dismissal_restrictions"] = dismissal_restrictions
276
+
277
+ bypass_pull_request_allowances = {}
278
+ if is_defined(users_bypass_pull_request_allowances):
279
+ bypass_pull_request_allowances["users"] = users_bypass_pull_request_allowances
280
+ if is_defined(teams_bypass_pull_request_allowances):
281
+ bypass_pull_request_allowances["teams"] = teams_bypass_pull_request_allowances
282
+ if is_defined(apps_bypass_pull_request_allowances):
283
+ bypass_pull_request_allowances["apps"] = apps_bypass_pull_request_allowances
284
+
285
+ if bypass_pull_request_allowances:
286
+ post_parameters["required_pull_request_reviews"][
287
+ "bypass_pull_request_allowances"
288
+ ] = bypass_pull_request_allowances
289
+ else:
290
+ post_parameters["required_pull_request_reviews"] = None
291
+ if (
292
+ is_defined(user_push_restrictions)
293
+ or is_defined(team_push_restrictions)
294
+ or is_defined(app_push_restrictions)
295
+ ):
296
+ if is_undefined(user_push_restrictions):
297
+ user_push_restrictions = []
298
+ if is_undefined(team_push_restrictions):
299
+ team_push_restrictions = []
300
+ if is_undefined(app_push_restrictions):
301
+ app_push_restrictions = []
302
+ post_parameters["restrictions"] = {
303
+ "users": user_push_restrictions,
304
+ "teams": team_push_restrictions,
305
+ "apps": app_push_restrictions,
306
+ }
307
+ else:
308
+ post_parameters["restrictions"] = None
309
+ if is_defined(required_linear_history):
310
+ post_parameters["required_linear_history"] = required_linear_history
311
+ else:
312
+ post_parameters["required_linear_history"] = None
313
+ if is_defined(allow_force_pushes):
314
+ post_parameters["allow_force_pushes"] = allow_force_pushes
315
+ else:
316
+ post_parameters["allow_force_pushes"] = None
317
+ if is_defined(required_conversation_resolution):
318
+ post_parameters["required_conversation_resolution"] = required_conversation_resolution
319
+ else:
320
+ post_parameters["required_conversation_resolution"] = None
321
+ if is_defined(lock_branch):
322
+ post_parameters["lock_branch"] = lock_branch
323
+ else:
324
+ post_parameters["lock_branch"] = None
325
+ if is_defined(allow_fork_syncing):
326
+ post_parameters["allow_fork_syncing"] = allow_fork_syncing
327
+ else:
328
+ post_parameters["allow_fork_syncing"] = None
329
+ if is_defined(block_creations):
330
+ post_parameters["block_creations"] = block_creations
331
+ else:
332
+ post_parameters["block_creations"] = None
333
+ if is_defined(allow_deletions):
334
+ post_parameters["allow_deletions"] = allow_deletions
335
+ else:
336
+ post_parameters["allow_deletions"] = None
337
+
338
+ headers, data = self._requester.requestJsonAndCheck(
339
+ "PUT",
340
+ self.protection_url,
341
+ headers={"Accept": Consts.mediaTypeRequireMultipleApprovingReviews},
342
+ input=post_parameters,
343
+ )
344
+
345
+ return github.BranchProtection.BranchProtection(self._requester, headers, data, completed=True)
346
+
347
+ def remove_protection(self) -> None:
348
+ """
349
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection <https://docs.github.com/en/rest/reference/repos#branches>`_
350
+ """
351
+ headers, data = self._requester.requestJsonAndCheck(
352
+ "DELETE",
353
+ self.protection_url,
354
+ )
355
+
356
+ def get_required_status_checks(self) -> RequiredStatusChecks:
357
+ """
358
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks <https://docs.github.com/en/rest/reference/repos#branches>`_
359
+ :rtype: :class:`github.RequiredStatusChecks.RequiredStatusChecks`
360
+ """
361
+ headers, data = self._requester.requestJsonAndCheck("GET", f"{self.protection_url}/required_status_checks")
362
+ return github.RequiredStatusChecks.RequiredStatusChecks(self._requester, headers, data, completed=True)
363
+
364
+ def edit_required_status_checks(
365
+ self,
366
+ strict: Opt[bool] = NotSet,
367
+ contexts: Opt[list[str]] = NotSet,
368
+ checks: Opt[list[str | tuple[str, int]]] = NotSet,
369
+ ) -> RequiredStatusChecks:
370
+ """
371
+ :calls: `PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks <https://docs.github.com/en/rest/reference/repos#branches>`_
372
+ """
373
+ assert is_optional(strict, bool), strict
374
+ assert is_optional_list(contexts, str), contexts
375
+ assert is_optional_list(checks, (str, tuple)), checks
376
+ if is_defined(checks):
377
+ assert all(not isinstance(check, tuple) or list(map(type, check)) == [str, int] for check in checks), checks
378
+
379
+ checks_parameters: Opt[list[dict[str, Any]]] = NotSet
380
+ if is_defined(checks):
381
+ checks_parameters = [
382
+ {"context": check[0], "app_id": check[1]} if isinstance(check, tuple) else {"context": check}
383
+ for check in checks
384
+ ]
385
+ elif is_defined(contexts):
386
+ checks_parameters = [{"context": context} for context in contexts]
387
+
388
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items({"strict": strict, "checks": checks_parameters})
389
+
390
+ headers, data = self._requester.requestJsonAndCheck(
391
+ "PATCH",
392
+ f"{self.protection_url}/required_status_checks",
393
+ input=post_parameters,
394
+ )
395
+
396
+ return github.RequiredStatusChecks.RequiredStatusChecks(self._requester, headers, data, completed=True)
397
+
398
+ def remove_required_status_checks(self) -> None:
399
+ """
400
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks <https://docs.github.com/en/rest/reference/repos#branches>`_
401
+ """
402
+ headers, data = self._requester.requestJsonAndCheck(
403
+ "DELETE",
404
+ f"{self.protection_url}/required_status_checks",
405
+ )
406
+
407
+ def get_required_pull_request_reviews(self) -> RequiredPullRequestReviews:
408
+ """
409
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews <https://docs.github.com/en/rest/reference/repos#branches>`_
410
+ """
411
+ headers, data = self._requester.requestJsonAndCheck(
412
+ "GET",
413
+ f"{self.protection_url}/required_pull_request_reviews",
414
+ headers={"Accept": Consts.mediaTypeRequireMultipleApprovingReviews},
415
+ )
416
+ return github.RequiredPullRequestReviews.RequiredPullRequestReviews(
417
+ self._requester, headers, data, completed=True
418
+ )
419
+
420
+ def edit_required_pull_request_reviews(
421
+ self,
422
+ dismissal_users: Opt[list[str]] = NotSet,
423
+ dismissal_teams: Opt[list[str]] = NotSet,
424
+ dismissal_apps: Opt[list[str]] = NotSet,
425
+ dismiss_stale_reviews: Opt[bool] = NotSet,
426
+ require_code_owner_reviews: Opt[bool] = NotSet,
427
+ required_approving_review_count: Opt[int] = NotSet,
428
+ require_last_push_approval: Opt[bool] = NotSet,
429
+ ) -> RequiredStatusChecks:
430
+ """
431
+ :calls: `PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews <https://docs.github.com/en/rest/reference/repos#branches>`_
432
+ """
433
+ assert is_optional_list(dismissal_users, str), dismissal_users
434
+ assert is_optional_list(dismissal_teams, str), dismissal_teams
435
+ assert is_optional(dismiss_stale_reviews, bool), dismiss_stale_reviews
436
+ assert is_optional(require_code_owner_reviews, bool), require_code_owner_reviews
437
+ assert is_optional(required_approving_review_count, int), required_approving_review_count
438
+ assert is_optional(require_last_push_approval, bool), require_last_push_approval
439
+
440
+ post_parameters: dict[str, Any] = NotSet.remove_unset_items(
441
+ {
442
+ "dismiss_stale_reviews": dismiss_stale_reviews,
443
+ "require_code_owner_reviews": require_code_owner_reviews,
444
+ "required_approving_review_count": required_approving_review_count,
445
+ "require_last_push_approval": require_last_push_approval,
446
+ }
447
+ )
448
+
449
+ dismissal_restrictions: dict[str, Any] = NotSet.remove_unset_items(
450
+ {"users": dismissal_users, "teams": dismissal_teams, "apps": dismissal_apps}
451
+ )
452
+
453
+ if dismissal_restrictions:
454
+ post_parameters["dismissal_restrictions"] = dismissal_restrictions
455
+
456
+ headers, data = self._requester.requestJsonAndCheck(
457
+ "PATCH",
458
+ f"{self.protection_url}/required_pull_request_reviews",
459
+ headers={"Accept": Consts.mediaTypeRequireMultipleApprovingReviews},
460
+ input=post_parameters,
461
+ )
462
+
463
+ return github.RequiredStatusChecks.RequiredStatusChecks(self._requester, headers, data, completed=True)
464
+
465
+ def remove_required_pull_request_reviews(self) -> None:
466
+ """
467
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews <https://docs.github.com/en/rest/reference/repos#branches>`_
468
+ """
469
+ headers, data = self._requester.requestJsonAndCheck(
470
+ "DELETE",
471
+ f"{self.protection_url}/required_pull_request_reviews",
472
+ )
473
+
474
+ def get_admin_enforcement(self) -> bool:
475
+ """
476
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins <https://docs.github.com/en/rest/reference/repos#branches>`_
477
+ """
478
+ headers, data = self._requester.requestJsonAndCheck("GET", f"{self.protection_url}/enforce_admins")
479
+ return data["enabled"]
480
+
481
+ def set_admin_enforcement(self) -> None:
482
+ """
483
+ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins <https://docs.github.com/en/rest/reference/repos#branches>`_
484
+ """
485
+ headers, data = self._requester.requestJsonAndCheck("POST", f"{self.protection_url}/enforce_admins")
486
+
487
+ def remove_admin_enforcement(self) -> None:
488
+ """
489
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins <https://docs.github.com/en/rest/reference/repos#branches>`_
490
+ """
491
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"{self.protection_url}/enforce_admins")
492
+
493
+ def get_user_push_restrictions(self) -> PaginatedList[NamedUser]:
494
+ """
495
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users <https://docs.github.com/en/rest/reference/repos#branches>`_
496
+ """
497
+ return github.PaginatedList.PaginatedList(
498
+ github.NamedUser.NamedUser,
499
+ self._requester,
500
+ f"{self.protection_url}/restrictions/users",
501
+ None,
502
+ )
503
+
504
+ def get_team_push_restrictions(self) -> PaginatedList[Team]:
505
+ """
506
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams <https://docs.github.com/en/rest/reference/repos#branches>`_
507
+ """
508
+ return github.PaginatedList.PaginatedList(
509
+ github.Team.Team,
510
+ self._requester,
511
+ f"{self.protection_url}/restrictions/teams",
512
+ None,
513
+ )
514
+
515
+ def add_user_push_restrictions(self, *users: str) -> None:
516
+ """
517
+ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users <https://docs.github.com/en/rest/reference/repos#branches>`_
518
+ :users: list of strings (user names)
519
+ """
520
+ assert all(isinstance(element, str) for element in users), users
521
+
522
+ headers, data = self._requester.requestJsonAndCheck(
523
+ "POST", f"{self.protection_url}/restrictions/users", input=users
524
+ )
525
+
526
+ def replace_user_push_restrictions(self, *users: str) -> None:
527
+ """
528
+ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users <https://docs.github.com/en/rest/reference/repos#branches>`_
529
+ :users: list of strings (user names)
530
+ """
531
+ assert all(isinstance(element, str) for element in users), users
532
+
533
+ headers, data = self._requester.requestJsonAndCheck(
534
+ "PUT", f"{self.protection_url}/restrictions/users", input=users
535
+ )
536
+
537
+ def remove_user_push_restrictions(self, *users: str) -> None:
538
+ """
539
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users <https://docs.github.com/en/rest/reference/repos#branches>`_
540
+ :users: list of strings (user names)
541
+ """
542
+ assert all(isinstance(element, str) for element in users), users
543
+
544
+ headers, data = self._requester.requestJsonAndCheck(
545
+ "DELETE", f"{self.protection_url}/restrictions/users", input=users
546
+ )
547
+
548
+ def add_team_push_restrictions(self, *teams: str) -> None:
549
+ """
550
+ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams <https://docs.github.com/en/rest/reference/repos#branches>`_
551
+ :teams: list of strings (team slugs)
552
+ """
553
+ assert all(isinstance(element, str) for element in teams), teams
554
+
555
+ headers, data = self._requester.requestJsonAndCheck(
556
+ "POST", f"{self.protection_url}/restrictions/teams", input=teams
557
+ )
558
+
559
+ def replace_team_push_restrictions(self, *teams: str) -> None:
560
+ """
561
+ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams <https://docs.github.com/en/rest/reference/repos#branches>`_
562
+ :teams: list of strings (team slugs)
563
+ """
564
+ assert all(isinstance(element, str) for element in teams), teams
565
+
566
+ headers, data = self._requester.requestJsonAndCheck(
567
+ "PUT", f"{self.protection_url}/restrictions/teams", input=teams
568
+ )
569
+
570
+ def remove_team_push_restrictions(self, *teams: str) -> None:
571
+ """
572
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams <https://docs.github.com/en/rest/reference/repos#branches>`_
573
+ :teams: list of strings (team slugs)
574
+ """
575
+ assert all(isinstance(element, str) for element in teams), teams
576
+
577
+ headers, data = self._requester.requestJsonAndCheck(
578
+ "DELETE", f"{self.protection_url}/restrictions/teams", input=teams
579
+ )
580
+
581
+ def remove_push_restrictions(self) -> None:
582
+ """
583
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions <https://docs.github.com/en/rest/reference/repos#branches>`_
584
+ """
585
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"{self.protection_url}/restrictions")
586
+
587
+ def get_required_signatures(self) -> bool:
588
+ """
589
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures <https://docs.github.com/en/rest/reference/repos#branches>`_
590
+ """
591
+ headers, data = self._requester.requestJsonAndCheck(
592
+ "GET",
593
+ f"{self.protection_url}/required_signatures",
594
+ headers={"Accept": Consts.signaturesProtectedBranchesPreview},
595
+ )
596
+ return data["enabled"]
597
+
598
+ def add_required_signatures(self) -> None:
599
+ """
600
+ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures <https://docs.github.com/en/rest/reference/repos#branches>`_
601
+ """
602
+ headers, data = self._requester.requestJsonAndCheck(
603
+ "POST",
604
+ f"{self.protection_url}/required_signatures",
605
+ headers={"Accept": Consts.signaturesProtectedBranchesPreview},
606
+ )
607
+
608
+ def remove_required_signatures(self) -> None:
609
+ """
610
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures <https://docs.github.com/en/rest/reference/repos#branches>`_
611
+ """
612
+ headers, data = self._requester.requestJsonAndCheck(
613
+ "DELETE",
614
+ f"{self.protection_url}/required_signatures",
615
+ headers={"Accept": Consts.signaturesProtectedBranchesPreview},
616
+ )
617
+
618
+ def get_allow_deletions(self) -> bool:
619
+ """
620
+ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/allow_deletions <https://docs.github.com/en/rest/reference/repos#branches>`_
621
+ """
622
+ headers, data = self._requester.requestJsonAndCheck("GET", f"{self.protection_url}/allow_deletions")
623
+ return data["enabled"]
624
+
625
+ def set_allow_deletions(self) -> None:
626
+ """
627
+ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/allow_deletions <https://docs.github.com/en/rest/reference/repos#branches>`_
628
+ """
629
+ headers, data = self._requester.requestJsonAndCheck("POST", f"{self.protection_url}/allow_deletions")
630
+
631
+ def remove_allow_deletions(self) -> None:
632
+ """
633
+ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/allow_deletions <https://docs.github.com/en/rest/reference/repos#branches>`_
634
+ """
635
+ headers, data = self._requester.requestJsonAndCheck("DELETE", f"{self.protection_url}/allow_deletions")
636
+
637
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
638
+ if "_links" in attributes: # pragma no branch
639
+ self.__links = self._makeDictAttribute(attributes["_links"])
640
+ if "commit" in attributes: # pragma no branch
641
+ self._commit = self._makeClassAttribute(github.Commit.Commit, attributes["commit"])
642
+ if "name" in attributes: # pragma no branch
643
+ self._name = self._makeStringAttribute(attributes["name"])
644
+ if "pattern" in attributes: # pragma no branch
645
+ self._pattern = self._makeStringAttribute(attributes["pattern"])
646
+ if "protected" in attributes: # pragma no branch
647
+ self._protected = self._makeBoolAttribute(attributes["protected"])
648
+ if "protection" in attributes: # pragma no branch
649
+ self._protection = self._makeClassAttribute(
650
+ github.BranchProtection.BranchProtection, attributes["protection"]
651
+ )
652
+ if "protection_url" in attributes: # pragma no branch
653
+ self._protection_url = self._makeStringAttribute(attributes["protection_url"])
654
+ if "required_approving_review_count" in attributes: # pragma no branch
655
+ self._required_approving_review_count = self._makeIntAttribute(
656
+ attributes["required_approving_review_count"]
657
+ )
venv/lib/python3.10/site-packages/github/BranchProtection.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
4
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
5
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
6
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
7
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
8
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
9
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
10
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
11
+ # Copyright 2024 Benjamin K <53038537+treee111@users.noreply.github.com> #
12
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
13
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
14
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
15
+ # #
16
+ # This file is part of PyGithub. #
17
+ # http://pygithub.readthedocs.io/ #
18
+ # #
19
+ # PyGithub is free software: you can redistribute it and/or modify it under #
20
+ # the terms of the GNU Lesser General Public License as published by the Free #
21
+ # Software Foundation, either version 3 of the License, or (at your option) #
22
+ # any later version. #
23
+ # #
24
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
25
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
26
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
27
+ # details. #
28
+ # #
29
+ # You should have received a copy of the GNU Lesser General Public License #
30
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
31
+ # #
32
+ ################################################################################
33
+
34
+ from __future__ import annotations
35
+
36
+ from typing import TYPE_CHECKING, Any
37
+
38
+ import github.GithubObject
39
+ import github.NamedUser
40
+ import github.RequiredPullRequestReviews
41
+ import github.RequiredStatusChecks
42
+ import github.Team
43
+ from github.GithubObject import Attribute, NotSet, Opt, is_defined
44
+ from github.PaginatedList import PaginatedList
45
+
46
+ if TYPE_CHECKING:
47
+ from github.NamedUser import NamedUser
48
+ from github.RequiredPullRequestReviews import RequiredPullRequestReviews
49
+ from github.RequiredStatusChecks import RequiredStatusChecks
50
+ from github.Team import Team
51
+
52
+
53
+ class BranchProtection(github.GithubObject.CompletableGithubObject):
54
+ """
55
+ This class represents Branch Protection.
56
+
57
+ The reference can be found here
58
+ https://docs.github.com/en/rest/reference/repos#get-branch-protection
59
+
60
+ The OpenAPI schema can be found at
61
+ - /components/schemas/branch-protection
62
+ - /components/schemas/protected-branch
63
+
64
+ """
65
+
66
+ def _initAttributes(self) -> None:
67
+ self._allow_deletions: Attribute[bool] = NotSet
68
+ self._allow_force_pushes: Attribute[bool] = NotSet
69
+ self._allow_fork_syncing: Attribute[bool] = NotSet
70
+ self._block_creations: Attribute[bool] = NotSet
71
+ self._enabled: Attribute[bool] = NotSet
72
+ self._enforce_admins: Attribute[bool] = NotSet
73
+ self._lock_branch: Attribute[bool] = NotSet
74
+ self._name: Attribute[str] = NotSet
75
+ self._protection_url: Attribute[str] = NotSet
76
+ self._required_conversation_resolution: Attribute[bool] = NotSet
77
+ self._required_linear_history: Attribute[bool] = github.GithubObject.NotSet
78
+ self._required_pull_request_reviews: Attribute[RequiredPullRequestReviews] = NotSet
79
+ self._required_signatures: Attribute[bool] = NotSet
80
+ self._required_status_checks: Attribute[RequiredStatusChecks] = NotSet
81
+ self._restrictions: Attribute[dict[str, Any]] = NotSet
82
+ self._team_push_restrictions: Opt[str] = NotSet
83
+ self._url: Attribute[str] = NotSet
84
+ self._user_push_restrictions: Opt[str] = NotSet
85
+
86
+ def __repr__(self) -> str:
87
+ return self.get__repr__({"url": self._url.value})
88
+
89
+ @property
90
+ def allow_deletions(self) -> bool:
91
+ self._completeIfNotSet(self._allow_deletions)
92
+ return self._allow_deletions.value
93
+
94
+ @property
95
+ def allow_force_pushes(self) -> bool:
96
+ self._completeIfNotSet(self._allow_force_pushes)
97
+ return self._allow_force_pushes.value
98
+
99
+ @property
100
+ def allow_fork_syncing(self) -> bool:
101
+ self._completeIfNotSet(self._allow_fork_syncing)
102
+ return self._allow_fork_syncing.value
103
+
104
+ @property
105
+ def block_creations(self) -> bool:
106
+ return self._block_creations.value
107
+
108
+ @property
109
+ def enabled(self) -> bool:
110
+ return self._enabled.value
111
+
112
+ @property
113
+ def enforce_admins(self) -> bool:
114
+ self._completeIfNotSet(self._enforce_admins)
115
+ return self._enforce_admins.value
116
+
117
+ @property
118
+ def lock_branch(self) -> bool:
119
+ self._completeIfNotSet(self._lock_branch)
120
+ return self._lock_branch.value
121
+
122
+ @property
123
+ def name(self) -> str:
124
+ return self._name.value
125
+
126
+ @property
127
+ def protection_url(self) -> str:
128
+ return self._protection_url.value
129
+
130
+ @property
131
+ def required_conversation_resolution(self) -> bool:
132
+ self._completeIfNotSet(self._required_conversation_resolution)
133
+ return self._required_conversation_resolution.value
134
+
135
+ @property
136
+ def required_linear_history(self) -> bool:
137
+ self._completeIfNotSet(self._required_linear_history)
138
+ return self._required_linear_history.value
139
+
140
+ @property
141
+ def required_pull_request_reviews(self) -> RequiredPullRequestReviews:
142
+ self._completeIfNotSet(self._required_pull_request_reviews)
143
+ return self._required_pull_request_reviews.value
144
+
145
+ @property
146
+ def required_signatures(self) -> bool:
147
+ return self._required_signatures.value
148
+
149
+ @property
150
+ def required_status_checks(self) -> RequiredStatusChecks:
151
+ self._completeIfNotSet(self._required_status_checks)
152
+ return self._required_status_checks.value
153
+
154
+ @property
155
+ def restrictions(self) -> dict[str, Any]:
156
+ return self._restrictions.value
157
+
158
+ @property
159
+ def url(self) -> str:
160
+ return self._url.value
161
+
162
+ def get_user_push_restrictions(self) -> PaginatedList[NamedUser] | None:
163
+ if not is_defined(self._user_push_restrictions):
164
+ return None
165
+ return PaginatedList(
166
+ github.NamedUser.NamedUser,
167
+ self._requester,
168
+ self._user_push_restrictions,
169
+ None,
170
+ )
171
+
172
+ def get_team_push_restrictions(self) -> PaginatedList[Team] | None:
173
+ if not is_defined(self._team_push_restrictions):
174
+ return None
175
+ return github.PaginatedList.PaginatedList(github.Team.Team, self._requester, self._team_push_restrictions, None)
176
+
177
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
178
+ if "allow_deletions" in attributes: # pragma no branch
179
+ self._allow_deletions = self._makeBoolAttribute(attributes["allow_deletions"]["enabled"])
180
+ if "allow_force_pushes" in attributes: # pragma no branch
181
+ self._allow_force_pushes = self._makeBoolAttribute(attributes["allow_force_pushes"]["enabled"])
182
+ if "allow_fork_syncing" in attributes: # pragma no branch
183
+ self._allow_fork_syncing = self._makeBoolAttribute(attributes["allow_fork_syncing"]["enabled"])
184
+ if "block_creations" in attributes: # pragma no branch
185
+ self._block_creations = self._makeBoolAttribute(attributes["block_creations"]["enabled"])
186
+ if "enabled" in attributes: # pragma no branch
187
+ self._enabled = self._makeBoolAttribute(attributes["enabled"])
188
+ if "enforce_admins" in attributes: # pragma no branch
189
+ self._enforce_admins = self._makeBoolAttribute(attributes["enforce_admins"]["enabled"])
190
+ if "lock_branch" in attributes: # pragma no branch
191
+ self._lock_branch = self._makeBoolAttribute(attributes["lock_branch"]["enabled"])
192
+ if "name" in attributes: # pragma no branch
193
+ self._name = self._makeStringAttribute(attributes["name"])
194
+ if "protection_url" in attributes: # pragma no branch
195
+ self._protection_url = self._makeStringAttribute(attributes["protection_url"])
196
+ if "required_conversation_resolution" in attributes: # pragma no branch
197
+ self._required_conversation_resolution = self._makeBoolAttribute(
198
+ attributes["required_conversation_resolution"]["enabled"]
199
+ )
200
+ if "required_linear_history" in attributes: # pragma no branch
201
+ self._required_linear_history = self._makeBoolAttribute(attributes["required_linear_history"]["enabled"])
202
+ if "required_pull_request_reviews" in attributes: # pragma no branch
203
+ self._required_pull_request_reviews = self._makeClassAttribute(
204
+ github.RequiredPullRequestReviews.RequiredPullRequestReviews,
205
+ attributes["required_pull_request_reviews"],
206
+ )
207
+ if "required_signatures" in attributes: # pragma no branch
208
+ self._required_signatures = self._makeBoolAttribute(attributes["required_signatures"]["enabled"])
209
+ if "required_status_checks" in attributes: # pragma no branch
210
+ self._required_status_checks = self._makeClassAttribute(
211
+ github.RequiredStatusChecks.RequiredStatusChecks,
212
+ attributes["required_status_checks"],
213
+ )
214
+ if "restrictions" in attributes: # pragma no branch
215
+ self._restrictions = attributes["restrictions"]
216
+ self._user_push_restrictions = attributes["restrictions"]["users_url"]
217
+ self._team_push_restrictions = attributes["restrictions"]["teams_url"]
218
+ if "url" in attributes: # pragma no branch
219
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/CVSS.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from decimal import Decimal
43
+ from typing import Any, Dict
44
+
45
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
46
+
47
+
48
+ class CVSS(NonCompletableGithubObject):
49
+ """
50
+ This class represents a CVSS.
51
+
52
+ The reference can be found here
53
+ <https://docs.github.com/en/rest/security-advisories/global-advisories>
54
+
55
+ """
56
+
57
+ def _initAttributes(self) -> None:
58
+ self._score: Attribute[Decimal] = NotSet
59
+ self._vector_string: Attribute[str] = NotSet
60
+ self._version: Attribute[Decimal] = NotSet
61
+
62
+ @property
63
+ def score(self) -> Decimal:
64
+ return self._score.value
65
+
66
+ @property
67
+ def vector_string(self) -> str:
68
+ return self._vector_string.value
69
+
70
+ @property
71
+ def version(self) -> Decimal:
72
+ return self._version.value
73
+
74
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
75
+ if "score" in attributes and attributes["score"] is not None: # pragma no branch
76
+ # ensure string so we don't have all the float extra nonsense
77
+ self._score = self._makeDecimalAttribute(Decimal(str(attributes["score"])))
78
+ if "vector_string" in attributes and attributes["vector_string"] is not None: # pragma no branch
79
+ self._vector_string = self._makeStringAttribute(attributes["vector_string"])
80
+ self._version = self._makeDecimalAttribute(Decimal(self.vector_string.split(":")[1].split("/")[0]))
venv/lib/python3.10/site-packages/github/CWE.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+
42
+ from typing import Any, Dict
43
+
44
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
45
+
46
+
47
+ class CWE(CompletableGithubObject):
48
+ """
49
+ This class represents a CWE.
50
+
51
+ The reference can be found here
52
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
53
+
54
+ """
55
+
56
+ def _initAttributes(self) -> None:
57
+ self._cwe_id: Attribute[str] = NotSet
58
+ self._name: Attribute[str] = NotSet
59
+
60
+ @property
61
+ def cwe_id(self) -> str:
62
+ return self._cwe_id.value
63
+
64
+ @property
65
+ def name(self) -> str:
66
+ return self._name.value
67
+
68
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
69
+ if "cwe_id" in attributes: # pragma no branch
70
+ self._cwe_id = self._makeStringAttribute(attributes["cwe_id"])
71
+ if "name" in attributes: # pragma no branch
72
+ self._name = self._makeStringAttribute(attributes["name"])
venv/lib/python3.10/site-packages/github/CheckRun.py ADDED
@@ -0,0 +1,298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2020 Dhruv Manilawala <dhruvmanila@gmail.com> #
4
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
5
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
6
+ # Copyright 2021 majorvin <majorvin.tan@outlook.com> #
7
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
8
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
9
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
10
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
11
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
12
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
13
+ # #
14
+ # This file is part of PyGithub. #
15
+ # http://pygithub.readthedocs.io/ #
16
+ # #
17
+ # PyGithub is free software: you can redistribute it and/or modify it under #
18
+ # the terms of the GNU Lesser General Public License as published by the Free #
19
+ # Software Foundation, either version 3 of the License, or (at your option) #
20
+ # any later version. #
21
+ # #
22
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
23
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
24
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
25
+ # details. #
26
+ # #
27
+ # You should have received a copy of the GNU Lesser General Public License #
28
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
29
+ # #
30
+ ################################################################################
31
+
32
+ from __future__ import annotations
33
+
34
+ from datetime import datetime
35
+ from typing import TYPE_CHECKING, Any
36
+
37
+ import deprecated
38
+
39
+ import github.CheckRunAnnotation
40
+ import github.CheckRunOutput
41
+ import github.CheckSuite
42
+ import github.Deployment
43
+ import github.GithubApp
44
+ import github.GithubObject
45
+ import github.PullRequest
46
+ from github.GithubObject import (
47
+ Attribute,
48
+ CompletableGithubObject,
49
+ NotSet,
50
+ Opt,
51
+ is_defined,
52
+ is_optional,
53
+ is_optional_list,
54
+ )
55
+ from github.PaginatedList import PaginatedList
56
+
57
+ if TYPE_CHECKING:
58
+ from github.CheckRunAnnotation import CheckRunAnnotation
59
+ from github.CheckRunOutput import CheckRunOutput
60
+ from github.CheckSuite import CheckSuite
61
+ from github.Deployment import Deployment
62
+ from github.GithubApp import GithubApp
63
+ from github.PullRequest import PullRequest
64
+
65
+
66
+ class CheckRun(CompletableGithubObject):
67
+ """
68
+ This class represents check runs.
69
+
70
+ The reference can be found here
71
+ https://docs.github.com/en/rest/reference/checks#check-runs
72
+
73
+ The OpenAPI schema can be found at
74
+ - /components/schemas/check-run
75
+
76
+ """
77
+
78
+ def _initAttributes(self) -> None:
79
+ self._app: Attribute[GithubApp] = NotSet
80
+ self._check_suite: Attribute[CheckSuite] = NotSet
81
+ self._check_suite_id: Attribute[int] = NotSet
82
+ self._completed_at: Attribute[datetime | None] = NotSet
83
+ self._conclusion: Attribute[str] = NotSet
84
+ self._deployment: Attribute[Deployment] = NotSet
85
+ self._details_url: Attribute[str] = NotSet
86
+ self._external_id: Attribute[str] = NotSet
87
+ self._head_sha: Attribute[str] = NotSet
88
+ self._html_url: Attribute[str] = NotSet
89
+ self._id: Attribute[int] = NotSet
90
+ self._name: Attribute[str] = NotSet
91
+ self._node_id: Attribute[str] = NotSet
92
+ self._output: Attribute[github.CheckRunOutput.CheckRunOutput] = NotSet
93
+ self._pull_requests: Attribute[list[PullRequest]] = NotSet
94
+ self._started_at: Attribute[datetime] = NotSet
95
+ self._status: Attribute[str] = NotSet
96
+ self._url: Attribute[str] = NotSet
97
+
98
+ def __repr__(self) -> str:
99
+ return self.get__repr__({"id": self._id.value, "conclusion": self._conclusion.value})
100
+
101
+ @property
102
+ def app(self) -> GithubApp:
103
+ self._completeIfNotSet(self._app)
104
+ return self._app.value
105
+
106
+ @property
107
+ def check_suite(self) -> CheckSuite:
108
+ self._completeIfNotSet(self._check_suite)
109
+ return self._check_suite.value
110
+
111
+ @property
112
+ @deprecated.deprecated("Use property check_suite.id instead")
113
+ def check_suite_id(self) -> int:
114
+ self._completeIfNotSet(self._check_suite_id)
115
+ return self._check_suite_id.value
116
+
117
+ @property
118
+ def completed_at(self) -> datetime | None:
119
+ self._completeIfNotSet(self._completed_at)
120
+ return self._completed_at.value
121
+
122
+ @property
123
+ def conclusion(self) -> str:
124
+ self._completeIfNotSet(self._conclusion)
125
+ return self._conclusion.value
126
+
127
+ @property
128
+ def deployment(self) -> Deployment:
129
+ self._completeIfNotSet(self._deployment)
130
+ return self._deployment.value
131
+
132
+ @property
133
+ def details_url(self) -> str:
134
+ self._completeIfNotSet(self._details_url)
135
+ return self._details_url.value
136
+
137
+ @property
138
+ def external_id(self) -> str:
139
+ self._completeIfNotSet(self._external_id)
140
+ return self._external_id.value
141
+
142
+ @property
143
+ def head_sha(self) -> str:
144
+ self._completeIfNotSet(self._head_sha)
145
+ return self._head_sha.value
146
+
147
+ @property
148
+ def html_url(self) -> str:
149
+ self._completeIfNotSet(self._html_url)
150
+ return self._html_url.value
151
+
152
+ @property
153
+ def id(self) -> int:
154
+ self._completeIfNotSet(self._id)
155
+ return self._id.value
156
+
157
+ @property
158
+ def name(self) -> str:
159
+ self._completeIfNotSet(self._name)
160
+ return self._name.value
161
+
162
+ @property
163
+ def node_id(self) -> str:
164
+ self._completeIfNotSet(self._node_id)
165
+ return self._node_id.value
166
+
167
+ @property
168
+ def output(self) -> CheckRunOutput:
169
+ self._completeIfNotSet(self._output)
170
+ return self._output.value
171
+
172
+ @property
173
+ def pull_requests(self) -> list[PullRequest]:
174
+ self._completeIfNotSet(self._pull_requests)
175
+ return self._pull_requests.value
176
+
177
+ @property
178
+ def started_at(self) -> datetime:
179
+ self._completeIfNotSet(self._started_at)
180
+ return self._started_at.value
181
+
182
+ @property
183
+ def status(self) -> str:
184
+ self._completeIfNotSet(self._status)
185
+ return self._status.value
186
+
187
+ @property
188
+ def url(self) -> str:
189
+ return self._url.value
190
+
191
+ def get_annotations(self) -> PaginatedList[CheckRunAnnotation]:
192
+ """
193
+ :calls: `GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations <https://docs.github.com/en/rest/reference/checks#list-check-run-annotations>`_
194
+ """
195
+ return PaginatedList(
196
+ github.CheckRunAnnotation.CheckRunAnnotation,
197
+ self._requester,
198
+ f"{self.url}/annotations",
199
+ None,
200
+ headers={"Accept": "application/vnd.github.v3+json"},
201
+ )
202
+
203
+ def edit(
204
+ self,
205
+ name: Opt[str] = NotSet,
206
+ head_sha: Opt[str] = NotSet,
207
+ details_url: Opt[str] = NotSet,
208
+ external_id: Opt[str] = NotSet,
209
+ status: Opt[str] = NotSet,
210
+ started_at: Opt[datetime] = NotSet,
211
+ conclusion: Opt[str] = NotSet,
212
+ completed_at: Opt[datetime] = NotSet,
213
+ output: Opt[dict] = NotSet,
214
+ actions: Opt[list[dict]] = NotSet,
215
+ ) -> None:
216
+ """
217
+ :calls: `PATCH /repos/{owner}/{repo}/check-runs/{check_run_id} <https://docs.github.com/en/rest/reference/checks#update-a-check-run>`_
218
+ """
219
+ assert is_optional(name, str), name
220
+ assert is_optional(head_sha, str), head_sha
221
+ assert is_optional(details_url, str), details_url
222
+ assert is_optional(external_id, str), external_id
223
+ assert is_optional(status, str), status
224
+ assert is_optional(started_at, datetime), started_at
225
+ assert is_optional(conclusion, str), conclusion
226
+ assert is_optional(completed_at, datetime), completed_at
227
+ assert is_optional(output, dict), output
228
+ assert is_optional_list(actions, dict), actions
229
+
230
+ post_parameters: dict[str, Any] = {}
231
+ if is_defined(name):
232
+ post_parameters["name"] = name
233
+ if is_defined(head_sha):
234
+ post_parameters["head_sha"] = head_sha
235
+ if is_defined(details_url):
236
+ post_parameters["details_url"] = details_url
237
+ if is_defined(external_id):
238
+ post_parameters["external_id"] = external_id
239
+ if is_defined(status):
240
+ post_parameters["status"] = status
241
+ if is_defined(started_at):
242
+ post_parameters["started_at"] = started_at.strftime("%Y-%m-%dT%H:%M:%SZ")
243
+ if is_defined(completed_at):
244
+ post_parameters["completed_at"] = completed_at.strftime("%Y-%m-%dT%H:%M:%SZ")
245
+ if is_defined(conclusion):
246
+ post_parameters["conclusion"] = conclusion
247
+ if is_defined(output):
248
+ post_parameters["output"] = output
249
+ if is_defined(actions):
250
+ post_parameters["actions"] = actions
251
+
252
+ headers, data = self._requester.requestJsonAndCheck("PATCH", self.url, input=post_parameters)
253
+ self._useAttributes(data)
254
+
255
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
256
+ if "app" in attributes: # pragma no branch
257
+ self._app = self._makeClassAttribute(github.GithubApp.GithubApp, attributes["app"])
258
+ # This only gives us a dictionary with `id` attribute of `check_suite`
259
+ if "check_suite" in attributes and "id" in attributes["check_suite"]: # pragma no branch
260
+ id = attributes["check_suite"]["id"]
261
+ if "url" not in attributes["check_suite"] and "url" in attributes:
262
+ url = attributes["url"].split("/")[:-2] + ["check-suites", str(id)]
263
+ attributes["check_suite"]["url"] = "/".join(url)
264
+ self._check_suite = self._makeClassAttribute(github.CheckSuite.CheckSuite, attributes["check_suite"])
265
+ # deprecated check suite id property
266
+ self._check_suite_id = self._makeIntAttribute(id)
267
+ if "completed_at" in attributes: # pragma no branch
268
+ self._completed_at = self._makeDatetimeAttribute(attributes["completed_at"])
269
+ if "conclusion" in attributes: # pragma no branch
270
+ self._conclusion = self._makeStringAttribute(attributes["conclusion"])
271
+ if "deployment" in attributes: # pragma no branch
272
+ self._deployment = self._makeClassAttribute(github.Deployment.Deployment, attributes["deployment"])
273
+ if "details_url" in attributes: # pragma no branch
274
+ self._details_url = self._makeStringAttribute(attributes["details_url"])
275
+ if "external_id" in attributes: # pragma no branch
276
+ self._external_id = self._makeStringAttribute(attributes["external_id"])
277
+ if "head_sha" in attributes: # pragma no branch
278
+ self._head_sha = self._makeStringAttribute(attributes["head_sha"])
279
+ if "html_url" in attributes: # pragma no branch
280
+ self._html_url = self._makeStringAttribute(attributes["html_url"])
281
+ if "id" in attributes: # pragma no branch
282
+ self._id = self._makeIntAttribute(attributes["id"])
283
+ if "name" in attributes: # pragma no branch
284
+ self._name = self._makeStringAttribute(attributes["name"])
285
+ if "node_id" in attributes: # pragma no branch
286
+ self._node_id = self._makeStringAttribute(attributes["node_id"])
287
+ if "output" in attributes: # pragma no branch
288
+ self._output = self._makeClassAttribute(github.CheckRunOutput.CheckRunOutput, attributes["output"])
289
+ if "pull_requests" in attributes: # pragma no branch
290
+ self._pull_requests = self._makeListOfClassesAttribute(
291
+ github.PullRequest.PullRequest, attributes["pull_requests"]
292
+ )
293
+ if "started_at" in attributes: # pragma no branch
294
+ self._started_at = self._makeDatetimeAttribute(attributes["started_at"])
295
+ if "status" in attributes: # pragma no branch
296
+ self._status = self._makeStringAttribute(attributes["status"])
297
+ if "url" in attributes: # pragma no branch
298
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/CheckRunAnnotation.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2020 Dhruv Manilawala <dhruvmanila@gmail.com> #
4
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
5
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
6
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
7
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
8
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
9
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
10
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
11
+ # #
12
+ # This file is part of PyGithub. #
13
+ # http://pygithub.readthedocs.io/ #
14
+ # #
15
+ # PyGithub is free software: you can redistribute it and/or modify it under #
16
+ # the terms of the GNU Lesser General Public License as published by the Free #
17
+ # Software Foundation, either version 3 of the License, or (at your option) #
18
+ # any later version. #
19
+ # #
20
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
22
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
23
+ # details. #
24
+ # #
25
+ # You should have received a copy of the GNU Lesser General Public License #
26
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
27
+ # #
28
+ ################################################################################
29
+
30
+ from __future__ import annotations
31
+
32
+ from typing import Any
33
+
34
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
35
+
36
+
37
+ class CheckRunAnnotation(NonCompletableGithubObject):
38
+ """
39
+ This class represents check run annotations.
40
+
41
+ The reference can be found here: https://docs.github.com/en/rest/reference/checks#list-check-run-annotations
42
+
43
+ The OpenAPI schema can be found at
44
+ - /components/schemas/check-annotation
45
+
46
+ """
47
+
48
+ def _initAttributes(self) -> None:
49
+ self._annotation_level: Attribute[str] = NotSet
50
+ self._blob_href: Attribute[str] = NotSet
51
+ self._end_column: Attribute[int] = NotSet
52
+ self._end_line: Attribute[int] = NotSet
53
+ self._message: Attribute[str] = NotSet
54
+ self._path: Attribute[str] = NotSet
55
+ self._raw_details: Attribute[str] = NotSet
56
+ self._start_column: Attribute[int] = NotSet
57
+ self._start_line: Attribute[int] = NotSet
58
+ self._title: Attribute[str] = NotSet
59
+
60
+ def __repr__(self) -> str:
61
+ return self.get__repr__({"title": self._title.value})
62
+
63
+ @property
64
+ def annotation_level(self) -> str:
65
+ return self._annotation_level.value
66
+
67
+ @property
68
+ def blob_href(self) -> str:
69
+ return self._blob_href.value
70
+
71
+ @property
72
+ def end_column(self) -> int:
73
+ return self._end_column.value
74
+
75
+ @property
76
+ def end_line(self) -> int:
77
+ return self._end_line.value
78
+
79
+ @property
80
+ def message(self) -> str:
81
+ return self._message.value
82
+
83
+ @property
84
+ def path(self) -> str:
85
+ return self._path.value
86
+
87
+ @property
88
+ def raw_details(self) -> str:
89
+ return self._raw_details.value
90
+
91
+ @property
92
+ def start_column(self) -> int:
93
+ return self._start_column.value
94
+
95
+ @property
96
+ def start_line(self) -> int:
97
+ return self._start_line.value
98
+
99
+ @property
100
+ def title(self) -> str:
101
+ return self._title.value
102
+
103
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
104
+ if "annotation_level" in attributes: # pragma no branch
105
+ self._annotation_level = self._makeStringAttribute(attributes["annotation_level"])
106
+ if "blob_href" in attributes: # pragma no branch
107
+ self._blob_href = self._makeStringAttribute(attributes["blob_href"])
108
+ if "end_column" in attributes: # pragma no branch
109
+ self._end_column = self._makeIntAttribute(attributes["end_column"])
110
+ if "end_line" in attributes: # pragma no branch
111
+ self._end_line = self._makeIntAttribute(attributes["end_line"])
112
+ if "message" in attributes: # pragma no branch
113
+ self._message = self._makeStringAttribute(attributes["message"])
114
+ if "path" in attributes: # pragma no branch
115
+ self._path = self._makeStringAttribute(attributes["path"])
116
+ if "raw_details" in attributes: # pragma no branch
117
+ self._raw_details = self._makeStringAttribute(attributes["raw_details"])
118
+ if "start_column" in attributes: # pragma no branch
119
+ self._start_column = self._makeIntAttribute(attributes["start_column"])
120
+ if "start_line" in attributes: # pragma no branch
121
+ self._start_line = self._makeIntAttribute(attributes["start_line"])
122
+ if "title" in attributes: # pragma no branch
123
+ self._title = self._makeStringAttribute(attributes["title"])
venv/lib/python3.10/site-packages/github/CheckRunOutput.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Dhruv Manilawala <dhruvmanila@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from typing import Any, Dict
42
+
43
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
44
+
45
+
46
+ class CheckRunOutput(NonCompletableGithubObject):
47
+ """
48
+ This class represents the output of check run.
49
+
50
+ The OpenAPI schema can be found at
51
+ - /components/schemas/check-run/properties/output
52
+
53
+ """
54
+
55
+ def _initAttributes(self) -> None:
56
+ self._annotations_count: Attribute[int] = NotSet
57
+ self._annotations_url: Attribute[str] = NotSet
58
+ self._summary: Attribute[str] = NotSet
59
+ self._text: Attribute[str] = NotSet
60
+ self._title: Attribute[str] = NotSet
61
+
62
+ def __repr__(self) -> str:
63
+ return self.get__repr__({"title": self._title.value})
64
+
65
+ @property
66
+ def annotations_count(self) -> int:
67
+ return self._annotations_count.value
68
+
69
+ @property
70
+ def annotations_url(self) -> str:
71
+ return self._annotations_url.value
72
+
73
+ @property
74
+ def summary(self) -> str:
75
+ return self._summary.value
76
+
77
+ @property
78
+ def text(self) -> str:
79
+ return self._text.value
80
+
81
+ @property
82
+ def title(self) -> str:
83
+ return self._title.value
84
+
85
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
86
+ if "annotations_count" in attributes: # pragma no branch
87
+ self._annotations_count = self._makeIntAttribute(attributes["annotations_count"])
88
+ if "annotations_url" in attributes: # pragma no branch
89
+ self._annotations_url = self._makeStringAttribute(attributes["annotations_url"])
90
+ if "summary" in attributes: # pragma no branch
91
+ self._summary = self._makeStringAttribute(attributes["summary"])
92
+ if "text" in attributes: # pragma no branch
93
+ self._text = self._makeStringAttribute(attributes["text"])
94
+ if "title" in attributes: # pragma no branch
95
+ self._title = self._makeStringAttribute(attributes["title"])
venv/lib/python3.10/site-packages/github/CheckSuite.py ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2020 Dhruv Manilawala <dhruvmanila@gmail.com> #
4
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
5
+ # Copyright 2020 Yannick Jadoul <yannick.jadoul@belgacom.net> #
6
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
7
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
8
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
9
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
10
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
11
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
12
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
13
+ # #
14
+ # This file is part of PyGithub. #
15
+ # http://pygithub.readthedocs.io/ #
16
+ # #
17
+ # PyGithub is free software: you can redistribute it and/or modify it under #
18
+ # the terms of the GNU Lesser General Public License as published by the Free #
19
+ # Software Foundation, either version 3 of the License, or (at your option) #
20
+ # any later version. #
21
+ # #
22
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
23
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
24
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
25
+ # details. #
26
+ # #
27
+ # You should have received a copy of the GNU Lesser General Public License #
28
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
29
+ # #
30
+ ################################################################################
31
+
32
+ from __future__ import annotations
33
+
34
+ from datetime import datetime
35
+ from typing import TYPE_CHECKING, Any
36
+
37
+ import github.CheckRun
38
+ import github.GitCommit
39
+ import github.GithubApp
40
+ import github.PullRequest
41
+ import github.Repository
42
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet, Opt, is_defined, is_optional
43
+ from github.PaginatedList import PaginatedList
44
+
45
+ if TYPE_CHECKING:
46
+ from github.CheckRun import CheckRun
47
+ from github.GitCommit import GitCommit
48
+ from github.GithubApp import GithubApp
49
+ from github.PullRequest import PullRequest
50
+ from github.Repository import Repository
51
+
52
+
53
+ class CheckSuite(CompletableGithubObject):
54
+ """
55
+ This class represents check suites.
56
+
57
+ The reference can be found here
58
+ https://docs.github.com/en/rest/reference/checks#check-suites
59
+
60
+ The OpenAPI schema can be found at
61
+ - /components/schemas/check-run/properties/check_suite
62
+ - /components/schemas/check-suite
63
+
64
+ """
65
+
66
+ def _initAttributes(self) -> None:
67
+ self._after: Attribute[str] = NotSet
68
+ self._app: Attribute[GithubApp] = NotSet
69
+ self._before: Attribute[str] = NotSet
70
+ self._check_runs_url: Attribute[str] = NotSet
71
+ self._conclusion: Attribute[str] = NotSet
72
+ self._created_at: Attribute[datetime] = NotSet
73
+ self._head_branch: Attribute[str] = NotSet
74
+ self._head_commit: Attribute[GitCommit] = NotSet
75
+ self._head_sha: Attribute[str] = NotSet
76
+ self._id: Attribute[int] = NotSet
77
+ self._latest_check_runs_count: Attribute[int] = NotSet
78
+ self._node_id: Attribute[str] = NotSet
79
+ self._pull_requests: Attribute[list[PullRequest]] = NotSet
80
+ self._repository: Attribute[Repository] = NotSet
81
+ self._rerequestable: Attribute[bool] = NotSet
82
+ self._runs_rerequestable: Attribute[bool] = NotSet
83
+ self._status: Attribute[str] = NotSet
84
+ self._updated_at: Attribute[datetime] = NotSet
85
+ self._url: Attribute[str] = NotSet
86
+
87
+ def __repr__(self) -> str:
88
+ return self.get__repr__({"id": self._id.value, "url": self._url.value})
89
+
90
+ @property
91
+ def after(self) -> str:
92
+ """
93
+ :type: string
94
+ """
95
+ self._completeIfNotSet(self._after)
96
+ return self._after.value
97
+
98
+ @property
99
+ def app(self) -> GithubApp:
100
+ """
101
+ :type: :class:`github.GithubApp.GithubApp`
102
+ """
103
+ self._completeIfNotSet(self._app)
104
+ return self._app.value
105
+
106
+ @property
107
+ def before(self) -> str:
108
+ """
109
+ :type: string
110
+ """
111
+ self._completeIfNotSet(self._before)
112
+ return self._before.value
113
+
114
+ @property
115
+ def check_runs_url(self) -> str:
116
+ """
117
+ :type: string
118
+ """
119
+ self._completeIfNotSet(self._check_runs_url)
120
+ return self._check_runs_url.value
121
+
122
+ @property
123
+ def conclusion(self) -> str:
124
+ """
125
+ :type: string
126
+ """
127
+ self._completeIfNotSet(self._conclusion)
128
+ return self._conclusion.value
129
+
130
+ @property
131
+ def created_at(self) -> datetime:
132
+ """
133
+ :type: datetime.datetime
134
+ """
135
+ self._completeIfNotSet(self._created_at)
136
+ return self._created_at.value
137
+
138
+ @property
139
+ def head_branch(self) -> str:
140
+ """
141
+ :type: string
142
+ """
143
+ self._completeIfNotSet(self._head_branch)
144
+ return self._head_branch.value
145
+
146
+ @property
147
+ def head_commit(self) -> GitCommit:
148
+ """
149
+ :type: :class:`github.GitCommit.GitCommit`
150
+ """
151
+ self._completeIfNotSet(self._head_commit)
152
+ return self._head_commit.value
153
+
154
+ @property
155
+ def head_sha(self) -> str:
156
+ """
157
+ :type: string
158
+ """
159
+ self._completeIfNotSet(self._head_sha)
160
+ return self._head_sha.value
161
+
162
+ @property
163
+ def id(self) -> int:
164
+ """
165
+ :type: int
166
+ """
167
+ self._completeIfNotSet(self._id)
168
+ return self._id.value
169
+
170
+ @property
171
+ def latest_check_runs_count(self) -> int:
172
+ """
173
+ :type: int
174
+ """
175
+ self._completeIfNotSet(self._latest_check_runs_count)
176
+ return self._latest_check_runs_count.value
177
+
178
+ @property
179
+ def node_id(self) -> str:
180
+ self._completeIfNotSet(self._node_id)
181
+ return self._node_id.value
182
+
183
+ @property
184
+ def pull_requests(self) -> list[PullRequest]:
185
+ """
186
+ :type: list of :class:`github.PullRequest.PullRequest`
187
+ """
188
+ self._completeIfNotSet(self._pull_requests)
189
+ return self._pull_requests.value
190
+
191
+ @property
192
+ def repository(self) -> Repository:
193
+ """
194
+ :type: :class:`github.Repository.Repository`
195
+ """
196
+ self._completeIfNotSet(self._repository)
197
+ return self._repository.value
198
+
199
+ @property
200
+ def rerequestable(self) -> bool:
201
+ self._completeIfNotSet(self._rerequestable)
202
+ return self._rerequestable.value
203
+
204
+ @property
205
+ def runs_rerequestable(self) -> bool:
206
+ self._completeIfNotSet(self._runs_rerequestable)
207
+ return self._runs_rerequestable.value
208
+
209
+ @property
210
+ def status(self) -> str:
211
+ """
212
+ :type: string
213
+ """
214
+ self._completeIfNotSet(self._status)
215
+ return self._status.value
216
+
217
+ @property
218
+ def updated_at(self) -> datetime:
219
+ """
220
+ :type: datetime.datetime
221
+ """
222
+ self._completeIfNotSet(self._updated_at)
223
+ return self._updated_at.value
224
+
225
+ @property
226
+ def url(self) -> str:
227
+ """
228
+ :type: string
229
+ """
230
+ return self._url.value
231
+
232
+ def rerequest(self) -> bool:
233
+ """
234
+ :calls: `POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest <https://docs.github.com/en/rest/reference/checks#rerequest-a-check-suite>`_
235
+ :rtype: bool
236
+ """
237
+ request_headers = {"Accept": "application/vnd.github.v3+json"}
238
+ status, _, _ = self._requester.requestJson("POST", f"{self.url}/rerequest", headers=request_headers)
239
+ return status == 201
240
+
241
+ def get_check_runs(
242
+ self,
243
+ check_name: Opt[str] = NotSet,
244
+ status: Opt[str] = NotSet,
245
+ filter: Opt[str] = NotSet,
246
+ ) -> PaginatedList[CheckRun]:
247
+ """
248
+ :calls: `GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs <https://docs.github.com/en/rest/reference/checks#list-check-runs-in-a-check-suite>`_
249
+ """
250
+ assert is_optional(check_name, str), check_name
251
+ assert is_optional(status, str), status
252
+ assert is_optional(filter, str), filter
253
+ url_parameters: dict[str, Any] = {}
254
+ if is_defined(check_name):
255
+ url_parameters["check_name"] = check_name
256
+ if is_defined(status):
257
+ url_parameters["status"] = status
258
+ if is_defined(filter):
259
+ url_parameters["filter"] = filter
260
+ return PaginatedList(
261
+ github.CheckRun.CheckRun,
262
+ self._requester,
263
+ f"{self.url}/check-runs",
264
+ url_parameters,
265
+ headers={"Accept": "application/vnd.github.v3+json"},
266
+ list_item="check_runs",
267
+ )
268
+
269
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
270
+ if "after" in attributes: # pragma no branch
271
+ self._after = self._makeStringAttribute(attributes["after"])
272
+ if "app" in attributes: # pragma no branch
273
+ self._app = self._makeClassAttribute(github.GithubApp.GithubApp, attributes["app"])
274
+ if "before" in attributes: # pragma no branch
275
+ self._before = self._makeStringAttribute(attributes["before"])
276
+ if "check_runs_url" in attributes: # pragma no branch
277
+ self._check_runs_url = self._makeStringAttribute(attributes["check_runs_url"])
278
+ if "conclusion" in attributes: # pragma no branch
279
+ self._conclusion = self._makeStringAttribute(attributes["conclusion"])
280
+ if "created_at" in attributes: # pragma no branch
281
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
282
+ if "head_branch" in attributes: # pragma no branch
283
+ self._head_branch = self._makeStringAttribute(attributes["head_branch"])
284
+ if "head_commit" in attributes: # pragma no branch
285
+ # This JSON swaps the 'sha' attribute for an 'id' attribute.
286
+ # The GitCommit object only looks for 'sha'
287
+ if "id" in attributes["head_commit"]:
288
+ attributes["head_commit"]["sha"] = attributes["head_commit"]["id"]
289
+ self._head_commit = self._makeClassAttribute(github.GitCommit.GitCommit, attributes["head_commit"])
290
+ if "head_sha" in attributes: # pragma no branch
291
+ self._head_sha = self._makeStringAttribute(attributes["head_sha"])
292
+ if "id" in attributes: # pragma no branch
293
+ self._id = self._makeIntAttribute(attributes["id"])
294
+ if "latest_check_runs_count" in attributes: # pragma no branch
295
+ self._latest_check_runs_count = self._makeIntAttribute(attributes["latest_check_runs_count"])
296
+ if "node_id" in attributes: # pragma no branch
297
+ self._node_id = self._makeStringAttribute(attributes["node_id"])
298
+ if "pull_requests" in attributes: # pragma no branch
299
+ self._pull_requests = self._makeListOfClassesAttribute(
300
+ github.PullRequest.PullRequest, attributes["pull_requests"]
301
+ )
302
+ if "repository" in attributes: # pragma no branch
303
+ self._repository = self._makeClassAttribute(github.Repository.Repository, attributes["repository"])
304
+ if "rerequestable" in attributes: # pragma no branch
305
+ self._rerequestable = self._makeBoolAttribute(attributes["rerequestable"])
306
+ if "runs_rerequestable" in attributes: # pragma no branch
307
+ self._runs_rerequestable = self._makeBoolAttribute(attributes["runs_rerequestable"])
308
+ if "status" in attributes: # pragma no branch
309
+ self._status = self._makeStringAttribute(attributes["status"])
310
+ if "updated_at" in attributes: # pragma no branch
311
+ self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
312
+ if "url" in attributes: # pragma no branch
313
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/Clones.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Justin Kufro <jkufro@andrew.cmu.edu> #
11
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
12
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
13
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from __future__ import annotations
42
+
43
+ from typing import TYPE_CHECKING, Any
44
+
45
+ import github.Traffic
46
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
47
+
48
+ if TYPE_CHECKING:
49
+ from github.Traffic import Traffic
50
+
51
+
52
+ class Clones(NonCompletableGithubObject):
53
+ """
54
+ This class represents the total number of clones and breakdown per day or week for a GitHub repository.
55
+
56
+ The reference can be found here
57
+ https://docs.github.com/en/rest/metrics/traffic#get-repository-clones
58
+
59
+ The OpenAPI schema can be found at
60
+ - /components/schemas/clone-traffic
61
+
62
+ """
63
+
64
+ def _initAttributes(self) -> None:
65
+ self._clones: Attribute[list[Traffic]] = NotSet
66
+ self._count: Attribute[int] = NotSet
67
+ self._uniques: Attribute[int] = NotSet
68
+
69
+ def __repr__(self) -> str:
70
+ return self.get__repr__(
71
+ {
72
+ "count": self._count.value,
73
+ "uniques": self._uniques.value,
74
+ }
75
+ )
76
+
77
+ @property
78
+ def clones(self) -> list[Traffic]:
79
+ return self._clones.value
80
+
81
+ @property
82
+ def count(self) -> int:
83
+ return self._count.value
84
+
85
+ @property
86
+ def uniques(self) -> int:
87
+ return self._uniques.value
88
+
89
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
90
+ if "clones" in attributes: # pragma no branch
91
+ self._clones = self._makeListOfClassesAttribute(github.Traffic.Traffic, attributes["clones"])
92
+ if "count" in attributes: # pragma no branch
93
+ self._count = self._makeIntAttribute(attributes["count"])
94
+ if "uniques" in attributes: # pragma no branch
95
+ self._uniques = self._makeIntAttribute(attributes["uniques"])
venv/lib/python3.10/site-packages/github/CodeScanAlert.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
4
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
5
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
6
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
7
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
8
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
9
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
10
+ # #
11
+ # This file is part of PyGithub. #
12
+ # http://pygithub.readthedocs.io/ #
13
+ # #
14
+ # PyGithub is free software: you can redistribute it and/or modify it under #
15
+ # the terms of the GNU Lesser General Public License as published by the Free #
16
+ # Software Foundation, either version 3 of the License, or (at your option) #
17
+ # any later version. #
18
+ # #
19
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
20
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
21
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
22
+ # details. #
23
+ # #
24
+ # You should have received a copy of the GNU Lesser General Public License #
25
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
26
+ # #
27
+ ################################################################################
28
+
29
+ from __future__ import annotations
30
+
31
+ from datetime import datetime
32
+ from typing import Any
33
+
34
+ import github.CodeScanAlertInstance
35
+ import github.CodeScanRule
36
+ import github.CodeScanTool
37
+ import github.GithubObject
38
+ import github.NamedUser
39
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
40
+ from github.PaginatedList import PaginatedList
41
+
42
+
43
+ class CodeScanAlert(NonCompletableGithubObject):
44
+ """
45
+ This class represents alerts from code scanning.
46
+
47
+ The reference can be found here
48
+ https://docs.github.com/en/rest/reference/code-scanning.
49
+
50
+ """
51
+
52
+ def _initAttributes(self) -> None:
53
+ self._created_at: Attribute[datetime] = NotSet
54
+ self._dismissed_at: Attribute[datetime | None] = NotSet
55
+ self._dismissed_by: Attribute[github.NamedUser.NamedUser | None] = NotSet
56
+ self._dismissed_reason: Attribute[str | None] = NotSet
57
+ self._html_url: Attribute[str] = NotSet
58
+ self._instances_url: Attribute[str] = NotSet
59
+ self._most_recent_instance: Attribute[github.CodeScanAlertInstance.CodeScanAlertInstance] = NotSet
60
+ self._number: Attribute[int] = NotSet
61
+ self._rule: Attribute[github.CodeScanRule.CodeScanRule] = NotSet
62
+ self._state: Attribute[str] = NotSet
63
+ self._tool: Attribute[github.CodeScanTool.CodeScanTool] = NotSet
64
+ self._url: Attribute[str] = NotSet
65
+
66
+ def __repr__(self) -> str:
67
+ return self.get__repr__({"number": self.number})
68
+
69
+ @property
70
+ def created_at(self) -> datetime:
71
+ return self._created_at.value
72
+
73
+ @property
74
+ def dismissed_at(self) -> datetime | None:
75
+ return self._dismissed_at.value
76
+
77
+ @property
78
+ def dismissed_by(self) -> github.NamedUser.NamedUser | None:
79
+ return self._dismissed_by.value
80
+
81
+ @property
82
+ def dismissed_reason(self) -> str | None:
83
+ return self._dismissed_reason.value
84
+
85
+ @property
86
+ def html_url(self) -> str:
87
+ return self._html_url.value
88
+
89
+ @property
90
+ def instances_url(self) -> str:
91
+ return self._instances_url.value
92
+
93
+ @property
94
+ def most_recent_instance(self) -> github.CodeScanAlertInstance.CodeScanAlertInstance:
95
+ return self._most_recent_instance.value
96
+
97
+ @property
98
+ def number(self) -> int:
99
+ return self._number.value
100
+
101
+ @property
102
+ def rule(self) -> github.CodeScanRule.CodeScanRule:
103
+ return self._rule.value
104
+
105
+ @property
106
+ def state(self) -> str:
107
+ return self._state.value
108
+
109
+ @property
110
+ def tool(self) -> github.CodeScanTool.CodeScanTool:
111
+ return self._tool.value
112
+
113
+ @property
114
+ def url(self) -> str:
115
+ return self._url.value
116
+
117
+ def get_instances(self) -> PaginatedList[github.CodeScanAlertInstance.CodeScanAlertInstance]:
118
+ """
119
+ Get instances.
120
+
121
+ :calls: `GET` on the URL for instances as provided by Github.
122
+
123
+ """
124
+ return PaginatedList(
125
+ github.CodeScanAlertInstance.CodeScanAlertInstance,
126
+ self._requester,
127
+ self.instances_url,
128
+ None,
129
+ )
130
+
131
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
132
+ if "created_at" in attributes: # pragma no branch
133
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
134
+ if "dismissed_at" in attributes: # pragma no branch
135
+ self._dismissed_at = self._makeDatetimeAttribute(attributes["dismissed_at"])
136
+ if "dismissed_by" in attributes: # pragma no branch
137
+ self._dismissed_by = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["dismissed_by"])
138
+ if "dismissed_reason" in attributes: # pragma no branch
139
+ self._dismissed_reason = self._makeStringAttribute(attributes["dismissed_reason"])
140
+ if "html_url" in attributes: # pragma no branch
141
+ self._html_url = self._makeStringAttribute(attributes["html_url"])
142
+ if "instances_url" in attributes: # pragma no branch
143
+ self._instances_url = self._makeStringAttribute(attributes["instances_url"])
144
+
145
+ if "most_recent_instance" in attributes: # pragma no branch
146
+ self._most_recent_instance = self._makeClassAttribute(
147
+ github.CodeScanAlertInstance.CodeScanAlertInstance,
148
+ attributes["most_recent_instance"],
149
+ )
150
+ if "number" in attributes: # pragma no branch
151
+ self._number = self._makeIntAttribute(attributes["number"])
152
+ if "rule" in attributes: # pragma no branch
153
+ self._rule = self._makeClassAttribute(github.CodeScanRule.CodeScanRule, attributes["rule"])
154
+ if "state" in attributes: # pragma no branch
155
+ self._state = self._makeStringAttribute(attributes["state"])
156
+ if "tool" in attributes: # pragma no branch
157
+ self._tool = self._makeClassAttribute(github.CodeScanTool.CodeScanTool, attributes["tool"])
158
+
159
+ if "url" in attributes: # pragma no branch
160
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/PullRequestMergeStatus.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2013 martinqt <m.ki2@laposte.net> #
8
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
9
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
10
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
11
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
12
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
13
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
17
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
18
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from typing import Any, Dict
42
+
43
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
44
+
45
+
46
+ class PullRequestMergeStatus(NonCompletableGithubObject):
47
+ """
48
+ This class represents PullRequestMergeStatuses.
49
+
50
+ The reference can be found here
51
+ https://docs.github.com/en/rest/reference/pulls#check-if-a-pull-request-has-been-merged
52
+
53
+ """
54
+
55
+ def _initAttributes(self) -> None:
56
+ self._merged: Attribute[bool] = NotSet
57
+ self._message: Attribute[str] = NotSet
58
+ self._sha: Attribute[str] = NotSet
59
+
60
+ def __repr__(self) -> str:
61
+ return self.get__repr__({"sha": self._sha.value, "merged": self._merged.value})
62
+
63
+ @property
64
+ def merged(self) -> bool:
65
+ return self._merged.value
66
+
67
+ @property
68
+ def message(self) -> str:
69
+ return self._message.value
70
+
71
+ @property
72
+ def sha(self) -> str:
73
+ return self._sha.value
74
+
75
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
76
+ if "merged" in attributes: # pragma no branch
77
+ self._merged = self._makeBoolAttribute(attributes["merged"])
78
+ if "message" in attributes: # pragma no branch
79
+ self._message = self._makeStringAttribute(attributes["message"])
80
+ if "sha" in attributes: # pragma no branch
81
+ self._sha = self._makeStringAttribute(attributes["sha"])
venv/lib/python3.10/site-packages/github/RateLimit.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
6
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
8
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
9
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
10
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
11
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
12
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
13
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Bill Napier <napier@pobox.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from __future__ import annotations
43
+
44
+ from typing import TYPE_CHECKING, Any
45
+
46
+ import github.Rate
47
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
48
+
49
+ if TYPE_CHECKING:
50
+ from github.Rate import Rate
51
+
52
+
53
+ class RateLimit(NonCompletableGithubObject):
54
+ """
55
+ This class represents RateLimits.
56
+
57
+ The reference can be found here
58
+ https://docs.github.com/en/rest/reference/rate-limit
59
+
60
+ The OpenAPI schema can be found at
61
+ - /components/schemas/rate-limit-overview/properties/resources
62
+
63
+ """
64
+
65
+ def _initAttributes(self) -> None:
66
+ self._actions_runner_registration: Attribute[Rate] = NotSet
67
+ self._code_scanning_upload: Attribute[Rate] = NotSet
68
+ self._code_search: Attribute[Rate] = NotSet
69
+ self._core: Attribute[Rate] = NotSet
70
+ self._dependency_snapshots: Attribute[Rate] = NotSet
71
+ self._graphql: Attribute[Rate] = NotSet
72
+ self._integration_manifest: Attribute[Rate] = NotSet
73
+ self._scim: Attribute[Rate] = NotSet
74
+ self._search: Attribute[Rate] = NotSet
75
+ self._source_import: Attribute[Rate] = NotSet
76
+
77
+ def __repr__(self) -> str:
78
+ return self.get__repr__({"core": self._core.value})
79
+
80
+ @property
81
+ def actions_runner_registration(self) -> Rate:
82
+ """
83
+ Rate limit for registering self-hosted runners in GitHub Actions.
84
+ """
85
+ return self._actions_runner_registration.value
86
+
87
+ @property
88
+ def code_scanning_upload(self) -> Rate:
89
+ """
90
+ Rate limit for uploading SARIF results to code scanning.
91
+ """
92
+ return self._code_scanning_upload.value
93
+
94
+ @property
95
+ def code_search(self) -> Rate:
96
+ """
97
+ Rate limit for the REST API for searching code.
98
+ """
99
+ return self._code_search.value
100
+
101
+ @property
102
+ def core(self) -> Rate:
103
+ """
104
+ Rate limit for the non-search-related API.
105
+ """
106
+ return self._core.value
107
+
108
+ @property
109
+ def dependency_snapshots(self) -> Rate:
110
+ """
111
+ Rate limit for submitting snapshots to the dependency graph.
112
+ """
113
+ return self._dependency_snapshots.value
114
+
115
+ @property
116
+ def graphql(self) -> Rate:
117
+ """
118
+ (Experimental) Rate limit for GraphQL API, use with caution.
119
+ """
120
+ return self._graphql.value
121
+
122
+ @property
123
+ def integration_manifest(self) -> Rate:
124
+ """
125
+ Rate limit for POST /app-manifests/{code}/conversions operation.
126
+ """
127
+ return self._integration_manifest.value
128
+
129
+ @property
130
+ def scim(self) -> github.Rate.Rate:
131
+ return self._scim.value
132
+
133
+ @property
134
+ def search(self) -> Rate:
135
+ """
136
+ Rate limit for the Search API.
137
+ """
138
+ return self._search.value
139
+
140
+ @property
141
+ def source_import(self) -> github.Rate.Rate:
142
+ return self._source_import.value
143
+
144
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
145
+ if "actions_runner_registration" in attributes: # pragma no branch
146
+ self._actions_runner_registration = self._makeClassAttribute(
147
+ github.Rate.Rate, attributes["actions_runner_registration"]
148
+ )
149
+ if "code_scanning_upload" in attributes: # pragma no branch
150
+ self._code_scanning_upload = self._makeClassAttribute(github.Rate.Rate, attributes["code_scanning_upload"])
151
+ if "code_search" in attributes: # pragma no branch
152
+ self._code_search = self._makeClassAttribute(github.Rate.Rate, attributes["code_search"])
153
+ if "core" in attributes: # pragma no branch
154
+ self._core = self._makeClassAttribute(github.Rate.Rate, attributes["core"])
155
+ if "dependency_snapshots" in attributes: # pragma no branch
156
+ self._dependency_snapshots = self._makeClassAttribute(github.Rate.Rate, attributes["dependency_snapshots"])
157
+ if "graphql" in attributes: # pragma no branch
158
+ self._graphql = self._makeClassAttribute(github.Rate.Rate, attributes["graphql"])
159
+ if "integration_manifest" in attributes: # pragma no branch
160
+ self._integration_manifest = self._makeClassAttribute(github.Rate.Rate, attributes["integration_manifest"])
161
+ if "scim" in attributes: # pragma no branch
162
+ self._scim = self._makeClassAttribute(github.Rate.Rate, attributes["scim"])
163
+ if "search" in attributes: # pragma no branch
164
+ self._search = self._makeClassAttribute(github.Rate.Rate, attributes["search"])
165
+ if "source_import" in attributes: # pragma no branch
166
+ self._source_import = self._makeClassAttribute(github.Rate.Rate, attributes["source_import"])
venv/lib/python3.10/site-packages/github/Reaction.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2017 Nicolas Agustín Torres <nicolastrres@gmail.com> #
11
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
12
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
13
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
17
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
18
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
20
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
21
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
22
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from __future__ import annotations
43
+
44
+ from datetime import datetime
45
+ from typing import TYPE_CHECKING, Any
46
+
47
+ import github.NamedUser
48
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
49
+
50
+ from . import Consts
51
+
52
+ if TYPE_CHECKING:
53
+ from github.NamedUser import NamedUser
54
+
55
+
56
+ class Reaction(CompletableGithubObject):
57
+ """
58
+ This class represents Reactions.
59
+
60
+ The reference can be found here
61
+ https://docs.github.com/en/rest/reference/reactions
62
+
63
+ """
64
+
65
+ def _initAttributes(self) -> None:
66
+ self._content: Attribute[str] = NotSet
67
+ self._created_at: Attribute[datetime] = NotSet
68
+ self._id: Attribute[int] = NotSet
69
+ self._user: Attribute[NamedUser] = NotSet
70
+
71
+ def __repr__(self) -> str:
72
+ return self.get__repr__({"id": self._id.value, "user": self._user.value})
73
+
74
+ @property
75
+ def content(self) -> str:
76
+ self._completeIfNotSet(self._content)
77
+ return self._content.value
78
+
79
+ @property
80
+ def created_at(self) -> datetime:
81
+ self._completeIfNotSet(self._created_at)
82
+ return self._created_at.value
83
+
84
+ @property
85
+ def id(self) -> int:
86
+ self._completeIfNotSet(self._id)
87
+ return self._id.value
88
+
89
+ @property
90
+ def user(self) -> NamedUser:
91
+ self._completeIfNotSet(self._user)
92
+ return self._user.value
93
+
94
+ def delete(self) -> None:
95
+ """
96
+ :calls: `DELETE /reactions/{id} <https://docs.github.com/en/rest/reference/reactions#delete-a-reaction-legacy>`_
97
+ :rtype: None
98
+ """
99
+ self._requester.requestJsonAndCheck(
100
+ "DELETE",
101
+ f"{self._parentUrl('')}/reactions/{self.id}",
102
+ headers={"Accept": Consts.mediaTypeReactionsPreview},
103
+ )
104
+
105
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
106
+ if "content" in attributes: # pragma no branch
107
+ self._content = self._makeStringAttribute(attributes["content"])
108
+ if "created_at" in attributes: # pragma no branch
109
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
110
+ if "id" in attributes: # pragma no branch
111
+ self._id = self._makeIntAttribute(attributes["id"])
112
+ if "user" in attributes: # pragma no branch
113
+ self._user = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["user"])
venv/lib/python3.10/site-packages/github/RepoCodeSecurityConfig.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Justin Kufro <jkufro@andrew.cmu.edu> #
11
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
12
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
13
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2025 Bill Napier <napier@pobox.com> #
22
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from __future__ import annotations
43
+
44
+ from typing import TYPE_CHECKING, Any
45
+
46
+ import github.CodeSecurityConfig
47
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
48
+
49
+ if TYPE_CHECKING:
50
+ pass
51
+
52
+
53
+ class RepoCodeSecurityConfig(NonCompletableGithubObject):
54
+ """
55
+ This class represents Configurations for Code Security for a Repository.
56
+
57
+ The reference can be found here
58
+ https://docs.github.com/en/rest/code-security/configurations.
59
+
60
+ """
61
+
62
+ def _initAttributes(self) -> None:
63
+ self._configuration: Attribute[github.CodeSecurityConfig.CodeSecurityConfig] = NotSet
64
+ self._status: Attribute[str] = NotSet
65
+
66
+ def __repr__(self) -> str:
67
+ return self.get__repr__(
68
+ {
69
+ "configuration": self.configuration,
70
+ }
71
+ )
72
+
73
+ @property
74
+ def configuration(self) -> github.CodeSecurityConfig.CodeSecurityConfig:
75
+ return self._configuration.value
76
+
77
+ @property
78
+ def status(self) -> str:
79
+ return self._status.value
80
+
81
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
82
+ if "configuration" in attributes: # pragma no branch
83
+ self._configuration = self._makeClassAttribute(
84
+ github.CodeSecurityConfig.CodeSecurityConfig, attributes["configuration"]
85
+ )
86
+ if "status" in attributes: # pragma no branch
87
+ self._status = self._makeStringAttribute(attributes["status"])
venv/lib/python3.10/site-packages/github/Repository.py ADDED
The diff for this file is too large to render. See raw diff
 
venv/lib/python3.10/site-packages/github/RepositoryAdvisory.py ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
4
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
5
+ # Copyright 2023 Jonathan Leitschuh <jonathan.leitschuh@gmail.com> #
6
+ # Copyright 2023 Joseph Henrich <crimsonknave@gmail.com> #
7
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
8
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
9
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
10
+ # Copyright 2024 Thomas Cooper <coopernetes@proton.me> #
11
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
12
+ # #
13
+ # This file is part of PyGithub. #
14
+ # http://pygithub.readthedocs.io/ #
15
+ # #
16
+ # PyGithub is free software: you can redistribute it and/or modify it under #
17
+ # the terms of the GNU Lesser General Public License as published by the Free #
18
+ # Software Foundation, either version 3 of the License, or (at your option) #
19
+ # any later version. #
20
+ # #
21
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
22
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
23
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
24
+ # details. #
25
+ # #
26
+ # You should have received a copy of the GNU Lesser General Public License #
27
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
28
+ # #
29
+ ################################################################################
30
+
31
+ from __future__ import annotations
32
+
33
+ from datetime import datetime
34
+ from typing import TYPE_CHECKING, Any, Iterable
35
+
36
+ import github.AdvisoryCredit
37
+ import github.AdvisoryCreditDetailed
38
+ import github.AdvisoryVulnerability
39
+ import github.NamedUser
40
+ import github.Repository
41
+ import github.Team
42
+ from github.AdvisoryBase import AdvisoryBase
43
+ from github.GithubObject import Attribute, NotSet, Opt
44
+
45
+ if TYPE_CHECKING:
46
+ from github.AdvisoryCredit import AdvisoryCredit, Credit
47
+ from github.AdvisoryCreditDetailed import AdvisoryCreditDetailed
48
+ from github.AdvisoryVulnerability import AdvisoryVulnerability, AdvisoryVulnerabilityInput
49
+ from github.NamedUser import NamedUser
50
+ from github.Repository import Repository
51
+ from github.Team import Team
52
+
53
+
54
+ class RepositoryAdvisory(AdvisoryBase):
55
+ """
56
+ This class represents a RepositoryAdvisory.
57
+
58
+ The reference can be found here
59
+ https://docs.github.com/en/rest/security-advisories/repository-advisories
60
+
61
+ The OpenAPI schema can be found at
62
+ - /components/schemas/repository-advisory
63
+
64
+ """
65
+
66
+ def _initAttributes(self) -> None:
67
+ super()._initAttributes()
68
+ self._author: Attribute[NamedUser] = NotSet
69
+ self._closed_at: Attribute[datetime] = NotSet
70
+ self._collaborating_teams: Attribute[list[Team]] = NotSet
71
+ self._collaborating_users: Attribute[list[NamedUser]] = NotSet
72
+ self._created_at: Attribute[datetime] = NotSet
73
+ self._credits: Attribute[list[AdvisoryCredit]] = NotSet
74
+ self._credits_detailed: Attribute[list[AdvisoryCreditDetailed]] = NotSet
75
+ self._cwe_ids: Attribute[list[str]] = NotSet
76
+ self._private_fork: Attribute[Repository] = NotSet
77
+ self._publisher: Attribute[NamedUser] = NotSet
78
+ self._state: Attribute[str] = NotSet
79
+ self._submission: Attribute[dict[str, Any]] = NotSet
80
+ self._vulnerabilities: Attribute[list[AdvisoryVulnerability]] = NotSet
81
+ super()._initAttributes()
82
+
83
+ @property
84
+ def author(self) -> NamedUser:
85
+ return self._author.value
86
+
87
+ @property
88
+ def closed_at(self) -> datetime:
89
+ return self._closed_at.value
90
+
91
+ @property
92
+ def collaborating_teams(self) -> list[Team]:
93
+ return self._collaborating_teams.value
94
+
95
+ @property
96
+ def collaborating_users(self) -> list[NamedUser]:
97
+ return self._collaborating_users.value
98
+
99
+ @property
100
+ def created_at(self) -> datetime:
101
+ return self._created_at.value
102
+
103
+ @property
104
+ def credits(
105
+ self,
106
+ ) -> list[AdvisoryCredit]:
107
+ return self._credits.value
108
+
109
+ @property
110
+ def credits_detailed(
111
+ self,
112
+ ) -> list[AdvisoryCreditDetailed]:
113
+ return self._credits_detailed.value
114
+
115
+ @property
116
+ def cwe_ids(self) -> list[str]:
117
+ return self._cwe_ids.value
118
+
119
+ @property
120
+ def private_fork(self) -> Repository:
121
+ return self._private_fork.value
122
+
123
+ @property
124
+ def publisher(self) -> NamedUser:
125
+ return self._publisher.value
126
+
127
+ @property
128
+ def state(self) -> str:
129
+ return self._state.value
130
+
131
+ @property
132
+ def submission(self) -> dict[str, Any]:
133
+ return self._submission.value
134
+
135
+ @property
136
+ def vulnerabilities(self) -> list[AdvisoryVulnerability]:
137
+ return self._vulnerabilities.value
138
+
139
+ def add_vulnerability(
140
+ self,
141
+ ecosystem: str,
142
+ package_name: str | None = None,
143
+ vulnerable_version_range: str | None = None,
144
+ patched_versions: str | None = None,
145
+ vulnerable_functions: list[str] | None = None,
146
+ ) -> None:
147
+ """
148
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`\
149
+ """
150
+ return self.add_vulnerabilities(
151
+ [
152
+ {
153
+ "package": {
154
+ "ecosystem": ecosystem,
155
+ "name": package_name,
156
+ },
157
+ "vulnerable_version_range": vulnerable_version_range,
158
+ "patched_versions": patched_versions,
159
+ "vulnerable_functions": vulnerable_functions,
160
+ }
161
+ ]
162
+ )
163
+
164
+ def add_vulnerabilities(self, vulnerabilities: Iterable[AdvisoryVulnerabilityInput]) -> None:
165
+ """
166
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
167
+ """
168
+ assert isinstance(vulnerabilities, Iterable), vulnerabilities
169
+ for vulnerability in vulnerabilities:
170
+ github.AdvisoryVulnerability.AdvisoryVulnerability._validate_vulnerability(vulnerability)
171
+
172
+ post_parameters = {
173
+ "vulnerabilities": [
174
+ github.AdvisoryVulnerability.AdvisoryVulnerability._to_github_dict(vulnerability)
175
+ for vulnerability in (self.vulnerabilities + list(vulnerabilities))
176
+ ]
177
+ }
178
+ headers, data = self._requester.requestJsonAndCheck(
179
+ "PATCH",
180
+ self.url,
181
+ input=post_parameters,
182
+ )
183
+ self._useAttributes(data)
184
+
185
+ def offer_credit(
186
+ self,
187
+ login_or_user: str | github.NamedUser.NamedUser,
188
+ credit_type: str,
189
+ ) -> None:
190
+ """
191
+ Offers credit to a user for a vulnerability in a repository.
192
+
193
+ Unless you are giving credit to yourself, the user having credit offered will need to explicitly accept the credit.
194
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
195
+
196
+ """
197
+ self.offer_credits([{"login": login_or_user, "type": credit_type}])
198
+
199
+ def offer_credits(
200
+ self,
201
+ credited: Iterable[Credit],
202
+ ) -> None:
203
+ """
204
+ Offers credit to a list of users for a vulnerability in a repository.
205
+
206
+ Unless you are giving credit to yourself, the user having credit offered will need to explicitly accept the credit.
207
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
208
+ :param credited: iterable of dict with keys "login" and "type"
209
+
210
+ """
211
+ assert isinstance(credited, Iterable), credited
212
+ for credit in credited:
213
+ github.AdvisoryCredit.AdvisoryCredit._validate_credit(credit)
214
+
215
+ patch_parameters = {
216
+ "credits": [
217
+ github.AdvisoryCredit.AdvisoryCredit._to_github_dict(credit)
218
+ for credit in (self.credits + list(credited))
219
+ ]
220
+ }
221
+ headers, data = self._requester.requestJsonAndCheck(
222
+ "PATCH",
223
+ self.url,
224
+ input=patch_parameters,
225
+ )
226
+ self._useAttributes(data)
227
+
228
+ def revoke_credit(self, login_or_user: str | github.NamedUser.NamedUser) -> None:
229
+ """
230
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
231
+ """
232
+ assert isinstance(login_or_user, (str, github.NamedUser.NamedUser)), login_or_user
233
+ if isinstance(login_or_user, github.NamedUser.NamedUser):
234
+ login_or_user = login_or_user.login
235
+ patch_parameters = {
236
+ "credits": [
237
+ dict(login=credit.login, type=credit.type) for credit in self.credits if credit.login != login_or_user
238
+ ]
239
+ }
240
+ headers, data = self._requester.requestJsonAndCheck(
241
+ "PATCH",
242
+ self.url,
243
+ input=patch_parameters,
244
+ )
245
+ self._useAttributes(data)
246
+
247
+ def clear_credits(self) -> None:
248
+ """
249
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
250
+ """
251
+ patch_parameters: dict[str, Any] = {"credits": []}
252
+ headers, data = self._requester.requestJsonAndCheck(
253
+ "PATCH",
254
+ self.url,
255
+ input=patch_parameters,
256
+ )
257
+ self._useAttributes(data)
258
+
259
+ def edit(
260
+ self,
261
+ summary: Opt[str] = NotSet,
262
+ description: Opt[str] = NotSet,
263
+ severity_or_cvss_vector_string: Opt[str] = NotSet,
264
+ cve_id: Opt[str] = NotSet,
265
+ vulnerabilities: Opt[Iterable[AdvisoryVulnerabilityInput]] = NotSet,
266
+ cwe_ids: Opt[Iterable[str]] = NotSet,
267
+ credits: Opt[Iterable[Credit]] = NotSet,
268
+ state: Opt[str] = NotSet,
269
+ ) -> RepositoryAdvisory:
270
+ """
271
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
272
+ """
273
+ assert summary is NotSet or isinstance(summary, str), summary
274
+ assert description is NotSet or isinstance(description, str), description
275
+ assert severity_or_cvss_vector_string is NotSet or isinstance(
276
+ severity_or_cvss_vector_string, str
277
+ ), severity_or_cvss_vector_string
278
+ assert cve_id is NotSet or isinstance(cve_id, str), cve_id
279
+ assert vulnerabilities is NotSet or isinstance(vulnerabilities, Iterable), vulnerabilities
280
+ if isinstance(vulnerabilities, Iterable):
281
+ for vulnerability in vulnerabilities:
282
+ github.AdvisoryVulnerability.AdvisoryVulnerability._validate_vulnerability(vulnerability)
283
+ assert cwe_ids is NotSet or (
284
+ isinstance(cwe_ids, Iterable) and all(isinstance(element, str) for element in cwe_ids)
285
+ ), cwe_ids
286
+ if isinstance(credits, Iterable):
287
+ for credit in credits:
288
+ github.AdvisoryCredit.AdvisoryCredit._validate_credit(credit)
289
+ assert state is NotSet or isinstance(state, str), state
290
+ patch_parameters: dict[str, Any] = {}
291
+ if summary is not NotSet:
292
+ patch_parameters["summary"] = summary
293
+ if description is not NotSet:
294
+ patch_parameters["description"] = description
295
+ if isinstance(severity_or_cvss_vector_string, str):
296
+ if severity_or_cvss_vector_string.startswith("CVSS:"):
297
+ patch_parameters["cvss_vector_string"] = severity_or_cvss_vector_string
298
+ else:
299
+ patch_parameters["severity"] = severity_or_cvss_vector_string
300
+ if cve_id is not NotSet:
301
+ patch_parameters["cve_id"] = cve_id
302
+ if isinstance(vulnerabilities, Iterable):
303
+ patch_parameters["vulnerabilities"] = [
304
+ github.AdvisoryVulnerability.AdvisoryVulnerability._to_github_dict(vulnerability)
305
+ for vulnerability in vulnerabilities
306
+ ]
307
+ if isinstance(cwe_ids, Iterable):
308
+ patch_parameters["cwe_ids"] = list(cwe_ids)
309
+ if isinstance(credits, Iterable):
310
+ patch_parameters["credits"] = [
311
+ github.AdvisoryCredit.AdvisoryCredit._to_github_dict(credit) for credit in credits
312
+ ]
313
+ if state is not NotSet:
314
+ patch_parameters["state"] = state
315
+ headers, data = self._requester.requestJsonAndCheck(
316
+ "PATCH",
317
+ self.url,
318
+ input=patch_parameters,
319
+ )
320
+ self._useAttributes(data)
321
+ return self
322
+
323
+ def accept_report(self) -> None:
324
+ """
325
+ Accepts the advisory reported from an external reporter via private vulnerability reporting.
326
+
327
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
328
+
329
+ """
330
+ patch_parameters = {"state": "draft"}
331
+ headers, data = self._requester.requestJsonAndCheck(
332
+ "PATCH",
333
+ self.url,
334
+ input=patch_parameters,
335
+ )
336
+ self._useAttributes(data)
337
+
338
+ def publish(self) -> None:
339
+ """
340
+ Publishes the advisory.
341
+
342
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
343
+
344
+ """
345
+ patch_parameters = {"state": "published"}
346
+ headers, data = self._requester.requestJsonAndCheck(
347
+ "PATCH",
348
+ self.url,
349
+ input=patch_parameters,
350
+ )
351
+ self._useAttributes(data)
352
+
353
+ def request_cve(self) -> None:
354
+ """
355
+ Requests a CVE for the advisory.
356
+
357
+ :calls: `POST /repos/{owner}/{repo}/security-advisories/{ghsa_id}/cve <https://docs.github.com/en/rest/security-advisories/repository-advisories#request-a-cve-for-a-repository-security-advisory>`_
358
+
359
+ """
360
+ self._requester.requestJsonAndCheck(
361
+ "POST",
362
+ self.url + "/cve",
363
+ )
364
+
365
+ def close(self) -> None:
366
+ """
367
+ Closes the advisory.
368
+
369
+ :calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
370
+
371
+ """
372
+ patch_parameters = {"state": "closed"}
373
+ headers, data = self._requester.requestJsonAndCheck(
374
+ "PATCH",
375
+ self.url,
376
+ input=patch_parameters,
377
+ )
378
+ self._useAttributes(data)
379
+
380
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
381
+ if "author" in attributes: # pragma no branch
382
+ self._author = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["author"])
383
+ if "closed_at" in attributes: # pragma no branch
384
+ assert attributes["closed_at"] is None or isinstance(attributes["closed_at"], str), attributes["closed_at"]
385
+ self._closed_at = self._makeDatetimeAttribute(attributes["closed_at"])
386
+ if "collaborating_teams" in attributes: # pragma no branch
387
+ self._collaborating_teams = self._makeListOfClassesAttribute(
388
+ github.Team.Team, attributes["collaborating_teams"]
389
+ )
390
+ if "collaborating_users" in attributes: # pragma no branch
391
+ self._collaborating_users = self._makeListOfClassesAttribute(
392
+ github.NamedUser.NamedUser, attributes["collaborating_users"]
393
+ )
394
+ if "created_at" in attributes: # pragma no branch
395
+ assert attributes["created_at"] is None or isinstance(attributes["created_at"], str), attributes[
396
+ "created_at"
397
+ ]
398
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
399
+ if "credits" in attributes: # pragma no branch
400
+ self._credits = self._makeListOfClassesAttribute(
401
+ github.AdvisoryCredit.AdvisoryCredit,
402
+ attributes["credits"],
403
+ )
404
+ if "credits_detailed" in attributes: # pragma no branch
405
+ self._credits_detailed = self._makeListOfClassesAttribute(
406
+ github.AdvisoryCreditDetailed.AdvisoryCreditDetailed,
407
+ attributes["credits_detailed"],
408
+ )
409
+ if "cwe_ids" in attributes: # pragma no branch
410
+ self._cwe_ids = self._makeListOfStringsAttribute(attributes["cwe_ids"])
411
+ if "private_fork" in attributes: # pragma no branch
412
+ self._private_fork = self._makeClassAttribute(github.Repository.Repository, attributes["private_fork"])
413
+ if "publisher" in attributes: # pragma no branch
414
+ self._publisher = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["publisher"])
415
+ if "state" in attributes: # pragma no branch
416
+ self._state = self._makeStringAttribute(attributes["state"])
417
+ if "submission" in attributes: # pragma no branch
418
+ self._submission = self._makeDictAttribute(attributes["submission"])
419
+ if "vulnerabilities" in attributes:
420
+ self._vulnerabilities = self._makeListOfClassesAttribute(
421
+ github.AdvisoryVulnerability.AdvisoryVulnerability,
422
+ attributes["vulnerabilities"],
423
+ )
424
+ super()._useAttributes(attributes)
venv/lib/python3.10/site-packages/github/RepositoryDiscussion.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
4
+ # #
5
+ # This file is part of PyGithub. #
6
+ # http://pygithub.readthedocs.io/ #
7
+ # #
8
+ # PyGithub is free software: you can redistribute it and/or modify it under #
9
+ # the terms of the GNU Lesser General Public License as published by the Free #
10
+ # Software Foundation, either version 3 of the License, or (at your option) #
11
+ # any later version. #
12
+ # #
13
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
14
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
15
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
16
+ # details. #
17
+ # #
18
+ # You should have received a copy of the GNU Lesser General Public License #
19
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
20
+ # #
21
+ ################################################################################
22
+
23
+ from __future__ import annotations
24
+
25
+ from typing import TYPE_CHECKING, Any
26
+
27
+ import github
28
+ import github.Label
29
+ import github.NamedUser
30
+ import github.Reaction
31
+ import github.Repository
32
+ import github.RepositoryDiscussionCategory
33
+ import github.RepositoryDiscussionComment
34
+ from github.DiscussionBase import DiscussionBase
35
+ from github.GithubObject import (
36
+ Attribute,
37
+ GraphQlObject,
38
+ NotSet,
39
+ as_rest_api_attributes,
40
+ as_rest_api_attributes_list,
41
+ is_undefined,
42
+ )
43
+ from github.PaginatedList import PaginatedList
44
+
45
+ if TYPE_CHECKING:
46
+ from github.Label import Label
47
+ from github.NamedUser import NamedUser
48
+ from github.Reaction import Reaction
49
+ from github.Repository import Repository
50
+ from github.RepositoryDiscussionCategory import RepositoryDiscussionCategory
51
+ from github.RepositoryDiscussionComment import RepositoryDiscussionComment
52
+
53
+
54
+ class RepositoryDiscussion(GraphQlObject, DiscussionBase):
55
+ """
56
+ This class represents GraphQL Discussion.
57
+
58
+ The reference can be found here
59
+ https://docs.github.com/en/graphql/reference/objects#discussion
60
+
61
+ """
62
+
63
+ def _initAttributes(self) -> None:
64
+ super()._initAttributes()
65
+ self._answer: Attribute[RepositoryDiscussionComment | None] = NotSet
66
+ self._body_text: Attribute[str] = NotSet
67
+ self._category: Attribute[RepositoryDiscussionCategory] = NotSet
68
+ self._comments_page = None
69
+ self._database_id: Attribute[int] = NotSet
70
+ self._editor: Attribute[NamedUser] = NotSet
71
+ self._id: Attribute[str] = NotSet
72
+ self._labels_page = None
73
+ self._reactions_page = None
74
+ self._repository: Attribute[Repository] = NotSet
75
+
76
+ @property
77
+ def answer(self) -> RepositoryDiscussionComment | None:
78
+ return self._answer.value
79
+
80
+ @property
81
+ def body_text(self) -> str:
82
+ return self._body_text.value
83
+
84
+ @property
85
+ def category(self) -> RepositoryDiscussionCategory:
86
+ return self._category.value
87
+
88
+ @property
89
+ def database_id(self) -> int:
90
+ return self._database_id.value
91
+
92
+ @property
93
+ def editor(self) -> NamedUser:
94
+ return self._editor.value
95
+
96
+ @property
97
+ def id(self) -> str:
98
+ return self._id.value
99
+
100
+ @property
101
+ def node_id(self) -> str:
102
+ return self.id
103
+
104
+ @property
105
+ def repository(self) -> Repository:
106
+ return self._repository.value
107
+
108
+ def get_comments(self, comment_graphql_schema: str) -> PaginatedList[RepositoryDiscussionComment]:
109
+ if self._comments_page is not None:
110
+ return PaginatedList(
111
+ github.RepositoryDiscussionComment.RepositoryDiscussionComment,
112
+ self._requester,
113
+ firstData=self._comments_page,
114
+ firstHeaders={},
115
+ )
116
+
117
+ if is_undefined(self._id):
118
+ raise RuntimeError("Retrieving discussion comments requires the discussion field 'id'")
119
+ if not comment_graphql_schema.startswith("\n"):
120
+ comment_graphql_schema = f" {comment_graphql_schema} "
121
+
122
+ query = (
123
+ """
124
+ query Q($discussionId: ID!, $first: Int, $last: Int, $before: String, $after: String) {
125
+ node(id: $discussionId) {
126
+ ... on Discussion {
127
+ comments(first: $first, last: $last, before: $before, after: $after) {
128
+ totalCount
129
+ pageInfo {
130
+ startCursor
131
+ endCursor
132
+ hasNextPage
133
+ hasPreviousPage
134
+ }
135
+ nodes {"""
136
+ + comment_graphql_schema
137
+ + """}
138
+ }
139
+ }
140
+ }
141
+ }"""
142
+ )
143
+ variables = {"discussionId": self.node_id}
144
+ return PaginatedList(
145
+ github.RepositoryDiscussionComment.RepositoryDiscussionComment,
146
+ self._requester,
147
+ graphql_query=query,
148
+ graphql_variables=variables,
149
+ list_item=["node", "comments"],
150
+ )
151
+
152
+ def get_labels(self) -> PaginatedList[Label]:
153
+ if self._labels_page is None:
154
+ raise RuntimeError("Fetching labels not implemented")
155
+ return PaginatedList(github.Label.Label, self._requester, firstData=self._labels_page, firstHeaders={})
156
+
157
+ def get_reactions(self) -> PaginatedList[Reaction]:
158
+ if self._reactions_page is None:
159
+ raise RuntimeError("Fetching reactions not implemented")
160
+ return PaginatedList(github.Reaction.Reaction, self._requester, firstData=self._reactions_page, firstHeaders={})
161
+
162
+ def add_comment(
163
+ self, body: str, reply_to: RepositoryDiscussionComment | str | None = None, output_schema: str = "id"
164
+ ) -> RepositoryDiscussionComment:
165
+ reply_to_id = (
166
+ reply_to.id
167
+ if isinstance(reply_to, github.RepositoryDiscussionComment.RepositoryDiscussionComment)
168
+ else reply_to
169
+ )
170
+ if not output_schema.startswith("\n"):
171
+ output_schema = f" {output_schema} "
172
+
173
+ variables = {"body": body, "discussionId": self.id, "replyToId": reply_to_id}
174
+ return self._requester.graphql_named_mutation_class(
175
+ "addDiscussionComment",
176
+ NotSet.remove_unset_items(variables),
177
+ f"comment {{{output_schema}}}",
178
+ "comment",
179
+ github.RepositoryDiscussionComment.RepositoryDiscussionComment,
180
+ )
181
+
182
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
183
+ # super class is a REST API GithubObject, attributes are coming from GraphQL
184
+ super()._useAttributes(as_rest_api_attributes(attributes))
185
+ if "answer" in attributes: # pragma no branch
186
+ self._answer = self._makeClassAttribute(
187
+ github.RepositoryDiscussionComment.RepositoryDiscussionComment, attributes["answer"]
188
+ )
189
+ if "bodyText" in attributes: # pragma no branch
190
+ self._body_text = self._makeStringAttribute(attributes["bodyText"])
191
+ if "category" in attributes: # pragma no branch
192
+ self._category = self._makeClassAttribute(
193
+ github.RepositoryDiscussionCategory.RepositoryDiscussionCategory, attributes["category"]
194
+ )
195
+ if "comments" in attributes: # pragma no branch
196
+ # comments are GraphQL API objects
197
+ self._comments_page = attributes["comments"]["nodes"]
198
+ if "databaseId" in attributes: # pragma no branch
199
+ self._database_id = self._makeIntAttribute(attributes["databaseId"])
200
+ if "editor" in attributes: # pragma no branch
201
+ self._editor = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["editor"])
202
+ if "id" in attributes: # pragma no branch
203
+ self._id = self._makeStringAttribute(attributes["id"])
204
+ if "labels" in attributes: # pragma no branch
205
+ # labels are REST API objects
206
+ self._labels_page = as_rest_api_attributes_list(attributes["labels"]["nodes"]) # type: ignore
207
+ if "reactions" in attributes: # pragma no branch
208
+ # reactions are REST API objects
209
+ self._reactions_page = as_rest_api_attributes_list(attributes["reactions"]["nodes"]) # type: ignore
210
+ if "repository" in attributes: # pragma no branch
211
+ self._repository = self._makeClassAttribute(
212
+ github.Repository.Repository, as_rest_api_attributes(attributes["repository"])
213
+ )
venv/lib/python3.10/site-packages/github/RepositoryDiscussionCategory.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2020 Victor Zeng <zacker150@users.noreply.github.com> #
16
+ # Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from __future__ import annotations
43
+
44
+ from datetime import datetime
45
+ from typing import TYPE_CHECKING, Any
46
+
47
+ import github.Reaction
48
+ from github.GithubObject import Attribute, GraphQlObject, NonCompletableGithubObject, NotSet, as_rest_api_attributes
49
+
50
+ if TYPE_CHECKING:
51
+ from github.Repository import Repository
52
+
53
+
54
+ class RepositoryDiscussionCategory(GraphQlObject, NonCompletableGithubObject):
55
+ """
56
+ This class represents GraphQL DiscussionCategory.
57
+
58
+ The reference can be found here
59
+ https://docs.github.com/en/graphql/reference/objects#discussioncategory
60
+
61
+ """
62
+
63
+ def _initAttributes(self) -> None:
64
+ self._created_at: Attribute[datetime] = NotSet
65
+ self._description: Attribute[str] = NotSet
66
+ self._emoji: Attribute[str] = NotSet
67
+ self._emoji_html: Attribute[str] = NotSet
68
+ self._id: Attribute[str] = NotSet
69
+ self._is_answerable: Attribute[bool] = NotSet
70
+ self._name: Attribute[str] = NotSet
71
+ self._repository: Attribute[Repository] = NotSet
72
+ self._slug: Attribute[str] = NotSet
73
+ self._updated_at: Attribute[datetime] = NotSet
74
+
75
+ @property
76
+ def created_at(self) -> datetime:
77
+ return self._created_at.value
78
+
79
+ @property
80
+ def description(self) -> str:
81
+ return self._description.value
82
+
83
+ @property
84
+ def emoji(self) -> str:
85
+ return self._emoji.value
86
+
87
+ @property
88
+ def emoji_html(self) -> str:
89
+ return self._emoji_html.value
90
+
91
+ @property
92
+ def id(self) -> str:
93
+ return self._id.value
94
+
95
+ @property
96
+ def is_answerable(self) -> bool:
97
+ return self._is_answerable.value
98
+
99
+ @property
100
+ def name(self) -> str:
101
+ return self._name.value
102
+
103
+ @property
104
+ def node_id(self) -> str:
105
+ return self.id
106
+
107
+ @property
108
+ def repository(self) -> Repository:
109
+ return self._repository.value
110
+
111
+ @property
112
+ def slug(self) -> str:
113
+ return self._slug.value
114
+
115
+ @property
116
+ def updated_at(self) -> datetime:
117
+ return self._updated_at.value
118
+
119
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
120
+ if "createdAt" in attributes: # pragma no branch
121
+ self._created_at = self._makeDatetimeAttribute(attributes["createdAt"])
122
+ if "description" in attributes: # pragma no branch
123
+ self._description = self._makeStringAttribute(attributes["description"])
124
+ if "emoji" in attributes: # pragma no branch
125
+ self._emoji = self._makeStringAttribute(attributes["emoji"])
126
+ if "emojiHTML" in attributes: # pragma no branch
127
+ self._emoji_html = self._makeStringAttribute(attributes["emojiHTML"])
128
+ if "id" in attributes: # pragma no branch
129
+ self._id = self._makeStringAttribute(attributes["id"])
130
+ if "isAnswerable" in attributes: # pragma no branch
131
+ self._is_answerable = self._makeBoolAttribute(attributes["isAnswerable"])
132
+ if "name" in attributes: # pragma no branch
133
+ self._name = self._makeStringAttribute(attributes["name"])
134
+ if "repository" in attributes: # pragma no branch
135
+ # repository is a REST API object
136
+ self._repository = self._makeClassAttribute(
137
+ github.Repository.Repository, as_rest_api_attributes(attributes["repository"])
138
+ )
139
+ if "slug" in attributes: # pragma no branch
140
+ self._slug = self._makeStringAttribute(attributes["slug"])
141
+ if "updatedAt" in attributes: # pragma no branch
142
+ self._updated_at = self._makeDatetimeAttribute(attributes["updatedAt"])
venv/lib/python3.10/site-packages/github/RepositoryDiscussionComment.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
4
+ # #
5
+ # This file is part of PyGithub. #
6
+ # http://pygithub.readthedocs.io/ #
7
+ # #
8
+ # PyGithub is free software: you can redistribute it and/or modify it under #
9
+ # the terms of the GNU Lesser General Public License as published by the Free #
10
+ # Software Foundation, either version 3 of the License, or (at your option) #
11
+ # any later version. #
12
+ # #
13
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
14
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
15
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
16
+ # details. #
17
+ # #
18
+ # You should have received a copy of the GNU Lesser General Public License #
19
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
20
+ # #
21
+ ################################################################################
22
+
23
+ from __future__ import annotations
24
+
25
+ from typing import TYPE_CHECKING, Any
26
+
27
+ import github.NamedUser
28
+ import github.Reaction
29
+ from github.DiscussionCommentBase import DiscussionCommentBase
30
+ from github.GithubObject import (
31
+ Attribute,
32
+ GraphQlObject,
33
+ NotSet,
34
+ as_rest_api_attributes,
35
+ as_rest_api_attributes_list,
36
+ is_defined,
37
+ )
38
+ from github.PaginatedList import PaginatedList
39
+
40
+ if TYPE_CHECKING:
41
+ from github.NamedUser import NamedUser
42
+ from github.Reaction import Reaction
43
+ from github.RepositoryDiscussion import RepositoryDiscussion
44
+
45
+
46
+ class RepositoryDiscussionComment(GraphQlObject, DiscussionCommentBase):
47
+ """
48
+ This class represents GraphQL DiscussionComment.
49
+
50
+ The reference can be found here
51
+ https://docs.github.com/en/graphql/reference/objects#discussioncomment
52
+
53
+ """
54
+
55
+ def _initAttributes(self) -> None:
56
+ super()._initAttributes()
57
+ self._body_text: Attribute[str] = NotSet
58
+ self._database_id: Attribute[int] = NotSet
59
+ self._discussion: Attribute[RepositoryDiscussion]
60
+ self._editor: Attribute[NamedUser] = NotSet
61
+ self._id: Attribute[str] = NotSet
62
+ self._reactions_page = None
63
+ self._replies_page = None
64
+
65
+ @property
66
+ def body_text(self) -> str:
67
+ return self._body_text.value
68
+
69
+ @property
70
+ def database_id(self) -> int:
71
+ return self._database_id.value
72
+
73
+ @property
74
+ def discussion(self) -> RepositoryDiscussion:
75
+ return self._discussion.value
76
+
77
+ @property
78
+ def editor(self) -> NamedUser:
79
+ return self._editor.value
80
+
81
+ @property
82
+ def id(self) -> str:
83
+ return self._id.value
84
+
85
+ @property
86
+ def node_id(self) -> str:
87
+ if is_defined(self._node_id):
88
+ return super().node_id
89
+ return self.id
90
+
91
+ def get_reactions(self) -> PaginatedList[Reaction]:
92
+ if self._reactions_page is None:
93
+ raise RuntimeError("Fetching reactions not implemented")
94
+ return PaginatedList(github.Reaction.Reaction, self._requester, firstData=self._reactions_page, firstHeaders={})
95
+
96
+ def get_replies(self) -> PaginatedList[RepositoryDiscussionComment]:
97
+ if self._replies_page is None:
98
+ raise RuntimeError("Fetching replies not implemented")
99
+ return PaginatedList(
100
+ RepositoryDiscussionComment, self._requester, firstData=self._replies_page, firstHeaders={}
101
+ )
102
+
103
+ def edit(self, body: str, output_schema: str = "id") -> RepositoryDiscussionComment:
104
+ if not output_schema.startswith("\n"):
105
+ output_schema = f" {output_schema} "
106
+ return self._requester.graphql_named_mutation_class(
107
+ "updateDiscussionComment",
108
+ {"commentId": self.node_id, "body": body},
109
+ f"comment {{{output_schema}}}",
110
+ "comment",
111
+ github.RepositoryDiscussionComment.RepositoryDiscussionComment,
112
+ )
113
+
114
+ def delete(self, output_schema: str = "id") -> RepositoryDiscussionComment:
115
+ if not output_schema.startswith("\n"):
116
+ output_schema = f" {output_schema} "
117
+ return self._requester.graphql_named_mutation_class(
118
+ "deleteDiscussionComment",
119
+ {"id": self.id},
120
+ f"comment {{{output_schema}}}",
121
+ "comment",
122
+ github.RepositoryDiscussionComment.RepositoryDiscussionComment,
123
+ )
124
+
125
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
126
+ # super class is a REST API GithubObject, attributes are coming from GraphQL
127
+ super()._useAttributes(as_rest_api_attributes(attributes))
128
+ if "bodyText" in attributes: # pragma no branch
129
+ self._body_text = self._makeStringAttribute(attributes["bodyText"])
130
+ if "databaseId" in attributes: # pragma no branch
131
+ self._database_id = self._makeIntAttribute(attributes["databaseId"])
132
+ if "discussion" in attributes: # pragma no branch
133
+ # RepositoryDiscussion is a GraphQL API object
134
+ self._discussion = self._makeClassAttribute(
135
+ github.RepositoryDiscussion.RepositoryDiscussion, attributes["discussion"]
136
+ )
137
+ if "editor" in attributes: # pragma no branch
138
+ # NamedUser is a REST API object
139
+ self._editor = self._makeClassAttribute(
140
+ github.NamedUser.NamedUser, as_rest_api_attributes(attributes["editor"])
141
+ )
142
+ if "id" in attributes: # pragma no branch
143
+ self._id = self._makeStringAttribute(attributes["id"])
144
+ if "reactions" in attributes: # pragma no branch
145
+ # reactions are REST API objects
146
+ self._reactions_page = as_rest_api_attributes_list(attributes["reactions"]["nodes"]) # type: ignore
147
+ if "replies" in attributes: # pragma no branch
148
+ # replies are GraphQL API objects
149
+ self._replies_page = attributes["replies"]["nodes"]
venv/lib/python3.10/site-packages/github/RepositoryKey.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Srijan Choudhary <srijan4@gmail.com> #
7
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2013 martinqt <m.ki2@laposte.net> #
9
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
10
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
11
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
12
+ # Copyright 2017 Jimmy Zelinskie <jimmy.zelinskie+git@gmail.com> #
13
+ # Copyright 2017 Simon <spam@esemi.ru> #
14
+ # Copyright 2018 Laurent Raufaste <analogue@glop.org> #
15
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
16
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
17
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
18
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
19
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
20
+ # Copyright 2021 Floyd Hightower <floyd.hightower27@gmail.com> #
21
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
22
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
23
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
24
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
25
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
26
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
27
+ # Copyright 2024 Ramiro Morales <ramiro@users.noreply.github.com> #
28
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
29
+ # #
30
+ # This file is part of PyGithub. #
31
+ # http://pygithub.readthedocs.io/ #
32
+ # #
33
+ # PyGithub is free software: you can redistribute it and/or modify it under #
34
+ # the terms of the GNU Lesser General Public License as published by the Free #
35
+ # Software Foundation, either version 3 of the License, or (at your option) #
36
+ # any later version. #
37
+ # #
38
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
39
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
40
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
41
+ # details. #
42
+ # #
43
+ # You should have received a copy of the GNU Lesser General Public License #
44
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
45
+ # #
46
+ ################################################################################
47
+
48
+ from __future__ import annotations
49
+
50
+ from datetime import datetime
51
+ from typing import Any
52
+
53
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
54
+
55
+
56
+ class RepositoryKey(CompletableGithubObject):
57
+ """
58
+ This class represents RepositoryKeys.
59
+
60
+ The reference can be found here
61
+ https://docs.github.com/en/rest/reference/repos#deploy-keys
62
+
63
+ The OpenAPI schema can be found at
64
+ - /components/schemas/deploy-key
65
+
66
+ """
67
+
68
+ def _initAttributes(self) -> None:
69
+ self._added_by: Attribute[str] = NotSet
70
+ self._created_at: Attribute[datetime] = NotSet
71
+ self._id: Attribute[int] = NotSet
72
+ self._key: Attribute[str] = NotSet
73
+ self._last_used: Attribute[datetime] = NotSet
74
+ self._read_only: Attribute[bool] = NotSet
75
+ self._title: Attribute[str] = NotSet
76
+ self._url: Attribute[str] = NotSet
77
+ self._verified: Attribute[bool] = NotSet
78
+
79
+ def __repr__(self) -> str:
80
+ return self.get__repr__({"id": self._id.value, "title": self._title.value})
81
+
82
+ @property
83
+ def added_by(self) -> str:
84
+ self._completeIfNotSet(self._added_by)
85
+ return self._added_by.value
86
+
87
+ @property
88
+ def created_at(self) -> datetime:
89
+ self._completeIfNotSet(self._created_at)
90
+ return self._created_at.value
91
+
92
+ @property
93
+ def id(self) -> int:
94
+ self._completeIfNotSet(self._id)
95
+ return self._id.value
96
+
97
+ @property
98
+ def key(self) -> str:
99
+ self._completeIfNotSet(self._key)
100
+ return self._key.value
101
+
102
+ @property
103
+ def last_used(self) -> datetime:
104
+ self._completeIfNotSet(self._last_used)
105
+ return self._last_used.value
106
+
107
+ @property
108
+ def read_only(self) -> bool:
109
+ self._completeIfNotSet(self._read_only)
110
+ return self._read_only.value
111
+
112
+ @property
113
+ def title(self) -> str:
114
+ self._completeIfNotSet(self._title)
115
+ return self._title.value
116
+
117
+ @property
118
+ def url(self) -> str:
119
+ self._completeIfNotSet(self._url)
120
+ return self._url.value
121
+
122
+ @property
123
+ def verified(self) -> bool:
124
+ self._completeIfNotSet(self._verified)
125
+ return self._verified.value
126
+
127
+ def delete(self) -> None:
128
+ """
129
+ :calls: `DELETE /repos/{owner}/{repo}/keys/{id} <https://docs.github.com/en/rest/reference/repos#deploy-keys>`_
130
+ """
131
+ headers, data = self._requester.requestJsonAndCheck("DELETE", self.url)
132
+
133
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
134
+ if "added_by" in attributes: # pragma no branch
135
+ self._added_by = self._makeStringAttribute(attributes["added_by"])
136
+ if "created_at" in attributes: # pragma no branch
137
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
138
+ if "id" in attributes: # pragma no branch
139
+ self._id = self._makeIntAttribute(attributes["id"])
140
+ if "key" in attributes: # pragma no branch
141
+ self._key = self._makeStringAttribute(attributes["key"])
142
+ if "last_used" in attributes: # pragma no branch
143
+ assert attributes["last_used"] is None or isinstance(attributes["last_used"], str), attributes["last_used"]
144
+ self._last_used = self._makeDatetimeAttribute(attributes["last_used"])
145
+ if "read_only" in attributes: # pragma no branch
146
+ self._read_only = self._makeBoolAttribute(attributes["read_only"])
147
+ if "title" in attributes: # pragma no branch
148
+ self._title = self._makeStringAttribute(attributes["title"])
149
+ if "url" in attributes: # pragma no branch
150
+ self._url = self._makeStringAttribute(attributes["url"])
151
+ if "verified" in attributes: # pragma no branch
152
+ self._verified = self._makeBoolAttribute(attributes["verified"])
venv/lib/python3.10/site-packages/github/RepositoryPreferences.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
6
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
8
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
9
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
10
+ # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
11
+ # Copyright 2019 Nick Campbell <nicholas.j.campbell@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Dhruv Manilawala <dhruvmanila@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from __future__ import annotations
42
+
43
+ from typing import TYPE_CHECKING, Any
44
+
45
+ import github.Repository
46
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
47
+
48
+ if TYPE_CHECKING:
49
+ from github.Repository import Repository
50
+
51
+
52
+ class RepositoryPreferences(NonCompletableGithubObject):
53
+ """
54
+ This class represents repository preferences.
55
+
56
+ The reference can be found here
57
+ https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#update-repository-preferences-for-check-suites
58
+
59
+ The OpenAPI schema can be found at
60
+ - /components/schemas/check-suite-preference
61
+
62
+ """
63
+
64
+ def _initAttributes(self) -> None:
65
+ self._preferences: Attribute[dict[str, list[dict[str, bool | int]]]] = NotSet
66
+ self._repository: Attribute[Repository] = NotSet
67
+
68
+ @property
69
+ def preferences(self) -> dict[str, list[dict[str, bool | int]]]:
70
+ return self._preferences.value
71
+
72
+ @property
73
+ def repository(self) -> Repository:
74
+ return self._repository.value
75
+
76
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
77
+ if "preferences" in attributes: # pragma no branch
78
+ self._preferences = self._makeDictAttribute(attributes["preferences"])
79
+ if "repository" in attributes: # pragma no branch
80
+ self._repository = self._makeClassAttribute(github.Repository.Repository, attributes["repository"])
venv/lib/python3.10/site-packages/github/Requester.py ADDED
@@ -0,0 +1,1317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Andrew Bettison <andrewb@zip.com.au> #
4
+ # Copyright 2012 Dima Kukushkin <dima@kukushkin.me> #
5
+ # Copyright 2012 Michael Woodworth <mwoodworth@upverter.com> #
6
+ # Copyright 2012 Petteri Muilu <pmuilu@xena.(none)> #
7
+ # Copyright 2012 Steve English <steve.english@navetas.com> #
8
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
9
+ # Copyright 2012 Zearin <zearin@gonk.net> #
10
+ # Copyright 2013 AKFish <akfish@gmail.com> #
11
+ # Copyright 2013 Cameron White <cawhite@pdx.edu> #
12
+ # Copyright 2013 Ed Jackson <ed.jackson@gmail.com> #
13
+ # Copyright 2013 Jonathan J Hunt <hunt@braincorporation.com> #
14
+ # Copyright 2013 Mark Roddy <markroddy@gmail.com> #
15
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
16
+ # Copyright 2014 Jimmy Zelinskie <jimmyzelinskie@gmail.com> #
17
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
18
+ # Copyright 2015 Brian Eugley <Brian.Eugley@capitalone.com> #
19
+ # Copyright 2015 Daniel Pocock <daniel@pocock.pro> #
20
+ # Copyright 2016 Denis K <f1nal@cgaming.org> #
21
+ # Copyright 2016 Jared K. Smith <jaredsmith@jaredsmith.net> #
22
+ # Copyright 2016 Mathieu Mitchell <mmitchell@iweb.com> #
23
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
24
+ # Copyright 2017 Chris McBride <thehighlander@users.noreply.github.com> #
25
+ # Copyright 2017 Hugo <hugovk@users.noreply.github.com> #
26
+ # Copyright 2017 Simon <spam@esemi.ru> #
27
+ # Copyright 2018 Arda Kuyumcu <kuyumcuarda@gmail.com> #
28
+ # Copyright 2018 Dylan <djstein@ncsu.edu> #
29
+ # Copyright 2018 Maarten Fonville <mfonville@users.noreply.github.com> #
30
+ # Copyright 2018 Mike Miller <github@mikeage.net> #
31
+ # Copyright 2018 R1kk3r <R1kk3r@users.noreply.github.com> #
32
+ # Copyright 2018 Shubham Singh <41840111+singh811@users.noreply.github.com> #
33
+ # Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
34
+ # Copyright 2018 Tuuu Nya <yuzesheji@qq.com> #
35
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
36
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
37
+ # Copyright 2019 Isac Souza <isouza@daitan.com> #
38
+ # Copyright 2019 Rigas Papathanasopoulos <rigaspapas@gmail.com> #
39
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
40
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
41
+ # Copyright 2020 Jesse Li <jesse.li2002@gmail.com> #
42
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
43
+ # Copyright 2021 Amador Pahim <apahim@redhat.com> #
44
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
45
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
46
+ # Copyright 2022 Liuyang Wan <tsfdye@gmail.com> #
47
+ # Copyright 2023 Denis Blanchette <dblanchette@coveo.com> #
48
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
49
+ # Copyright 2023 Heitor Polidoro <heitor.polidoro@gmail.com> #
50
+ # Copyright 2023 Hemslo Wang <hemslo.wang@gmail.com> #
51
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
52
+ # Copyright 2023 Phillip Tran <phillip.qtr@gmail.com> #
53
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
54
+ # Copyright 2023 adosibalo <94008816+adosibalo@users.noreply.github.com> #
55
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
56
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
57
+ # Copyright 2024 Jonathan Kliem <jonathan.kliem@gmail.com> #
58
+ # Copyright 2024 Kobbi Gal <85439776+kgal-pan@users.noreply.github.com> #
59
+ # Copyright 2024 Min RK <benjaminrk@gmail.com> #
60
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
61
+ # Copyright 2025 Neel Malik <41765022+neel-m@users.noreply.github.com> #
62
+ # Copyright 2025 Timothy Klopotoski <tklopotoski@ebsco.com> #
63
+ # #
64
+ # This file is part of PyGithub. #
65
+ # http://pygithub.readthedocs.io/ #
66
+ # #
67
+ # PyGithub is free software: you can redistribute it and/or modify it under #
68
+ # the terms of the GNU Lesser General Public License as published by the Free #
69
+ # Software Foundation, either version 3 of the License, or (at your option) #
70
+ # any later version. #
71
+ # #
72
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
73
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
74
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
75
+ # details. #
76
+ # #
77
+ # You should have received a copy of the GNU Lesser General Public License #
78
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
79
+ # #
80
+ ################################################################################
81
+
82
+ import io
83
+ import json
84
+ import logging
85
+ import mimetypes
86
+ import os
87
+ import re
88
+ import threading
89
+ import time
90
+ import urllib
91
+ import urllib.parse
92
+ from collections import deque
93
+ from datetime import datetime, timezone
94
+ from io import IOBase
95
+ from typing import (
96
+ TYPE_CHECKING,
97
+ Any,
98
+ BinaryIO,
99
+ Callable,
100
+ Deque,
101
+ Dict,
102
+ Generic,
103
+ ItemsView,
104
+ Iterator,
105
+ List,
106
+ Optional,
107
+ Tuple,
108
+ Type,
109
+ TypeVar,
110
+ Union,
111
+ )
112
+
113
+ import requests
114
+ import requests.adapters
115
+ from urllib3 import Retry
116
+
117
+ import github.Consts as Consts
118
+ import github.GithubException
119
+ import github.GithubException as GithubException
120
+ from github.GithubObject import as_rest_api_attributes
121
+
122
+ if TYPE_CHECKING:
123
+ from .AppAuthentication import AppAuthentication
124
+ from .Auth import Auth
125
+ from .GithubObject import GithubObject
126
+ from .InstallationAuthorization import InstallationAuthorization
127
+
128
+ T = TypeVar("T")
129
+ T_gh = TypeVar("T_gh", bound="GithubObject")
130
+
131
+ # For App authentication, time remaining before token expiration to request a new one
132
+ ACCESS_TOKEN_REFRESH_THRESHOLD_SECONDS = 20
133
+
134
+
135
+ class RequestsResponse:
136
+ # mimic the httplib response object
137
+ def __init__(self, r: requests.Response):
138
+ self.status = r.status_code
139
+ self.headers = r.headers
140
+ self.response = r
141
+
142
+ def getheaders(self) -> ItemsView[str, str]:
143
+ return self.headers.items()
144
+
145
+ def read(self) -> str:
146
+ return self.response.text
147
+
148
+ def iter_content(self, chunk_size: Union[int, None] = 1) -> Iterator:
149
+ return self.response.iter_content(chunk_size=chunk_size)
150
+
151
+ def raise_for_status(self) -> None:
152
+ self.response.raise_for_status()
153
+
154
+
155
+ class HTTPSRequestsConnectionClass:
156
+ retry: Union[int, Retry]
157
+
158
+ # mimic the httplib connection object
159
+ def __init__(
160
+ self,
161
+ host: str,
162
+ port: Optional[int] = None,
163
+ strict: bool = False,
164
+ timeout: Optional[int] = None,
165
+ retry: Optional[Union[int, Retry]] = None,
166
+ pool_size: Optional[int] = None,
167
+ **kwargs: Any,
168
+ ) -> None:
169
+ self.port = port if port else 443
170
+ self.host = host
171
+ self.protocol = "https"
172
+ self.timeout = timeout
173
+ self.verify = kwargs.get("verify", True)
174
+ self.session = requests.Session()
175
+ # having Session.auth set something other than None disables falling back to .netrc file
176
+ # https://github.com/psf/requests/blob/d63e94f552ebf77ccf45d97e5863ac46500fa2c7/src/requests/sessions.py#L480-L481
177
+ # see https://github.com/PyGithub/PyGithub/pull/2703
178
+ self.session.auth = Requester.noopAuth
179
+
180
+ if retry is None:
181
+ self.retry = requests.adapters.DEFAULT_RETRIES
182
+ else:
183
+ self.retry = retry
184
+
185
+ if pool_size is None:
186
+ self.pool_size = requests.adapters.DEFAULT_POOLSIZE
187
+ else:
188
+ self.pool_size = pool_size
189
+
190
+ self.adapter = requests.adapters.HTTPAdapter(
191
+ max_retries=self.retry,
192
+ pool_connections=self.pool_size,
193
+ pool_maxsize=self.pool_size,
194
+ )
195
+ self.session.mount("https://", self.adapter)
196
+
197
+ def request(
198
+ self,
199
+ verb: str,
200
+ url: str,
201
+ input: Optional[Union[str, io.BufferedReader]],
202
+ headers: Dict[str, str],
203
+ stream: bool = False,
204
+ ) -> None:
205
+ self.verb = verb
206
+ self.url = url
207
+ self.input = input
208
+ self.headers = headers
209
+ self.stream = stream
210
+
211
+ def getresponse(self) -> RequestsResponse:
212
+ verb = getattr(self.session, self.verb.lower())
213
+ url = f"{self.protocol}://{self.host}:{self.port}{self.url}"
214
+ r = verb(
215
+ url,
216
+ headers=self.headers,
217
+ data=self.input,
218
+ timeout=self.timeout,
219
+ verify=self.verify,
220
+ allow_redirects=False,
221
+ )
222
+ return RequestsResponse(r)
223
+
224
+ def close(self) -> None:
225
+ self.session.close()
226
+
227
+
228
+ class HTTPRequestsConnectionClass:
229
+ # mimic the httplib connection object
230
+ def __init__(
231
+ self,
232
+ host: str,
233
+ port: Optional[int] = None,
234
+ strict: bool = False,
235
+ timeout: Optional[int] = None,
236
+ retry: Optional[Union[int, Retry]] = None,
237
+ pool_size: Optional[int] = None,
238
+ **kwargs: Any,
239
+ ):
240
+ self.port = port if port else 80
241
+ self.host = host
242
+ self.protocol = "http"
243
+ self.timeout = timeout
244
+ self.verify = kwargs.get("verify", True)
245
+ self.session = requests.Session()
246
+ # having Session.auth set something other than None disables falling back to .netrc file
247
+ # https://github.com/psf/requests/blob/d63e94f552ebf77ccf45d97e5863ac46500fa2c7/src/requests/sessions.py#L480-L481
248
+ # see https://github.com/PyGithub/PyGithub/pull/2703
249
+ self.session.auth = Requester.noopAuth
250
+
251
+ if retry is None:
252
+ self.retry = requests.adapters.DEFAULT_RETRIES
253
+ else:
254
+ self.retry = retry # type: ignore
255
+
256
+ if pool_size is None:
257
+ self.pool_size = requests.adapters.DEFAULT_POOLSIZE
258
+ else:
259
+ self.pool_size = pool_size
260
+
261
+ self.adapter = requests.adapters.HTTPAdapter(
262
+ max_retries=self.retry,
263
+ pool_connections=self.pool_size,
264
+ pool_maxsize=self.pool_size,
265
+ )
266
+ self.session.mount("http://", self.adapter)
267
+
268
+ def request(self, verb: str, url: str, input: None, headers: Dict[str, str], stream: bool = False) -> None:
269
+ self.verb = verb
270
+ self.url = url
271
+ self.input = input
272
+ self.headers = headers
273
+ self.stream = stream
274
+
275
+ def getresponse(self) -> RequestsResponse:
276
+ verb = getattr(self.session, self.verb.lower())
277
+ url = f"{self.protocol}://{self.host}:{self.port}{self.url}"
278
+ r = verb(
279
+ url,
280
+ headers=self.headers,
281
+ data=self.input,
282
+ timeout=self.timeout,
283
+ verify=self.verify,
284
+ allow_redirects=False,
285
+ )
286
+ return RequestsResponse(r)
287
+
288
+ def close(self) -> None:
289
+ self.session.close()
290
+
291
+
292
+ class Requester:
293
+ __installation_authorization: Optional["InstallationAuthorization"]
294
+ __app_auth: Optional["AppAuthentication"]
295
+
296
+ __httpConnectionClass = HTTPRequestsConnectionClass
297
+ __httpsConnectionClass = HTTPSRequestsConnectionClass
298
+ __persist = True
299
+ __logger: Optional[logging.Logger] = None
300
+
301
+ _frameBuffer: List[Any]
302
+
303
+ @staticmethod
304
+ def noopAuth(request: requests.models.PreparedRequest) -> requests.models.PreparedRequest:
305
+ return request
306
+
307
+ @classmethod
308
+ def injectConnectionClasses(
309
+ cls,
310
+ httpConnectionClass: Type[HTTPRequestsConnectionClass],
311
+ httpsConnectionClass: Type[HTTPSRequestsConnectionClass],
312
+ ) -> None:
313
+ cls.__persist = False
314
+ cls.__httpConnectionClass = httpConnectionClass
315
+ cls.__httpsConnectionClass = httpsConnectionClass
316
+
317
+ @classmethod
318
+ def resetConnectionClasses(cls) -> None:
319
+ cls.__persist = True
320
+ cls.__httpConnectionClass = HTTPRequestsConnectionClass
321
+ cls.__httpsConnectionClass = HTTPSRequestsConnectionClass
322
+
323
+ @classmethod
324
+ def injectLogger(cls, logger: logging.Logger) -> None:
325
+ cls.__logger = logger
326
+
327
+ @classmethod
328
+ def resetLogger(cls) -> None:
329
+ cls.__logger = None
330
+
331
+ #############################################################
332
+ # For Debug
333
+ @classmethod
334
+ def setDebugFlag(cls, flag: bool) -> None:
335
+ cls.DEBUG_FLAG = flag
336
+
337
+ @classmethod
338
+ def setOnCheckMe(cls, onCheckMe: Callable) -> None:
339
+ cls.ON_CHECK_ME = onCheckMe
340
+
341
+ DEBUG_FLAG = False
342
+
343
+ DEBUG_FRAME_BUFFER_SIZE = 1024
344
+
345
+ DEBUG_HEADER_KEY = "DEBUG_FRAME"
346
+
347
+ ON_CHECK_ME: Optional[Callable] = None
348
+
349
+ def NEW_DEBUG_FRAME(self, requestHeader: Dict[str, str]) -> None:
350
+ """
351
+ Initialize a debug frame with requestHeader
352
+ Frame count is updated and will be attached to respond header
353
+ The structure of a frame: [requestHeader, statusCode, responseHeader, raw_data]
354
+ Some of them may be None
355
+ """
356
+ if self.DEBUG_FLAG: # pragma no branch (Flag always set in tests)
357
+ new_frame = [requestHeader, None, None, None]
358
+ if self._frameCount < self.DEBUG_FRAME_BUFFER_SIZE - 1: # pragma no branch (Should be covered)
359
+ self._frameBuffer.append(new_frame)
360
+ else:
361
+ self._frameBuffer[0] = new_frame # pragma no cover (Should be covered)
362
+
363
+ self._frameCount = len(self._frameBuffer) - 1
364
+
365
+ def DEBUG_ON_RESPONSE(self, statusCode: int, responseHeader: Dict[str, Union[str, int]], data: str) -> None:
366
+ """
367
+ Update current frame with response Current frame index will be attached to responseHeader.
368
+ """
369
+ if self.DEBUG_FLAG: # pragma no branch (Flag always set in tests)
370
+ self._frameBuffer[self._frameCount][1:4] = [
371
+ statusCode,
372
+ responseHeader,
373
+ data,
374
+ ]
375
+ responseHeader[self.DEBUG_HEADER_KEY] = self._frameCount
376
+
377
+ def check_me(self, obj: "GithubObject") -> None:
378
+ if self.DEBUG_FLAG and self.ON_CHECK_ME is not None: # pragma no branch (Flag always set in tests)
379
+ frame = None
380
+ if self.DEBUG_HEADER_KEY in obj._headers:
381
+ frame_index = obj._headers[self.DEBUG_HEADER_KEY]
382
+ frame = self._frameBuffer[frame_index] # type: ignore
383
+ self.ON_CHECK_ME(obj, frame)
384
+
385
+ def _initializeDebugFeature(self) -> None:
386
+ self._frameCount = 0
387
+ self._frameBuffer = []
388
+
389
+ #############################################################
390
+
391
+ _frameCount: int
392
+ __connectionClass: Union[Type[HTTPRequestsConnectionClass], Type[HTTPSRequestsConnectionClass]]
393
+ __hostname: str
394
+ __authorizationHeader: Optional[str]
395
+ __seconds_between_requests: Optional[float]
396
+ __seconds_between_writes: Optional[float]
397
+
398
+ # keep arguments in-sync with github.MainClass and GithubIntegration
399
+ def __init__(
400
+ self,
401
+ auth: Optional["Auth"],
402
+ base_url: str,
403
+ timeout: int,
404
+ user_agent: str,
405
+ per_page: int,
406
+ verify: Union[bool, str],
407
+ retry: Optional[Union[int, Retry]],
408
+ pool_size: Optional[int],
409
+ seconds_between_requests: Optional[float] = None,
410
+ seconds_between_writes: Optional[float] = None,
411
+ lazy: bool = False,
412
+ ):
413
+ self._initializeDebugFeature()
414
+
415
+ self.__auth = auth
416
+ self.__base_url = base_url
417
+
418
+ o = urllib.parse.urlparse(base_url)
419
+ self.__graphql_prefix = self.get_graphql_prefix(o.path)
420
+ self.__graphql_url = urllib.parse.urlunparse(o._replace(path=self.__graphql_prefix))
421
+ self.__hostname = o.hostname # type: ignore
422
+ self.__port = o.port
423
+ self.__prefix = o.path
424
+ self.__timeout = timeout
425
+ self.__retry = retry # NOTE: retry can be either int or an urllib3 Retry object
426
+ self.__pool_size = pool_size
427
+ self.__seconds_between_requests = seconds_between_requests
428
+ self.__seconds_between_writes = seconds_between_writes
429
+ self.__last_requests: Dict[str, float] = dict()
430
+ self.__scheme = o.scheme
431
+ if o.scheme == "https":
432
+ self.__connectionClass = self.__httpsConnectionClass
433
+ elif o.scheme == "http":
434
+ self.__connectionClass = self.__httpConnectionClass
435
+ else:
436
+ assert False, "Unknown URL scheme"
437
+ self.__connection: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None
438
+ self.__connection_lock = threading.Lock()
439
+ self.__custom_connections: Deque[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = deque()
440
+ self.rate_limiting = (-1, -1)
441
+ self.rate_limiting_resettime = 0
442
+ self.FIX_REPO_GET_GIT_REF = True
443
+ self.per_page = per_page
444
+
445
+ self.oauth_scopes = None
446
+
447
+ assert user_agent is not None, (
448
+ "github now requires a user-agent. "
449
+ "See https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-required"
450
+ )
451
+ self.__userAgent = user_agent
452
+ self.__verify = verify
453
+ self.__lazy = lazy
454
+
455
+ self.__installation_authorization = None
456
+
457
+ # provide auth implementations that require a requester with this requester
458
+ if isinstance(self.__auth, WithRequester):
459
+ self.__auth.withRequester(self)
460
+
461
+ def __getstate__(self) -> Dict[str, Any]:
462
+ state = self.__dict__.copy()
463
+ # __connection_lock is not picklable
464
+ del state["_Requester__connection_lock"]
465
+ # __connection is not usable on remote, so ignore it
466
+ del state["_Requester__connection"]
467
+ # __custom_connections is not usable on remote, so ignore it
468
+ del state["_Requester__custom_connections"]
469
+ return state
470
+
471
+ def __setstate__(self, state: Dict[str, Any]) -> None:
472
+ self.__dict__.update(state)
473
+ self.__connection_lock = threading.Lock()
474
+ self.__connection = None
475
+ self.__custom_connections = deque()
476
+
477
+ @staticmethod
478
+ # replace with str.removesuffix once support for Python 3.8 is dropped
479
+ def remove_suffix(string: str, suffix: str) -> str:
480
+ if string.endswith(suffix):
481
+ return string[: -len(suffix)]
482
+ return string
483
+
484
+ @staticmethod
485
+ def get_graphql_prefix(path: Optional[str]) -> str:
486
+ if path is None or path in ["", "/"]:
487
+ path = ""
488
+ if path.endswith(("/v3", "/v3/")):
489
+ path = Requester.remove_suffix(path, "/")
490
+ path = Requester.remove_suffix(path, "/v3")
491
+ return path + "/graphql"
492
+
493
+ @staticmethod
494
+ def get_parameters_of_url(url: str) -> Dict[str, list]:
495
+ query = urllib.parse.urlparse(url)[4]
496
+ return urllib.parse.parse_qs(query)
497
+
498
+ @staticmethod
499
+ def add_parameters_to_url(
500
+ url: str,
501
+ parameters: Dict[str, Any],
502
+ ) -> str:
503
+ scheme, netloc, url, params, query, fragment = urllib.parse.urlparse(url)
504
+ url_params = urllib.parse.parse_qs(query)
505
+ # union parameters in url with given parameters, the latter have precedence
506
+ url_params.update(**{k: v if isinstance(v, list) else [v] for k, v in parameters.items()})
507
+ parameter_list = [(key, value) for key, values in url_params.items() for value in values]
508
+ # remove query from url
509
+ url = urllib.parse.urlunparse((scheme, netloc, url, params, "", fragment))
510
+
511
+ if len(parameter_list) == 0:
512
+ return url
513
+ else:
514
+ return f"{url}?{urllib.parse.urlencode(parameter_list)}"
515
+
516
+ def close(self) -> None:
517
+ """
518
+ Close the connection to the server.
519
+ """
520
+ with self.__connection_lock:
521
+ if self.__connection is not None:
522
+ self.__connection.close()
523
+ self.__connection = None
524
+ while self.__custom_connections:
525
+ self.__custom_connections.popleft().close()
526
+
527
+ @property
528
+ def kwargs(self) -> Dict[str, Any]:
529
+ """
530
+ Returns arguments required to recreate this Requester with Requester.__init__, as well as with
531
+ MainClass.__init__ and GithubIntegration.__init__.
532
+ """
533
+ return dict(
534
+ auth=self.__auth,
535
+ base_url=self.__base_url,
536
+ timeout=self.__timeout,
537
+ user_agent=self.__userAgent,
538
+ per_page=self.per_page,
539
+ verify=self.__verify,
540
+ retry=self.__retry,
541
+ pool_size=self.__pool_size,
542
+ seconds_between_requests=self.__seconds_between_requests,
543
+ seconds_between_writes=self.__seconds_between_writes,
544
+ lazy=self.__lazy,
545
+ )
546
+
547
+ @property
548
+ def base_url(self) -> str:
549
+ return self.__base_url
550
+
551
+ @property
552
+ def graphql_url(self) -> str:
553
+ return self.__graphql_url
554
+
555
+ @property
556
+ def scheme(self) -> str:
557
+ return self.__scheme
558
+
559
+ @property
560
+ def hostname(self) -> str:
561
+ return self.__hostname
562
+
563
+ @property
564
+ def hostname_and_port(self) -> str:
565
+ if self.__port is None:
566
+ return self.hostname
567
+ return f"{self.hostname}:{self.__port}"
568
+
569
+ @property
570
+ def auth(self) -> Optional["Auth"]:
571
+ return self.__auth
572
+
573
+ def withAuth(self, auth: Optional["Auth"]) -> "Requester":
574
+ """
575
+ Create a new requester instance with identical configuration but the given authentication method.
576
+
577
+ :param auth: authentication method
578
+ :return: new Requester instance
579
+
580
+ """
581
+ kwargs = self.kwargs
582
+ kwargs.update(auth=auth)
583
+ return Requester(**kwargs)
584
+
585
+ @property
586
+ def is_lazy(self) -> bool:
587
+ return self.__lazy
588
+
589
+ @property
590
+ def is_not_lazy(self) -> bool:
591
+ return not self.__lazy
592
+
593
+ def withLazy(self, lazy: bool) -> "Requester":
594
+ """
595
+ Create a new requester instance with identical configuration but the given lazy setting.
596
+
597
+ :param lazy: completable objects created from this instance are lazy, as well as completable objects created
598
+ from those, and so on
599
+ :return: new Requester instance
600
+
601
+ """
602
+ kwargs = self.kwargs
603
+ kwargs.update(lazy=lazy)
604
+ return Requester(**kwargs)
605
+
606
+ def requestJsonAndCheck(
607
+ self,
608
+ verb: str,
609
+ url: str,
610
+ parameters: Optional[Dict[str, Any]] = None,
611
+ headers: Optional[Dict[str, str]] = None,
612
+ input: Optional[Any] = None,
613
+ follow_302_redirect: bool = False,
614
+ ) -> Tuple[Dict[str, Any], Any]:
615
+ """
616
+ Send a request with JSON body.
617
+
618
+ :param input: request body, serialized to JSON if specified
619
+
620
+ :return: ``(headers: dict, JSON Response: Any)``
621
+ :raises: :class:`GithubException` for error status codes
622
+
623
+ """
624
+ return self.__check(
625
+ *self.requestJson(
626
+ verb,
627
+ url,
628
+ parameters,
629
+ headers,
630
+ input,
631
+ self.__customConnection(url),
632
+ follow_302_redirect=follow_302_redirect,
633
+ )
634
+ )
635
+
636
+ def requestMultipartAndCheck(
637
+ self,
638
+ verb: str,
639
+ url: str,
640
+ parameters: Optional[Dict[str, Any]] = None,
641
+ headers: Optional[Dict[str, Any]] = None,
642
+ input: Optional[Dict[str, str]] = None,
643
+ ) -> Tuple[Dict[str, Any], Optional[Dict[str, Any]]]:
644
+ """
645
+ Send a request with multi-part-encoded body.
646
+
647
+ :param input: request body, will be multi-part encoded if specified
648
+
649
+ :return: ``(headers: dict, JSON Response: Any)``
650
+ :raises: :class:`GithubException` for error status codes
651
+
652
+ """
653
+ return self.__check(*self.requestMultipart(verb, url, parameters, headers, input, self.__customConnection(url)))
654
+
655
+ def requestBlobAndCheck(
656
+ self,
657
+ verb: str,
658
+ url: str,
659
+ parameters: Optional[Dict[str, str]] = None,
660
+ headers: Optional[Dict[str, str]] = None,
661
+ input: Optional[str] = None,
662
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
663
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
664
+ """
665
+ Send a request with a file for the body.
666
+
667
+ :param input: path to a file to use for the request body
668
+
669
+ :return: ``(headers: dict, JSON Response: Any)``
670
+ :raises: :class:`GithubException` for error status codes
671
+
672
+ """
673
+ return self.__check(*self.requestBlob(verb, url, parameters, headers, input, self.__customConnection(url)))
674
+
675
+ def graphql_query(self, query: str, variables: Dict[str, Any]) -> Tuple[Dict[str, Any], Dict[str, Any]]:
676
+ """
677
+ :calls: `POST /graphql <https://docs.github.com/en/graphql>`_
678
+ """
679
+ input_ = {"query": query, "variables": variables}
680
+
681
+ response_headers, data = self.requestJsonAndCheck("POST", self.graphql_url, input=input_)
682
+ if "errors" in data:
683
+ if len(data["errors"]) == 1:
684
+ error = data["errors"][0]
685
+ if error.get("type") == "NOT_FOUND":
686
+ raise github.UnknownObjectException(404, data, response_headers, error.get("message"))
687
+ raise self.createException(400, response_headers, data)
688
+ return response_headers, data
689
+
690
+ @classmethod
691
+ def paths_of_dict(cls, d: dict) -> dict:
692
+ return {key: cls.paths_of_dict(val) if isinstance(val, dict) else None for key, val in d.items()}
693
+
694
+ def data_as_class(
695
+ self, headers: Dict[str, Any], data: Dict[str, Any], data_path: List[str], klass: Type[T_gh]
696
+ ) -> T_gh:
697
+ for item in data_path:
698
+ if item not in data:
699
+ raise RuntimeError(f"GraphQL path {data_path} not found in data: {self.paths_of_dict(data)}")
700
+ data = data[item]
701
+ if klass.is_rest():
702
+ data = as_rest_api_attributes(data)
703
+ return klass(self, headers, data)
704
+
705
+ def graphql_node(self, node_id: str, graphql_schema: str, node_type: str) -> Tuple[Dict[str, Any], Dict[str, Any]]:
706
+ """
707
+ :calls: `POST /graphql <https://docs.github.com/en/graphql>`_
708
+ """
709
+ if not graphql_schema.startswith("\n"):
710
+ graphql_schema = f" {graphql_schema} "
711
+ query = (
712
+ """
713
+ query Q($id: ID!) {
714
+ node(id: $id) {
715
+ __typename
716
+ ... on """
717
+ + f"{node_type} {{{graphql_schema}}}"
718
+ + """
719
+ }
720
+ }
721
+ """
722
+ )
723
+
724
+ headers, data = self.graphql_query(query, {"id": node_id})
725
+ actual_node_type = data.get("data", {}).get("node", {}).get("__typename", node_type)
726
+ if actual_node_type != node_type:
727
+ raise github.GithubException(
728
+ 400,
729
+ data,
730
+ message=f"Retrieved {node_type} object is of different type: {actual_node_type}",
731
+ )
732
+ return headers, data
733
+
734
+ def graphql_node_class(
735
+ self, node_id: str, graphql_schema: str, klass: Type[T_gh], node_type: Optional[str] = None
736
+ ) -> T_gh:
737
+ """
738
+ :calls: `POST /graphql <https://docs.github.com/en/graphql>`_
739
+ """
740
+ if node_type is None:
741
+ node_type = klass.__name__
742
+
743
+ headers, data = self.graphql_node(node_id, graphql_schema, node_type)
744
+ return self.data_as_class(headers, data, ["data", "node"], klass)
745
+
746
+ def graphql_query_class(
747
+ self, query: str, variables: Dict[str, Any], data_path: List[str], klass: Type[T_gh]
748
+ ) -> T_gh:
749
+ """
750
+ :calls: `POST /graphql <https://docs.github.com/en/graphql>`_
751
+ """
752
+ headers, data = self.graphql_query(query, variables)
753
+ return self.data_as_class(headers, data, ["data"] + data_path, klass)
754
+
755
+ def graphql_named_mutation(
756
+ self, mutation_name: str, mutation_input: Dict[str, Any], output_schema: str
757
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
758
+ """
759
+ Create a mutation in the format:
760
+ mutation Mutation($input: MutationNameInput!) {
761
+ mutationName(input: $input) { <output_schema> }
762
+ }
763
+ and call the self.graphql_query method.
764
+
765
+ Returns the response data according to given output schema.
766
+ """
767
+ mutation_input_name = mutation_name[:1].upper() + mutation_name[1:] + "Input!"
768
+ query = f"mutation Mutation($input: {mutation_input_name}) {{ {mutation_name}(input: $input) {{ {output_schema} }} }}"
769
+ headers, data = self.graphql_query(query, {"input": mutation_input})
770
+ return headers, data.get("data", {}).get(mutation_name, {})
771
+
772
+ def graphql_named_mutation_class(
773
+ self, mutation_name: str, mutation_input: Dict[str, Any], output_schema: str, item: str, klass: Type[T_gh]
774
+ ) -> T_gh:
775
+ """
776
+ Executes a mutation and returns the output object as the given GithubObject.
777
+
778
+ See {@link graphql_named_mutation}.
779
+
780
+ """
781
+ headers, data = self.graphql_named_mutation(mutation_name, mutation_input, output_schema)
782
+ return self.data_as_class(headers, data, [item], klass)
783
+
784
+ def __check(
785
+ self,
786
+ status: int,
787
+ responseHeaders: Dict[str, Any],
788
+ output: str,
789
+ ) -> Tuple[Dict[str, Any], Any]:
790
+ data = self.__structuredFromJson(output)
791
+ if status >= 400:
792
+ raise self.createException(status, responseHeaders, data)
793
+ return responseHeaders, data
794
+
795
+ def __customConnection(
796
+ self, url: str
797
+ ) -> Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]]:
798
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None
799
+ if not url.startswith("/"):
800
+ o = urllib.parse.urlparse(url)
801
+ if (
802
+ o.hostname != self.__hostname
803
+ or (o.port and o.port != self.__port)
804
+ or (o.scheme != self.__scheme and not (o.scheme == "https" and self.__scheme == "http"))
805
+ ): # issue80
806
+ if o.scheme == "http":
807
+ cnx = self.__httpConnectionClass(
808
+ o.hostname, # type: ignore
809
+ o.port,
810
+ retry=self.__retry,
811
+ pool_size=self.__pool_size,
812
+ )
813
+ self.__custom_connections.append(cnx)
814
+ elif o.scheme == "https":
815
+ cnx = self.__httpsConnectionClass(
816
+ o.hostname, # type: ignore
817
+ o.port,
818
+ retry=self.__retry,
819
+ pool_size=self.__pool_size,
820
+ )
821
+ self.__custom_connections.append(cnx)
822
+ return cnx
823
+
824
+ @classmethod
825
+ def createException(
826
+ cls,
827
+ status: int,
828
+ headers: Dict[str, Any],
829
+ output: Dict[str, Any],
830
+ ) -> GithubException.GithubException:
831
+ message = output.get("message") if output else None
832
+ lc_message = message.lower() if message else ""
833
+
834
+ msg = None
835
+ exc = GithubException.GithubException
836
+ if status == 401 and lc_message == "bad credentials":
837
+ exc = GithubException.BadCredentialsException
838
+ elif status == 401 and Consts.headerOTP in headers and re.match(r".*required.*", headers[Consts.headerOTP]):
839
+ exc = GithubException.TwoFactorException
840
+ elif status == 403 and lc_message.startswith("missing or invalid user agent string"):
841
+ exc = GithubException.BadUserAgentException
842
+ elif status == 403 and cls.isRateLimitError(lc_message):
843
+ exc = GithubException.RateLimitExceededException
844
+ elif status == 404 and (lc_message == "not found" or "no object found" in lc_message):
845
+ exc = GithubException.UnknownObjectException
846
+ else:
847
+ # for general GithubException, provide the actual message
848
+ msg = message
849
+
850
+ return exc(status, output, headers, msg)
851
+
852
+ @classmethod
853
+ def isRateLimitError(cls, message: str) -> bool:
854
+ return cls.isPrimaryRateLimitError(message) or cls.isSecondaryRateLimitError(message)
855
+
856
+ @classmethod
857
+ def isPrimaryRateLimitError(cls, message: str) -> bool:
858
+ if not message:
859
+ return False
860
+
861
+ message = message.lower()
862
+ return message.startswith("api rate limit exceeded")
863
+
864
+ @classmethod
865
+ def isSecondaryRateLimitError(cls, message: str) -> bool:
866
+ if not message:
867
+ return False
868
+
869
+ message = message.lower()
870
+ return (
871
+ message.startswith("you have exceeded a secondary rate limit")
872
+ or message.endswith("please retry your request again later.")
873
+ or message.endswith("please wait a few minutes before you try again.")
874
+ )
875
+
876
+ def __structuredFromJson(self, data: str) -> Any:
877
+ if len(data) == 0:
878
+ return None
879
+ else:
880
+ if isinstance(data, bytes):
881
+ data = data.decode("utf-8")
882
+ try:
883
+ return json.loads(data)
884
+ except ValueError:
885
+ if data.startswith("{") or data.startswith("["):
886
+ raise
887
+ return {"data": data}
888
+
889
+ def getFile(
890
+ self,
891
+ url: str,
892
+ path: str,
893
+ parameters: Optional[Dict[str, Any]] = None,
894
+ headers: Optional[Dict[str, str]] = None,
895
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
896
+ chunk_size: Optional[Union[int, None]] = 1,
897
+ ) -> None:
898
+ """
899
+ GET a file from the server and save it to the given path, which includes the filename.
900
+ """
901
+ _, _, stream_chunk_iterator = self.getStream(url, parameters, headers, cnx, chunk_size=chunk_size)
902
+ with open(path, "wb") as f:
903
+ for chunk in stream_chunk_iterator:
904
+ if chunk:
905
+ f.write(chunk)
906
+
907
+ def getStream(
908
+ self,
909
+ url: str,
910
+ parameters: Optional[Dict[str, Any]] = None,
911
+ headers: Optional[Dict[str, str]] = None,
912
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
913
+ chunk_size: Optional[Union[int, None]] = 1,
914
+ ) -> Tuple[int, Dict[str, Any], Iterator]:
915
+ """
916
+ GET a stream from the server.
917
+
918
+ :returns:``(status, headers, stream_chunk_iterator)``
919
+
920
+ """
921
+ if headers is None:
922
+ headers = {}
923
+ headers["Accept"] = "application/octet-stream"
924
+
925
+ def encode(_: Any) -> Tuple[str, str]:
926
+ return "", ""
927
+
928
+ status, responseHeaders, output = self.__requestEncode(
929
+ cnx, "GET", url, parameters, headers, None, encode, stream=True, follow_302_redirect=True
930
+ )
931
+ if isinstance(output, RequestsResponse) or (
932
+ hasattr(output, "iter_content") and hasattr(output, "raise_for_status")
933
+ ):
934
+ output.raise_for_status()
935
+ return status, responseHeaders, output.iter_content(chunk_size=chunk_size)
936
+ raise TypeError(f"Expected a RequestsResponse object: {type(output)}")
937
+
938
+ def requestJson(
939
+ self,
940
+ verb: str,
941
+ url: str,
942
+ parameters: Optional[Dict[str, Any]] = None,
943
+ headers: Optional[Dict[str, Any]] = None,
944
+ input: Optional[Any] = None,
945
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
946
+ follow_302_redirect: bool = False,
947
+ ) -> Tuple[int, Dict[str, Any], str]:
948
+ """
949
+ Send a request with JSON input.
950
+
951
+ :param input: request body, will be serialized as JSON
952
+ :returns:``(status, headers, body)``
953
+
954
+ """
955
+
956
+ def encode(input: Any) -> Tuple[str, str]:
957
+ return "application/json", json.dumps(input)
958
+
959
+ status, responseHeaders, output = self.__requestEncode(
960
+ cnx, verb, url, parameters, headers, input, encode, follow_302_redirect=follow_302_redirect
961
+ )
962
+ if isinstance(output, str):
963
+ return status, responseHeaders, output
964
+ raise ValueError("requestJson() Expected a str, should never happen")
965
+
966
+ def requestMultipart(
967
+ self,
968
+ verb: str,
969
+ url: str,
970
+ parameters: Optional[Dict[str, Any]] = None,
971
+ headers: Optional[Dict[str, Any]] = None,
972
+ input: Optional[Dict[str, str]] = None,
973
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
974
+ ) -> Tuple[int, Dict[str, Any], str]:
975
+ """
976
+ Send a request with multi-part encoding.
977
+
978
+ :param input: request body, will be serialized as multipart form data
979
+ :returns:``(status, headers, body)``
980
+
981
+ """
982
+
983
+ def encode(input: Dict[str, Any]) -> Tuple[str, str]:
984
+ boundary = "----------------------------3c3ba8b523b2"
985
+ eol = "\r\n"
986
+
987
+ encoded_input = ""
988
+ for name, value in input.items():
989
+ encoded_input += f"--{boundary}{eol}"
990
+ encoded_input += f'Content-Disposition: form-data; name="{name}"{eol}'
991
+ encoded_input += eol
992
+ encoded_input += value + eol
993
+ encoded_input += f"--{boundary}--{eol}"
994
+ return f"multipart/form-data; boundary={boundary}", encoded_input
995
+
996
+ status, responseHeaders, output = self.__requestEncode(cnx, verb, url, parameters, headers, input, encode)
997
+ if isinstance(output, str):
998
+ return status, responseHeaders, output
999
+ raise ValueError("requestMultipart() Expected a str, should never happen")
1000
+
1001
+ def requestBlob(
1002
+ self,
1003
+ verb: str,
1004
+ url: str,
1005
+ parameters: Optional[Dict[str, str]] = None,
1006
+ headers: Optional[Dict[str, str]] = None,
1007
+ input: Optional[str] = None,
1008
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
1009
+ ) -> Tuple[int, Dict[str, Any], str]:
1010
+ """
1011
+ Send a request with a file as request body.
1012
+
1013
+ :param input: path to a local file to use for request body
1014
+ :returns:``(status, headers, body)``
1015
+
1016
+ """
1017
+ if headers is None:
1018
+ headers = {}
1019
+
1020
+ def encode(local_path: str) -> Tuple[str, Any]:
1021
+ if "Content-Type" in headers: # type: ignore
1022
+ mime_type = headers["Content-Type"] # type: ignore
1023
+ else:
1024
+ guessed_type = mimetypes.guess_type(local_path)
1025
+ mime_type = guessed_type[0] if guessed_type[0] is not None else Consts.defaultMediaType
1026
+ f = open(local_path, "rb")
1027
+ return mime_type, f
1028
+
1029
+ if input:
1030
+ headers["Content-Length"] = str(os.path.getsize(input))
1031
+
1032
+ status, responseHeaders, output = self.__requestEncode(cnx, verb, url, parameters, headers, input, encode)
1033
+ if isinstance(output, str):
1034
+ return status, responseHeaders, output
1035
+ raise ValueError("requestBlob() Expected a str, should never happen")
1036
+
1037
+ def requestMemoryBlobAndCheck(
1038
+ self,
1039
+ verb: str,
1040
+ url: str,
1041
+ parameters: Any,
1042
+ headers: Dict[str, Any],
1043
+ file_like: BinaryIO,
1044
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]] = None,
1045
+ ) -> Tuple[Dict[str, Any], Any]:
1046
+ """
1047
+ Send a request with a binary file-like for the body.
1048
+
1049
+ :param file_like: file-like object to use for the request body
1050
+ :return: ``(headers: dict, JSON Response: Any)``
1051
+ :raises: :class:`GithubException` for error status codes
1052
+
1053
+ """
1054
+
1055
+ # The expected signature of encode means that the argument is ignored.
1056
+ def encode(_: Any) -> Tuple[str, Any]:
1057
+ return headers["Content-Type"], file_like
1058
+
1059
+ if not cnx:
1060
+ cnx = self.__customConnection(url)
1061
+
1062
+ status, responseHeaders, output = self.__requestEncode(cnx, verb, url, parameters, headers, file_like, encode)
1063
+ if isinstance(output, str):
1064
+ return self.__check(status, responseHeaders, output)
1065
+ raise ValueError("requestMemoryBlobAndCheck() Expected a str, should never happen")
1066
+
1067
+ def __requestEncode(
1068
+ self,
1069
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]],
1070
+ verb: str,
1071
+ url: str,
1072
+ parameters: Optional[Dict[str, str]],
1073
+ requestHeaders: Optional[Dict[str, str]],
1074
+ input: Optional[T],
1075
+ encode: Callable[[T], Tuple[str, Any]],
1076
+ stream: bool = False,
1077
+ follow_302_redirect: bool = False,
1078
+ ) -> Tuple[int, Dict[str, Any], Union[str, object]]:
1079
+ assert verb in ["HEAD", "GET", "POST", "PATCH", "PUT", "DELETE"]
1080
+ if parameters is None:
1081
+ parameters = {}
1082
+ if requestHeaders is None:
1083
+ requestHeaders = {}
1084
+
1085
+ if self.__auth is not None:
1086
+ self.__auth.authentication(requestHeaders)
1087
+ requestHeaders["User-Agent"] = self.__userAgent
1088
+
1089
+ url = self.__makeAbsoluteUrl(url)
1090
+ url = Requester.add_parameters_to_url(url, parameters)
1091
+
1092
+ encoded_input = None
1093
+ if input is not None:
1094
+ requestHeaders["Content-Type"], encoded_input = encode(input)
1095
+
1096
+ self.NEW_DEBUG_FRAME(requestHeaders)
1097
+
1098
+ status, responseHeaders, output = self.__requestRaw(
1099
+ cnx, verb, url, requestHeaders, encoded_input, stream=stream, follow_302_redirect=follow_302_redirect
1100
+ )
1101
+
1102
+ if Consts.headerRateRemaining in responseHeaders and Consts.headerRateLimit in responseHeaders:
1103
+ self.rate_limiting = (
1104
+ # ints expected but sometimes floats returned: https://github.com/PyGithub/PyGithub/pull/2697
1105
+ int(float(responseHeaders[Consts.headerRateRemaining])),
1106
+ int(float(responseHeaders[Consts.headerRateLimit])),
1107
+ )
1108
+ if Consts.headerRateReset in responseHeaders:
1109
+ # ints expected but sometimes floats returned: https://github.com/PyGithub/PyGithub/pull/2697
1110
+ self.rate_limiting_resettime = int(float(responseHeaders[Consts.headerRateReset]))
1111
+
1112
+ if Consts.headerOAuthScopes in responseHeaders:
1113
+ self.oauth_scopes = responseHeaders[Consts.headerOAuthScopes].split(", ")
1114
+
1115
+ self.DEBUG_ON_RESPONSE(status, responseHeaders, output if isinstance(output, str) else "stream")
1116
+
1117
+ return status, responseHeaders, output
1118
+
1119
+ def __requestRaw(
1120
+ self,
1121
+ cnx: Optional[Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]],
1122
+ verb: str,
1123
+ url: str,
1124
+ requestHeaders: Dict[str, str],
1125
+ input: Optional[Any],
1126
+ stream: bool = False,
1127
+ follow_302_redirect: bool = False,
1128
+ ) -> Tuple[int, Dict[str, Any], Union[str, object]]:
1129
+ self.__deferRequest(verb)
1130
+
1131
+ try:
1132
+ original_cnx = cnx
1133
+ if cnx is None:
1134
+ cnx = self.__createConnection()
1135
+ cnx.request(verb, url, input, requestHeaders, stream)
1136
+ response = cnx.getresponse()
1137
+ output = response if stream else response.read()
1138
+ status = response.status
1139
+ responseHeaders = {k.lower(): v for k, v in response.getheaders()}
1140
+
1141
+ if input:
1142
+ if isinstance(input, IOBase):
1143
+ input.close()
1144
+
1145
+ self.__log(verb, url, requestHeaders, input, status, responseHeaders, output)
1146
+
1147
+ if status == 202 and (
1148
+ verb == "GET" or verb == "HEAD"
1149
+ ): # only for requests that are considered 'safe' in RFC 2616
1150
+ time.sleep(Consts.PROCESSING_202_WAIT_TIME)
1151
+ return self.__requestRaw(original_cnx, verb, url, requestHeaders, input, stream=stream)
1152
+
1153
+ if status == 301 and "location" in responseHeaders:
1154
+ location = responseHeaders["location"]
1155
+ o = urllib.parse.urlparse(location)
1156
+ if o.scheme != self.__scheme:
1157
+ raise RuntimeError(
1158
+ f"Github server redirected from {self.__scheme} protocol to {o.scheme}, "
1159
+ f"please correct your Github server URL via base_url: Github(base_url=...)"
1160
+ )
1161
+ if o.hostname != self.__hostname:
1162
+ raise RuntimeError(
1163
+ f"Github server redirected from host {self.__hostname} to {o.hostname}, "
1164
+ f"please correct your Github server URL via base_url: Github(base_url=...)"
1165
+ )
1166
+ if o.path == url:
1167
+ port = ":" + str(self.__port) if self.__port is not None else ""
1168
+ requested_location = f"{self.__scheme}://{self.__hostname}{port}{url}"
1169
+ raise RuntimeError(
1170
+ f"Requested {requested_location} but server redirected to {location}, "
1171
+ f"you may need to correct your Github server URL "
1172
+ f"via base_url: Github(base_url=...)"
1173
+ )
1174
+ if self._logger.isEnabledFor(logging.INFO):
1175
+ self._logger.info(f"Following Github server redirection from {url} to {o.path}")
1176
+ return self.__requestRaw(original_cnx, verb, o.path, requestHeaders, input, stream=stream)
1177
+ if status == 302 and follow_302_redirect and "location" in responseHeaders:
1178
+ location = responseHeaders["location"]
1179
+ o = urllib.parse.urlparse(location)
1180
+ cnx = self.__customConnection(location)
1181
+ path = self.__makeAbsoluteUrl(location)
1182
+ if self._logger.isEnabledFor(logging.DEBUG):
1183
+ self._logger.debug(f"Following Github server redirection (302) from {url} to {o.path}")
1184
+ # remove auth to not leak authentication to redirection location
1185
+ if o.hostname != self.__hostname:
1186
+ del requestHeaders["Authorization"]
1187
+ return self.__requestRaw(
1188
+ cnx, verb, path, requestHeaders, input, stream=stream, follow_302_redirect=True
1189
+ )
1190
+ return status, responseHeaders, output
1191
+ finally:
1192
+ # we record the time of this request after it finished
1193
+ # to defer next request starting from this request's end, not start
1194
+ self.__recordRequestTime(verb)
1195
+
1196
+ def __deferRequest(self, verb: str) -> None:
1197
+ # Ensures at least self.__seconds_between_requests seconds have passed since any last request
1198
+ # and self.__seconds_between_writes seconds have passed since last write request (if verb refers to a write).
1199
+ # Uses self.__last_requests.
1200
+ requests = self.__last_requests.values()
1201
+ writes = [l for v, l in self.__last_requests.items() if v != "GET"]
1202
+
1203
+ last_request = max(requests) if requests else 0
1204
+ last_write = max(writes) if writes else 0
1205
+
1206
+ next_request = (last_request + self.__seconds_between_requests) if self.__seconds_between_requests else 0
1207
+ next_write = (last_write + self.__seconds_between_writes) if self.__seconds_between_writes else 0
1208
+
1209
+ next = next_request if verb == "GET" else max(next_request, next_write)
1210
+ defer = max(next - datetime.now(timezone.utc).timestamp(), 0)
1211
+ if defer > 0:
1212
+ if self.__logger is None:
1213
+ self.__logger = logging.getLogger(__name__)
1214
+ self.__logger.debug(f"sleeping {defer}s before next GitHub request")
1215
+ time.sleep(defer)
1216
+
1217
+ def __recordRequestTime(self, verb: str) -> None:
1218
+ # Updates self.__last_requests with current timestamp for given verb
1219
+ self.__last_requests[verb] = datetime.now(timezone.utc).timestamp()
1220
+
1221
+ def __makeAbsoluteUrl(self, url: str) -> str:
1222
+ # URLs generated locally will be relative to __base_url
1223
+ # URLs returned from the server will start with __base_url
1224
+ if url.startswith("/"):
1225
+ url = f"{self.__prefix}{url}"
1226
+ else:
1227
+ o = urllib.parse.urlparse(url)
1228
+ assert o.hostname in [
1229
+ self.__hostname,
1230
+ "uploads.github.com",
1231
+ "status.github.com",
1232
+ "github.com",
1233
+ "objects.githubusercontent.com",
1234
+ ], o.hostname
1235
+ assert o.path.startswith((self.__prefix, self.__graphql_prefix, "/api/", "/login/oauth")), o.path
1236
+ assert o.port == self.__port, o.port
1237
+ url = o.path
1238
+ if o.query != "":
1239
+ url += f"?{o.query}"
1240
+ return url
1241
+
1242
+ def __createConnection(
1243
+ self, hostname: Optional[str] = None
1244
+ ) -> Union[HTTPRequestsConnectionClass, HTTPSRequestsConnectionClass]:
1245
+ if self.__persist and self.__connection is not None and hostname is not None and hostname == self.__hostname:
1246
+ return self.__connection
1247
+
1248
+ with self.__connection_lock:
1249
+ if self.__connection is not None and hostname is not None and hostname == self.__hostname:
1250
+ if self.__persist:
1251
+ return self.__connection
1252
+ if self.__connection is not None:
1253
+ self.__connection.close()
1254
+ self.__connection = None
1255
+ self.__connection = self.__connectionClass(
1256
+ hostname if hostname is not None else self.__hostname,
1257
+ self.__port,
1258
+ retry=self.__retry,
1259
+ pool_size=self.__pool_size,
1260
+ timeout=self.__timeout,
1261
+ verify=self.__verify,
1262
+ )
1263
+
1264
+ return self.__connection
1265
+
1266
+ @property
1267
+ def _logger(self) -> logging.Logger:
1268
+ if self.__logger is None:
1269
+ self.__logger = logging.getLogger(__name__)
1270
+ return self.__logger
1271
+
1272
+ def __log(
1273
+ self,
1274
+ verb: str,
1275
+ url: str,
1276
+ requestHeaders: Dict[str, str],
1277
+ input: Optional[Any],
1278
+ status: Optional[int],
1279
+ responseHeaders: Dict[str, Any],
1280
+ output: Optional[Union[str, object]],
1281
+ ) -> None:
1282
+ if self._logger.isEnabledFor(logging.DEBUG):
1283
+ headersForRequest = requestHeaders.copy()
1284
+ if self.__auth:
1285
+ self.__auth.mask_authentication(headersForRequest)
1286
+ self._logger.debug(
1287
+ "%s %s://%s%s %s %s ==> %i %s %s",
1288
+ verb,
1289
+ self.__scheme,
1290
+ self.__hostname,
1291
+ url,
1292
+ headersForRequest,
1293
+ input,
1294
+ status,
1295
+ responseHeaders,
1296
+ output if isinstance(output, str) else "stream",
1297
+ )
1298
+
1299
+
1300
+ class WithRequester(Generic[T]):
1301
+ """
1302
+ Mixin class that allows to set a requester.
1303
+ """
1304
+
1305
+ __requester: Requester
1306
+
1307
+ def __init__(self) -> None:
1308
+ self.__requester: Optional[Requester] = None # type: ignore
1309
+
1310
+ @property
1311
+ def requester(self) -> Requester:
1312
+ return self.__requester
1313
+
1314
+ def withRequester(self, requester: Requester) -> "WithRequester[T]":
1315
+ assert isinstance(requester, Requester), requester
1316
+ self.__requester = requester
1317
+ return self
venv/lib/python3.10/site-packages/github/RequiredPullRequestReviews.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2017 Jannis Gebauer <ja.geb@me.com> #
11
+ # Copyright 2017 Simon <spam@esemi.ru> #
12
+ # Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
14
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
16
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
18
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
19
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
22
+ # Copyright 2024 Benjamin K <53038537+treee111@users.noreply.github.com> #
23
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
24
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
25
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
26
+ # #
27
+ # This file is part of PyGithub. #
28
+ # http://pygithub.readthedocs.io/ #
29
+ # #
30
+ # PyGithub is free software: you can redistribute it and/or modify it under #
31
+ # the terms of the GNU Lesser General Public License as published by the Free #
32
+ # Software Foundation, either version 3 of the License, or (at your option) #
33
+ # any later version. #
34
+ # #
35
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
36
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
37
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
38
+ # details. #
39
+ # #
40
+ # You should have received a copy of the GNU Lesser General Public License #
41
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
42
+ # #
43
+ ################################################################################
44
+
45
+ from __future__ import annotations
46
+
47
+ from typing import TYPE_CHECKING, Any
48
+
49
+ import github.NamedUser
50
+ import github.Team
51
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
52
+
53
+ if TYPE_CHECKING:
54
+ from github.NamedUser import NamedUser
55
+ from github.Team import Team
56
+
57
+
58
+ class RequiredPullRequestReviews(CompletableGithubObject):
59
+ """
60
+ This class represents Required Pull Request Reviews.
61
+
62
+ The reference can be found here
63
+ https://docs.github.com/en/rest/reference/repos#get-pull-request-review-protection
64
+
65
+ The OpenAPI schema can be found at
66
+ - /components/schemas/protected-branch-pull-request-review
67
+ - /components/schemas/protected-branch/properties/required_pull_request_reviews
68
+
69
+ """
70
+
71
+ def _initAttributes(self) -> None:
72
+ self._dismiss_stale_reviews: Attribute[bool] = NotSet
73
+ self._require_code_owner_reviews: Attribute[bool] = NotSet
74
+ self._require_last_push_approval: Attribute[bool] = NotSet
75
+ self._required_approving_review_count: Attribute[int] = NotSet
76
+ self._teams: Attribute[list[Team]] = NotSet
77
+ self._users: Attribute[list[NamedUser]] = NotSet
78
+
79
+ def __repr__(self) -> str:
80
+ return self.get__repr__(
81
+ {
82
+ "url": self._url.value,
83
+ "dismiss_stale_reviews": self._dismiss_stale_reviews.value,
84
+ "require_code_owner_reviews": self._require_code_owner_reviews.value,
85
+ "require_last_push_approval": self._require_last_push_approval.value,
86
+ }
87
+ )
88
+
89
+ @property
90
+ def dismiss_stale_reviews(self) -> bool:
91
+ self._completeIfNotSet(self._dismiss_stale_reviews)
92
+ return self._dismiss_stale_reviews.value
93
+
94
+ @property
95
+ def dismissal_teams(self) -> list[Team]:
96
+ self._completeIfNotSet(self._teams)
97
+ return self._teams.value
98
+
99
+ @property
100
+ def dismissal_users(self) -> list[NamedUser]:
101
+ self._completeIfNotSet(self._users)
102
+ return self._users.value
103
+
104
+ @property
105
+ def require_code_owner_reviews(self) -> bool:
106
+ self._completeIfNotSet(self._require_code_owner_reviews)
107
+ return self._require_code_owner_reviews.value
108
+
109
+ @property
110
+ def require_last_push_approval(self) -> bool:
111
+ self._completeIfNotSet(self._require_last_push_approval)
112
+ return self._require_last_push_approval.value
113
+
114
+ @property
115
+ def required_approving_review_count(self) -> int:
116
+ self._completeIfNotSet(self._required_approving_review_count)
117
+ return self._required_approving_review_count.value
118
+
119
+ @property
120
+ def url(self) -> str:
121
+ self._completeIfNotSet(self._url)
122
+ return self._url.value
123
+
124
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
125
+ if "dismiss_stale_reviews" in attributes: # pragma no branch
126
+ self._dismiss_stale_reviews = self._makeBoolAttribute(attributes["dismiss_stale_reviews"])
127
+ if "dismissal_restrictions" in attributes: # pragma no branch
128
+ if "users" in attributes["dismissal_restrictions"]:
129
+ self._users = self._makeListOfClassesAttribute(
130
+ github.NamedUser.NamedUser,
131
+ attributes["dismissal_restrictions"]["users"],
132
+ )
133
+ if "teams" in attributes["dismissal_restrictions"]: # pragma no branch
134
+ self._teams = self._makeListOfClassesAttribute(
135
+ github.Team.Team, attributes["dismissal_restrictions"]["teams"]
136
+ )
137
+ if "require_code_owner_reviews" in attributes: # pragma no branch
138
+ self._require_code_owner_reviews = self._makeBoolAttribute(attributes["require_code_owner_reviews"])
139
+ if "require_last_push_approval" in attributes: # pragma no branch
140
+ self._require_last_push_approval = self._makeBoolAttribute(attributes["require_last_push_approval"])
141
+ if "required_approving_review_count" in attributes: # pragma no branch
142
+ self._required_approving_review_count = self._makeIntAttribute(
143
+ attributes["required_approving_review_count"]
144
+ )
145
+ if "url" in attributes: # pragma no branch
146
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/RequiredStatusChecks.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
11
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
12
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
13
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
15
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
17
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
18
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
21
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
22
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
23
+ # #
24
+ # This file is part of PyGithub. #
25
+ # http://pygithub.readthedocs.io/ #
26
+ # #
27
+ # PyGithub is free software: you can redistribute it and/or modify it under #
28
+ # the terms of the GNU Lesser General Public License as published by the Free #
29
+ # Software Foundation, either version 3 of the License, or (at your option) #
30
+ # any later version. #
31
+ # #
32
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
33
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
34
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
35
+ # details. #
36
+ # #
37
+ # You should have received a copy of the GNU Lesser General Public License #
38
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
39
+ # #
40
+ ################################################################################
41
+
42
+ from __future__ import annotations
43
+
44
+ from typing import Any
45
+
46
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
47
+
48
+
49
+ class RequiredStatusChecks(CompletableGithubObject):
50
+ """
51
+ This class represents Required Status Checks.
52
+
53
+ The reference can be found here
54
+ https://docs.github.com/en/rest/reference/repos#get-status-checks-protection
55
+
56
+ The OpenAPI schema can be found at
57
+ - /components/schemas/protected-branch-pull-request-review
58
+ - /components/schemas/protected-branch-required-status-check
59
+ - /components/schemas/status-check-policy
60
+
61
+ """
62
+
63
+ def _initAttributes(self) -> None:
64
+ self._contexts: Attribute[list[str]] = NotSet
65
+ self._strict: Attribute[bool] = NotSet
66
+ self._url: Attribute[str] = NotSet
67
+
68
+ def __repr__(self) -> str:
69
+ return self.get__repr__({"strict": self._strict.value, "url": self._url.value})
70
+
71
+ @property
72
+ def contexts(self) -> list[str]:
73
+ self._completeIfNotSet(self._contexts)
74
+ return self._contexts.value
75
+
76
+ @property
77
+ def strict(self) -> bool:
78
+ self._completeIfNotSet(self._strict)
79
+ return self._strict.value
80
+
81
+ @property
82
+ def url(self) -> str:
83
+ self._completeIfNotSet(self._url)
84
+ return self._url.value
85
+
86
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
87
+ if "contexts" in attributes: # pragma no branch
88
+ self._contexts = self._makeListOfStringsAttribute(attributes["contexts"])
89
+ if "strict" in attributes: # pragma no branch
90
+ self._strict = self._makeBoolAttribute(attributes["strict"])
91
+ if "url" in attributes: # pragma no branch
92
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/Secret.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2023 Andrew Dawes <53574062+AndrewJDawes@users.noreply.github.com> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Mauricio Alejandro Martínez Pacheco <mauricio.martinez@premise.com>#
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from datetime import datetime
42
+ from typing import Any, Dict
43
+
44
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
45
+
46
+
47
+ class Secret(CompletableGithubObject):
48
+ """
49
+ This class represents a GitHub secret.
50
+
51
+ The reference can be found here
52
+ https://docs.github.com/en/rest/actions/secrets
53
+
54
+ """
55
+
56
+ def _initAttributes(self) -> None:
57
+ self._created_at: Attribute[datetime] = NotSet
58
+ self._name: Attribute[str] = NotSet
59
+ self._secrets_url: Attribute[str] = NotSet
60
+ self._updated_at: Attribute[datetime] = NotSet
61
+ self._url: Attribute[str] = NotSet
62
+
63
+ def __repr__(self) -> str:
64
+ return self.get__repr__({"name": self.name})
65
+
66
+ @property
67
+ def created_at(self) -> datetime:
68
+ """
69
+ :type: datetime.datetime
70
+ """
71
+ self._completeIfNotSet(self._created_at)
72
+ return self._created_at.value
73
+
74
+ @property
75
+ def name(self) -> str:
76
+ """
77
+ :type: string
78
+ """
79
+ self._completeIfNotSet(self._name)
80
+ return self._name.value
81
+
82
+ @property
83
+ def secrets_url(self) -> str:
84
+ """
85
+ :type: string
86
+ """
87
+ return self._secrets_url.value
88
+
89
+ @property
90
+ def updated_at(self) -> datetime:
91
+ """
92
+ :type: datetime.datetime
93
+ """
94
+ self._completeIfNotSet(self._updated_at)
95
+ return self._updated_at.value
96
+
97
+ @property
98
+ def url(self) -> str:
99
+ """
100
+ :type: string
101
+ """
102
+ # Construct url from secrets_url and name, if self._url. is not set
103
+ if self._url is NotSet:
104
+ self._url = self._makeStringAttribute(self.secrets_url + "/" + self.name)
105
+ return self._url.value
106
+
107
+ def delete(self) -> None:
108
+ """
109
+ :calls: `DELETE {secret_url} <https://docs.github.com/en/rest/actions/secrets>`_
110
+ :rtype: None
111
+ """
112
+ self._requester.requestJsonAndCheck("DELETE", self.url)
113
+
114
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
115
+ if "created_at" in attributes:
116
+ self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
117
+ if "name" in attributes:
118
+ self._name = self._makeStringAttribute(attributes["name"])
119
+ if "secrets_url" in attributes:
120
+ self._secrets_url = self._makeStringAttribute(attributes["secrets_url"])
121
+ if "updated_at" in attributes:
122
+ self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
123
+ if "url" in attributes:
124
+ self._url = self._makeStringAttribute(attributes["url"])
venv/lib/python3.10/site-packages/github/SecurityAndAnalysis.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
16
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Nikolay Yurin <yurinnick93@gmail.com> #
19
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
20
+ # Copyright 2024 Caleb McCombs <caleb@mccombalot.net> #
21
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
22
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
23
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
24
+ # #
25
+ # This file is part of PyGithub. #
26
+ # http://pygithub.readthedocs.io/ #
27
+ # #
28
+ # PyGithub is free software: you can redistribute it and/or modify it under #
29
+ # the terms of the GNU Lesser General Public License as published by the Free #
30
+ # Software Foundation, either version 3 of the License, or (at your option) #
31
+ # any later version. #
32
+ # #
33
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
34
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
35
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
36
+ # details. #
37
+ # #
38
+ # You should have received a copy of the GNU Lesser General Public License #
39
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
40
+ # #
41
+ ################################################################################
42
+
43
+ from __future__ import annotations
44
+
45
+ from typing import Any
46
+
47
+ import github.SecurityAndAnalysisFeature
48
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
49
+
50
+
51
+ class SecurityAndAnalysis(NonCompletableGithubObject):
52
+ """
53
+ This class represents Security and Analysis Settings.
54
+
55
+ The OpenAPI schema can be found at
56
+ - /components/schemas/security-and-analysis
57
+
58
+ """
59
+
60
+ def _initAttributes(self) -> None:
61
+ self._advanced_security: Attribute[github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature] = NotSet
62
+ self._dependabot_security_updates: Attribute[
63
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature
64
+ ] = NotSet
65
+ self._secret_scanning: Attribute[github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature] = NotSet
66
+ self._secret_scanning_ai_detection: Attribute[str] = NotSet
67
+ self._secret_scanning_non_provider_patterns: Attribute[
68
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature
69
+ ] = NotSet
70
+ self._secret_scanning_push_protection: Attribute[
71
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature
72
+ ] = NotSet
73
+ self._secret_scanning_validity_checks: Attribute[
74
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature
75
+ ] = NotSet
76
+
77
+ def __repr__(self) -> str:
78
+ repr_attributes = {
79
+ "advanced_security": repr(self._advanced_security.value),
80
+ "dependabot_security_updates": repr(self._dependabot_security_updates.value),
81
+ "secret_scanning": repr(self._secret_scanning.value),
82
+ "secret_scanning_non_provider_patterns": repr(self._secret_scanning_non_provider_patterns.value),
83
+ "secret_scanning_push_protection": repr(self._secret_scanning_push_protection.value),
84
+ "secret_scanning_validity_checks": repr(self._secret_scanning_validity_checks.value),
85
+ }
86
+
87
+ return self.get__repr__(repr_attributes)
88
+
89
+ @property
90
+ def advanced_security(self) -> github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature:
91
+ return self._advanced_security.value
92
+
93
+ @property
94
+ def dependabot_security_updates(self) -> github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature:
95
+ return self._dependabot_security_updates.value
96
+
97
+ @property
98
+ def secret_scanning(self) -> github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature:
99
+ return self._secret_scanning.value
100
+
101
+ @property
102
+ def secret_scanning_ai_detection(self) -> str:
103
+ return self._secret_scanning_ai_detection.value
104
+
105
+ @property
106
+ def secret_scanning_non_provider_patterns(self) -> github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature:
107
+ return self._secret_scanning_non_provider_patterns.value
108
+
109
+ @property
110
+ def secret_scanning_push_protection(self) -> github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature:
111
+ return self._secret_scanning_push_protection.value
112
+
113
+ @property
114
+ def secret_scanning_validity_checks(self) -> github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature:
115
+ return self._secret_scanning_validity_checks.value
116
+
117
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
118
+ if "advanced_security" in attributes: # pragma no branch
119
+ self._advanced_security = self._makeClassAttribute(
120
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature, attributes["advanced_security"]
121
+ )
122
+ if "dependabot_security_updates" in attributes: # pragma no branch
123
+ self._dependabot_security_updates = self._makeClassAttribute(
124
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature, attributes["dependabot_security_updates"]
125
+ )
126
+ if "secret_scanning" in attributes: # pragma no branch
127
+ self._secret_scanning = self._makeClassAttribute(
128
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature, attributes["secret_scanning"]
129
+ )
130
+ if "secret_scanning_ai_detection" in attributes: # pragma no branch
131
+ self._secret_scanning_ai_detection = self._makeStringAttribute(attributes["secret_scanning_ai_detection"])
132
+ if "secret_scanning_non_provider_patterns" in attributes: # pragma no branch
133
+ self._secret_scanning_non_provider_patterns = self._makeClassAttribute(
134
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature,
135
+ attributes["secret_scanning_non_provider_patterns"],
136
+ )
137
+ if "secret_scanning_push_protection" in attributes: # pragma no branch
138
+ self._secret_scanning_push_protection = self._makeClassAttribute(
139
+ github.SecurityAndAnalysisFeature.SecurityAndAnalysisFeature,
140
+ attributes["secret_scanning_push_protection"],
141
+ )
venv/lib/python3.10/site-packages/github/SecurityAndAnalysisFeature.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
16
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
17
+ # Copyright 2024 Caleb McCombs <caleb@mccombalot.net> #
18
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
20
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
21
+ # #
22
+ # This file is part of PyGithub. #
23
+ # http://pygithub.readthedocs.io/ #
24
+ # #
25
+ # PyGithub is free software: you can redistribute it and/or modify it under #
26
+ # the terms of the GNU Lesser General Public License as published by the Free #
27
+ # Software Foundation, either version 3 of the License, or (at your option) #
28
+ # any later version. #
29
+ # #
30
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
31
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
32
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
33
+ # details. #
34
+ # #
35
+ # You should have received a copy of the GNU Lesser General Public License #
36
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
37
+ # #
38
+ ################################################################################
39
+
40
+ from typing import Any, Dict
41
+
42
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
43
+
44
+
45
+ class SecurityAndAnalysisFeature(NonCompletableGithubObject):
46
+ """
47
+ This class represents a Security and Analysis feature status.
48
+
49
+ The OpenAPI schema can be found at
50
+ - /components/schemas/security-and-analysis/properties/advanced_security
51
+ - /components/schemas/security-and-analysis/properties/dependabot_security_updates
52
+ - /components/schemas/security-and-analysis/properties/secret_scanning
53
+ - /components/schemas/security-and-analysis/properties/secret_scanning_non_provider_patterns
54
+ - /components/schemas/security-and-analysis/properties/secret_scanning_push_protection
55
+
56
+ """
57
+
58
+ def _initAttributes(self) -> None:
59
+ self._status: Attribute[str] = NotSet
60
+
61
+ def __repr__(self) -> str:
62
+ return self.get__repr__({"status": self._status.value})
63
+
64
+ @property
65
+ def status(self) -> str:
66
+ return self._status.value
67
+
68
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
69
+ if "status" in attributes: # pragma no branch
70
+ self._status = self._makeStringAttribute(attributes["status"])
venv/lib/python3.10/site-packages/github/SelfHostedActionsRunner.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
9
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
10
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
11
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2020 Victor Zeng <zacker150@users.noreply.github.com> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
18
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
20
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
21
+ # #
22
+ # This file is part of PyGithub. #
23
+ # http://pygithub.readthedocs.io/ #
24
+ # #
25
+ # PyGithub is free software: you can redistribute it and/or modify it under #
26
+ # the terms of the GNU Lesser General Public License as published by the Free #
27
+ # Software Foundation, either version 3 of the License, or (at your option) #
28
+ # any later version. #
29
+ # #
30
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
31
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
32
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
33
+ # details. #
34
+ # #
35
+ # You should have received a copy of the GNU Lesser General Public License #
36
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
37
+ # #
38
+ ################################################################################
39
+
40
+ from __future__ import annotations
41
+
42
+ from typing import Any
43
+
44
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
45
+
46
+
47
+ class SelfHostedActionsRunner(NonCompletableGithubObject):
48
+ """
49
+ This class represents Self-hosted GitHub Actions Runners.
50
+
51
+ The reference can be found at
52
+ https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#self-hosted-runners
53
+
54
+ The OpenAPI schema can be found at
55
+ - /components/schemas/runner
56
+
57
+ """
58
+
59
+ def _initAttributes(self) -> None:
60
+ self._busy: Attribute[bool] = NotSet
61
+ self._id: Attribute[int] = NotSet
62
+ self._labels: Attribute[list[dict[str, int | str]]] = NotSet
63
+ self._name: Attribute[str] = NotSet
64
+ self._os: Attribute[str] = NotSet
65
+ self._runner_group_id: Attribute[int] = NotSet
66
+ self._status: Attribute[str] = NotSet
67
+
68
+ def __repr__(self) -> str:
69
+ return self.get__repr__({"name": self._name.value})
70
+
71
+ @property
72
+ def busy(self) -> bool:
73
+ return self._busy.value
74
+
75
+ @property
76
+ def id(self) -> int:
77
+ return self._id.value
78
+
79
+ @property
80
+ def labels(self) -> list[dict[str, int | str]]:
81
+ return self._labels.value
82
+
83
+ @property
84
+ def name(self) -> str:
85
+ return self._name.value
86
+
87
+ @property
88
+ def os(self) -> str:
89
+ return self._os.value
90
+
91
+ @property
92
+ def runner_group_id(self) -> int:
93
+ return self._runner_group_id.value
94
+
95
+ @property
96
+ def status(self) -> str:
97
+ return self._status.value
98
+
99
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
100
+ if "busy" in attributes:
101
+ self._busy = self._makeBoolAttribute(attributes["busy"])
102
+ if "id" in attributes: # pragma no branch
103
+ self._id = self._makeIntAttribute(attributes["id"])
104
+ if "labels" in attributes:
105
+ self._labels = self._makeListOfDictsAttribute(attributes["labels"])
106
+ if "name" in attributes: # pragma no branch
107
+ self._name = self._makeStringAttribute(attributes["name"])
108
+ if "os" in attributes: # pragma no branch
109
+ self._os = self._makeStringAttribute(attributes["os"])
110
+ if "runner_group_id" in attributes: # pragma no branch
111
+ self._runner_group_id = self._makeIntAttribute(attributes["runner_group_id"])
112
+ if "status" in attributes: # pragma no branch
113
+ self._status = self._makeStringAttribute(attributes["status"])
venv/lib/python3.10/site-packages/github/SourceImport.py ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2018 Hayden Fuss <wifu1234@gmail.com> #
4
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
5
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
6
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
7
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
8
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
9
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
10
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
11
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
12
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
13
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
14
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
15
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
16
+ # #
17
+ # This file is part of PyGithub. #
18
+ # http://pygithub.readthedocs.io/ #
19
+ # #
20
+ # PyGithub is free software: you can redistribute it and/or modify it under #
21
+ # the terms of the GNU Lesser General Public License as published by the Free #
22
+ # Software Foundation, either version 3 of the License, or (at your option) #
23
+ # any later version. #
24
+ # #
25
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
26
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
27
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
28
+ # details. #
29
+ # #
30
+ # You should have received a copy of the GNU Lesser General Public License #
31
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
32
+ # #
33
+ ################################################################################
34
+
35
+ from __future__ import annotations
36
+
37
+ from typing import Any
38
+
39
+ from github import Consts
40
+ from github.GithubObject import Attribute, CompletableGithubObject, NotSet
41
+
42
+
43
+ class SourceImport(CompletableGithubObject):
44
+ """
45
+ This class represents SourceImports.
46
+
47
+ The reference can be found here
48
+ https://docs.github.com/en/rest/reference/migrations#source-imports
49
+
50
+ The OpenAPI schema can be found at
51
+ - /components/schemas/import
52
+
53
+ """
54
+
55
+ def _initAttributes(self) -> None:
56
+ self._authors_count: Attribute[int] = NotSet
57
+ self._authors_url: Attribute[str] = NotSet
58
+ self._commit_count: Attribute[int] = NotSet
59
+ self._error_message: Attribute[str] = NotSet
60
+ self._failed_step: Attribute[str] = NotSet
61
+ self._has_large_files: Attribute[bool] = NotSet
62
+ self._html_url: Attribute[str] = NotSet
63
+ self._import_percent: Attribute[int] = NotSet
64
+ self._large_files_count: Attribute[int] = NotSet
65
+ self._large_files_size: Attribute[int] = NotSet
66
+ self._message: Attribute[str] = NotSet
67
+ self._project_choices: Attribute[list[dict[str, Any]]] = NotSet
68
+ self._push_percent: Attribute[int] = NotSet
69
+ self._repository_url: Attribute[str] = NotSet
70
+ self._status: Attribute[str] = NotSet
71
+ self._status_text: Attribute[str] = NotSet
72
+ self._svc_root: Attribute[str] = NotSet
73
+ self._svn_root: Attribute[str] = NotSet
74
+ self._tfvc_project: Attribute[str] = NotSet
75
+ self._url: Attribute[str] = NotSet
76
+ self._use_lfs: Attribute[str] = NotSet
77
+ self._vcs: Attribute[str] = NotSet
78
+ self._vcs_url: Attribute[str] = NotSet
79
+
80
+ def __repr__(self) -> str:
81
+ return self.get__repr__(
82
+ {
83
+ "vcs_url": self._vcs_url.value,
84
+ "repository_url": self._repository_url.value,
85
+ "status": self._status.value,
86
+ "url": self._url.value,
87
+ }
88
+ )
89
+
90
+ @property
91
+ def authors_count(self) -> int:
92
+ self._completeIfNotSet(self._authors_count)
93
+ return self._authors_count.value
94
+
95
+ @property
96
+ def authors_url(self) -> str:
97
+ self._completeIfNotSet(self._authors_url)
98
+ return self._authors_url.value
99
+
100
+ @property
101
+ def commit_count(self) -> int:
102
+ self._completeIfNotSet(self._commit_count)
103
+ return self._commit_count.value
104
+
105
+ @property
106
+ def error_message(self) -> str:
107
+ self._completeIfNotSet(self._error_message)
108
+ return self._error_message.value
109
+
110
+ @property
111
+ def failed_step(self) -> str:
112
+ self._completeIfNotSet(self._failed_step)
113
+ return self._failed_step.value
114
+
115
+ @property
116
+ def has_large_files(self) -> bool:
117
+ self._completeIfNotSet(self._has_large_files)
118
+ return self._has_large_files.value
119
+
120
+ @property
121
+ def html_url(self) -> str:
122
+ self._completeIfNotSet(self._html_url)
123
+ return self._html_url.value
124
+
125
+ @property
126
+ def import_percent(self) -> int:
127
+ self._completeIfNotSet(self._import_percent)
128
+ return self._import_percent.value
129
+
130
+ @property
131
+ def large_files_count(self) -> int:
132
+ self._completeIfNotSet(self._large_files_count)
133
+ return self._large_files_count.value
134
+
135
+ @property
136
+ def large_files_size(self) -> int:
137
+ self._completeIfNotSet(self._large_files_size)
138
+ return self._large_files_size.value
139
+
140
+ @property
141
+ def message(self) -> str:
142
+ self._completeIfNotSet(self._message)
143
+ return self._message.value
144
+
145
+ @property
146
+ def project_choices(self) -> list[dict[str, Any]]:
147
+ self._completeIfNotSet(self._project_choices)
148
+ return self._project_choices.value
149
+
150
+ @property
151
+ def push_percent(self) -> int:
152
+ self._completeIfNotSet(self._push_percent)
153
+ return self._push_percent.value
154
+
155
+ @property
156
+ def repository_url(self) -> str:
157
+ self._completeIfNotSet(self._repository_url)
158
+ return self._repository_url.value
159
+
160
+ @property
161
+ def status(self) -> str:
162
+ self._completeIfNotSet(self._status)
163
+ return self._status.value
164
+
165
+ @property
166
+ def status_text(self) -> str:
167
+ self._completeIfNotSet(self._status_text)
168
+ return self._status_text.value
169
+
170
+ @property
171
+ def svc_root(self) -> str:
172
+ self._completeIfNotSet(self._svc_root)
173
+ return self._svc_root.value
174
+
175
+ @property
176
+ def svn_root(self) -> str:
177
+ self._completeIfNotSet(self._svn_root)
178
+ return self._svn_root.value
179
+
180
+ @property
181
+ def tfvc_project(self) -> str:
182
+ self._completeIfNotSet(self._tfvc_project)
183
+ return self._tfvc_project.value
184
+
185
+ @property
186
+ def url(self) -> str:
187
+ self._completeIfNotSet(self._url)
188
+ return self._url.value
189
+
190
+ @property
191
+ def use_lfs(self) -> str:
192
+ self._completeIfNotSet(self._use_lfs)
193
+ return self._use_lfs.value
194
+
195
+ @property
196
+ def vcs(self) -> str:
197
+ self._completeIfNotSet(self._vcs)
198
+ return self._vcs.value
199
+
200
+ @property
201
+ def vcs_url(self) -> str:
202
+ self._completeIfNotSet(self._vcs_url)
203
+ return self._vcs_url.value
204
+
205
+ def update(self, additional_headers: None | dict[str, Any] = None) -> bool:
206
+ import_header = {"Accept": Consts.mediaTypeImportPreview}
207
+ return super().update(additional_headers=import_header)
208
+
209
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
210
+ if "authors_count" in attributes: # pragma no branch
211
+ self._authors_count = self._makeIntAttribute(attributes["authors_count"])
212
+ if "authors_url" in attributes: # pragma no branch
213
+ self._authors_url = self._makeStringAttribute(attributes["authors_url"])
214
+ if "commit_count" in attributes: # pragma no branch
215
+ self._commit_count = self._makeIntAttribute(attributes["commit_count"])
216
+ if "error_message" in attributes: # pragma no branch
217
+ self._error_message = self._makeStringAttribute(attributes["error_message"])
218
+ if "failed_step" in attributes: # pragma no branch
219
+ self._failed_step = self._makeStringAttribute(attributes["failed_step"])
220
+ if "has_large_files" in attributes: # pragma no branch
221
+ self._has_large_files = self._makeBoolAttribute(attributes["has_large_files"])
222
+ if "html_url" in attributes: # pragma no branch
223
+ self._html_url = self._makeStringAttribute(attributes["html_url"])
224
+ if "import_percent" in attributes: # pragma no branch
225
+ self._import_percent = self._makeIntAttribute(attributes["import_percent"])
226
+ if "large_files_count" in attributes: # pragma no branch
227
+ self._large_files_count = self._makeIntAttribute(attributes["large_files_count"])
228
+ if "large_files_size" in attributes: # pragma no branch
229
+ self._large_files_size = self._makeIntAttribute(attributes["large_files_size"])
230
+ if "message" in attributes: # pragma no branch
231
+ self._message = self._makeStringAttribute(attributes["message"])
232
+ if "project_choices" in attributes: # pragma no branch
233
+ self._project_choices = self._makeListOfDictsAttribute(attributes["project_choices"])
234
+ if "push_percent" in attributes: # pragma no branch
235
+ self._push_percent = self._makeIntAttribute(attributes["push_percent"])
236
+ if "repository_url" in attributes: # pragma no branch
237
+ self._repository_url = self._makeStringAttribute(attributes["repository_url"])
238
+ if "status" in attributes: # pragma no branch
239
+ self._status = self._makeStringAttribute(attributes["status"])
240
+ if "status_text" in attributes: # pragma no branch
241
+ self._status_text = self._makeStringAttribute(attributes["status_text"])
242
+ if "svc_root" in attributes: # pragma no branch
243
+ self._svc_root = self._makeStringAttribute(attributes["svc_root"])
244
+ if "svn_root" in attributes: # pragma no branch
245
+ self._svn_root = self._makeStringAttribute(attributes["svn_root"])
246
+ if "tfvc_project" in attributes: # pragma no branch
247
+ self._tfvc_project = self._makeStringAttribute(attributes["tfvc_project"])
248
+ if "url" in attributes: # pragma no branch
249
+ self._url = self._makeStringAttribute(attributes["url"])
250
+ if "use_lfs" in attributes: # pragma no branch
251
+ self._use_lfs = self._makeStringAttribute(attributes["use_lfs"])
252
+ if "vcs" in attributes: # pragma no branch
253
+ self._vcs = self._makeStringAttribute(attributes["vcs"])
254
+ if "vcs_url" in attributes: # pragma no branch
255
+ self._vcs_url = self._makeStringAttribute(attributes["vcs_url"])
venv/lib/python3.10/site-packages/github/Stargazer.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2013 martinqt <m.ki2@laposte.net> #
8
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
9
+ # Copyright 2015 Dan Vanderkam <danvdk@gmail.com> #
10
+ # Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
11
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
12
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
13
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
14
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
16
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
18
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
19
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
22
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
23
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
24
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
25
+ # #
26
+ # This file is part of PyGithub. #
27
+ # http://pygithub.readthedocs.io/ #
28
+ # #
29
+ # PyGithub is free software: you can redistribute it and/or modify it under #
30
+ # the terms of the GNU Lesser General Public License as published by the Free #
31
+ # Software Foundation, either version 3 of the License, or (at your option) #
32
+ # any later version. #
33
+ # #
34
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
35
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
36
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
37
+ # details. #
38
+ # #
39
+ # You should have received a copy of the GNU Lesser General Public License #
40
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
41
+ # #
42
+ ################################################################################
43
+
44
+ from __future__ import annotations
45
+
46
+ from datetime import datetime
47
+ from typing import TYPE_CHECKING, Any
48
+
49
+ import github.NamedUser
50
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
51
+
52
+ if TYPE_CHECKING:
53
+ from github.NamedUser import NamedUser
54
+
55
+
56
+ class Stargazer(NonCompletableGithubObject):
57
+ """
58
+ This class represents Stargazers.
59
+
60
+ The reference can be found here
61
+ https://docs.github.com/en/rest/reference/activity#starring
62
+
63
+ """
64
+
65
+ def _initAttributes(self) -> None:
66
+ self._starred_at: Attribute[datetime] = NotSet
67
+ self._url: Attribute[str] = NotSet
68
+ self._user: Attribute[NamedUser] = NotSet
69
+
70
+ def __repr__(self) -> str:
71
+ # this is not a type error, just we didn't type `NamedUser` yet.
72
+ # enable type checker here after we typed attribute of `NamedUser`
73
+ return self.get__repr__({"user": self._user.value._login.value}) # type: ignore
74
+
75
+ @property
76
+ def starred_at(self) -> datetime:
77
+ return self._starred_at.value
78
+
79
+ @property
80
+ def user(self) -> NamedUser:
81
+ return self._user.value
82
+
83
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
84
+ if "starred_at" in attributes:
85
+ self._starred_at = self._makeDatetimeAttribute(attributes["starred_at"])
86
+ if "user" in attributes:
87
+ self._user = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["user"])
venv/lib/python3.10/site-packages/github/StatsCodeFrequency.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
9
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
10
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
11
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
12
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
13
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
18
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
20
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
21
+ # #
22
+ # This file is part of PyGithub. #
23
+ # http://pygithub.readthedocs.io/ #
24
+ # #
25
+ # PyGithub is free software: you can redistribute it and/or modify it under #
26
+ # the terms of the GNU Lesser General Public License as published by the Free #
27
+ # Software Foundation, either version 3 of the License, or (at your option) #
28
+ # any later version. #
29
+ # #
30
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
31
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
32
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
33
+ # details. #
34
+ # #
35
+ # You should have received a copy of the GNU Lesser General Public License #
36
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
37
+ # #
38
+ ################################################################################
39
+
40
+ from __future__ import annotations
41
+
42
+ from datetime import datetime
43
+
44
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
45
+
46
+
47
+ class StatsCodeFrequency(NonCompletableGithubObject):
48
+ """
49
+ This class represents statistics of StatsCodeFrequencies.
50
+
51
+ The reference can be found here
52
+ https://docs.github.com/en/rest/metrics/statistics?apiVersion=2022-11-28#get-the-weekly-commit-activity
53
+
54
+ The OpenAPI schema can be found at
55
+ - /components/schemas/code-frequency-stat
56
+
57
+ """
58
+
59
+ def _initAttributes(self) -> None:
60
+ self._additions: Attribute[int] = NotSet
61
+ self._deletions: Attribute[int] = NotSet
62
+ self._week: Attribute[datetime] = NotSet
63
+
64
+ @property
65
+ def additions(self) -> int:
66
+ return self._additions.value
67
+
68
+ @property
69
+ def deletions(self) -> int:
70
+ return self._deletions.value
71
+
72
+ @property
73
+ def week(self) -> datetime:
74
+ return self._week.value
75
+
76
+ def _useAttributes(self, attributes: tuple[int, int, int]) -> None:
77
+ self._week = self._makeTimestampAttribute(attributes[0])
78
+ self._additions = self._makeIntAttribute(attributes[1])
79
+ self._deletions = self._makeIntAttribute(attributes[2])
venv/lib/python3.10/site-packages/github/StatsCommitActivity.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
9
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
10
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
11
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
12
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
13
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
14
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
15
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
16
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
18
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
19
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
20
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
21
+ # #
22
+ # This file is part of PyGithub. #
23
+ # http://pygithub.readthedocs.io/ #
24
+ # #
25
+ # PyGithub is free software: you can redistribute it and/or modify it under #
26
+ # the terms of the GNU Lesser General Public License as published by the Free #
27
+ # Software Foundation, either version 3 of the License, or (at your option) #
28
+ # any later version. #
29
+ # #
30
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
31
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
32
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
33
+ # details. #
34
+ # #
35
+ # You should have received a copy of the GNU Lesser General Public License #
36
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
37
+ # #
38
+ ################################################################################
39
+
40
+ from datetime import datetime
41
+ from typing import Any, Dict
42
+
43
+ import github.GithubObject
44
+ from github.GithubObject import Attribute
45
+
46
+
47
+ class StatsCommitActivity(github.GithubObject.NonCompletableGithubObject):
48
+ """
49
+ This class represents StatsCommitActivities.
50
+
51
+ The reference can be found here
52
+ https://docs.github.com/en/rest/reference/repos#get-the-last-year-of-commit-activity
53
+
54
+ The OpenAPI schema can be found at
55
+ - /components/schemas/commit-activity
56
+
57
+ """
58
+
59
+ def _initAttributes(self) -> None:
60
+ self._days: Attribute[int] = github.GithubObject.NotSet
61
+ self._total: Attribute[int] = github.GithubObject.NotSet
62
+ self._week: Attribute[datetime] = github.GithubObject.NotSet
63
+
64
+ @property
65
+ def days(self) -> int:
66
+ return self._days.value
67
+
68
+ @property
69
+ def total(self) -> int:
70
+ return self._total.value
71
+
72
+ @property
73
+ def week(self) -> datetime:
74
+ return self._week.value
75
+
76
+ def _useAttributes(self, attributes: Dict[str, Any]) -> None:
77
+ if "days" in attributes: # pragma no branch
78
+ self._days = self._makeListOfIntsAttribute(attributes["days"])
79
+ if "total" in attributes: # pragma no branch
80
+ self._total = self._makeIntAttribute(attributes["total"])
81
+ if "week" in attributes: # pragma no branch
82
+ self._week = self._makeTimestampAttribute(attributes["week"])
venv/lib/python3.10/site-packages/github/StatsContributor.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
5
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
6
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
7
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
8
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
9
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
10
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
11
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
12
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
14
+ # Copyright 2023 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
15
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
16
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
17
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
18
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
19
+ # #
20
+ # This file is part of PyGithub. #
21
+ # http://pygithub.readthedocs.io/ #
22
+ # #
23
+ # PyGithub is free software: you can redistribute it and/or modify it under #
24
+ # the terms of the GNU Lesser General Public License as published by the Free #
25
+ # Software Foundation, either version 3 of the License, or (at your option) #
26
+ # any later version. #
27
+ # #
28
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
29
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
30
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
31
+ # details. #
32
+ # #
33
+ # You should have received a copy of the GNU Lesser General Public License #
34
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
35
+ # #
36
+ ################################################################################
37
+
38
+ from __future__ import annotations
39
+
40
+ from datetime import datetime
41
+ from typing import Any
42
+
43
+ import github.GithubObject
44
+ import github.NamedUser
45
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
46
+
47
+
48
+ class StatsContributor(NonCompletableGithubObject):
49
+ """
50
+ This class represents StatsContributors.
51
+
52
+ The reference can be found here
53
+ https://docs.github.com/en/rest/reference/repos#get-all-contributor-commit-activity
54
+
55
+ The OpenAPI schema can be found at
56
+ - /components/schemas/contributor-activity
57
+
58
+ """
59
+
60
+ class Week(NonCompletableGithubObject):
61
+ """
62
+ This class represents weekly statistics of a contributor.
63
+
64
+ The OpenAPI schema can be found at
65
+ - /components/schemas/contributor-activity/properties/weeks/items
66
+
67
+ """
68
+
69
+ def _initAttributes(self) -> None:
70
+ self._a: Attribute[int] = NotSet
71
+ self._c: Attribute[int] = NotSet
72
+ self._d: Attribute[int] = NotSet
73
+ self._w: Attribute[datetime] = NotSet
74
+
75
+ @property
76
+ def a(self) -> int:
77
+ return self._a.value
78
+
79
+ @property
80
+ def c(self) -> int:
81
+ return self._c.value
82
+
83
+ @property
84
+ def d(self) -> int:
85
+ return self._d.value
86
+
87
+ @property
88
+ def w(self) -> datetime:
89
+ return self._w.value
90
+
91
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
92
+ if "a" in attributes: # pragma no branch
93
+ self._a = self._makeIntAttribute(attributes["a"])
94
+ if "c" in attributes: # pragma no branch
95
+ self._c = self._makeIntAttribute(attributes["c"])
96
+ if "d" in attributes: # pragma no branch
97
+ self._d = self._makeIntAttribute(attributes["d"])
98
+ if "w" in attributes: # pragma no branch
99
+ self._w = self._makeTimestampAttribute(attributes["w"])
100
+
101
+ def _initAttributes(self) -> None:
102
+ self._author: Attribute[github.NamedUser.NamedUser] = NotSet
103
+ self._total: Attribute[int] = NotSet
104
+ self._weeks: Attribute[list[StatsContributor.Week]] = NotSet
105
+
106
+ @property
107
+ def author(self) -> github.NamedUser.NamedUser:
108
+ return self._author.value
109
+
110
+ @property
111
+ def total(self) -> int:
112
+ return self._total.value
113
+
114
+ @property
115
+ def weeks(self) -> list[Week]:
116
+ return self._weeks.value
117
+
118
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
119
+ if "author" in attributes: # pragma no branch
120
+ self._author = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["author"])
121
+ if "total" in attributes: # pragma no branch
122
+ self._total = self._makeIntAttribute(attributes["total"])
123
+ if "weeks" in attributes: # pragma no branch
124
+ self._weeks = self._makeListOfClassesAttribute(self.Week, attributes["weeks"])
venv/lib/python3.10/site-packages/github/StatsParticipation.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ############################ Copyrights and license ############################
2
+ # #
3
+ # Copyright 2012 Vincent Jacques <vincent@vincent-jacques.net> #
4
+ # Copyright 2012 Zearin <zearin@gonk.net> #
5
+ # Copyright 2013 AKFish <akfish@gmail.com> #
6
+ # Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net> #
7
+ # Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
8
+ # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
9
+ # Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
10
+ # Copyright 2018 sfdye <tsfdye@gmail.com> #
11
+ # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
12
+ # Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
13
+ # Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
14
+ # Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
15
+ # Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
16
+ # Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
17
+ # Copyright 2023 Enrico Minack <github@enrico.minack.dev> #
18
+ # Copyright 2023 Trim21 <trim21.me@gmail.com> #
19
+ # Copyright 2024 Enrico Minack <github@enrico.minack.dev> #
20
+ # Copyright 2024 Jirka Borovec <6035284+Borda@users.noreply.github.com> #
21
+ # Copyright 2025 Enrico Minack <github@enrico.minack.dev> #
22
+ # #
23
+ # This file is part of PyGithub. #
24
+ # http://pygithub.readthedocs.io/ #
25
+ # #
26
+ # PyGithub is free software: you can redistribute it and/or modify it under #
27
+ # the terms of the GNU Lesser General Public License as published by the Free #
28
+ # Software Foundation, either version 3 of the License, or (at your option) #
29
+ # any later version. #
30
+ # #
31
+ # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY #
32
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
33
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
34
+ # details. #
35
+ # #
36
+ # You should have received a copy of the GNU Lesser General Public License #
37
+ # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. #
38
+ # #
39
+ ################################################################################
40
+
41
+ from __future__ import annotations
42
+
43
+ from typing import Any
44
+
45
+ from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
46
+
47
+
48
+ class StatsParticipation(NonCompletableGithubObject):
49
+ """
50
+ This class represents StatsParticipations.
51
+
52
+ The reference can be found here
53
+ https://docs.github.com/en/rest/reference/repos#get-the-weekly-commit-count
54
+
55
+ The OpenAPI schema can be found at
56
+ - /components/schemas/participation-stats
57
+
58
+ """
59
+
60
+ def _initAttributes(self) -> None:
61
+ self._all: Attribute[list[int]] = NotSet
62
+ self._owner: Attribute[list[int]] = NotSet
63
+
64
+ @property
65
+ def all(self) -> list[int]:
66
+ return self._all.value
67
+
68
+ @property
69
+ def owner(self) -> list[int]:
70
+ return self._owner.value
71
+
72
+ def _useAttributes(self, attributes: dict[str, Any]) -> None:
73
+ if "all" in attributes: # pragma no branch
74
+ self._all = self._makeListOfIntsAttribute(attributes["all"])
75
+ if "owner" in attributes: # pragma no branch
76
+ self._owner = self._makeListOfIntsAttribute(attributes["owner"])