/ tests / Repository.py
Repository.py
   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 2015 Christopher Wilcox <git@crwilcox.com>                         #
   8  # Copyright 2015 Dan Vanderkam <danvdk@gmail.com>                              #
   9  # Copyright 2015 Enix Yu <enix223@163.com>                                     #
  10  # Copyright 2015 Kyle Hornberg <khornberg@users.noreply.github.com>            #
  11  # Copyright 2015 Uriel Corfa <uriel@corfa.fr>                                  #
  12  # Copyright 2016 @tmshn <tmshn@r.recruit.co.jp>                                #
  13  # Copyright 2016 Enix Yu <enix223@163.com>                                     #
  14  # Copyright 2016 Jannis Gebauer <ja.geb@me.com>                                #
  15  # Copyright 2016 Jimmy Zelinskie <jimmyzelinskie@gmail.com>                    #
  16  # Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #
  17  # Copyright 2018 Hayden Fuss <wifu1234@gmail.com>                              #
  18  # Copyright 2018 Iraquitan Cordeiro Filho <iraquitanfilho@gmail.com>           #
  19  # Copyright 2018 Jacopo Notarstefano <jacopo.notarstefano@gmail.com>           #
  20  # Copyright 2018 Maarten Fonville <mfonville@users.noreply.github.com>         #
  21  # Copyright 2018 Mateusz Loskot <mateusz@loskot.net>                           #
  22  # Copyright 2018 Raihaan <31362124+res0nance@users.noreply.github.com>         #
  23  # Copyright 2018 Shinichi TAMURA <shnch.tmr@gmail.com>                         #
  24  # Copyright 2018 Steve Kowalik <steven@wedontsleep.org>                        #
  25  # Copyright 2018 Victor Granic <vmg@boreal321.com>                             #
  26  # Copyright 2018 Wan Liuyang <tsfdye@gmail.com>                                #
  27  # Copyright 2018 Will Yardley <wyardley@users.noreply.github.com>              #
  28  # Copyright 2018 sfdye <tsfdye@gmail.com>                                      #
  29  # Copyright 2020 Pascal Hofmann <mail@pascalhofmann.de>                        #
  30  # Copyright 2023 Mauricio Martinez <mauricio.martinez@premise.com>             #
  31  # Copyright 2023 Armen Martirosyan <armartirosyan@users.noreply.github.com>    #
  32  # Copyright 2023 DB Systel GmbH                                                #
  33  #                                                                              #
  34  # This file is part of PyGithub.                                               #
  35  # http://pygithub.readthedocs.io/                                              #
  36  #                                                                              #
  37  # PyGithub is free software: you can redistribute it and/or modify it under    #
  38  # the terms of the GNU Lesser General Public License as published by the Free  #
  39  # Software Foundation, either version 3 of the License, or (at your option)    #
  40  # any later version.                                                           #
  41  #                                                                              #
  42  # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #
  43  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #
  44  # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
  45  # details.                                                                     #
  46  #                                                                              #
  47  # You should have received a copy of the GNU Lesser General Public License     #
  48  # along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #
  49  #                                                                              #
  50  ################################################################################
  51  
  52  from datetime import date, datetime, timezone
  53  from unittest import mock
  54  
  55  import github
  56  
  57  from . import Framework
  58  
  59  
  60  class Repository(Framework.TestCase):
  61      def setUp(self):
  62          super().setUp()
  63          self.user = self.g.get_user()
  64          self.repo = self.user.get_repo("PyGithub")
  65  
  66      def testAttributes(self):
  67          self.assertEqual(self.repo.clone_url, "https://github.com/jacquev6/PyGithub.git")
  68          self.assertEqual(
  69              self.repo.created_at,
  70              datetime(2012, 2, 25, 12, 53, 47, tzinfo=timezone.utc),
  71          )
  72          self.assertEqual(self.repo.description, "Python library implementing the full Github API v3")
  73          self.assertFalse(self.repo.fork)
  74          self.assertEqual(self.repo.forks, 3)
  75          self.assertEqual(self.repo.full_name, "jacquev6/PyGithub")
  76          self.assertEqual(self.repo.git_url, "git://github.com/jacquev6/PyGithub.git")
  77          self.assertTrue(self.repo.has_downloads)
  78          self.assertTrue(self.repo.has_issues)
  79          self.assertEqual(
  80              self.repo.deployments_url,
  81              "https://api.github.com/repos/jacquev6/PyGithub/deployments",
  82          )
  83          self.assertFalse(self.repo.has_pages)
  84          self.assertEqual(
  85              self.repo.releases_url,
  86              "https://api.github.com/repos/jacquev6/PyGithub/releases{/id}",
  87          )
  88          self.assertFalse(self.repo.has_wiki)
  89          self.assertEqual(self.repo.homepage, "http://vincent-jacques.net/PyGithub")
  90          self.assertEqual(self.repo.html_url, "https://github.com/jacquev6/PyGithub")
  91          self.assertEqual(self.repo.id, 3544490)
  92          self.assertIs(self.repo.is_template, None)
  93          self.assertEqual(self.repo.language, "Python")
  94          self.assertEqual(self.repo.license.spdx_id, "LGPL-3.0")
  95          self.assertEqual(self.repo.master_branch, None)
  96          self.assertEqual(self.repo.name, "PyGithub")
  97          self.assertEqual(self.repo.open_issues, 16)
  98          self.assertEqual(self.repo.organization, None)
  99          self.assertEqual(self.repo.owner.login, "jacquev6")
 100          self.assertEqual(self.repo.parent, None)
 101          self.assertTrue(self.repo.permissions.admin)
 102          self.assertTrue(self.repo.permissions.pull)
 103          self.assertTrue(self.repo.permissions.push)
 104          self.assertFalse(self.repo.private)
 105          self.assertEqual(
 106              self.repo.pushed_at,
 107              datetime(2012, 5, 27, 6, 0, 28, tzinfo=timezone.utc),
 108          )
 109          self.assertEqual(self.repo.size, 308)
 110          self.assertEqual(self.repo.source, None)
 111          self.assertEqual(self.repo.ssh_url, "git@github.com:jacquev6/PyGithub.git")
 112          self.assertEqual(self.repo.svn_url, "https://github.com/jacquev6/PyGithub")
 113          self.assertEqual(
 114              self.repo.updated_at,
 115              datetime(2012, 5, 27, 6, 55, 28, tzinfo=timezone.utc),
 116          )
 117          self.assertEqual(self.repo.url, "https://api.github.com/repos/jacquev6/PyGithub")
 118          self.assertEqual(self.repo.watchers, 15)
 119          self.assertEqual(repr(self.repo), 'Repository(full_name="jacquev6/PyGithub")')
 120          self.assertTrue(self.repo.permissions.admin)
 121          self.assertTrue(self.repo.permissions.push)
 122          self.assertTrue(self.repo.permissions.pull)
 123          # Allow None or any boolean value for backwards compatibility
 124          self.assertIn(self.repo.permissions.maintain, [None, False, True])
 125          self.assertIn(self.repo.permissions.triage, [None, False, True])
 126  
 127          self.assertTrue(self.repo.use_squash_pr_title_as_default)
 128          self.assertEqual(self.repo.squash_merge_commit_title, "PR_TITLE")
 129          self.assertEqual(self.repo.squash_merge_commit_message, "COMMIT_MESSAGES")
 130          self.assertEqual(self.repo.merge_commit_title, "PR_TITLE")
 131          self.assertEqual(self.repo.merge_commit_message, "PR_BODY")
 132          self.assertTrue(self.repo.web_commit_signoff_required)
 133  
 134      def testEditWithoutArguments(self):
 135          self.repo.edit("PyGithub")
 136  
 137      def testEditWithAllArguments(self):
 138          self.repo.edit(
 139              "PyGithub",
 140              "Description edited by PyGithub",
 141              "http://vincent-jacques.net/PyGithub",
 142              private=True,
 143              has_issues=True,
 144              has_projects=False,
 145              has_wiki=False,
 146              allow_auto_merge=True,
 147              allow_forking=True,
 148              allow_update_branch=True,
 149              allow_squash_merge=True,
 150              allow_merge_commit=True,
 151              allow_rebase_merge=True,
 152              delete_branch_on_merge=True,
 153              use_squash_pr_title_as_default=True,
 154              is_template=True,
 155              squash_merge_commit_title="PR_TITLE",
 156              squash_merge_commit_message="COMMIT_MESSAGES",
 157              merge_commit_title="PR_TITLE",
 158              merge_commit_message="PR_BODY",
 159              web_commit_signoff_required=True,
 160          )
 161          self.assertEqual(self.repo.description, "Description edited by PyGithub")
 162          self.repo.edit("PyGithub", "Python library implementing the full Github API v3")
 163          self.assertEqual(self.repo.description, "Python library implementing the full Github API v3")
 164          self.assertFalse(self.repo.archived)
 165          self.assertTrue(self.repo.allow_update_branch)
 166          self.assertTrue(self.repo.has_issues)
 167          self.assertFalse(self.repo.has_projects)
 168          self.assertFalse(self.repo.has_wiki)
 169          self.assertTrue(self.repo.allow_auto_merge)
 170          self.assertTrue(self.repo.allow_forking)
 171          self.assertTrue(self.repo.allow_squash_merge)
 172          self.assertTrue(self.repo.allow_merge_commit)
 173          self.assertTrue(self.repo.allow_rebase_merge)
 174          self.assertTrue(self.repo.delete_branch_on_merge)
 175          self.assertTrue(self.repo.use_squash_pr_title_as_default)
 176          self.assertEqual(self.repo.squash_merge_commit_title, "PR_TITLE")
 177          self.assertEqual(self.repo.squash_merge_commit_message, "COMMIT_MESSAGES")
 178          self.assertEqual(self.repo.merge_commit_title, "PR_TITLE")
 179          self.assertEqual(self.repo.merge_commit_message, "PR_BODY")
 180          self.assertTrue(self.repo.web_commit_signoff_required)
 181  
 182      def testEditWithDefaultBranch(self):
 183          self.assertEqual(self.repo.master_branch, None)
 184          self.repo.edit("PyGithub", default_branch="master")
 185          self.assertEqual(self.repo.master_branch, "master")
 186  
 187      def testDelete(self):
 188          repo = self.g.get_user().get_repo("TestPyGithub")
 189          repo.delete()
 190  
 191      def testGetContributors(self):
 192          self.assertListKeyEqual(
 193              self.repo.get_contributors(),
 194              lambda c: (c.login, c.contributions),
 195              [("jacquev6", 355)],
 196          )
 197  
 198      def testCreateMilestone(self):
 199          milestone = self.repo.create_milestone(
 200              "Milestone created by PyGithub",
 201              state="open",
 202              description="Description created by PyGithub",
 203              due_on=date(2012, 6, 15),
 204          )
 205          self.assertEqual(milestone.number, 5)
 206  
 207      def testCreateMilestoneWithMinimalArguments(self):
 208          milestone = self.repo.create_milestone("Milestone also created by PyGithub")
 209          self.assertEqual(milestone.number, 6)
 210  
 211      def testCreateIssue(self):
 212          issue = self.repo.create_issue("Issue created by PyGithub")
 213          self.assertEqual(issue.number, 28)
 214  
 215      def testCreateIssueWithAllArguments(self):
 216          user = self.g.get_user("jacquev6")
 217          milestone = self.repo.get_milestone(2)
 218          question = self.repo.get_label("Question")
 219          issue = self.repo.create_issue(
 220              "Issue also created by PyGithub",
 221              "Body created by PyGithub",
 222              user,
 223              milestone,
 224              [question],
 225              ["jacquev6", "stuglaser"],
 226          )
 227          self.assertEqual(issue.number, 30)
 228  
 229      def testCreateIssueWithAllArgumentsStringLabel(self):
 230          user = self.g.get_user("jacquev6")
 231          milestone = self.repo.get_milestone(2)
 232          issue = self.repo.create_issue(
 233              "Issue also created by PyGithub",
 234              "Body created by PyGithub",
 235              user,
 236              milestone,
 237              ["Question"],
 238              ["jacquev6", "stuglaser"],
 239          )
 240          self.assertEqual(issue.number, 30)
 241  
 242      def testCreateLabel(self):
 243          label = self.repo.create_label(
 244              "Label with silly name % * + created by PyGithub",
 245              "00ff00",
 246              "Description of label with silly name",
 247          )
 248          self.assertEqual(label.color, "00ff00")
 249          self.assertEqual(label.description, "Description of label with silly name")
 250          self.assertEqual(label.name, "Label with silly name % * + created by PyGithub")
 251          self.assertEqual(
 252              label.url,
 253              "https://api.github.com/repos/jacquev6/PyGithub/labels/Label+with+silly+name+%25+%2A+%2B+created+by+PyGithub",
 254          )
 255  
 256      def testGetLabel(self):
 257          label = self.repo.get_label("Label with silly name % * + created by PyGithub")
 258          self.assertEqual(label.color, "00ff00")
 259          self.assertEqual(label.name, "Label with silly name % * + created by PyGithub")
 260          self.assertEqual(
 261              label.url,
 262              "https://api.github.com/repos/jacquev6/PyGithub/labels/Label+with+silly+name+%25+%2A+%2B+created+by+PyGithub",
 263          )
 264  
 265      def testCreateHookWithMinimalParameters(self):
 266          hook = self.repo.create_hook("web", {"url": "http://foobar.com"})
 267          self.assertEqual(hook.id, 257967)
 268  
 269      def testCreateHookWithAllParameters(self):
 270          hook = self.repo.create_hook("web", {"url": "http://foobar.com"}, ["fork"], False)
 271          self.assertTrue(hook.active)  # WTF
 272          self.assertEqual(hook.id, 257993)
 273  
 274      def testCreateGitRef(self):
 275          ref = self.repo.create_git_ref(
 276              "refs/heads/BranchCreatedByPyGithub",
 277              "4303c5b90e2216d927155e9609436ccb8984c495",
 278          )
 279          self.assertEqual(
 280              ref.url,
 281              "https://api.github.com/repos/jacquev6/PyGithub/git/refs/heads/BranchCreatedByPyGithub",
 282          )
 283  
 284      def testCreateAutolink(self):
 285          key = self.repo.create_autolink("DUMMY-", "https://github.com/PyGithub/PyGithub/issues/<num>")
 286          self.assertEqual(key.id, 209614)
 287  
 288      def testCreateGitBlob(self):
 289          blob = self.repo.create_git_blob("Blob created by PyGithub", "latin1")
 290          self.assertEqual(blob.sha, "5dd930f591cd5188e9ea7200e308ad355182a1d8")
 291  
 292      def testCreateGitTree(self):
 293          tree = self.repo.create_git_tree(
 294              [github.InputGitTreeElement("Foobar.txt", "100644", "blob", content="File created by PyGithub")]
 295          )
 296          self.assertEqual(tree.sha, "41cf8c178c636a018d537cb20daae09391efd70b")
 297  
 298      def testCreateGitTreeWithBaseTree(self):
 299          base_tree = self.repo.get_git_tree("41cf8c178c636a018d537cb20daae09391efd70b", recursive=False)
 300          tree = self.repo.create_git_tree(
 301              [
 302                  github.InputGitTreeElement(
 303                      "Barbaz.txt",
 304                      "100644",
 305                      "blob",
 306                      content="File also created by PyGithub",
 307                  )
 308              ],
 309              base_tree,
 310          )
 311          self.assertEqual(tree.sha, "107139a922f33bab6fbeb9f9eb8787e7f19e0528")
 312  
 313      def testCreateGitTreeWithSha(self):
 314          tree = self.repo.create_git_tree(
 315              [
 316                  github.InputGitTreeElement(
 317                      "Barbaz.txt",
 318                      "100644",
 319                      "blob",
 320                      sha="5dd930f591cd5188e9ea7200e308ad355182a1d8",
 321                  )
 322              ]
 323          )
 324          self.assertEqual(tree.sha, "fae707821159639589bf94f3fb0a7154ec5d441b")
 325  
 326      def testCreateGitTreeWithNullSha(self):
 327          tree = self.repo.create_git_tree(
 328              [
 329                  github.InputGitTreeElement(
 330                      "Baz.bar",
 331                      "100644",
 332                      "blob",
 333                      sha=None,
 334                  )
 335              ]
 336          )
 337          self.assertEqual(tree.sha, "9b8166fc80d0f0fe9192d4bf1dbaa87f194e012f")
 338  
 339      def testCreateGitCommit(self):
 340          tree = self.repo.get_git_tree("107139a922f33bab6fbeb9f9eb8787e7f19e0528")
 341          commit = self.repo.create_git_commit("Commit created by PyGithub", tree, [])
 342          self.assertEqual(commit.sha, "0b820628236ab8bab3890860fc414fa757ca15f4")
 343  
 344      def testCreateGitCommitWithParents(self):
 345          parents = [
 346              self.repo.get_git_commit("7248e66831d4ffe09ef1f30a1df59ec0a9331ece"),
 347              self.repo.get_git_commit("12d427464f8d91c8e981043a86ba8a2a9e7319ea"),
 348          ]
 349          tree = self.repo.get_git_tree("fae707821159639589bf94f3fb0a7154ec5d441b")
 350          commit = self.repo.create_git_commit("Commit created by PyGithub", tree, parents)
 351          self.assertEqual(commit.sha, "6adf9ea25ff8a8f2a42bcb1c09e42526339037cd")
 352  
 353      def testCreateGitCommitWithAllArguments(self):
 354          tree = self.repo.get_git_tree("107139a922f33bab6fbeb9f9eb8787e7f19e0528")
 355          commit = self.repo.create_git_commit(
 356              "Commit created by PyGithub",
 357              tree,
 358              [],
 359              github.InputGitAuthor("John Doe", "j.doe@vincent-jacques.net", "2008-07-09T16:13:30+12:00"),
 360              github.InputGitAuthor("John Doe", "j.doe@vincent-jacques.net", "2008-07-09T16:13:30+12:00"),
 361          )
 362          self.assertEqual(commit.sha, "526946197ae9da59c6507cacd13ad6f1cfb686ea")
 363  
 364      def testCreateGitRelease(self):
 365          release = self.repo.create_git_release(
 366              "vX.Y.Z-by-PyGithub-acctest",
 367              "vX.Y.Z: PyGithub acctest",
 368              "This release is created by PyGithub",
 369          )
 370          self.assertEqual(release.tag_name, "vX.Y.Z-by-PyGithub-acctest")
 371          self.assertEqual(release.title, "vX.Y.Z: PyGithub acctest")
 372          self.assertEqual(release.body, "This release is created by PyGithub")
 373          self.assertEqual(release.draft, False)
 374          self.assertEqual(release.prerelease, False)
 375  
 376      def testCreateGitReleaseWithAllArguments(self):
 377          release = self.repo.create_git_release(
 378              "vX.Y.Z-by-PyGithub-acctest2",
 379              "vX.Y.Z: PyGithub acctest2",
 380              "This release is also created by PyGithub",
 381              False,
 382              True,
 383              False,
 384              "da9a285fd8b782461e56cba39ae8d2fa41ca7cdc",
 385          )
 386          self.assertEqual(release.tag_name, "vX.Y.Z-by-PyGithub-acctest2")
 387          self.assertEqual(release.title, "vX.Y.Z: PyGithub acctest2")
 388          self.assertEqual(release.body, "This release is also created by PyGithub")
 389          self.assertEqual(release.draft, False)
 390          self.assertEqual(release.prerelease, True)
 391          tag = [tag for tag in self.repo.get_tags() if tag.name == "vX.Y.Z-by-PyGithub-acctest2"].pop()
 392          self.assertEqual(tag.commit.sha, "da9a285fd8b782461e56cba39ae8d2fa41ca7cdc")
 393  
 394      def testCreateGitTag(self):
 395          tag = self.repo.create_git_tag(
 396              "TaggedByPyGithub",
 397              "Tag created by PyGithub",
 398              "0b820628236ab8bab3890860fc414fa757ca15f4",
 399              "commit",
 400          )
 401          self.assertEqual(tag.sha, "5ba561eaa2b7ca9015662510157b15d8f3b0232a")
 402  
 403      def testCreateGitTagWithAllArguments(self):
 404          tag = self.repo.create_git_tag(
 405              "TaggedByPyGithub2",
 406              "Tag also created by PyGithub",
 407              "526946197ae9da59c6507cacd13ad6f1cfb686ea",
 408              "commit",
 409              github.InputGitAuthor("John Doe", "j.doe@vincent-jacques.net", "2008-07-09T16:13:30+12:00"),
 410          )
 411          self.assertEqual(tag.sha, "f0e99a8335fbc84c53366c4a681118468f266625")
 412  
 413      def testCreateKey(self):
 414          key = self.repo.create_key(
 415              "Key added through PyGithub",
 416              "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2Mm0RjTNAYFfSCtUpO54usdseroUSIYg5KX4JoseTpqyiB/hqewjYLAdUq/tNIQzrkoEJWSyZrQt0ma7/YCyMYuNGd3DU6q6ZAyBeY3E9RyCiKjO3aTL2VKQGFvBVVmGdxGVSCITRphAcsKc/PF35/fg9XP9S0anMXcEFtdfMHz41SSw+XtE+Vc+6cX9FuI5qUfLGbkv8L1v3g4uw9VXlzq4GfTA+1S7D6mcoGHopAIXFlVr+2RfDKdSURMcB22z41fljO1MW4+zUS/4FyUTpL991es5fcwKXYoiE+x06VJeJJ1Krwx+DZj45uweV6cHXt2JwJEI9fWB6WyBlDejWw== vincent@IDEE",
 417          )
 418          self.assertEqual(key.id, 2626761)
 419  
 420      def testCreateSourceImport(self):
 421          import_repo = self.g.get_user("brix4dayz").get_repo("source-import-test")
 422          source_import = import_repo.create_source_import("mercurial", "https://bitbucket.org/hfuss/source-import-test")
 423          self.assertEqual(source_import.authors_count, 0)
 424          self.assertEqual(
 425              source_import.authors_url,
 426              "https://api.github.com/repos/brix4dayz/source-import-test/import/authors",
 427          )
 428          self.assertEqual(
 429              source_import.html_url,
 430              "https://github.com/brix4dayz/source-import-test/import",
 431          )
 432          self.assertEqual(
 433              source_import.repository_url,
 434              "https://api.github.com/repos/brix4dayz/source-import-test",
 435          )
 436          self.assertEqual(source_import.status, "importing")
 437          self.assertEqual(source_import.status_text, "Importing...")
 438          self.assertEqual(
 439              source_import.url,
 440              "https://api.github.com/repos/brix4dayz/source-import-test/import",
 441          )
 442          self.assertEqual(source_import.vcs, "mercurial")
 443          self.assertEqual(source_import.vcs_url, "https://bitbucket.org/hfuss/source-import-test")
 444  
 445      def testCreateRepositoryDispatch(self):
 446          with_payload = self.repo.create_repository_dispatch("type", {"foo": "bar"})
 447          self.assertTrue(with_payload)
 448          without_payload = self.repo.create_repository_dispatch("type")
 449          self.assertTrue(without_payload)
 450  
 451      @mock.patch("github.PublicKey.encrypt")
 452      def testCreateSecret(self, encrypt):
 453          # encrypt returns a non-deterministic value, we need to mock it so the replay data matches
 454          encrypt.return_value = "M+5Fm/BqTfB90h3nC7F3BoZuu3nXs+/KtpXwxm9gG211tbRo0F5UiN0OIfYT83CKcx9oKES9Va4E96/b"
 455          secret = self.repo.create_secret("secret-name", "secret-value")
 456          self.assertIsNotNone(secret)
 457  
 458      def testCodeScanAlerts(self):
 459          codescan_alerts = self.repo.get_codescan_alerts()
 460          self.assertListKeyEqual(
 461              codescan_alerts,
 462              lambda c: c.number,
 463              [
 464                  6,
 465              ],
 466          )
 467          codescan_alert = codescan_alerts[0]
 468          self.assertEqual(repr(codescan_alert), "CodeScanAlert(number=6)")
 469          self.assertEqual(codescan_alert.state, "open")
 470          self.assertEqual(
 471              codescan_alert.url,
 472              "https://api.github.com/repos/jacquev6/PyGithub/code-scanning/alerts/6",
 473          )
 474          self.assertEqual(
 475              codescan_alert.created_at,
 476              datetime(2021, 6, 29, 12, 28, 30, tzinfo=timezone.utc),
 477          )
 478          self.assertEqual(
 479              codescan_alert.dismissed_at,
 480              datetime(2021, 6, 30, 5, 5, 5, tzinfo=timezone.utc),
 481          )
 482          self.assertEqual(codescan_alert.dismissed_reason, "Won't tell")
 483          dismissed_by = codescan_alert.dismissed_by
 484          self.assertEqual(dismissed_by.login, "dismisser.login")
 485          instance = codescan_alert.most_recent_instance
 486          self.assertEqual(
 487              repr(instance),
 488              "CodeScanAlertInstance("
 489              'ref="refs/heads/master", '
 490              'analysis_key=".github/workflows/codeql-analysis.yml:analyze"'
 491              ")",
 492          )
 493          self.assertEqual(instance.ref, "refs/heads/master")
 494          self.assertEqual(instance.analysis_key, ".github/workflows/codeql-analysis.yml:analyze")
 495          self.assertEqual(instance.environment, "{language:python}")
 496          self.assertEqual(instance.state, "open")
 497          self.assertListEqual(instance.classifications, ["stupid typo"])
 498          self.assertDictEqual(instance.message, {"text": "Awful stuff might happen."})
 499          self.assertEqual(instance.commit_sha, "deadbeef")
 500          location = instance.location
 501          self.assertEqual(
 502              str(location),
 503              "tests/ReplayData/Repository.testCodeScanAlerts.txt @ l10:c2-l10:c48",
 504          )
 505          self.assertEqual(
 506              repr(location),
 507              "CodeScanAlertInstanceLocation("
 508              "start_line=10, start_column=2, "
 509              'path="tests/ReplayData/Repository.testCodeScanAlerts.txt", '
 510              "end_line=10, end_column=48"
 511              ")",
 512          )
 513          self.assertEqual(location.path, "tests/ReplayData/Repository.testCodeScanAlerts.txt")
 514          self.assertEqual(location.start_line, 10)
 515          self.assertEqual(location.start_column, 2)
 516          self.assertEqual(location.end_line, 10)
 517          self.assertEqual(location.end_column, 48)
 518          rule = codescan_alert.rule
 519          self.assertEqual(repr(rule), 'CodeScanRule(name="py/rule-name", id="py/rule-id")')
 520          self.assertEqual(rule.id, "py/rule-id")
 521          self.assertEqual(rule.name, "py/rule-name")
 522          self.assertEqual(rule.security_severity_level, "high")
 523          self.assertEqual(rule.severity, "warning")
 524          self.assertEqual(rule.description, "Bad practice")
 525          tool = codescan_alert.tool
 526          self.assertEqual(repr(tool), 'CodeScanTool(version="2.5.7", name="CodeQL", guid=None)')
 527          self.assertEqual(tool.guid, None)
 528          self.assertEqual(tool.name, "CodeQL")
 529          self.assertEqual(tool.version, "2.5.7")
 530          instances = list(codescan_alert.get_instances())
 531          self.assertEqual(len(instances), 2)
 532          #
 533          instance = instances[0]
 534          self.assertEqual(instance.ref, "instances[0].ref")
 535          self.assertEqual(instance.analysis_key, "instances[0].analysis_key")
 536          self.assertEqual(instance.environment, "instances[0].environment")
 537          self.assertEqual(instance.state, "instances[0].state")
 538          self.assertListEqual(instance.classifications, ["instances[0].classifications"])
 539          self.assertDictEqual(instance.message, {"text": "instances[0].message"})
 540          self.assertEqual(instance.commit_sha, "instances[0].commit_sha")
 541          location = instance.location
 542          self.assertEqual(location.path, "tests/ReplayData/Repository.testCodeScanAlerts.txt")
 543          self.assertEqual(location.start_line, 10)
 544          self.assertEqual(location.start_column, 2)
 545          self.assertEqual(location.end_line, 10)
 546          self.assertEqual(location.end_column, 48)
 547          #
 548          instance = instances[1]
 549          self.assertEqual(instance.ref, "instances[1].ref")
 550          self.assertEqual(instance.analysis_key, "instances[1].analysis_key")
 551          self.assertEqual(instance.environment, "instances[1].environment")
 552          self.assertEqual(instance.state, "instances[1].state")
 553          self.assertListEqual(instance.classifications, ["instances[1].classifications"])
 554          self.assertDictEqual(instance.message, {"text": "instances[1].message"})
 555          self.assertEqual(instance.commit_sha, "instances[1].commit_sha")
 556          location = instance.location
 557          self.assertEqual(location.path, "tests/ReplayData/Repository.testCodeScanAlerts.txt")
 558          self.assertEqual(location.start_line, 20)
 559          self.assertEqual(location.start_column, 17)
 560          self.assertEqual(location.end_line, 20)
 561          self.assertEqual(location.end_column, 42)
 562  
 563      def testCollaborators(self):
 564          lyloa = self.g.get_user("Lyloa")
 565          self.assertFalse(self.repo.has_in_collaborators(lyloa))
 566          self.repo.add_to_collaborators(lyloa)
 567          self.assertTrue(self.repo.has_in_collaborators(lyloa))
 568          collaborators = self.repo.get_collaborators()
 569          self.assertListKeyEqual(collaborators, lambda u: u.login, ["jacquev6", "Lyloa"])
 570          jacquev6 = [u for u in collaborators if u.login == "jacquev6"][0]
 571          self.assertTrue(jacquev6.permissions.admin, True)
 572          self.assertTrue(jacquev6.permissions.pull, True)
 573          self.assertTrue(jacquev6.permissions.push, True)
 574          self.assertFalse(jacquev6.site_admin)
 575          self.repo.remove_from_collaborators(lyloa)
 576          self.assertFalse(self.repo.has_in_collaborators(lyloa))
 577  
 578      def testCollaboratorPermission(self):
 579          self.assertEqual(self.repo.get_collaborator_permission("jacquev6"), "admin")
 580  
 581      def testGetPendingInvitations(self):
 582          lyloa = self.g.get_user("Lyloa")
 583          self.repo.add_to_collaborators(lyloa)
 584          invitations = self.repo.get_pending_invitations()
 585          self.assertListKeyEqual(invitations, lambda u: u.invitee.login, ["Lyloa"])
 586  
 587      def testRemoveInvitation(self):
 588          self.repo.remove_invitation(17285388)
 589  
 590      def testRemoveAutolink(self):
 591          self.repo.remove_autolink(209611)
 592  
 593      def testCollaboratorPermissionNoPushAccess(self):
 594          with self.assertRaises(github.GithubException) as raisedexp:
 595              self.repo.get_collaborator_permission("lyloa")
 596          self.assertEqual(raisedexp.exception.status, 403)
 597          self.assertEqual(
 598              raisedexp.exception.data,
 599              {
 600                  "documentation_url": "https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level",
 601                  "message": "Must have push access to view collaborator permission.",
 602              },
 603          )
 604  
 605      def testCompare(self):
 606          comparison = self.repo.compare("v0.6", "v0.7")
 607          self.assertEqual(comparison.status, "ahead")
 608          self.assertEqual(comparison.ahead_by, 4)
 609          self.assertEqual(comparison.behind_by, 0)
 610          self.assertEqual(
 611              comparison.diff_url,
 612              "https://github.com/jacquev6/PyGithub/compare/v0.6...v0.7.diff",
 613          )
 614          self.assertEqual(
 615              comparison.html_url,
 616              "https://github.com/jacquev6/PyGithub/compare/v0.6...v0.7",
 617          )
 618          self.assertEqual(
 619              comparison.url,
 620              "https://api.github.com/repos/jacquev6/PyGithub/compare/v0.6...v0.7",
 621          )
 622          self.assertEqual(
 623              comparison.patch_url,
 624              "https://github.com/jacquev6/PyGithub/compare/v0.6...v0.7.patch",
 625          )
 626          self.assertEqual(
 627              comparison.permalink_url,
 628              "https://github.com/jacquev6/PyGithub/compare/jacquev6:4303c5b...jacquev6:ecda065",
 629          )
 630          self.assertEqual(comparison.total_commits, 4)
 631          self.assertListKeyEqual(
 632              comparison.files,
 633              lambda f: f.filename,
 634              [
 635                  "ReferenceOfClasses.md",
 636                  "github/Github.py",
 637                  "github/Requester.py",
 638                  "setup.py",
 639              ],
 640          )
 641          self.assertEqual(comparison.base_commit.sha, "4303c5b90e2216d927155e9609436ccb8984c495")
 642          self.assertListKeyEqual(
 643              comparison.commits,
 644              lambda c: c.sha,
 645              [
 646                  "5bb654d26dd014d36794acd1e6ecf3736f12aad7",
 647                  "cb0313157bf904f2d364377d35d9397b269547a5",
 648                  "0cec0d25e606c023a62a4fc7cdc815309ebf6d16",
 649                  "ecda065e01876209d2bdf5fe4e91cee8ffaa9ff7",
 650              ],
 651          )
 652  
 653      def testGetComments(self):
 654          self.assertListKeyEqual(
 655              self.repo.get_comments(),
 656              lambda c: c.body,
 657              [
 658                  "probably a noob question: does this completion refer to autocompletion in IDE's/editors? \nI have observed that this is pretty erratic sometimes. I'm using PyDev+Eclipse.\nFor example, in the tutorial from the readme, `g.get_u` gets autocompleted correctly, but `g.get_user().get_r` (or any method or attribute applicable to NamedUsers/AuthenticatedUser, really) does not show autocompletion to `g.get_user().get_repo()`. Is that by design? It makes exploring the library/API a bit cumbersome. ",
 659                  "No, it has nothing to do with auto-completion in IDEs :D\n\nGithub API v3 sends only the main part of objects in reply to some requests. So, if the user wants an attribute that has not been received yet, I have to do another request to complete the object.\n\nYet, in version 1.0 (see the milesone), my library will be much more readable for IDEs and their auto-completion mechanisms, because I am giving up the meta-description that I used until 0.6, and I'm now generating much more traditional code, that you will be able to explore as if it was written manually.\n\nIf you want to take the time to open an issue about auto-completion in IDEs, I'll deal with it in milestone 1.0.\n\nThanks !",
 660                  "Ah, thanks for the clarification. :blush:\n\nI made issue #27 for the autocompletion. I already suspected something like this meta-description magic, since I tried to read some of the code and it was pretty arcane. I attributed that to my pythonic noobness, though. Thank you. ",
 661                  "Comment created by PyGithub",
 662              ],
 663          )
 664  
 665      def testGetCommits(self):
 666          self.assertListKeyBegin(
 667              self.repo.get_commits(),
 668              lambda c: c.sha,
 669              [
 670                  "ecda065e01876209d2bdf5fe4e91cee8ffaa9ff7",
 671                  "0cec0d25e606c023a62a4fc7cdc815309ebf6d16",
 672                  "cb0313157bf904f2d364377d35d9397b269547a5",
 673                  "5bb654d26dd014d36794acd1e6ecf3736f12aad7",
 674                  "4303c5b90e2216d927155e9609436ccb8984c495",
 675                  "2a7e80e6421c5d4d201d60619068dea6bae612cb",
 676                  "0af24499a98e85f8ab2191898e8b809e5cebd4c5",
 677                  "e5ae923a68a9ae295ce5aa20b1227253de60e918",
 678                  "2f64b625f7e2afc9bef61d0decb459e2ef65c550",
 679                  "590798d349cba7de6e83b43aa5d4f8b0a38e685d",
 680                  "e7dca9143a23b8e2045a4a910a4a329007b10086",
 681                  "ab3f9b422cb3043d35cf6002fc9c042f8ead8c2a",
 682                  "632d8b63c32a2b79e87eb3b93e1ad228724de4bd",
 683                  "64c6a1e975e61b9c1449bed016cd19f33ee4b1c5",
 684                  "99963536fc81db3b9986c761b9dd08de22089aa2",
 685                  "8d57522bbd15d1fb6b616fae795cd8721deb1c4d",
 686                  "1140a91f3e45d09bc15463724f178a7ebf8e3149",
 687                  "936f4a97f1a86392637ec002bbf89ff036a5062d",
 688                  "e10470481795506e2c232720e2a9ecf588c8b567",
 689                  "e456549e5265406f8090ae5145255c8ca9ea5e4e",
 690                  "a91131be42eb328ae030f584af500f56aa08424b",
 691                  "2469c6e1aeb7919126a8271f6980b555b167e8b0",
 692                  "a655d0424135befd3a0d53f3f7eff2d1c754854f",
 693                  "ce62e91268aa34dad0ba0dbee4769933e3a71e50",
 694                  "1c88ee221b7f995855a1fdfac7d0ba19db918739",
 695                  "bd1a5dff3c547c634b2d89f5847218820e343883",
 696                  "b226b5b4e2f44107dde674e7a5d3e88d4e3518df",
 697                  "25dbd4053e982402c7d92139f167dbe46008c932",
 698                  "a0cc821c1beada4aa9ca0d5218664c5372720936",
 699                  "c1440bdf20bfeb62684c6d1779448719dce9d2df",
 700                  "1095d304b7fab3818dcb4c42093c8c56d3ac05e4",
 701                  "bd39726f7cf86ea7ffb33b5718241fdab5fc8f53",
 702                  "1d2b27824d20612066d84be42d6691c66bb18ef4",
 703                  "6af2bfd0d46bc0eeb8c37b85c7b3003e0e4ae297",
 704                  "a475d685d8ae709095d09094ea0962ac182d33f0",
 705                  "a85de99ea5b5e7b38bd68e076d09c49207b8687e",
 706                  "d24cf209ddd1758188c5f35344f76df818d09a46",
 707                  "0909fec395bb1f97e2580d6a029cfc64b352aff9",
 708                  "6e421e9e85e12008758870bc046bc2c6120af72a",
 709                  "32ed0ebc377efbed5b482b3d49ff54bf1715d55a",
 710                  "8213df1d744f251aa8e52229643a9f6ce352f3c0",
 711                  "69cc298fd159f19eb204dd09f17d31dc4abc3d41",
 712                  "85eef756353e13efcb24c726320cd2617c2a7bd8",
 713                  "50ac55b25ceba555b84709839f80447552450697",
 714                  "767d75a580279e457f9bc52bc308a17ff8ea0509",
 715                  "75e72ffa3066693291f7da03070666e8f885097a",
 716                  "504047e218e6b34a3828ccc408431634f17b9504",
 717                  "960db1d5c9853e9f5fbbc9237c2c166ceef1f080",
 718                  "877dde23e140bbf038f9a2d8f0f07b4e3a965c61",
 719                  "1c95ddfa09ec0aa1f07ee9ad50a77be1dd74b55e",
 720                  "99564c1cab139d1e4678f5f83f60d26f1210db7e",
 721                  "231926207709ceaa61e87b64e34e17d85adecd9c",
 722                  "fb722625dddb9a32f75190723f7da12683b7c4b2",
 723                  "cab9d71603e127bdd1f600a759dccea1781fa1ab",
 724                  "e648e5aeb5edc1fbf83e9d37d2a3cb57c005019a",
 725                  "4a5cf98e7f959f1b5d9af484760c25cd27d9180d",
 726                  "5d1add448e0b0b1dadb8c6094a9e5e19b255f67e",
 727                  "0d9fc99a4b5d1ec6473c9c81c888917c132ffa65",
 728                  "b56aa09011378b014221f86dffb8304957a9e6bd",
 729                  "3e8169c0a98ce1e2c6a32ae1256ae0f735065df5",
 730                  "378558f6cac6183b4a7100c0ce5eaad1cfff6717",
 731                  "58b4396aa0e7cb72911b75cb035798143a06e0ee",
 732                  "a3be28756101370fbc689eec3a7825c4c385a6c9",
 733                  "3d6bd49ce229243fea4bb46a937622d0ec7d4d1c",
 734                  "58cb0dbdef9765e0e913c726f923a47315aaf80e",
 735                  "7b7ac20c6fa27f72a24483c73ab1bf4deffc89f0",
 736                  "97f308e67383368a2d15788cac28e126c8528bb2",
 737                  "fc33a6de4f0e08d7ff2de05935517ec3932d212e",
 738                  "cc6d0fc044eadf2e6fde5da699f61654c1e691f3",
 739                  "2dd71f3777b87f2ba61cb20d2c67f10401e3eb2c",
 740                  "366ca58ca004b9129f9d435db8204ce0f5bc57c3",
 741                  "0d3b3ffd1e5c143af8725fdee808101f626f683d",
 742                  "157f9c13275738b6b39b8d7a874f5f0aee47cb18",
 743              ],
 744          )
 745  
 746      def testGetCommitsWithArguments(self):
 747          self.assertListKeyEqual(
 748              self.repo.get_commits("topic/RewriteWithGeneratedCode", "codegen/GenerateCode.py"),
 749              lambda c: c.sha,
 750              [
 751                  "de386d5dc9cf103c90c4128eeca0e6abdd382065",
 752                  "5b44982f6111bff2454243869df2e1c3086ccbba",
 753                  "d6835ff949141957a733c8ddfa147026515ae493",
 754                  "075d3d961d4614a2a0835d5583248adfc0687a7d",
 755                  "8956796e7f462a49f499eac52fab901cdb59abdb",
 756                  "283da5e7de6a4a3b6aaae7045909d70b643ad380",
 757                  "d631e83b7901b0a0b6061b361130700a79505319",
 758              ],
 759          )
 760  
 761      def testGetCommitsWithSinceUntil(self):
 762          self.assertListKeyEqual(
 763              self.repo.get_commits(
 764                  since=datetime(2013, 3, 1),
 765                  until=datetime(2013, 3, 31),
 766              ),
 767              lambda c: c.sha,
 768              [
 769                  "db5560bd658b5d8057a864f7037ace4d5f618f1b",
 770                  "f266fed520fea4f683caabe0b38e1f758cfc5cff",
 771                  "dff094650011398fd8f0a57bf2668a066fb2cbcb",
 772                  "c1d747a9133a1c6cae1f0e11105a5f490f65fda6",
 773                  "0bc368973acfb50a531329b6c196ba92e0a81890",
 774                  "7b3e4c15ed6182963d66ffa9f0522acd0765275c",
 775                  "4df3a7eb47888f38c4c6dae50573f030a0a3f1e1",
 776                  "e0db8cad4ec01c65e5e0eb50e11765e425e88ef9",
 777                  "1c47be4e895b823baf907b25c647e43ab63c16dd",
 778                  "8a9afbb1aa36c6ba04142c6e6c1cfbd7de982a6a",
 779                  "1c67359a318f05e50bf457818e1983ce95aa5946",
 780                  "1d18bd66f3a4a4225435bd38df04b8a227b5e821",
 781                  "b9d71fa787a2ffb99b6631e4bd6df932a4d4adbb",
 782                  "f5d8e221d116b74a200d87afca32247f01204ba1",
 783                  "dc96fef052f2b5c6adb34da65169e8df3f35f611",
 784                  "c85af79db11ed1d2f93261ea4069a23ff1709125",
 785                  "0dd1adb4f06f45d554d12083b312fcdb6f6be8d1",
 786                  "b7e4000450e89b8c6e947e3a1e52fb06da7c9621",
 787                  "1d9ad14fa918866c418067e774f65cede8e38682",
 788                  "1bb05fef01d0a040cb2b931a4d44392784a2f0c1",
 789                  "d9b29851ddccc907f71f1ae662e57f2cd7c7dc71",
 790                  "f962bc71fee609cd54fe69c956c8b81703d2c19a",
 791                  "7a9c0b916c632be8d6a65bc1b6f558508f04bb22",
 792                  "82ce7b1ee30d308b48bdac6d8737dbca70500462",
 793                  "1e99e7d5b21c71bf68cc5cc21faec30ee603b8b8",
 794                  "a397fac6db9f87a903ec3ede9643cb2b4224ed82",
 795                  "109495175e926731703a55cafd8b542a07366513",
 796                  "da6bbdb69485fc3256030d8296589d4c2fb5df21",
 797                  "34c18342dcce9697abc6f522c3506485202e6e7e",
 798                  "ee29deddd27480401db484733ecde9e7b1df5eda",
 799                  "0901df1a2bed3f993cfe6e0d4cff5923bbf6ce32",
 800                  "edcf40bc7f25d1aff5c404406fbb37ad1bcf691e",
 801                  "f25c54e1d4eefb11c18f3de85270a4b19edea3ce",
 802                  "23d668f11bdd806a871e0979bf5295d001f66ef2",
 803                  "50a243671f1fa139cb1186c4a44c1e96b8cd5749",
 804                  "6a3a384fd0decac1203db6c2bddc58039b0390bc",
 805                  "82f5b4c61f86ae8c7cc85a31cb1a31180eeae32f",
 806                  "6ac783974d3985dd0c162c1e8d1150615cc0082e",
 807                  "0f9bb5d9fd2dcfbf03f094362e86323c9ef915e6",
 808                  "e25a6a49d1ab1a10c84db9b6722a6186ff6dfcbd",
 809                  "4f1780f427eba400cbc06897e69eda0ecdecd887",
 810                  "28648a51a15e430b85d6fe8f2514e1cb06bc76b8",
 811                  "a39f421ca24bd7aae984f8703159c7e30798a121",
 812                  "86fe370b97b62548317cb35bc02ece3fabb7fa03",
 813                  "03a256a4052cacea998d8205a83d5b5465f31e18",
 814                  "9e6b086c2db5e4884484a04934f6f2e53e3f441b",
 815                  "0ddb34d987b5a03813fdfa2fac13c933834a4804",
 816              ],
 817          )
 818  
 819      def testGetCommitsWithAuthor(self):
 820          self.g.per_page = 5
 821          akfish = self.g.get_user("AKFish")
 822          self.assertListKeyBegin(
 823              self.repo.get_commits(author=self.user),
 824              lambda c: c.sha,
 825              ["54f718a15770579a37ffbe7ae94ad30003407786"],
 826          )
 827          self.assertListKeyBegin(
 828              self.repo.get_commits(author=akfish),
 829              lambda c: c.sha,
 830              ["38b137fb37c0fdc74f8802a4184518e105db9121"],
 831          )
 832          self.assertListKeyBegin(
 833              self.repo.get_commits(author="m.ki2@laposte.net"),
 834              lambda c: c.sha,
 835              ["ab674dfcbc86c70bc32d9ecbe171b48a5694c337"],
 836          )
 837  
 838      def testGetDownloads(self):
 839          self.assertListKeyEqual(self.repo.get_downloads(), lambda d: d.id, [245143])
 840  
 841      def testGetEvents(self):
 842          self.assertListKeyBegin(
 843              self.repo.get_events(),
 844              lambda e: e.type,
 845              [
 846                  "DownloadEvent",
 847                  "DownloadEvent",
 848                  "PushEvent",
 849                  "IssuesEvent",
 850                  "MemberEvent",
 851                  "MemberEvent",
 852              ],
 853          )
 854  
 855      def testGetForks(self):
 856          self.assertListKeyEqual(self.repo.get_forks(), lambda r: r.owner.login, ["abersager"])
 857  
 858      def testCreateFork(self):
 859          self.assertEqual(self.repo.create_fork("prtg-dev").full_name, "prtg-dev/PyGithub")
 860  
 861      def testCreateForkOrg(self):
 862          c = self.g.get_organization("prtg-dev")
 863          self.assertEqual(self.repo.create_fork(c).full_name, "prtg-dev/PyGithub")
 864  
 865      def testGetGitRefs(self):
 866          self.assertListKeyEqual(
 867              self.repo.get_git_refs(),
 868              lambda r: r.ref,
 869              [
 870                  "refs/heads/develop",
 871                  "refs/heads/master",
 872                  "refs/heads/topic/DependencyGraph",
 873                  "refs/heads/topic/RewriteWithGeneratedCode",
 874                  "refs/tags/v0.1",
 875                  "refs/tags/v0.2",
 876                  "refs/tags/v0.3",
 877                  "refs/tags/v0.4",
 878                  "refs/tags/v0.5",
 879                  "refs/tags/v0.6",
 880                  "refs/tags/v0.7",
 881              ],
 882          )
 883  
 884      def testGetGitRef(self):
 885          self.assertTrue(self.g.FIX_REPO_GET_GIT_REF)
 886          self.assertEqual(
 887              self.repo.get_git_ref("heads/master").object.sha,
 888              "31110327ec45f3138e58ed247b2cf420fee481ec",
 889          )
 890  
 891      def testGetGitRefWithIssue102Reverted(self):
 892          self.g.FIX_REPO_GET_GIT_REF = False
 893          self.assertFalse(self.g.FIX_REPO_GET_GIT_REF)
 894          self.assertEqual(
 895              self.repo.get_git_ref("refs/heads/master").object.sha,
 896              "31110327ec45f3138e58ed247b2cf420fee481ec",
 897          )
 898          self.g.FIX_REPO_GET_GIT_REF = True
 899          self.assertTrue(self.g.FIX_REPO_GET_GIT_REF)
 900  
 901      def testGetGitTreeWithRecursive(self):
 902          tree = self.repo.get_git_tree("f492784d8ca837779650d1fb406a1a3587a764ad", True)
 903          self.assertEqual(len(tree.tree), 90)
 904          self.assertEqual(tree.tree[50].path, "github/GithubObjects/Gist.py")
 905  
 906      def testGetHooks(self):
 907          self.assertListKeyEqual(self.repo.get_hooks(), lambda h: h.id, [257993])
 908  
 909      def testGetHookDelivery(self):
 910          delivery = self.repo.get_hook_delivery(257993, 12345)
 911          self.assertEqual(delivery.id, 12345)
 912          self.assertEqual(delivery.guid, "abcde-12345")
 913          self.assertEqual(
 914              delivery.delivered_at,
 915              datetime(2012, 5, 27, 6, 0, 32, tzinfo=timezone.utc),
 916          )
 917          self.assertEqual(delivery.redelivery, False)
 918          self.assertEqual(delivery.duration, 0.27)
 919          self.assertEqual(delivery.status, "OK")
 920          self.assertEqual(delivery.status_code, 200)
 921          self.assertEqual(delivery.event, "issues")
 922          self.assertEqual(delivery.action, "opened")
 923          self.assertEqual(delivery.installation_id, 123)
 924          self.assertEqual(delivery.repository_id, 456)
 925          self.assertEqual(delivery.url, "https://www.example-webhook.com")
 926          self.assertIsInstance(delivery.request, github.HookDelivery.HookDeliveryRequest)
 927          self.assertEqual(delivery.request.headers, {"content-type": "application/json"})
 928          self.assertEqual(delivery.request.payload, {"action": "opened"})
 929          self.assertIsInstance(delivery.response, github.HookDelivery.HookDeliveryResponse)
 930          self.assertEqual(delivery.response.headers, {"content-type": "text/html;charset=utf-8"})
 931          self.assertEqual(delivery.response.payload, "ok")
 932  
 933      def testGetHookDeliveries(self):
 934          deliveries = list(self.repo.get_hook_deliveries(257993))
 935          self.assertEqual(len(deliveries), 1)
 936          self.assertEqual(deliveries[0].id, 12345)
 937          self.assertEqual(deliveries[0].guid, "abcde-12345")
 938          self.assertEqual(
 939              deliveries[0].delivered_at,
 940              datetime(2012, 5, 27, 6, 0, 32, tzinfo=timezone.utc),
 941          )
 942          self.assertEqual(deliveries[0].redelivery, False)
 943          self.assertEqual(deliveries[0].duration, 0.27)
 944          self.assertEqual(deliveries[0].status, "OK")
 945          self.assertEqual(deliveries[0].status_code, 200)
 946          self.assertEqual(deliveries[0].event, "issues")
 947          self.assertEqual(deliveries[0].action, "opened")
 948          self.assertEqual(deliveries[0].installation_id, 123)
 949          self.assertEqual(deliveries[0].repository_id, 456)
 950          self.assertEqual(deliveries[0].url, "https://www.example-webhook.com")
 951  
 952      def testGetIssues(self):
 953          self.assertListKeyEqual(
 954              self.repo.get_issues(),
 955              lambda i: i.id,
 956              [
 957                  4769659,
 958                  4639931,
 959                  4452000,
 960                  4356743,
 961                  3716033,
 962                  3715946,
 963                  3643837,
 964                  3628022,
 965                  3624595,
 966                  3624570,
 967                  3624561,
 968                  3624556,
 969                  3619973,
 970                  3527266,
 971                  3527245,
 972                  3527231,
 973              ],
 974          )
 975  
 976      def testGetIssuesWithArguments(self):
 977          milestone = self.repo.get_milestone(3)
 978          user = self.g.get_user("jacquev6")
 979          otherUser = self.g.get_user("Lyloa")
 980          bug = self.repo.get_label("Bug")
 981          self.assertListKeyEqual(
 982              self.repo.get_issues(milestone, "closed"),
 983              lambda i: i.id,
 984              [3624472, 3620132, 3619658, 3561926],
 985          )
 986          self.assertListKeyEqual(self.repo.get_issues(labels=[bug]), lambda i: i.id, [4780155])
 987          self.assertListKeyEqual(self.repo.get_issues(labels=[bug.name]), lambda i: i.id, [4780155])
 988          self.assertListKeyEqual(
 989              self.repo.get_issues(assignee=user, sort="comments", direction="asc"),
 990              lambda i: i.id,
 991              [
 992                  4793106,
 993                  3527231,
 994                  3527266,
 995                  3624556,
 996                  4793216,
 997                  3619973,
 998                  3624595,
 999                  4452000,
1000                  3643837,
1001                  3628022,
1002                  3527245,
1003                  4793162,
1004                  4356743,
1005                  4780155,
1006              ],
1007          )
1008          self.assertListKeyEqual(
1009              self.repo.get_issues(since=datetime(2012, 5, 28, 23, 0, 0, tzinfo=timezone.utc)),
1010              lambda i: i.id,
1011              [4793216, 4793162, 4793106, 3624556, 3619973, 3527266],
1012          )
1013          self.assertListKeyEqual(self.repo.get_issues(mentioned=otherUser), lambda i: i.id, [4793162])
1014  
1015      def testGetIssuesWithWildcards(self):
1016          self.assertListKeyEqual(
1017              self.repo.get_issues(milestone="*"),
1018              lambda i: i.id,
1019              [4809786, 4793216, 4789817, 4452000, 3628022, 3624595, 3619973, 3527231],
1020          )
1021          self.assertListKeyEqual(
1022              self.repo.get_issues(milestone="none"),
1023              lambda i: i.id,
1024              [4823331, 4809803, 4809778, 4793106, 3643837, 3527245],
1025          )
1026          self.assertListKeyEqual(
1027              self.repo.get_issues(assignee="*"),
1028              lambda i: i.id,
1029              [
1030                  4823331,
1031                  4809803,
1032                  4809786,
1033                  4809778,
1034                  4793216,
1035                  4793106,
1036                  4789817,
1037                  4452000,
1038                  3643837,
1039                  3628022,
1040                  3624595,
1041                  3527245,
1042                  3527231,
1043              ],
1044          )
1045          self.assertListKeyEqual(self.repo.get_issues(assignee="none"), lambda i: i.id, [3619973])
1046  
1047      def testGetKeys(self):
1048          self.assertListKeyEqual(self.repo.get_keys(), lambda k: k.title, ["Key added through PyGithub"])
1049  
1050      def testGetLabels(self):
1051          self.assertListKeyEqual(
1052              self.repo.get_labels(),
1053              lambda l: l.name,
1054              [
1055                  "Refactoring",
1056                  "Public interface",
1057                  "Functionalities",
1058                  "Project management",
1059                  "Bug",
1060                  "Question",
1061              ],
1062          )
1063  
1064      def testGetLanguages(self):
1065          self.assertEqual(self.repo.get_languages(), {"Python": 127266, "Shell": 673})
1066  
1067      def testGetMilestones(self):
1068          self.assertListKeyEqual(self.repo.get_milestones(), lambda m: m.id, [93547])
1069  
1070      def testGetMilestonesWithArguments(self):
1071          self.assertListKeyEqual(
1072              self.repo.get_milestones("closed", "due_date", "asc"),
1073              lambda m: m.id,
1074              [93546, 95354, 108652, 124045],
1075          )
1076  
1077      def testGetIssuesEvents(self):
1078          self.assertListKeyBegin(
1079              self.repo.get_issues_events(),
1080              lambda e: e.event,
1081              ["assigned", "subscribed", "closed", "assigned", "closed"],
1082          )
1083  
1084      def testGetNetworkEvents(self):
1085          self.assertListKeyBegin(
1086              self.repo.get_network_events(),
1087              lambda e: e.type,
1088              [
1089                  "DownloadEvent",
1090                  "DownloadEvent",
1091                  "PushEvent",
1092                  "IssuesEvent",
1093                  "MemberEvent",
1094              ],
1095          )
1096  
1097      def testGetTeams(self):
1098          repo = self.g.get_organization("BeaverSoftware").get_repo("FatherBeaver")
1099          self.assertListKeyEqual(repo.get_teams(), lambda t: t.name, ["Members"])
1100  
1101      def testGetWatchers(self):
1102          self.assertListKeyEqual(
1103              self.repo.get_watchers(),
1104              lambda u: u.login,
1105              [
1106                  "Stals",
1107                  "att14",
1108                  "jardon-u",
1109                  "huxley",
1110                  "mikofski",
1111                  "L42y",
1112                  "fanzeyi",
1113                  "abersager",
1114                  "waylan",
1115                  "adericbourg",
1116                  "tallforasmurf",
1117                  "pvicente",
1118                  "roskakori",
1119                  "michaelpedersen",
1120                  "BeaverSoftware",
1121              ],
1122          )
1123  
1124      def testGetWorkflows(self):
1125          workflows = self.g.get_repo("PyGithub/PyGithub").get_workflows()
1126          self.assertListKeyEqual(workflows, lambda w: w.name, ["check", "Publish to PyPI"])
1127  
1128      def testGetWorkflowId(self):
1129          workflows = self.g.get_repo("PyGithub/PyGithub").get_workflow("1122712")
1130          self.assertEqual(workflows.id, 1122712)
1131  
1132      def testGetWorkflowRuns(self):
1133          self.assertListKeyEqual(
1134              self.g.get_repo("PyGithub/PyGithub").get_workflow_runs(),
1135              lambda r: r.id,
1136              [110932306, 110932159, 110932072, 110286191, 110278769],
1137          )
1138  
1139      def testGetSourceImport(self):
1140          import_repo = self.g.get_user("brix4dayz").get_repo("source-import-test")
1141          source_import = import_repo.get_source_import()
1142          self.assertEqual(source_import.authors_count, 1)
1143          self.assertEqual(
1144              source_import.authors_url,
1145              "https://api.github.com/repos/brix4dayz/source-import-test/import/authors",
1146          )
1147          self.assertEqual(source_import.has_large_files, False)
1148          self.assertEqual(
1149              source_import.html_url,
1150              "https://github.com/brix4dayz/source-import-test/import",
1151          )
1152          self.assertEqual(source_import.large_files_count, 0)
1153          self.assertEqual(source_import.large_files_size, 0)
1154          self.assertEqual(
1155              source_import.repository_url,
1156              "https://api.github.com/repos/brix4dayz/source-import-test",
1157          )
1158          self.assertEqual(source_import.status, "complete")
1159          self.assertEqual(source_import.status_text, "Done")
1160          self.assertEqual(
1161              source_import.url,
1162              "https://api.github.com/repos/brix4dayz/source-import-test/import",
1163          )
1164          self.assertEqual(source_import.use_lfs, "undecided")
1165          self.assertEqual(source_import.vcs, "mercurial")
1166          self.assertEqual(source_import.vcs_url, "https://bitbucket.org/hfuss/source-import-test")
1167  
1168      def testGetStargazers(self):
1169          self.assertListKeyEqual(
1170              self.repo.get_stargazers(),
1171              lambda u: u.login,
1172              [
1173                  "Stals",
1174                  "att14",
1175                  "jardon-u",
1176                  "huxley",
1177                  "mikofski",
1178                  "L42y",
1179                  "fanzeyi",
1180                  "abersager",
1181                  "waylan",
1182                  "adericbourg",
1183                  "tallforasmurf",
1184                  "pvicente",
1185                  "roskakori",
1186                  "michaelpedersen",
1187                  "stefanfoulis",
1188                  "equus12",
1189                  "JuRogn",
1190                  "joshmoore",
1191                  "jsilter",
1192                  "dasapich",
1193                  "ritratt",
1194                  "hcilab",
1195                  "vxnick",
1196                  "pmuilu",
1197                  "herlo",
1198                  "malexw",
1199                  "ahmetvurgun",
1200                  "PengGu",
1201                  "cosmin",
1202                  "Swop",
1203                  "kennethreitz",
1204                  "bryandyck",
1205                  "jason2506",
1206                  "zsiciarz",
1207                  "waawal",
1208                  "gregorynicholas",
1209                  "sente",
1210                  "richmiller55",
1211                  "thouis",
1212                  "mazubieta",
1213                  "michaelhood",
1214                  "engie",
1215                  "jtriley",
1216                  "oangeor",
1217                  "coryking",
1218                  "noddi",
1219                  "alejo8591",
1220                  "omab",
1221                  "Carreau",
1222                  "bilderbuchi",
1223                  "schwa",
1224                  "rlerallut",
1225                  "PengHub",
1226                  "zoek1",
1227                  "xobb1t",
1228                  "notgary",
1229                  "hattya",
1230                  "ZebtinRis",
1231                  "aaronhall",
1232                  "youngsterxyf",
1233                  "ailling",
1234                  "gregwjacobs",
1235                  "n0rmrx",
1236                  "awylie",
1237                  "firstthumb",
1238                  "joshbrand",
1239                  "berndca",
1240              ],
1241          )
1242  
1243      def testGetStargazersWithDates(self):
1244          repo = self.g.get_user("danvk").get_repo("comparea")
1245          stargazers = repo.get_stargazers_with_dates()
1246          self.assertListKeyEqual(
1247              stargazers,
1248              lambda stargazer: (stargazer.starred_at, stargazer.user.login),
1249              [
1250                  (
1251                      datetime(2014, 8, 13, 19, 22, 5, tzinfo=timezone.utc),
1252                      "sAlexander",
1253                  ),
1254                  (
1255                      datetime(2014, 10, 15, 5, 2, 30, tzinfo=timezone.utc),
1256                      "ThomasG77",
1257                  ),
1258                  (
1259                      datetime(2015, 4, 14, 15, 22, 40, tzinfo=timezone.utc),
1260                      "therusek",
1261                  ),
1262                  (
1263                      datetime(2015, 4, 29, 0, 9, 40, tzinfo=timezone.utc),
1264                      "athomann",
1265                  ),
1266                  (
1267                      datetime(2015, 4, 29, 14, 26, 46, tzinfo=timezone.utc),
1268                      "jcapron",
1269                  ),
1270                  (
1271                      datetime(2015, 5, 9, 19, 14, 45, tzinfo=timezone.utc),
1272                      "JoePython1",
1273                  ),
1274              ],
1275          )
1276          self.assertEqual(repr(stargazers[0]), 'Stargazer(user="sAlexander")')
1277  
1278      def testGetSubscribers(self):
1279          self.assertListKeyEqual(
1280              self.repo.get_subscribers(),
1281              lambda u: u.login,
1282              [
1283                  "jacquev6",
1284                  "equus12",
1285                  "bilderbuchi",
1286                  "hcilab",
1287                  "hattya",
1288                  "firstthumb",
1289                  "gregwjacobs",
1290                  "sagarsane",
1291                  "liang456",
1292                  "berndca",
1293                  "Lyloa",
1294              ],
1295          )
1296  
1297      def testCreatePull(self):
1298          pull = self.repo.create_pull(
1299              title="Pull request created by PyGithub",
1300              body="Body of the pull request",
1301              base="topic/RewriteWithGeneratedCode",
1302              head="BeaverSoftware:master",
1303              draft=False,
1304              maintainer_can_modify=True,
1305          )
1306          self.assertEqual(pull.id, 1436215)
1307  
1308      def testCreateProject(self):
1309          project = self.repo.create_project("Project created by PyGithub", "Body of the project")
1310          self.assertEqual(project.id, 2013820)
1311  
1312      def testCreatePullFromIssue(self):
1313          issue = self.repo.get_issue(32)
1314          pull = self.repo.create_pull("topic/RewriteWithGeneratedCode", "BeaverSoftware:master", issue=issue)
1315          self.assertEqual(pull.id, 1436310)
1316  
1317      def testGetPulls(self):
1318          self.assertListKeyEqual(self.repo.get_pulls(), lambda p: p.id, [1436310])
1319  
1320      def testGetPullsWithArguments(self):
1321          self.assertListKeyEqual(self.repo.get_pulls("closed"), lambda p: p.id, [1448168, 1436310, 1436215])
1322  
1323      def testGetAutolinks(self):
1324          self.assertListKeyEqual(
1325              self.repo.get_autolinks(),
1326              lambda i: i.id,
1327              [
1328                  209614,
1329                  209611,
1330              ],
1331          )
1332  
1333      def testLegacySearchIssues(self):
1334          issues = self.repo.legacy_search_issues("open", "search")
1335          self.assertListKeyEqual(issues, lambda i: i.title, ["Support new Search API"])
1336  
1337          # Attributes retrieved from legacy API without lazy completion call
1338          self.assertEqual(issues[0].number, 49)
1339          self.assertEqual(
1340              issues[0].created_at,
1341              datetime(2012, 6, 21, 12, 27, 38, tzinfo=timezone.utc),
1342          )
1343          self.assertEqual(issues[0].comments, 4)
1344          self.assertEqual(issues[0].body[:20], "New API ported from ")
1345          self.assertEqual(issues[0].title, "Support new Search API")
1346          self.assertEqual(
1347              issues[0].updated_at,
1348              datetime(2012, 6, 28, 21, 13, 25, tzinfo=timezone.utc),
1349          )
1350          self.assertEqual(issues[0].user.login, "kukuts")
1351          self.assertEqual(issues[0].user.url, "/users/kukuts")
1352          self.assertListKeyEqual(issues[0].labels, lambda l: l.name, ["Functionalities", "RequestedByUser"])
1353          self.assertEqual(issues[0].state, "open")
1354  
1355      def testMarkNotificationsAsRead(self):
1356          repo = self.g.get_user().get_repo("PyGithub")
1357          repo.mark_notifications_as_read(datetime(2018, 10, 18, 18, 19, 43, 0))
1358  
1359      def testAssignees(self):
1360          lyloa = self.g.get_user("Lyloa")
1361          jacquev6 = self.g.get_user("jacquev6")
1362          self.assertTrue(self.repo.has_in_assignees(jacquev6))
1363          self.assertFalse(self.repo.has_in_assignees(lyloa))
1364          self.repo.add_to_collaborators(lyloa)
1365          self.assertTrue(self.repo.has_in_assignees(lyloa))
1366          self.assertListKeyEqual(self.repo.get_assignees(), lambda u: u.login, ["jacquev6", "Lyloa"])
1367          self.repo.remove_from_collaborators(lyloa)
1368          self.assertFalse(self.repo.has_in_assignees(lyloa))
1369  
1370      def testGetContents(self):
1371          self.assertEqual(len(self.repo.get_readme().content), 10212)
1372          self.assertEqual(len(self.repo.get_contents("doc/ReferenceOfClasses.md").content), 38121)
1373  
1374      def testGetContentsDir(self):
1375          contents = self.repo.get_contents("")
1376          self.assertTrue(isinstance(contents, list))
1377          self.assertEqual(len(contents), 14)
1378  
1379      def testGetContentsDirWithSlash(self):
1380          contents = self.repo.get_contents("/")
1381          self.assertTrue(isinstance(contents, list))
1382          self.assertEqual(len(contents), 14)
1383  
1384      def testGetContentsWithRef(self):
1385          self.assertEqual(
1386              len(self.repo.get_readme(ref="refs/heads/topic/ExperimentOnDocumentation").content),
1387              6747,
1388          )
1389          self.assertEqual(
1390              len(
1391                  self.repo.get_contents(
1392                      "doc/ReferenceOfClasses.md",
1393                      ref="refs/heads/topic/ExperimentOnDocumentation",
1394                  ).content
1395              ),
1396              43929,
1397          )
1398  
1399      def testCreateDeployment(self):
1400          deployment = self.repo.create_deployment(
1401              ref="743f5a58b0bce91c4eab744ff7e39dfca9e6e8a5",
1402              task="deploy",
1403              auto_merge=False,
1404              required_contexts=[],
1405              payload={"test": True},
1406              environment="test",
1407              description="Test deployment",
1408              transient_environment=True,
1409              production_environment=False,
1410          )
1411          self.assertEqual(deployment.id, 263877258)
1412  
1413      def testGetDeployments(self):
1414          deployments = self.repo.get_deployments()
1415          self.assertListKeyEqual(deployments, lambda d: d.id, [263877258, 262350588])
1416  
1417      def testCreateFile(self):
1418          newFile = "doc/testCreateUpdateDeleteFile.md"
1419          content = b"Hello world"
1420          author = github.InputGitAuthor("Enix Yu", "enix223@163.com", "2016-01-15T16:13:30+12:00")
1421          self.assertEqual(repr(author), 'InputGitAuthor(name="Enix Yu")')
1422          self.repo.create_file(
1423              path=newFile,
1424              message="Create file for testCreateFile",
1425              content=content,
1426              branch="master",
1427              committer=author,
1428              author=author,
1429          )
1430  
1431      def testUpdateFile(self):
1432          updateFile = "doc/testCreateUpdateDeleteFile.md"
1433          content = "Hello World"
1434          sha = self.repo.get_contents(updateFile).sha
1435          self.repo.update_file(
1436              path=updateFile,
1437              message="Update file for testUpdateFile",
1438              content=content,
1439              sha=sha,
1440              branch="master",
1441              committer=github.InputGitAuthor("Enix Yu", "enix223@163.com", "2016-01-15T16:13:30+12:00"),
1442              author=github.InputGitAuthor("Enix Yu", "enix223@163.com", "2016-01-15T16:13:30+12:00"),
1443          )
1444  
1445      def testDeleteFile(self):
1446          deleteFile = "doc/testCreateUpdateDeleteFile.md"
1447          sha = self.repo.get_contents(deleteFile).sha
1448          self.repo.delete_file(
1449              path=deleteFile,
1450              message="Delete file for testDeleteFile",
1451              sha=sha,
1452              branch="master",
1453          )
1454  
1455      def testGetArchiveLink(self):
1456          self.assertEqual(
1457              self.repo.get_archive_link("tarball"),
1458              "https://nodeload.github.com/jacquev6/PyGithub/tarball/master",
1459          )
1460          self.assertEqual(
1461              self.repo.get_archive_link("zipball"),
1462              "https://nodeload.github.com/jacquev6/PyGithub/zipball/master",
1463          )
1464          self.assertEqual(
1465              self.repo.get_archive_link("zipball", "master"),
1466              "https://nodeload.github.com/jacquev6/PyGithub/zipball/master",
1467          )
1468          self.assertEqual(
1469              self.repo.get_archive_link("tarball", "develop"),
1470              "https://nodeload.github.com/jacquev6/PyGithub/tarball/develop",
1471          )
1472  
1473      def testGetBranch(self):
1474          branch = self.repo.get_branch("develop")
1475          self.assertEqual(branch.commit.sha, "03058a36164d2a7d946db205f25538434fa27d94")
1476  
1477      def testRenameBranchObject(self):
1478          branch = self.repo.get_branch("neat-new-feature")
1479          self.assertTrue(self.repo.rename_branch(branch, "terrible-idea"))
1480  
1481      def testRenameBranchString(self):
1482          self.assertTrue(self.repo.rename_branch("neat-new-feature", "terrible-idea"))
1483  
1484      def testMergeWithoutMessage(self):
1485          commit = self.repo.merge("branchForBase", "branchForHead")
1486          self.assertEqual(commit.commit.message, "Merge branchForHead into branchForBase")
1487  
1488      def testMergeWithMessage(self):
1489          commit = self.repo.merge("branchForBase", "branchForHead", "Commit message created by PyGithub")
1490          self.assertEqual(commit.commit.message, "Commit message created by PyGithub")
1491  
1492      def testMergeWithNothingToDo(self):
1493          commit = self.repo.merge("branchForBase", "branchForHead", "Commit message created by PyGithub")
1494          self.assertEqual(commit, None)
1495  
1496      def testMergeWithConflict(self):
1497          with self.assertRaises(github.GithubException) as raisedexp:
1498              self.repo.merge("branchForBase", "branchForHead")
1499          self.assertEqual(raisedexp.exception.status, 409)
1500          self.assertEqual(raisedexp.exception.data, {"message": "Merge conflict"})
1501  
1502      def testGetIssuesComments(self):
1503          self.assertListKeyEqual(
1504              self.repo.get_issues_comments()[:40],
1505              lambda c: c.id,
1506              [
1507                  5168757,
1508                  5181640,
1509                  5183010,
1510                  5186061,
1511                  5226090,
1512                  5449237,
1513                  5518272,
1514                  5547576,
1515                  5780183,
1516                  5781803,
1517                  5820199,
1518                  5820912,
1519                  5924198,
1520                  5965724,
1521                  5965812,
1522                  5965891,
1523                  5966555,
1524                  5966633,
1525                  5981084,
1526                  5981232,
1527                  5981409,
1528                  5981451,
1529                  5991965,
1530                  6019700,
1531                  6088432,
1532                  6293572,
1533                  6305625,
1534                  6357374,
1535                  6357422,
1536                  6447481,
1537                  6467193,
1538                  6467312,
1539                  6467642,
1540                  6481200,
1541                  6481392,
1542                  6556134,
1543                  6557261,
1544                  6568164,
1545                  6568181,
1546                  6568553,
1547              ],
1548          )
1549          self.assertListKeyEqual(
1550              self.repo.get_issues_comments(sort="created", direction="asc")[:40],
1551              lambda c: c.id,
1552              [
1553                  5168757,
1554                  5181640,
1555                  5183010,
1556                  5186061,
1557                  5226090,
1558                  5449237,
1559                  5518272,
1560                  5547576,
1561                  5780183,
1562                  5781803,
1563                  5820199,
1564                  5820912,
1565                  5924198,
1566                  5965724,
1567                  5965812,
1568                  5965891,
1569                  5966555,
1570                  5966633,
1571                  5981084,
1572                  5981232,
1573                  5981409,
1574                  5981451,
1575                  5991965,
1576                  6019700,
1577                  6088432,
1578                  6293572,
1579                  6305625,
1580                  6357374,
1581                  6357422,
1582                  6447481,
1583                  6467193,
1584                  6467312,
1585                  6467642,
1586                  6481200,
1587                  6481392,
1588                  6556134,
1589                  6557261,
1590                  6568164,
1591                  6568181,
1592                  6568553,
1593              ],
1594          )
1595          self.assertListKeyEqual(
1596              self.repo.get_issues_comments(since=datetime(2012, 5, 28, 23, 0, 0))[:40],
1597              lambda c: c.id,
1598              [
1599                  5981084,
1600                  5981232,
1601                  5981409,
1602                  5981451,
1603                  5991965,
1604                  6019700,
1605                  6088432,
1606                  6293572,
1607                  6305625,
1608                  6357374,
1609                  6357422,
1610                  6447481,
1611                  6467193,
1612                  6467312,
1613                  6467642,
1614                  6481200,
1615                  6481392,
1616                  6556134,
1617                  6557261,
1618                  6568164,
1619                  6568181,
1620                  6568553,
1621                  6640187,
1622                  6640189,
1623                  6641223,
1624                  6673380,
1625                  6710355,
1626                  6727553,
1627                  6727659,
1628                  6727848,
1629                  6728069,
1630                  6728241,
1631                  6728370,
1632                  6886561,
1633                  6972414,
1634                  6994436,
1635                  7060818,
1636                  7060993,
1637                  7211543,
1638                  7407798,
1639              ],
1640          )
1641  
1642      def testGetPullsComments(self):
1643          self.assertListKeyEqual(self.repo.get_pulls_comments(), lambda c: c.id, [1580134])
1644          self.assertListKeyEqual(
1645              self.repo.get_pulls_comments(sort="created", direction="asc"),
1646              lambda c: c.id,
1647              [1580134],
1648          )
1649          self.assertListKeyEqual(
1650              self.repo.get_pulls_comments(since=datetime(2012, 5, 28, 23, 0, 0)),
1651              lambda c: c.id,
1652              [1580134],
1653          )
1654  
1655      def testSubscribePubSubHubbub(self):
1656          self.repo.subscribe_to_hub("push", "http://requestb.in/1bc1sc61", "my_secret")
1657  
1658      def testBadSubscribePubSubHubbub(self):
1659          with self.assertRaises(github.GithubException) as raisedexp:
1660              self.repo.subscribe_to_hub("non-existing-event", "http://requestb.in/1bc1sc61")
1661          self.assertEqual(raisedexp.exception.status, 422)
1662          self.assertEqual(raisedexp.exception.data, {"message": 'Invalid event: "non-existing-event"'})
1663  
1664      def testUnsubscribePubSubHubbub(self):
1665          self.repo.unsubscribe_from_hub("push", "http://requestb.in/1bc1sc61")
1666  
1667      def testStatisticsContributors(self):
1668          stats = self.repo.get_stats_contributors()
1669          seenJacquev6 = False
1670          for s in stats:
1671              adTotal = 0
1672              total = 0
1673              for w in s.weeks:
1674                  total += w.c
1675                  adTotal += w.a + w.d
1676              self.assertEqual(total, s.total)
1677              if s.author.login == "jacquev6":
1678                  seenJacquev6 = True
1679                  self.assertEqual(adTotal, 282147)
1680                  self.assertEqual(
1681                      s.weeks[0].w,
1682                      datetime(2012, 2, 12, tzinfo=timezone.utc),
1683                  )
1684          self.assertTrue(seenJacquev6)
1685  
1686      def testStatisticsCommitActivity(self):
1687          stats = self.repo.get_stats_commit_activity()
1688          self.assertEqual(
1689              stats[0].week,
1690              datetime(2012, 11, 18, 0, 0, tzinfo=timezone.utc),
1691          )
1692          self.assertEqual(stats[0].total, 29)
1693          self.assertEqual(stats[0].days, [0, 7, 3, 9, 7, 3, 0])
1694  
1695      def testStatisticsCodeFrequency(self):
1696          stats = self.repo.get_stats_code_frequency()
1697          self.assertEqual(
1698              stats[0].week,
1699              datetime(2012, 2, 12, 0, 0, tzinfo=timezone.utc),
1700          )
1701          self.assertEqual(stats[0].additions, 3853)
1702          self.assertEqual(stats[0].deletions, -2098)
1703  
1704      def testStatisticsParticipation(self):
1705          stats = self.repo.get_stats_participation()
1706          self.assertEqual(
1707              stats.owner,
1708              [
1709                  1,
1710                  36,
1711                  8,
1712                  0,
1713                  0,
1714                  8,
1715                  18,
1716                  0,
1717                  0,
1718                  0,
1719                  0,
1720                  7,
1721                  20,
1722                  6,
1723                  9,
1724                  0,
1725                  4,
1726                  11,
1727                  20,
1728                  16,
1729                  0,
1730                  3,
1731                  0,
1732                  16,
1733                  0,
1734                  0,
1735                  6,
1736                  1,
1737                  4,
1738                  0,
1739                  1,
1740                  6,
1741                  0,
1742                  0,
1743                  12,
1744                  10,
1745                  0,
1746                  0,
1747                  0,
1748                  1,
1749                  44,
1750                  0,
1751                  20,
1752                  10,
1753                  0,
1754                  0,
1755                  0,
1756                  0,
1757                  0,
1758                  10,
1759                  0,
1760                  0,
1761              ],
1762          )
1763          self.assertEqual(
1764              stats.all,
1765              [
1766                  4,
1767                  36,
1768                  8,
1769                  0,
1770                  0,
1771                  10,
1772                  20,
1773                  0,
1774                  0,
1775                  0,
1776                  0,
1777                  11,
1778                  20,
1779                  6,
1780                  9,
1781                  0,
1782                  4,
1783                  14,
1784                  21,
1785                  16,
1786                  0,
1787                  3,
1788                  0,
1789                  20,
1790                  0,
1791                  0,
1792                  8,
1793                  1,
1794                  9,
1795                  16,
1796                  1,
1797                  15,
1798                  1,
1799                  0,
1800                  12,
1801                  12,
1802                  0,
1803                  4,
1804                  6,
1805                  15,
1806                  116,
1807                  20,
1808                  20,
1809                  11,
1810                  0,
1811                  0,
1812                  0,
1813                  0,
1814                  0,
1815                  10,
1816                  0,
1817                  0,
1818              ],
1819          )
1820  
1821      def testStatisticsPunchCard(self):
1822          stats = self.repo.get_stats_punch_card()
1823          self.assertEqual(stats.get(4, 12), 7)
1824          self.assertEqual(stats.get(6, 18), 2)
1825  
1826      def testGetLicense(self):
1827          self.assertEqual(len(self.repo.get_license().content), 47646)
1828  
1829      def testGetTopics(self):
1830          topic_list = self.repo.get_topics()
1831          topic = "github"
1832          self.assertIn(topic, topic_list)
1833  
1834      def testReplaceTopics(self):
1835          self.repo.replace_topics(["github", "testing"])
1836  
1837      def testGetRepositoryWith301Redirect(self):
1838          repo = self.g.get_repo("protoncoin/protoncoin")
1839          self.assertEqual(repo.full_name, "padima2/protoncoin")
1840  
1841      def testGetMatchingRefs(self):
1842          refs = self.g.get_repo("FlorentClarret/PyGithub").get_git_matching_refs("tags")
1843          self.assertEqual(85, refs.totalCount)
1844          self.assertEqual("refs/tags/v0.1", refs[0].ref)
1845          self.assertEqual("refs/tags/v0.2", refs[1].ref)
1846          self.assertEqual("refs/tags/v0.3", refs[2].ref)
1847          self.assertEqual("refs/tags/v0.4", refs[3].ref)
1848          self.assertEqual("refs/tags/v0.5", refs[4].ref)
1849          self.assertEqual("refs/tags/v0.6", refs[5].ref)
1850  
1851      def testRepoVariable(self):
1852          variable = self.repo.create_variable("variable_name", "variable-value")
1853          self.assertTrue(variable.edit("variable-value123"))
1854          variable.delete()
1855  
1856  
1857  class LazyRepository(Framework.TestCase):
1858      def setUp(self):
1859          super().setUp()
1860          self.user = self.g.get_user()
1861          self.repository_name = f"{self.user.login}/PyGithub"
1862  
1863      def getLazyRepository(self):
1864          return self.g.get_repo(self.repository_name, lazy=True)
1865  
1866      def getEagerRepository(self):
1867          return self.g.get_repo(self.repository_name, lazy=False)
1868  
1869      def testGetIssues(self):
1870          lazy_repo = self.getLazyRepository()
1871          issues = lazy_repo.get_issues()
1872          eager_repo = self.getEagerRepository()
1873          issues2 = eager_repo.get_issues()
1874          self.assertListKeyEqual(issues2, id, [x for x in issues])
1875  
1876      def testOwner(self):
1877          lazy_repo = self.getLazyRepository()
1878          owner = lazy_repo.owner
1879          eager_repo = self.getEagerRepository()
1880          self.assertEqual(owner, eager_repo.owner)
1881  
1882      def testEnableVulnerabilityAlert(self):
1883          lazy_repo = self.getLazyRepository()
1884          self.assertTrue(lazy_repo.enable_vulnerability_alert())
1885  
1886          lazy_repo = self.g.get_repo("random", lazy=True)
1887          self.assertFalse(lazy_repo.enable_vulnerability_alert())
1888  
1889      def testEnableAutomatedSecurityFixes(self):
1890          lazy_repo = self.getLazyRepository()
1891          self.assertTrue(lazy_repo.enable_automated_security_fixes())
1892  
1893          lazy_repo = self.g.get_repo("random", lazy=True)
1894          self.assertFalse(lazy_repo.enable_automated_security_fixes())
1895  
1896      def testDisableAutomatedSecurityFixes(self):
1897          lazy_repo = self.getLazyRepository()
1898          self.assertTrue(lazy_repo.disable_automated_security_fixes())
1899  
1900          lazy_repo = self.g.get_repo("random", lazy=True)
1901          self.assertFalse(lazy_repo.disable_automated_security_fixes())
1902  
1903      def testGetVulnerabilityAlert(self):
1904          lazy_repo = self.getEagerRepository()
1905          self.assertTrue(lazy_repo.get_vulnerability_alert())
1906  
1907          lazy_repo = self.g.get_repo("random", lazy=True)
1908          self.assertFalse(lazy_repo.get_vulnerability_alert())
1909  
1910      def testDisableVulnerabilityAlert(self):
1911          lazy_repo = self.getLazyRepository()
1912          self.assertTrue(lazy_repo.disable_vulnerability_alert())
1913  
1914          lazy_repo = self.g.get_repo("random", lazy=True)
1915          self.assertFalse(lazy_repo.disable_vulnerability_alert())
1916  
1917      def testChangeAutomateFixWhenNoVulnerabilityAlert(self):
1918          lazy_repo = self.getLazyRepository()
1919          self.assertFalse(lazy_repo.enable_automated_security_fixes())
1920          self.assertFalse(lazy_repo.disable_automated_security_fixes())
1921  
1922      def testGetVulnerabilityAlertWhenTurnedOff(self):
1923          lazy_repo = self.getEagerRepository()
1924          self.assertFalse(lazy_repo.get_vulnerability_alert())