Repository: PyGithub/PyGithub

Issue:
Attributes "maintain" and "triage" missing in class "Permissions"
Current Github API returns a permission values for `admin`, `push`, `maintain`, `triage` and `pull` (see <https://docs.github.com/en/free-pro-team@latest/rest/reference/teams#check-team-permissions-for-a-repository>).
PyGithub so far only supports  `admin`, `push` and `pull`.

This is a feature request to add the two missing attributes to class `github.Permissions.Permissions`.
https://github.com/PyGithub/PyGithub/blob/34d097ce473601624722b90fc5d0396011dd3acb/github/Permissions.py#L34



Discussion:

Resolving patch:
diff --git a/github/Permissions.py b/github/Permissions.py
--- a/github/Permissions.py
+++ b/github/Permissions.py
@@ -40,8 +40,10 @@ def __repr__(self):
         return self.get__repr__(
             {
                 "admin": self._admin.value,
+                "maintain": self._maintain.value,
                 "pull": self._pull.value,
                 "push": self._push.value,
+                "triage": self._triage.value,
             }
         )
 
@@ -52,6 +54,13 @@ def admin(self):
         """
         return self._admin.value
 
+    @property
+    def maintain(self):
+        """
+        :type: bool
+        """
+        return self._maintain.value
+
     @property
     def pull(self):
         """
@@ -66,15 +75,28 @@ def push(self):
         """
         return self._push.value
 
+    @property
+    def triage(self):
+        """
+        :type: bool
+        """
+        return self._triage.value
+
     def _initAttributes(self):
         self._admin = github.GithubObject.NotSet
+        self._maintain = github.GithubObject.NotSet
         self._pull = github.GithubObject.NotSet
         self._push = github.GithubObject.NotSet
+        self._triage = github.GithubObject.NotSet
 
     def _useAttributes(self, attributes):
         if "admin" in attributes:  # pragma no branch
             self._admin = self._makeBoolAttribute(attributes["admin"])
+        if "maintain" in attributes:  # pragma no branch
+            self._maintain = self._makeBoolAttribute(attributes["maintain"])
         if "pull" in attributes:  # pragma no branch
             self._pull = self._makeBoolAttribute(attributes["pull"])
         if "push" in attributes:  # pragma no branch
             self._push = self._makeBoolAttribute(attributes["push"])
+        if "triage" in attributes:  # pragma no branch
+            self._triage = self._makeBoolAttribute(attributes["triage"])


Test patch:
diff --git a/tests/Permissions.py b/tests/Permissions.py
new file mode 100644
--- /dev/null
+++ b/tests/Permissions.py
@@ -0,0 +1,44 @@
+############################ Copyrights and license ############################
+#                                                                              #
+# Copyright 2020 Karsten Wagner <39054096+karsten-wagner@users.noreply.github.c#
+#                                                                              #
+# This file is part of PyGithub.                                               #
+# http://pygithub.readthedocs.io/                                              #
+#                                                                              #
+# PyGithub is free software: you can redistribute it and/or modify it under    #
+# the terms of the GNU Lesser General Public License as published by the Free  #
+# Software Foundation, either version 3 of the License, or (at your option)    #
+# any later version.                                                           #
+#                                                                              #
+# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
+# details.                                                                     #
+#                                                                              #
+# You should have received a copy of the GNU Lesser General Public License     #
+# along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #
+#                                                                              #
+################################################################################
+
+from . import Framework
+
+
+class Permissions(Framework.TestCase):
+    def setUp(self):
+        super().setUp()
+        self.userRepo = self.g.get_repo("PyGithub/PyGithub")
+
+    def testUserRepoPermissionAttributes(self):
+        self.assertEqual(self.userRepo.permissions.admin, False)
+        # Attribute is not present for users (only for teams)
+        self.assertEqual(self.userRepo.permissions.maintain, None)
+        self.assertEqual(self.userRepo.permissions.pull, True)
+        self.assertEqual(self.userRepo.permissions.push, False)
+        # Attribute is not present for users (only for teams)
+        self.assertEqual(self.userRepo.permissions.triage, None)
+
+    def testUserRepoPermissionRepresentation(self):
+        self.assertEqual(
+            repr(self.userRepo.permissions),
+            "Permissions(triage=None, push=False, pull=True, maintain=None, admin=False)",
+        )
diff --git a/tests/ReplayData/Permissions.setUp.txt b/tests/ReplayData/Permissions.setUp.txt
new file mode 100644
--- /dev/null
+++ b/tests/ReplayData/Permissions.setUp.txt
@@ -0,0 +1,10 @@
+https
+GET
+api.github.com
+None
+/repos/PyGithub/PyGithub
+{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Date', 'Wed, 30 Dec 2020 16:56:35 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Server', 'GitHub.com'), ('Status', '200 OK'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With, Accept-Encoding'), ('ETag', 'W/"c657b4c19db69d99845c82908b2a8f7f87dfc1fa058ecb82ffda11af8867667a"'), ('Last-Modified', 'Wed, 30 Dec 2020 01:50:06 GMT'), ('X-OAuth-Scopes', 'repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4968'), ('X-RateLimit-Reset', '1609349398'), ('X-RateLimit-Used', '32'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'CC87:48FE:1FC3AC59:247A4176:5FECB143')]
+{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars0.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2020-12-30T01:50:06Z","pushed_at":"2020-12-30T16:00:45Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13269,"stargazers_count":3989,"watchers_count":3989,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1244,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":77,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":1244,"open_issues":77,"watchers":3989,"default_branch":"master","permissions":{"admin":false,"push":false,"pull":true},"temp_clone_token":"","organization":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars0.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"network_count":1244,"subscribers_count":105}
diff --git a/tests/Repository.py b/tests/Repository.py
--- a/tests/Repository.py
+++ b/tests/Repository.py
@@ -112,9 +112,12 @@ def testAttributes(self):
         )
         self.assertEqual(self.repo.watchers, 15)
         self.assertEqual(repr(self.repo), 'Repository(full_name="jacquev6/PyGithub")')
-        self.assertEqual(
-            repr(self.repo.permissions), "Permissions(push=True, pull=True, admin=True)"
-        )
+        self.assertTrue(self.repo.permissions.admin)
+        self.assertTrue(self.repo.permissions.push)
+        self.assertTrue(self.repo.permissions.pull)
+        # Allow None or any boolean value for backwards compatibility
+        self.assertIn(self.repo.permissions.maintain, [None, False, True])
+        self.assertIn(self.repo.permissions.triage, [None, False, True])
 
     def testEditWithoutArguments(self):
         self.repo.edit("PyGithub")