Repository: PyGithub/PyGithub

Issue:
Add support for pending team invitations
Per the [docs](https://developer.github.com/v3/teams/members/#list-pending-team-invitations), it's just the following call:

```
GET /teams/:team_id/invitations
```

As mentioned in a blog [post](https://developer.github.com/changes/2018-01-25-organization-invitation-api-preview/) earlier this year, there are two new fields added to the response:

- team_count
- invitation_teams_url

These new fields only appear in the response if the following header is added to the request:

```
Accept: application/vnd.github.dazzler-preview+json
```

So I guess the only question would be whether or not to add the header? Given this is an existing endpoint, probably better to NOT include the header; then when Github moves the new "feature" (which includes the new fields) out of preview, it shows up in the response and PyGithub doesn't have to be changed to remove the above header.


Discussion:
I'm happy to pick this up and work on it.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/github/NamedUser.py b/github/NamedUser.py
--- a/github/NamedUser.py
+++ b/github/NamedUser.py
@@ -225,6 +225,22 @@ def id(self):
         self._completeIfNotSet(self._id)
         return self._id.value
 
+    @property
+    def invitation_teams_url(self):
+        """
+        :type: string
+        """
+        self._completeIfNotSet(self._invitation_teams_url)
+        return self._invitation_teams_url.value
+
+    @property
+    def inviter(self):
+        """
+        :type: github.NamedUser.NamedUser
+        """
+        self._completeIfNotSet(self._inviter)
+        return self._inviter.value
+
     @property
     def location(self):
         """
@@ -320,6 +336,13 @@ def repos_url(self):
         """
         self._completeIfNotSet(self._repos_url)
         return self._repos_url.value
+    @property
+    def role(self):
+        """
+        :type: string
+        """
+        self._completeIfNotSet(self._role)
+        return self._role.value
 
     @property
     def site_admin(self):
@@ -353,6 +376,14 @@ def suspended_at(self):
         self._completeIfNotSet(self._suspended_at)
         return self._suspended_at.value
 
+    @property
+    def team_count(self):
+        """
+        :type: integer
+        """
+        self._completeIfNotSet(self._team_count)
+        return self._team_count.value
+
     @property
     def total_private_repos(self):
         """
@@ -610,6 +641,8 @@ def _initAttributes(self):
         self._hireable = github.GithubObject.NotSet
         self._html_url = github.GithubObject.NotSet
         self._id = github.GithubObject.NotSet
+        self._invitation_teams_url = github.GithubObject.NotSet
+        self._inviter = github.GithubObject.NotSet
         self._location = github.GithubObject.NotSet
         self._login = github.GithubObject.NotSet
         self._name = github.GithubObject.NotSet
@@ -623,10 +656,12 @@ def _initAttributes(self):
         self._public_repos = github.GithubObject.NotSet
         self._received_events_url = github.GithubObject.NotSet
         self._repos_url = github.GithubObject.NotSet
+        self._role = github.GithubObject.NotSet
         self._site_admin = github.GithubObject.NotSet
         self._starred_url = github.GithubObject.NotSet
         self._subscriptions_url = github.GithubObject.NotSet
         self._suspended_at = github.GithubObject.NotSet
+        self._team_count = github.GithubObject.NotSet
         self._total_private_repos = github.GithubObject.NotSet
         self._type = github.GithubObject.NotSet
         self._updated_at = github.GithubObject.NotSet
@@ -671,6 +706,10 @@ def _useAttributes(self, attributes):
             self._html_url = self._makeStringAttribute(attributes["html_url"])
         if "id" in attributes:  # pragma no branch
             self._id = self._makeIntAttribute(attributes["id"])
+        if "invitation_teams_url" in attributes:  # pragma no branch
+            self._invitation_teams_url = self._makeStringAttribute(attributes["invitation_teams_url"])
+        if "inviter" in attributes:  # pragma no branch
+            self._inviter = self._makeClassAttribute(github.NamedUser.NamedUser, attributes["inviter"])
         if "location" in attributes:  # pragma no branch
             self._location = self._makeStringAttribute(attributes["location"])
         if "login" in attributes:  # pragma no branch
@@ -697,6 +736,8 @@ def _useAttributes(self, attributes):
             self._received_events_url = self._makeStringAttribute(attributes["received_events_url"])
         if "repos_url" in attributes:  # pragma no branch
             self._repos_url = self._makeStringAttribute(attributes["repos_url"])
+        if "role" in attributes: # pragma no branch
+            self._role = self._makeStringAttribute(attributes["role"])
         if "site_admin" in attributes:  # pragma no branch
             self._site_admin = self._makeBoolAttribute(attributes["site_admin"])
         if "starred_url" in attributes:  # pragma no branch
@@ -705,6 +746,8 @@ def _useAttributes(self, attributes):
             self._subscriptions_url = self._makeStringAttribute(attributes["subscriptions_url"])
         if "suspended_at" in attributes:  # pragma no branch
             self._suspended_at = self._makeDatetimeAttribute(attributes["suspended_at"])
+        if "team_count" in attributes:
+            self._team_count = self._makeIntAttribute(attributes["team_count"])
         if "total_private_repos" in attributes:  # pragma no branch
             self._total_private_repos = self._makeIntAttribute(attributes["total_private_repos"])
         if "type" in attributes:  # pragma no branch
diff --git a/github/Organization.py b/github/Organization.py
--- a/github/Organization.py
+++ b/github/Organization.py
@@ -798,6 +798,21 @@ def get_teams(self):
             None
         )
 
+    def invitations(self):
+        """
+        :calls: `GET /orgs/:org/invitations <https://developer.github.com/v3/orgs/members>`_
+        :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.NamedUser.NamedUser`
+        """
+        return github.PaginatedList.PaginatedList(
+            github.NamedUser.NamedUser,
+            self._requester,
+            self.url + "/invitations",
+            None,
+            headers={
+                "Accept": Consts.mediaTypeOrganizationInvitationPreview
+            }
+        )
+
     def invite_user(self, user=github.GithubObject.NotSet, email=github.GithubObject.NotSet, role=github.GithubObject.NotSet, teams=github.GithubObject.NotSet):
         """
         :calls: `POST /orgs/:org/invitations <http://developer.github.com/v3/orgs/members>`_
diff --git a/github/Team.py b/github/Team.py
--- a/github/Team.py
+++ b/github/Team.py
@@ -48,6 +48,7 @@
 import github.NamedUser
 import github.Organization
 
+import Consts
 
 class Team(github.GithubObject.CompletableGithubObject):
     """
@@ -291,6 +292,21 @@ def get_repos(self):
             None
         )
 
+    def invitations(self):
+        """
+        :calls: `GET /teams/:id/invitations <https://developer.github.com/v3/teams/members>`_
+        :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.NamedUser.NamedUser`
+        """
+        return github.PaginatedList.PaginatedList(
+            github.NamedUser.NamedUser,
+            self._requester,
+            self.url + "/invitations",
+            None,
+            headers={
+                "Accept": Consts.mediaTypeOrganizationInvitationPreview
+            }
+        )
+
     def has_in_members(self, member):
         """
         :calls: `GET /teams/:id/members/:user <http://developer.github.com/v3/orgs/teams>`_


Test patch:
diff --git a/tests/AllTests.py b/tests/AllTests.py
--- a/tests/AllTests.py
+++ b/tests/AllTests.py
@@ -126,3 +126,4 @@
 from Issue572 import *
 from Issue937 import *
 from Issue945 import *
+from Issue823 import *
\ No newline at end of file
diff --git a/tests/Issue823.py b/tests/Issue823.py
new file mode 100644
--- /dev/null
+++ b/tests/Issue823.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+
+############################ Copyrights and license ############################
+#                                                                              #
+# Copyright 2013 Vincent Jacques <vincent@vincent-jacques.net>                 #
+# Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net>                 #
+# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com>          #
+# Copyright 2018 sfdye <tsfdye@gmail.com>                                      #
+#                                                                              #
+# 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/>.             #
+#                                                                              #
+################################################################################
+
+import Framework
+import github
+
+
+class Issue823(Framework.TestCase):
+    def setUp(self):
+        Framework.TestCase.setUp(self)
+        self.org = self.g.get_organization('p-society')
+        self.team = self.org.get_team(2745783)
+        self.pending_invitations = self.team.invitations()
+
+    def testGetPendingInvitationAttributes(self):
+        team_url = self.pending_invitations[0].invitation_teams_url
+        self.assertEqual(team_url, 'https://api.github.com/organizations/29895434/invitations/6080804/teams')
+        inviter = self.pending_invitations[0].inviter.login
+        self.assertEqual(inviter,'palash25' )
+        role = self.pending_invitations[0].role
+        self.assertEqual(role, 'direct_member')
+        team_count = self.pending_invitations[0].team_count
+        self.assertEqual(team_count, 1)
diff --git a/tests/ReplayData/Issue823.setUp.txt b/tests/ReplayData/Issue823.setUp.txt
new file mode 100644
--- /dev/null
+++ b/tests/ReplayData/Issue823.setUp.txt
@@ -0,0 +1,22 @@
+https
+GET
+api.github.com
+None
+/orgs/p-society
+{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Server', 'GitHub.com'), ('Date', 'Wed, 26 Dec 2018 11:10:55 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4999'), ('X-RateLimit-Reset', '1545826255'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"6580793c7561d3bf848eb8a135d33833"'), ('Last-Modified', 'Wed, 05 Dec 2018 16:45:38 GMT'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('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', '8C70:6FB5:4C1D7B3:A5203B7:5C2361BD')]
+{"login":"p-society","id":29895434,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI5ODk1NDM0","url":"https://api.github.com/orgs/p-society","repos_url":"https://api.github.com/orgs/p-society/repos","events_url":"https://api.github.com/orgs/p-society/events","hooks_url":"https://api.github.com/orgs/p-society/hooks","issues_url":"https://api.github.com/orgs/p-society/issues","members_url":"https://api.github.com/orgs/p-society/members{/member}","public_members_url":"https://api.github.com/orgs/p-society/public_members{/member}","avatar_url":"https://avatars0.githubusercontent.com/u/29895434?v=4","description":"IIIT Bhubaneswar's Programming Society","name":"Programming Society","company":null,"blog":"https://p-society.herokuapp.com/","location":"Bhubaneswar","email":"psocietyiiitbh@gmail.com","is_verified":false,"has_organization_projects":true,"has_repository_projects":true,"public_repos":23,"public_gists":0,"followers":0,"following":0,"html_url":"https://github.com/p-society","created_at":"2017-07-04T14:47:55Z","updated_at":"2018-12-05T16:45:38Z","type":"Organization","total_private_repos":2,"owned_private_repos":2,"private_gists":0,"disk_usage":30533,"collaborators":0,"billing_email":"shibasishpatel@live.in","plan":{"name":"team","space":976562499,"private_repos":99999,"filled_seats":34,"seats":34},"default_repository_permission":"read","members_can_create_repositories":true,"two_factor_requirement_enabled":false}
+
+https
+GET
+api.github.com
+None
+/teams/2745783
+{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Server', 'GitHub.com'), ('Date', 'Wed, 26 Dec 2018 11:10:57 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4998'), ('X-RateLimit-Reset', '1545826255'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"0452ef7aded17dfd16179e5248c4bd14"'), ('Last-Modified', 'Tue, 01 May 2018 17:57:43 GMT'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('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', 'D55C:6FB2:118318A:2F5B512:5C2361C0')]
+{"name":"2019-batch","id":2745783,"node_id":"MDQ6VGVhbTI3NDU3ODM=","slug":"2019-batch","description":"Students from the batch of 2015-19","privacy":"closed","url":"https://api.github.com/teams/2745783","members_url":"https://api.github.com/teams/2745783/members{/member}","repositories_url":"https://api.github.com/teams/2745783/repos","permission":"pull","created_at":"2018-05-01T17:57:43Z","updated_at":"2018-05-01T17:57:43Z","members_count":6,"repos_count":1,"organization":{"login":"p-society","id":29895434,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI5ODk1NDM0","url":"https://api.github.com/orgs/p-society","repos_url":"https://api.github.com/orgs/p-society/repos","events_url":"https://api.github.com/orgs/p-society/events","hooks_url":"https://api.github.com/orgs/p-society/hooks","issues_url":"https://api.github.com/orgs/p-society/issues","members_url":"https://api.github.com/orgs/p-society/members{/member}","public_members_url":"https://api.github.com/orgs/p-society/public_members{/member}","avatar_url":"https://avatars0.githubusercontent.com/u/29895434?v=4","description":"IIIT Bhubaneswar's Programming Society","name":"Programming Society","company":null,"blog":"https://p-society.herokuapp.com/","location":"Bhubaneswar","email":"psocietyiiitbh@gmail.com","is_verified":false,"has_organization_projects":true,"has_repository_projects":true,"public_repos":23,"public_gists":0,"followers":0,"following":0,"html_url":"https://github.com/p-society","created_at":"2017-07-04T14:47:55Z","updated_at":"2018-12-05T16:45:38Z","type":"Organization"}}
+
diff --git a/tests/ReplayData/Issue823.testGetPendingInvitationAttributes.txt b/tests/ReplayData/Issue823.testGetPendingInvitationAttributes.txt
new file mode 100644
--- /dev/null
+++ b/tests/ReplayData/Issue823.testGetPendingInvitationAttributes.txt
@@ -0,0 +1,11 @@
+https
+GET
+api.github.com
+None
+/teams/2745783/invitations
+{'Accept': 'application/vnd.github.dazzler-preview+json', 'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('Server', 'GitHub.com'), ('Date', 'Wed, 26 Dec 2018 11:10:59 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4997'), ('X-RateLimit-Reset', '1545826255'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"debc51b3da093a55c674f2303663ab69"'), ('X-GitHub-Media-Type', 'github.dazzler-preview; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('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', '8C74:6FB4:3A8ABED:8659024:5C2361C2')]
+[{"id":6080804,"node_id":"MDIyOk9yZ2FuaXphdGlvbkludml0YXRpb242MDgwODA0","login":"pratchef","email":null,"role":"direct_member","created_at":"2018-05-02T00:19:26.000+05:30","inviter":{"login":"palash25","id":21367710,"node_id":"MDQ6VXNlcjIxMzY3NzEw","avatar_url":"https://avatars0.githubusercontent.com/u/21367710?v=4","gravatar_id":"","url":"https://api.github.com/users/palash25","html_url":"https://github.com/palash25","followers_url":"https://api.github.com/users/palash25/followers","following_url":"https://api.github.com/users/palash25/following{/other_user}","gists_url":"https://api.github.com/users/palash25/gists{/gist_id}","starred_url":"https://api.github.com/users/palash25/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/palash25/subscriptions","organizations_url":"https://api.github.com/users/palash25/orgs","repos_url":"https://api.github.com/users/palash25/repos","events_url":"https://api.github.com/users/palash25/events{/privacy}","received_events_url":"https://api.github.com/users/palash25/received_events","type":"User","site_admin":false},"team_count":1,"invitation_teams_url":"https://api.github.com/organizations/29895434/invitations/6080804/teams"}]
+