Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- venv/lib/python3.10/site-packages/PyGithub-2.6.1.dist-info/COPYING +674 -0
- venv/lib/python3.10/site-packages/PyGithub-2.6.1.dist-info/COPYING.LESSER +165 -0
- venv/lib/python3.10/site-packages/github/AccessToken.py +158 -0
- venv/lib/python3.10/site-packages/github/AdvisoryBase.py +157 -0
- venv/lib/python3.10/site-packages/github/AdvisoryCredit.py +126 -0
- venv/lib/python3.10/site-packages/github/AdvisoryCreditDetailed.py +104 -0
- venv/lib/python3.10/site-packages/github/AdvisoryVulnerability.py +190 -0
- venv/lib/python3.10/site-packages/github/AdvisoryVulnerabilityPackage.py +91 -0
- venv/lib/python3.10/site-packages/github/AppAuthentication.py +57 -0
- venv/lib/python3.10/site-packages/github/ApplicationOAuth.py +198 -0
- venv/lib/python3.10/site-packages/github/Artifact.py +172 -0
- venv/lib/python3.10/site-packages/github/Auth.py +551 -0
- venv/lib/python3.10/site-packages/github/AuthenticatedUser.py +1167 -0
- venv/lib/python3.10/site-packages/github/Authorization.py +191 -0
- venv/lib/python3.10/site-packages/github/AuthorizationApplication.py +69 -0
- venv/lib/python3.10/site-packages/github/Autolink.py +92 -0
- venv/lib/python3.10/site-packages/github/Branch.py +657 -0
- venv/lib/python3.10/site-packages/github/BranchProtection.py +219 -0
- venv/lib/python3.10/site-packages/github/CVSS.py +80 -0
- venv/lib/python3.10/site-packages/github/CWE.py +72 -0
- venv/lib/python3.10/site-packages/github/CheckRun.py +298 -0
- venv/lib/python3.10/site-packages/github/CheckRunAnnotation.py +123 -0
- venv/lib/python3.10/site-packages/github/CheckRunOutput.py +95 -0
- venv/lib/python3.10/site-packages/github/CheckSuite.py +313 -0
- venv/lib/python3.10/site-packages/github/Clones.py +95 -0
- venv/lib/python3.10/site-packages/github/CodeScanAlert.py +160 -0
- venv/lib/python3.10/site-packages/github/PullRequestMergeStatus.py +81 -0
- venv/lib/python3.10/site-packages/github/RateLimit.py +166 -0
- venv/lib/python3.10/site-packages/github/Reaction.py +113 -0
- venv/lib/python3.10/site-packages/github/RepoCodeSecurityConfig.py +87 -0
- venv/lib/python3.10/site-packages/github/Repository.py +0 -0
- venv/lib/python3.10/site-packages/github/RepositoryAdvisory.py +424 -0
- venv/lib/python3.10/site-packages/github/RepositoryDiscussion.py +213 -0
- venv/lib/python3.10/site-packages/github/RepositoryDiscussionCategory.py +142 -0
- venv/lib/python3.10/site-packages/github/RepositoryDiscussionComment.py +149 -0
- venv/lib/python3.10/site-packages/github/RepositoryKey.py +152 -0
- venv/lib/python3.10/site-packages/github/RepositoryPreferences.py +80 -0
- venv/lib/python3.10/site-packages/github/Requester.py +1317 -0
- venv/lib/python3.10/site-packages/github/RequiredPullRequestReviews.py +146 -0
- venv/lib/python3.10/site-packages/github/RequiredStatusChecks.py +92 -0
- venv/lib/python3.10/site-packages/github/Secret.py +124 -0
- venv/lib/python3.10/site-packages/github/SecurityAndAnalysis.py +141 -0
- venv/lib/python3.10/site-packages/github/SecurityAndAnalysisFeature.py +70 -0
- venv/lib/python3.10/site-packages/github/SelfHostedActionsRunner.py +113 -0
- venv/lib/python3.10/site-packages/github/SourceImport.py +255 -0
- venv/lib/python3.10/site-packages/github/Stargazer.py +87 -0
- venv/lib/python3.10/site-packages/github/StatsCodeFrequency.py +79 -0
- venv/lib/python3.10/site-packages/github/StatsCommitActivity.py +82 -0
- venv/lib/python3.10/site-packages/github/StatsContributor.py +124 -0
- 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"])
|