/ github / AuthenticatedUser.py
AuthenticatedUser.py
   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 Wan Liuyang <tsfdye@gmail.com>                                #
  19  # Copyright 2018 bryanhuntesl <31992054+bryanhuntesl@users.noreply.github.com> #
  20  # Copyright 2018 sfdye <tsfdye@gmail.com>                                      #
  21  # Copyright 2018 itsbruce <it.is.bruce@gmail.com>                              #
  22  # Copyright 2019 Rigas Papathanasopoulos <rigaspapas@gmail.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  from __future__ import annotations
  42  
  43  from datetime import datetime, timezone
  44  from typing import TYPE_CHECKING, Any, NamedTuple
  45  
  46  import github.Authorization
  47  import github.Event
  48  import github.Gist
  49  import github.GithubObject
  50  import github.Invitation
  51  import github.Issue
  52  import github.Membership
  53  import github.Migration
  54  import github.NamedUser
  55  import github.Notification
  56  import github.Organization
  57  import github.Plan
  58  import github.Repository
  59  import github.UserKey
  60  from github import Consts
  61  from github.GithubObject import (
  62      Attribute,
  63      CompletableGithubObject,
  64      NotSet,
  65      Opt,
  66      is_defined,
  67      is_optional,
  68      is_optional_list,
  69      is_undefined,
  70  )
  71  from github.PaginatedList import PaginatedList
  72  
  73  if TYPE_CHECKING:
  74      from github.Authorization import Authorization
  75      from github.Event import Event
  76      from github.Gist import Gist
  77      from github.InputFileContent import InputFileContent
  78      from github.Installation import Installation
  79      from github.Invitation import Invitation
  80      from github.Issue import Issue
  81      from github.Label import Label
  82      from github.Membership import Membership
  83      from github.Migration import Migration
  84      from github.NamedUser import NamedUser
  85      from github.Notification import Notification
  86      from github.Organization import Organization
  87      from github.Plan import Plan
  88      from github.Project import Project
  89      from github.Repository import Repository
  90      from github.Team import Team
  91      from github.UserKey import UserKey
  92  
  93  
  94  class EmailData(NamedTuple):
  95      email: str
  96      primary: bool
  97      verified: bool
  98      visibility: str
  99  
 100  
 101  class AuthenticatedUser(CompletableGithubObject):
 102      """
 103      This class represents AuthenticatedUsers as returned by https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
 104  
 105      An AuthenticatedUser object can be created by calling ``get_user()`` on a Github object.
 106      """
 107  
 108      def _initAttributes(self) -> None:
 109          self._avatar_url: Attribute[str] = NotSet
 110          self._bio: Attribute[str] = NotSet
 111          self._blog: Attribute[str] = NotSet
 112          self._collaborators: Attribute[int] = NotSet
 113          self._company: Attribute[str] = NotSet
 114          self._created_at: Attribute[datetime] = NotSet
 115          self._disk_usage: Attribute[int] = NotSet
 116          self._email: Attribute[str] = NotSet
 117          self._events_url: Attribute[str] = NotSet
 118          self._followers: Attribute[int] = NotSet
 119          self._followers_url: Attribute[str] = NotSet
 120          self._following: Attribute[int] = NotSet
 121          self._following_url: Attribute[str] = NotSet
 122          self._gists_url: Attribute[str] = NotSet
 123          self._gravatar_id: Attribute[str] = NotSet
 124          self._hireable: Attribute[bool] = NotSet
 125          self._html_url: Attribute[str] = NotSet
 126          self._id: Attribute[int] = NotSet
 127          self._location: Attribute[str] = NotSet
 128          self._login: Attribute[str] = NotSet
 129          self._name: Attribute[str] = NotSet
 130          self._node_id: Attribute[str] = NotSet
 131          self._organizations_url: Attribute[str] = NotSet
 132          self._owned_private_repos: Attribute[int] = NotSet
 133          self._plan: Attribute[github.Plan.Plan] = NotSet
 134          self._private_gists: Attribute[int] = NotSet
 135          self._public_gists: Attribute[int] = NotSet
 136          self._public_repos: Attribute[int] = NotSet
 137          self._received_events_url: Attribute[str] = NotSet
 138          self._repos_url: Attribute[str] = NotSet
 139          self._site_admin: Attribute[bool] = NotSet
 140          self._starred_url: Attribute[str] = NotSet
 141          self._subscriptions_url: Attribute[str] = NotSet
 142          self._total_private_repos: Attribute[int] = NotSet
 143          self._type: Attribute[str] = NotSet
 144          self._updated_at: Attribute[datetime] = NotSet
 145          self._url: Attribute[str] = NotSet
 146          self._two_factor_authentication: Attribute[bool] = NotSet
 147  
 148      def __repr__(self) -> str:
 149          return self.get__repr__({"login": self._login.value})
 150  
 151      @property
 152      def avatar_url(self) -> str:
 153          self._completeIfNotSet(self._avatar_url)
 154          return self._avatar_url.value
 155  
 156      @property
 157      def bio(self) -> str:
 158          self._completeIfNotSet(self._bio)
 159          return self._bio.value
 160  
 161      @property
 162      def blog(self) -> str:
 163          self._completeIfNotSet(self._blog)
 164          return self._blog.value
 165  
 166      @property
 167      def collaborators(self) -> int:
 168          self._completeIfNotSet(self._collaborators)
 169          return self._collaborators.value
 170  
 171      @property
 172      def company(self) -> str:
 173          self._completeIfNotSet(self._company)
 174          return self._company.value
 175  
 176      @property
 177      def created_at(self) -> datetime:
 178          self._completeIfNotSet(self._created_at)
 179          return self._created_at.value
 180  
 181      @property
 182      def disk_usage(self) -> int:
 183          self._completeIfNotSet(self._disk_usage)
 184          return self._disk_usage.value
 185  
 186      @property
 187      def email(self) -> str:
 188          self._completeIfNotSet(self._email)
 189          return self._email.value
 190  
 191      @property
 192      def events_url(self) -> str:
 193          self._completeIfNotSet(self._events_url)
 194          return self._events_url.value
 195  
 196      @property
 197      def followers(self) -> int:
 198          self._completeIfNotSet(self._followers)
 199          return self._followers.value
 200  
 201      @property
 202      def followers_url(self) -> str:
 203          self._completeIfNotSet(self._followers_url)
 204          return self._followers_url.value
 205  
 206      @property
 207      def following(self) -> int:
 208          self._completeIfNotSet(self._following)
 209          return self._following.value
 210  
 211      @property
 212      def following_url(self) -> str:
 213          self._completeIfNotSet(self._following_url)
 214          return self._following_url.value
 215  
 216      @property
 217      def gists_url(self) -> str:
 218          self._completeIfNotSet(self._gists_url)
 219          return self._gists_url.value
 220  
 221      @property
 222      def gravatar_id(self) -> str:
 223          self._completeIfNotSet(self._gravatar_id)
 224          return self._gravatar_id.value
 225  
 226      @property
 227      def hireable(self) -> bool:
 228          self._completeIfNotSet(self._hireable)
 229          return self._hireable.value
 230  
 231      @property
 232      def html_url(self) -> str:
 233          self._completeIfNotSet(self._html_url)
 234          return self._html_url.value
 235  
 236      @property
 237      def id(self) -> int:
 238          self._completeIfNotSet(self._id)
 239          return self._id.value
 240  
 241      @property
 242      def location(self) -> str:
 243          self._completeIfNotSet(self._location)
 244          return self._location.value
 245  
 246      @property
 247      def login(self) -> str:
 248          self._completeIfNotSet(self._login)
 249          return self._login.value
 250  
 251      @property
 252      def name(self) -> str:
 253          self._completeIfNotSet(self._name)
 254          return self._name.value
 255  
 256      @property
 257      def node_id(self) -> str:
 258          self._completeIfNotSet(self._node_id)
 259          return self._node_id.value
 260  
 261      @property
 262      def organizations_url(self) -> str:
 263          self._completeIfNotSet(self._organizations_url)
 264          return self._organizations_url.value
 265  
 266      @property
 267      def owned_private_repos(self) -> int:
 268          self._completeIfNotSet(self._owned_private_repos)
 269          return self._owned_private_repos.value
 270  
 271      @property
 272      def plan(self) -> Plan:
 273          self._completeIfNotSet(self._plan)
 274          return self._plan.value
 275  
 276      @property
 277      def private_gists(self) -> int:
 278          self._completeIfNotSet(self._private_gists)
 279          return self._private_gists.value
 280  
 281      @property
 282      def public_gists(self) -> int:
 283          self._completeIfNotSet(self._public_gists)
 284          return self._public_gists.value
 285  
 286      @property
 287      def public_repos(self) -> int:
 288          self._completeIfNotSet(self._public_repos)
 289          return self._public_repos.value
 290  
 291      @property
 292      def received_events_url(self) -> str:
 293          self._completeIfNotSet(self._received_events_url)
 294          return self._received_events_url.value
 295  
 296      @property
 297      def repos_url(self) -> str:
 298          self._completeIfNotSet(self._repos_url)
 299          return self._repos_url.value
 300  
 301      @property
 302      def site_admin(self) -> bool:
 303          self._completeIfNotSet(self._site_admin)
 304          return self._site_admin.value
 305  
 306      @property
 307      def starred_url(self) -> str:
 308          self._completeIfNotSet(self._starred_url)
 309          return self._starred_url.value
 310  
 311      @property
 312      def subscriptions_url(self) -> str:
 313          self._completeIfNotSet(self._subscriptions_url)
 314          return self._subscriptions_url.value
 315  
 316      @property
 317      def total_private_repos(self) -> int:
 318          self._completeIfNotSet(self._total_private_repos)
 319          return self._total_private_repos.value
 320  
 321      @property
 322      def type(self) -> str:
 323          self._completeIfNotSet(self._type)
 324          return self._type.value
 325  
 326      @property
 327      def updated_at(self) -> datetime:
 328          self._completeIfNotSet(self._updated_at)
 329          return self._updated_at.value
 330  
 331      @property
 332      def url(self) -> str:
 333          self._completeIfNotSet(self._url)
 334          return self._url.value
 335  
 336      @property
 337      def two_factor_authentication(self) -> bool:
 338          self._completeIfNotSet(self._two_factor_authentication)
 339          return self._two_factor_authentication.value
 340  
 341      def add_to_emails(self, *emails: str) -> None:
 342          """
 343          :calls: `POST /user/emails <http://docs.github.com/en/rest/reference/users#emails>`_
 344          """
 345          assert all(isinstance(element, str) for element in emails), emails
 346          post_parameters = {"emails": emails}
 347          headers, data = self._requester.requestJsonAndCheck("POST", "/user/emails", input=post_parameters)
 348  
 349      def add_to_following(self, following: NamedUser) -> None:
 350          """
 351          :calls: `PUT /user/following/{user} <http://docs.github.com/en/rest/reference/users#followers>`_
 352          """
 353          assert isinstance(following, github.NamedUser.NamedUser), following
 354          headers, data = self._requester.requestJsonAndCheck("PUT", f"/user/following/{following._identity}")
 355  
 356      def add_to_starred(self, starred: Repository) -> None:
 357          """
 358          :calls: `PUT /user/starred/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#starring>`_
 359          """
 360          assert isinstance(starred, github.Repository.Repository), starred
 361          headers, data = self._requester.requestJsonAndCheck("PUT", f"/user/starred/{starred._identity}")
 362  
 363      def add_to_subscriptions(self, subscription: Repository) -> None:
 364          """
 365          :calls: `PUT /user/subscriptions/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#watching>`_
 366          """
 367          assert isinstance(subscription, github.Repository.Repository), subscription
 368          headers, data = self._requester.requestJsonAndCheck("PUT", f"/user/subscriptions/{subscription._identity}")
 369  
 370      def add_to_watched(self, watched: Repository) -> None:
 371          """
 372          :calls: `PUT /repos/{owner}/{repo}/subscription <http://docs.github.com/en/rest/reference/activity#watching>`_
 373          """
 374          assert isinstance(watched, github.Repository.Repository), watched
 375          headers, data = self._requester.requestJsonAndCheck(
 376              "PUT",
 377              f"/repos/{watched._identity}/subscription",
 378              input={"subscribed": True},
 379          )
 380  
 381      def create_authorization(
 382          self,
 383          scopes: Opt[list[str]] = NotSet,
 384          note: Opt[str] = NotSet,
 385          note_url: Opt[str] = NotSet,
 386          client_id: Opt[str] = NotSet,
 387          client_secret: Opt[str] = NotSet,
 388          onetime_password: str | None = None,
 389      ) -> Authorization:
 390          """
 391          :calls: `POST /authorizations <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
 392          """
 393          assert is_optional_list(scopes, str), scopes
 394          assert is_optional(note, str), note
 395          assert is_optional(note_url, str), note_url
 396          assert is_optional(client_id, str), client_id
 397          assert is_optional(client_secret, str), client_secret
 398          assert onetime_password is None or isinstance(onetime_password, str), onetime_password
 399          post_parameters: dict[str, Any] = NotSet.remove_unset_items(
 400              {
 401                  "scopes": scopes,
 402                  "note": note,
 403                  "note_url": note_url,
 404                  "client_id": client_id,
 405                  "client_secret": client_secret,
 406              }
 407          )
 408  
 409          if onetime_password is not None:
 410              request_header = {Consts.headerOTP: onetime_password}  # pragma no cover (Should be covered)
 411          else:
 412              request_header = None
 413          headers, data = self._requester.requestJsonAndCheck(
 414              "POST",
 415              "/authorizations",
 416              input=post_parameters,
 417              headers=request_header,
 418          )
 419          return github.Authorization.Authorization(self._requester, headers, data, completed=True)
 420  
 421      @staticmethod
 422      def create_fork(
 423          repo: Repository,
 424          name: Opt[str] = NotSet,
 425          default_branch_only: Opt[bool] = NotSet,
 426      ) -> Repository:
 427          """
 428          :calls: `POST /repos/{owner}/{repo}/forks <http://docs.github.com/en/rest/reference/repos#forks>`_
 429          """
 430          assert isinstance(repo, github.Repository.Repository), repo
 431          return repo.create_fork(
 432              organization=github.GithubObject.NotSet,
 433              name=name,
 434              default_branch_only=default_branch_only,
 435          )
 436  
 437      def create_repo_from_template(
 438          self,
 439          name: str,
 440          repo: Repository,
 441          description: Opt[str] = NotSet,
 442          private: Opt[bool] = NotSet,
 443      ) -> Repository:
 444          """
 445          :calls: `POST /repos/{template_owner}/{template_repo}/generate <https://docs.github.com/en/rest/reference/repos#create-a-repository-using-a-template>`_
 446          """
 447          assert isinstance(name, str), name
 448          assert isinstance(repo, github.Repository.Repository), repo
 449          assert is_optional(description, str), description
 450          assert is_optional(private, bool), private
 451          post_parameters: dict[str, Any] = NotSet.remove_unset_items(
 452              {
 453                  "name": name,
 454                  "owner": self.login,
 455                  "description": description,
 456                  "private": private,
 457              }
 458          )
 459  
 460          headers, data = self._requester.requestJsonAndCheck(
 461              "POST",
 462              f"/repos/{repo.owner.login}/{repo.name}/generate",
 463              input=post_parameters,
 464              headers={"Accept": "application/vnd.github.v3+json"},
 465          )
 466          return github.Repository.Repository(self._requester, headers, data, completed=True)
 467  
 468      def create_gist(
 469          self,
 470          public: bool,
 471          files: dict[str, InputFileContent],
 472          description: Opt[str] = NotSet,
 473      ) -> Gist:
 474          """
 475          :calls: `POST /gists <http://docs.github.com/en/rest/reference/gists>`_
 476          """
 477          assert isinstance(public, bool), public
 478          assert all(isinstance(element, github.InputFileContent) for element in files.values()), files
 479          assert is_undefined(description) or isinstance(description, str), description
 480          post_parameters = {
 481              "public": public,
 482              "files": {key: value._identity for key, value in files.items()},
 483          }
 484          if is_defined(description):
 485              post_parameters["description"] = description
 486          headers, data = self._requester.requestJsonAndCheck("POST", "/gists", input=post_parameters)
 487          return github.Gist.Gist(self._requester, headers, data, completed=True)
 488  
 489      def create_key(self, title: str, key: str) -> UserKey:
 490          """
 491          :calls: `POST /user/keys <http://docs.github.com/en/rest/reference/users#git-ssh-keys>`_
 492          :param title: string
 493          :param key: string
 494          :rtype: :class:`github.UserKey.UserKey`
 495          """
 496          assert isinstance(title, str), title
 497          assert isinstance(key, str), key
 498          post_parameters = {
 499              "title": title,
 500              "key": key,
 501          }
 502          headers, data = self._requester.requestJsonAndCheck("POST", "/user/keys", input=post_parameters)
 503          return github.UserKey.UserKey(self._requester, headers, data, completed=True)
 504  
 505      def create_project(self, name: str, body: Opt[str] = NotSet) -> Project:
 506          """
 507          :calls: `POST /user/projects <https://docs.github.com/en/rest/reference/projects#create-a-user-project>`_
 508          :param name: string
 509          :param body: string
 510          :rtype: :class:`github.Project.Project`
 511          """
 512          assert isinstance(name, str), name
 513          assert is_undefined(body) or isinstance(body, str), body
 514          post_parameters = {
 515              "name": name,
 516              "body": body,
 517          }
 518          headers, data = self._requester.requestJsonAndCheck(
 519              "POST",
 520              "/user/projects",
 521              input=post_parameters,
 522              headers={"Accept": Consts.mediaTypeProjectsPreview},
 523          )
 524          return github.Project.Project(self._requester, headers, data, completed=True)
 525  
 526      def create_repo(
 527          self,
 528          name: str,
 529          description: Opt[str] = NotSet,
 530          homepage: Opt[str] = NotSet,
 531          private: Opt[bool] = NotSet,
 532          has_issues: Opt[bool] = NotSet,
 533          has_wiki: Opt[bool] = NotSet,
 534          has_downloads: Opt[bool] = NotSet,
 535          has_projects: Opt[bool] = NotSet,
 536          auto_init: Opt[bool] = NotSet,
 537          license_template: Opt[str] = NotSet,
 538          gitignore_template: Opt[str] = NotSet,
 539          allow_squash_merge: Opt[bool] = NotSet,
 540          allow_merge_commit: Opt[bool] = NotSet,
 541          allow_rebase_merge: Opt[bool] = NotSet,
 542          delete_branch_on_merge: Opt[bool] = NotSet,
 543      ) -> Repository:
 544          """
 545          :calls: `POST /user/repos <http://docs.github.com/en/rest/reference/repos>`_
 546          """
 547          assert isinstance(name, str), name
 548          assert is_optional(description, str), description
 549          assert is_optional(homepage, str), homepage
 550          assert is_optional(private, bool), private
 551          assert is_optional(has_issues, bool), has_issues
 552          assert is_optional(has_wiki, bool), has_wiki
 553          assert is_optional(has_downloads, bool), has_downloads
 554          assert is_optional(has_projects, bool), has_projects
 555          assert is_optional(auto_init, bool), auto_init
 556          assert is_optional(license_template, str), license_template
 557          assert is_optional(gitignore_template, str), gitignore_template
 558          assert is_optional(allow_squash_merge, bool), allow_squash_merge
 559          assert is_optional(allow_merge_commit, bool), allow_merge_commit
 560          assert is_optional(allow_rebase_merge, bool), allow_rebase_merge
 561          assert is_optional(delete_branch_on_merge, bool), delete_branch_on_merge
 562          post_parameters: dict[str, Any] = NotSet.remove_unset_items(
 563              {
 564                  "name": name,
 565                  "description": description,
 566                  "homepage": homepage,
 567                  "private": private,
 568                  "has_issues": has_issues,
 569                  "has_wiki": has_wiki,
 570                  "has_downloads": has_downloads,
 571                  "has_projects": has_projects,
 572                  "auto_init": auto_init,
 573                  "license_template": license_template,
 574                  "gitignore_template": gitignore_template,
 575                  "allow_squash_merge": allow_squash_merge,
 576                  "allow_merge_commit": allow_merge_commit,
 577                  "allow_rebase_merge": allow_rebase_merge,
 578                  "delete_branch_on_merge": delete_branch_on_merge,
 579              }
 580          )
 581  
 582          headers, data = self._requester.requestJsonAndCheck("POST", "/user/repos", input=post_parameters)
 583          return github.Repository.Repository(self._requester, headers, data, completed=True)
 584  
 585      def edit(
 586          self,
 587          name: Opt[str] = NotSet,
 588          email: Opt[str] = NotSet,
 589          blog: Opt[str] = NotSet,
 590          company: Opt[str] = NotSet,
 591          location: Opt[str] = NotSet,
 592          hireable: Opt[bool] = NotSet,
 593          bio: Opt[str] = NotSet,
 594      ) -> None:
 595          """
 596          :calls: `PATCH /user <http://docs.github.com/en/rest/reference/users>`_
 597          """
 598          assert is_optional(name, str), name
 599          assert is_optional(email, str), email
 600          assert is_optional(blog, str), blog
 601          assert is_optional(company, str), company
 602          assert is_optional(location, str), location
 603          assert is_optional(hireable, bool), hireable
 604          assert is_optional(bio, str), bio
 605          post_parameters: dict[str, Any] = NotSet.remove_unset_items(
 606              {
 607                  "name": name,
 608                  "email": email,
 609                  "blog": blog,
 610                  "company": company,
 611                  "location": location,
 612                  "hireable": hireable,
 613                  "bio": bio,
 614              }
 615          )
 616  
 617          headers, data = self._requester.requestJsonAndCheck("PATCH", "/user", input=post_parameters)
 618          self._useAttributes(data)
 619  
 620      def get_authorization(self, id: int) -> Authorization:
 621          """
 622          :calls: `GET /authorizations/{id} <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
 623          """
 624          assert isinstance(id, int), id
 625          headers, data = self._requester.requestJsonAndCheck("GET", f"/authorizations/{id}")
 626          return github.Authorization.Authorization(self._requester, headers, data, completed=True)
 627  
 628      def get_authorizations(self) -> PaginatedList[Authorization]:
 629          """
 630          :calls: `GET /authorizations <https://docs.github.com/en/developers/apps/authorizing-oauth-apps>`_
 631          """
 632          return PaginatedList(github.Authorization.Authorization, self._requester, "/authorizations", None)
 633  
 634      def get_emails(self) -> list[EmailData]:
 635          """
 636          :calls: `GET /user/emails <http://docs.github.com/en/rest/reference/users#emails>`_
 637          """
 638          headers, data = self._requester.requestJsonAndCheck("GET", "/user/emails")
 639          return [EmailData(**item) for item in data]
 640  
 641      def get_events(self) -> PaginatedList[Event]:
 642          """
 643          :calls: `GET /events <http://docs.github.com/en/rest/reference/activity#events>`_
 644          """
 645          return PaginatedList(github.Event.Event, self._requester, "/events", None)
 646  
 647      def get_followers(self) -> PaginatedList[NamedUser]:
 648          """
 649          :calls: `GET /user/followers <http://docs.github.com/en/rest/reference/users#followers>`_
 650          """
 651          return PaginatedList(github.NamedUser.NamedUser, self._requester, "/user/followers", None)
 652  
 653      def get_following(self) -> PaginatedList[NamedUser]:
 654          """
 655          :calls: `GET /user/following <http://docs.github.com/en/rest/reference/users#followers>`_
 656          """
 657          return PaginatedList(github.NamedUser.NamedUser, self._requester, "/user/following", None)
 658  
 659      def get_gists(self, since: Opt[datetime] = NotSet) -> PaginatedList[Gist]:
 660          """
 661          :calls: `GET /gists <http://docs.github.com/en/rest/reference/gists>`_
 662          :param since: datetime format YYYY-MM-DDTHH:MM:SSZ
 663          :rtype: :class:`PaginatedList` of :class:`github.Gist.Gist`
 664          """
 665          assert is_optional(since, datetime), since
 666          url_parameters: dict[str, Any] = {}
 667          if is_defined(since):
 668              url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
 669          return PaginatedList(github.Gist.Gist, self._requester, "/gists", url_parameters)
 670  
 671      def get_issues(
 672          self,
 673          filter: Opt[str] = NotSet,
 674          state: Opt[str] = NotSet,
 675          labels: Opt[list[Label]] = NotSet,
 676          sort: Opt[str] = NotSet,
 677          direction: Opt[str] = NotSet,
 678          since: Opt[datetime] = NotSet,
 679      ) -> PaginatedList[Issue]:
 680          """
 681          :calls: `GET /issues <http://docs.github.com/en/rest/reference/issues>`_
 682          """
 683          assert is_optional(filter, str), filter
 684          assert is_optional(state, str), state
 685          assert is_optional_list(labels, github.Label.Label), labels
 686          assert is_optional(sort, str), sort
 687          assert is_optional(direction, str), direction
 688          assert is_optional(since, datetime), since
 689          url_parameters: dict[str, Any] = {}
 690          if is_defined(filter):
 691              url_parameters["filter"] = filter
 692          if is_defined(state):
 693              url_parameters["state"] = state
 694          if is_defined(labels):
 695              url_parameters["labels"] = ",".join(label.name for label in labels)
 696          if is_defined(sort):
 697              url_parameters["sort"] = sort
 698          if is_defined(direction):
 699              url_parameters["direction"] = direction
 700          if is_defined(since):
 701              url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
 702          return PaginatedList(github.Issue.Issue, self._requester, "/issues", url_parameters)
 703  
 704      def get_user_issues(
 705          self,
 706          filter: Opt[str] = NotSet,
 707          state: Opt[str] = NotSet,
 708          labels: Opt[list[Label]] = NotSet,
 709          sort: Opt[str] = NotSet,
 710          direction: Opt[str] = NotSet,
 711          since: Opt[datetime] = NotSet,
 712      ) -> PaginatedList[Issue]:
 713          """
 714          :calls: `GET /user/issues <http://docs.github.com/en/rest/reference/issues>`_
 715          """
 716          assert is_optional(filter, str), filter
 717          assert is_optional(state, str), state
 718          assert is_optional_list(labels, github.Label.Label), labels
 719          assert is_optional(sort, str), sort
 720          assert is_optional(direction, str), direction
 721          assert is_optional(since, datetime), since
 722          url_parameters: dict[str, Any] = {}
 723          if is_defined(filter):
 724              url_parameters["filter"] = filter
 725          if is_defined(state):
 726              url_parameters["state"] = state
 727          if is_defined(labels):
 728              url_parameters["labels"] = ",".join(label.name for label in labels)
 729          if is_defined(sort):
 730              url_parameters["sort"] = sort
 731          if is_defined(direction):
 732              url_parameters["direction"] = direction
 733          if is_defined(since):
 734              url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
 735          return PaginatedList(github.Issue.Issue, self._requester, "/user/issues", url_parameters)
 736  
 737      def get_key(self, id: int) -> UserKey:
 738          """
 739          :calls: `GET /user/keys/{id} <http://docs.github.com/en/rest/reference/users#git-ssh-keys>`_
 740          """
 741          assert isinstance(id, int), id
 742          headers, data = self._requester.requestJsonAndCheck("GET", f"/user/keys/{id}")
 743          return github.UserKey.UserKey(self._requester, headers, data, completed=True)
 744  
 745      def get_keys(self) -> PaginatedList[UserKey]:
 746          """
 747          :calls: `GET /user/keys <http://docs.github.com/en/rest/reference/users#git-ssh-keys>`_
 748          """
 749          return PaginatedList(github.UserKey.UserKey, self._requester, "/user/keys", None)
 750  
 751      def get_notification(self, id: str) -> Notification:
 752          """
 753          :calls: `GET /notifications/threads/{id} <http://docs.github.com/en/rest/reference/activity#notifications>`_
 754          """
 755  
 756          assert isinstance(id, str), id
 757          headers, data = self._requester.requestJsonAndCheck("GET", f"/notifications/threads/{id}")
 758          return github.Notification.Notification(self._requester, headers, data, completed=True)
 759  
 760      def get_notifications(
 761          self,
 762          all: Opt[bool] = NotSet,
 763          participating: Opt[bool] = NotSet,
 764          since: Opt[datetime] = NotSet,
 765          before: Opt[datetime] = NotSet,
 766      ) -> PaginatedList[Notification]:
 767          """
 768          :calls: `GET /notifications <http://docs.github.com/en/rest/reference/activity#notifications>`_
 769          """
 770  
 771          assert is_optional(all, bool), all
 772          assert is_optional(participating, bool), participating
 773          assert is_optional(since, datetime), since
 774          assert is_optional(before, datetime), before
 775  
 776          params: dict[str, Any] = {}
 777          if is_defined(all):
 778              # convert True, False to true, false for api parameters
 779              params["all"] = "true" if all else "false"
 780          if is_defined(participating):
 781              # convert True, False to true, false for api parameters
 782              params["participating"] = "true" if participating else "false"
 783          if is_defined(since):
 784              params["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ")
 785          if is_defined(before):
 786              params["before"] = before.strftime("%Y-%m-%dT%H:%M:%SZ")
 787  
 788          return PaginatedList(github.Notification.Notification, self._requester, "/notifications", params)
 789  
 790      def get_organization_events(self, org: Organization) -> PaginatedList[Event]:
 791          """
 792          :calls: `GET /users/{user}/events/orgs/{org} <http://docs.github.com/en/rest/reference/activity#events>`_
 793          """
 794          assert isinstance(org, github.Organization.Organization), org
 795          return PaginatedList(
 796              github.Event.Event,
 797              self._requester,
 798              f"/users/{self.login}/events/orgs/{org.login}",
 799              None,
 800          )
 801  
 802      def get_orgs(self) -> PaginatedList[Organization]:
 803          """
 804          :calls: `GET /user/orgs <http://docs.github.com/en/rest/reference/orgs>`_
 805          """
 806          return PaginatedList(github.Organization.Organization, self._requester, "/user/orgs", None)
 807  
 808      def get_repo(self, name: str) -> Repository:
 809          """
 810          :calls: `GET /repos/{owner}/{repo} <http://docs.github.com/en/rest/reference/repos>`_
 811          """
 812          assert isinstance(name, str), name
 813          headers, data = self._requester.requestJsonAndCheck("GET", f"/repos/{self.login}/{name}")
 814          return github.Repository.Repository(self._requester, headers, data, completed=True)
 815  
 816      def get_repos(
 817          self,
 818          visibility: Opt[str] = NotSet,
 819          affiliation: Opt[str] = NotSet,
 820          type: Opt[str] = NotSet,
 821          sort: Opt[str] = NotSet,
 822          direction: Opt[str] = NotSet,
 823      ) -> PaginatedList[Repository]:
 824          """
 825          :calls: `GET /user/repos <http://docs.github.com/en/rest/reference/repos>`_
 826          """
 827          assert is_optional(visibility, str), visibility
 828          assert is_optional(affiliation, str), affiliation
 829          assert is_optional(type, str), type
 830          assert is_optional(sort, str), sort
 831          assert is_optional(direction, str), direction
 832          url_parameters = NotSet.remove_unset_items(
 833              {
 834                  "visibility": visibility,
 835                  "affiliation": affiliation,
 836                  "type": type,
 837                  "sort": sort,
 838                  "direction": direction,
 839              }
 840          )
 841          return PaginatedList(github.Repository.Repository, self._requester, "/user/repos", url_parameters)
 842  
 843      def get_starred(self) -> PaginatedList[Repository]:
 844          """
 845          :calls: `GET /user/starred <http://docs.github.com/en/rest/reference/activity#starring>`_
 846          """
 847          return PaginatedList(github.Repository.Repository, self._requester, "/user/starred", None)
 848  
 849      def get_starred_gists(self) -> PaginatedList[Gist]:
 850          """
 851          :calls: `GET /gists/starred <http://docs.github.com/en/rest/reference/gists>`_
 852          """
 853          return PaginatedList(github.Gist.Gist, self._requester, "/gists/starred", None)
 854  
 855      def get_subscriptions(self) -> PaginatedList[Repository]:
 856          """
 857          :calls: `GET /user/subscriptions <http://docs.github.com/en/rest/reference/activity#watching>`_
 858          """
 859          return PaginatedList(github.Repository.Repository, self._requester, "/user/subscriptions", None)
 860  
 861      def get_teams(self) -> PaginatedList[Team]:
 862          """
 863          :calls: `GET /user/teams <http://docs.github.com/en/rest/reference/teams>`_
 864          """
 865          return PaginatedList(github.Team.Team, self._requester, "/user/teams", None)
 866  
 867      def get_watched(self) -> PaginatedList[Repository]:
 868          """
 869          :calls: `GET /user/subscriptions <http://docs.github.com/en/rest/reference/activity#watching>`_
 870          """
 871          return PaginatedList(github.Repository.Repository, self._requester, "/user/subscriptions", None)
 872  
 873      def get_installations(self) -> PaginatedList[Installation]:
 874          """
 875          :calls: `GET /user/installations <http://docs.github.com/en/rest/reference/apps>`_
 876          """
 877          return PaginatedList(
 878              github.Installation.Installation,
 879              self._requester,
 880              "/user/installations",
 881              None,
 882              headers={"Accept": Consts.mediaTypeIntegrationPreview},
 883              list_item="installations",
 884          )
 885  
 886      def has_in_following(self, following: NamedUser) -> bool:
 887          """
 888          :calls: `GET /user/following/{user} <http://docs.github.com/en/rest/reference/users#followers>`_
 889          """
 890          assert isinstance(following, github.NamedUser.NamedUser), following
 891          status, headers, data = self._requester.requestJson("GET", f"/user/following/{following._identity}")
 892          return status == 204
 893  
 894      def has_in_starred(self, starred: Repository) -> bool:
 895          """
 896          :calls: `GET /user/starred/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#starring>`_
 897          """
 898          assert isinstance(starred, github.Repository.Repository), starred
 899          status, headers, data = self._requester.requestJson("GET", f"/user/starred/{starred._identity}")
 900          return status == 204
 901  
 902      def has_in_subscriptions(self, subscription: Repository) -> bool:
 903          """
 904          :calls: `GET /user/subscriptions/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#watching>`_
 905          """
 906          assert isinstance(subscription, github.Repository.Repository), subscription
 907          status, headers, data = self._requester.requestJson("GET", f"/user/subscriptions/{subscription._identity}")
 908          return status == 204
 909  
 910      def has_in_watched(self, watched: Repository) -> bool:
 911          """
 912          :calls: `GET /repos/{owner}/{repo}/subscription <http://docs.github.com/en/rest/reference/activity#watching>`_
 913          """
 914          assert isinstance(watched, github.Repository.Repository), watched
 915          status, headers, data = self._requester.requestJson("GET", f"/repos/{watched._identity}/subscription")
 916          return status == 200
 917  
 918      def mark_notifications_as_read(self, last_read_at: datetime | None = None) -> None:
 919          """
 920          :calls: `PUT /notifications <https://docs.github.com/en/rest/reference/activity#notifications>`_
 921          """
 922          if last_read_at is None:
 923              last_read_at = datetime.now(timezone.utc)
 924          assert isinstance(last_read_at, datetime)
 925          put_parameters = {"last_read_at": last_read_at.strftime("%Y-%m-%dT%H:%M:%SZ")}
 926  
 927          headers, data = self._requester.requestJsonAndCheck("PUT", "/notifications", input=put_parameters)
 928  
 929      def remove_from_emails(self, *emails: str) -> None:
 930          """
 931          :calls: `DELETE /user/emails <http://docs.github.com/en/rest/reference/users#emails>`_
 932          """
 933          assert all(isinstance(element, str) for element in emails), emails
 934          post_parameters = {"emails": emails}
 935          headers, data = self._requester.requestJsonAndCheck("DELETE", "/user/emails", input=post_parameters)
 936  
 937      def remove_from_following(self, following: NamedUser) -> None:
 938          """
 939          :calls: `DELETE /user/following/{user} <http://docs.github.com/en/rest/reference/users#followers>`_
 940          """
 941          assert isinstance(following, github.NamedUser.NamedUser), following
 942          headers, data = self._requester.requestJsonAndCheck("DELETE", f"/user/following/{following._identity}")
 943  
 944      def remove_from_starred(self, starred: Repository) -> None:
 945          """
 946          :calls: `DELETE /user/starred/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#starring>`_
 947          """
 948          assert isinstance(starred, github.Repository.Repository), starred
 949          headers, data = self._requester.requestJsonAndCheck("DELETE", f"/user/starred/{starred._identity}")
 950  
 951      def remove_from_subscriptions(self, subscription: Repository) -> None:
 952          """
 953          :calls: `DELETE /user/subscriptions/{owner}/{repo} <http://docs.github.com/en/rest/reference/activity#watching>`_
 954          """
 955          assert isinstance(subscription, github.Repository.Repository), subscription
 956          headers, data = self._requester.requestJsonAndCheck("DELETE", f"/user/subscriptions/{subscription._identity}")
 957  
 958      def remove_from_watched(self, watched: Repository) -> None:
 959          """
 960          :calls: `DELETE /repos/{owner}/{repo}/subscription <http://docs.github.com/en/rest/reference/activity#watching>`_
 961          """
 962          assert isinstance(watched, github.Repository.Repository), watched
 963          headers, data = self._requester.requestJsonAndCheck("DELETE", f"/repos/{watched._identity}/subscription")
 964  
 965      def accept_invitation(self, invitation: Invitation | int) -> None:
 966          """
 967          :calls: `PATCH /user/repository_invitations/{invitation_id} <https://docs.github.com/en/rest/reference/repos/invitations#>`_
 968          """
 969          assert isinstance(invitation, github.Invitation.Invitation) or isinstance(invitation, int)
 970  
 971          if isinstance(invitation, github.Invitation.Invitation):
 972              invitation = invitation.id
 973  
 974          headers, data = self._requester.requestJsonAndCheck(
 975              "PATCH", f"/user/repository_invitations/{invitation}", input={}
 976          )
 977  
 978      def get_invitations(self) -> PaginatedList[Invitation]:
 979          """
 980          :calls: `GET /user/repository_invitations <https://docs.github.com/en/rest/reference/repos#invitations>`_
 981          """
 982          return PaginatedList(
 983              github.Invitation.Invitation,
 984              self._requester,
 985              "/user/repository_invitations",
 986              None,
 987          )
 988  
 989      def create_migration(
 990          self,
 991          repos: list[Repository] | tuple[Repository],
 992          lock_repositories: Opt[bool] = NotSet,
 993          exclude_attachments: Opt[bool] = NotSet,
 994      ) -> Migration:
 995          """
 996          :calls: `POST /user/migrations <https://docs.github.com/en/rest/reference/migrations>`_
 997          """
 998          assert isinstance(repos, (list, tuple)), repos
 999          assert all(isinstance(repo, str) for repo in repos), repos
1000          assert is_optional(lock_repositories, bool), lock_repositories
1001          assert is_optional(exclude_attachments, bool), exclude_attachments
1002          post_parameters: dict[str, Any] = NotSet.remove_unset_items(
1003              {
1004                  "repositories": repos,
1005                  "lock_repositories": lock_repositories,
1006                  "exclude_attachments": exclude_attachments,
1007              }
1008          )
1009  
1010          headers, data = self._requester.requestJsonAndCheck(
1011              "POST",
1012              "/user/migrations",
1013              input=post_parameters,
1014              headers={"Accept": Consts.mediaTypeMigrationPreview},
1015          )
1016          return github.Migration.Migration(self._requester, headers, data, completed=True)
1017  
1018      def get_migrations(self) -> PaginatedList[Migration]:
1019          """
1020          :calls: `GET /user/migrations <https://docs.github.com/en/rest/reference/migrations>`_
1021          """
1022          return PaginatedList(
1023              github.Migration.Migration,
1024              self._requester,
1025              "/user/migrations",
1026              None,
1027              headers={"Accept": Consts.mediaTypeMigrationPreview},
1028          )
1029  
1030      def get_organization_membership(self, org: str) -> Membership:
1031          """
1032          :calls: `GET /user/memberships/orgs/{org} <https://docs.github.com/en/rest/reference/orgs#get-an-organization-membership-for-the-authenticated-user>`_
1033          """
1034          assert isinstance(org, str)
1035          headers, data = self._requester.requestJsonAndCheck("GET", f"/user/memberships/orgs/{org}")
1036          return github.Membership.Membership(self._requester, headers, data, completed=True)
1037  
1038      def _useAttributes(self, attributes: dict[str, Any]) -> None:
1039          if "avatar_url" in attributes:  # pragma no branch
1040              self._avatar_url = self._makeStringAttribute(attributes["avatar_url"])
1041          if "bio" in attributes:  # pragma no branch
1042              self._bio = self._makeStringAttribute(attributes["bio"])
1043          if "blog" in attributes:  # pragma no branch
1044              self._blog = self._makeStringAttribute(attributes["blog"])
1045          if "collaborators" in attributes:  # pragma no branch
1046              self._collaborators = self._makeIntAttribute(attributes["collaborators"])
1047          if "company" in attributes:  # pragma no branch
1048              self._company = self._makeStringAttribute(attributes["company"])
1049          if "created_at" in attributes:  # pragma no branch
1050              self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
1051          if "disk_usage" in attributes:  # pragma no branch
1052              self._disk_usage = self._makeIntAttribute(attributes["disk_usage"])
1053          if "email" in attributes:  # pragma no branch
1054              self._email = self._makeStringAttribute(attributes["email"])
1055          if "events_url" in attributes:  # pragma no branch
1056              self._events_url = self._makeStringAttribute(attributes["events_url"])
1057          if "followers" in attributes:  # pragma no branch
1058              self._followers = self._makeIntAttribute(attributes["followers"])
1059          if "followers_url" in attributes:  # pragma no branch
1060              self._followers_url = self._makeStringAttribute(attributes["followers_url"])
1061          if "following" in attributes:  # pragma no branch
1062              self._following = self._makeIntAttribute(attributes["following"])
1063          if "following_url" in attributes:  # pragma no branch
1064              self._following_url = self._makeStringAttribute(attributes["following_url"])
1065          if "gists_url" in attributes:  # pragma no branch
1066              self._gists_url = self._makeStringAttribute(attributes["gists_url"])
1067          if "gravatar_id" in attributes:  # pragma no branch
1068              self._gravatar_id = self._makeStringAttribute(attributes["gravatar_id"])
1069          if "hireable" in attributes:  # pragma no branch
1070              self._hireable = self._makeBoolAttribute(attributes["hireable"])
1071          if "html_url" in attributes:  # pragma no branch
1072              self._html_url = self._makeStringAttribute(attributes["html_url"])
1073          if "id" in attributes:  # pragma no branch
1074              self._id = self._makeIntAttribute(attributes["id"])
1075          if "location" in attributes:  # pragma no branch
1076              self._location = self._makeStringAttribute(attributes["location"])
1077          if "login" in attributes:  # pragma no branch
1078              self._login = self._makeStringAttribute(attributes["login"])
1079          if "name" in attributes:  # pragma no branch
1080              self._name = self._makeStringAttribute(attributes["name"])
1081          if "node_id" in attributes:  # pragma no branch
1082              self._node_id = self._makeStringAttribute(attributes["node_id"])
1083          if "organizations_url" in attributes:  # pragma no branch
1084              self._organizations_url = self._makeStringAttribute(attributes["organizations_url"])
1085          if "owned_private_repos" in attributes:  # pragma no branch
1086              self._owned_private_repos = self._makeIntAttribute(attributes["owned_private_repos"])
1087          if "plan" in attributes:  # pragma no branch
1088              self._plan = self._makeClassAttribute(github.Plan.Plan, attributes["plan"])
1089          if "private_gists" in attributes:  # pragma no branch
1090              self._private_gists = self._makeIntAttribute(attributes["private_gists"])
1091          if "public_gists" in attributes:  # pragma no branch
1092              self._public_gists = self._makeIntAttribute(attributes["public_gists"])
1093          if "public_repos" in attributes:  # pragma no branch
1094              self._public_repos = self._makeIntAttribute(attributes["public_repos"])
1095          if "received_events_url" in attributes:  # pragma no branch
1096              self._received_events_url = self._makeStringAttribute(attributes["received_events_url"])
1097          if "repos_url" in attributes:  # pragma no branch
1098              self._repos_url = self._makeStringAttribute(attributes["repos_url"])
1099          if "site_admin" in attributes:  # pragma no branch
1100              self._site_admin = self._makeBoolAttribute(attributes["site_admin"])
1101          if "starred_url" in attributes:  # pragma no branch
1102              self._starred_url = self._makeStringAttribute(attributes["starred_url"])
1103          if "subscriptions_url" in attributes:  # pragma no branch
1104              self._subscriptions_url = self._makeStringAttribute(attributes["subscriptions_url"])
1105          if "total_private_repos" in attributes:  # pragma no branch
1106              self._total_private_repos = self._makeIntAttribute(attributes["total_private_repos"])
1107          if "type" in attributes:  # pragma no branch
1108              self._type = self._makeStringAttribute(attributes["type"])
1109          if "updated_at" in attributes:  # pragma no branch
1110              self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
1111          if "url" in attributes:  # pragma no branch
1112              self._url = self._makeStringAttribute(attributes["url"])
1113          if "two_factor_authentication" in attributes:
1114              self._two_factor_authentication = self._makeBoolAttribute(attributes["two_factor_authentication"])