Repository: PyGithub/PyGithub

Issue:
Exception raised in get_contents()
```
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import github
>>> gh = github.Github('mytoken')
>>> repo = gh.get_repo('VIDA-NYU/reprozip')
>>> repo.get_commit('master')
Commit(sha="a9f1ea3767e2ae357d8e67d77554845d65f4c2e7")
>>> repo.get_contents('/', 'a9f1ea3767e2ae357d8e67d77554845d65f4c2e7')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lib/python3.6/site-packages/github/Repository.py", line 1479, in get_contents
    return self.get_file_contents(path, ref)
  File "lib/python3.6/site-packages/github/Repository.py", line 1503, in get_file_contents
    return github.ContentFile.ContentFile(self._requester, headers, data, completed=True)
  File "lib/python3.6/site-packages/github/GithubObject.py", line 252, in __init__
    GithubObject.__init__(self, requester, headers, attributes, completed)
  File "lib/python3.6/site-packages/github/GithubObject.py", line 86, in __init__
    self._storeAndUseAttributes(headers, attributes)
  File "lib/python3.6/site-packages/github/GithubObject.py", line 98, in _storeAndUseAttributes
    self._useAttributes(attributes)
  File "lib/python3.6/site-packages/github/ContentFile.py", line 192, in _useAttributes
    if "content" in attributes:  # pragma no branch
TypeError: argument of type 'NoneType' is not iterable
```
*[edit: removed my token (and revoked it). Doh!]*

Seems to be a regression.


Discussion:
I can reproduce this, looks like GitHub is returning a 302 redirect for contents of '/', currently thinking about how to solve this.

Resolving patch:
diff --git a/github/Repository.py b/github/Repository.py
--- a/github/Repository.py
+++ b/github/Repository.py
@@ -1478,6 +1478,9 @@ def get_contents(self, path, ref=github.GithubObject.NotSet):
         """
         assert isinstance(path, (str, unicode)), path
         assert ref is github.GithubObject.NotSet or isinstance(ref, (str, unicode)), ref
+        # Path of '/' should be the empty string.
+        if path == '/':
+            path = ''
         url_parameters = dict()
         if ref is not github.GithubObject.NotSet:
             url_parameters["ref"] = ref


Test patch:
diff --git a/tests/ReplayData/Repository.testGetContentDir.txt b/tests/ReplayData/Repository.testGetContentsDir.txt
similarity index 100%
rename from tests/ReplayData/Repository.testGetContentDir.txt
rename to tests/ReplayData/Repository.testGetContentsDir.txt
diff --git a/tests/ReplayData/Repository.testGetContentsDirWithSlash.txt b/tests/ReplayData/Repository.testGetContentsDirWithSlash.txt
new file mode 100644
--- /dev/null
+++ b/tests/ReplayData/Repository.testGetContentsDirWithSlash.txt
@@ -0,0 +1,11 @@
+https
+GET
+api.github.com
+None
+/repos/jacquev6/PyGithub/contents/
+{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('content-length', '9998'), ('vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding'), ('x-served-by', '01d096e6cfe28f8aea352e988c332cd3'), ('x-oauth-client-id', 'd408456562a3db38febf'), ('x-oauth-scopes', 'repo, write:repo_hook'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('x-accepted-oauth-scopes', ''), ('etag', '"c75510b6d23cfb87768b59121bb1763a"'), ('cache-control', 'private, max-age=60, s-maxage=60'), ('status', '200 OK'), ('x-ratelimit-remaining', '4984'), ('x-github-media-type', 'github.v3; format=json'), ('access-control-expose-headers', 'ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval'), ('x-github-request-id', '5DE87F72:75F9:9EF346:57DA8E59'), ('last-modified', 'Thu, 15 Sep 2016 12:04:32 GMT'), ('date', 'Thu, 15 Sep 2016 12:04:42 GMT'), ('access-control-allow-origin', '*'), ('content-security-policy', "default-src 'none'"), ('strict-transport-security', 'max-age=31536000; includeSubdomains; preload'), ('server', 'GitHub.com'), ('x-ratelimit-limit', '5000'), ('x-frame-options', 'deny'), ('content-type', 'application/json; charset=utf-8'), ('x-ratelimit-reset', '1473942365')]
+[{"name":".gitignore","path":".gitignore","sha":"43d495ed8185348ef800ccd768bf9eb47eea433b","size":2036,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/.gitignore?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/.gitignore","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/43d495ed8185348ef800ccd768bf9eb47eea433b","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/.gitignore","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/.gitignore?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/43d495ed8185348ef800ccd768bf9eb47eea433b","html":"https://github.com/jayfk/PyGithub/blob/master/.gitignore"}},{"name":".travis.yml","path":".travis.yml","sha":"5b7b29ac787f3a535eff409592ef40ccd04595d8","size":494,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/.travis.yml?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/.travis.yml","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/5b7b29ac787f3a535eff409592ef40ccd04595d8","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/.travis.yml","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/.travis.yml?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/5b7b29ac787f3a535eff409592ef40ccd04595d8","html":"https://github.com/jayfk/PyGithub/blob/master/.travis.yml"}},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","sha":"138fa737b13a13582bf53acea7ee534aa197328a","size":2424,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/CONTRIBUTING.md?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/CONTRIBUTING.md","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/138fa737b13a13582bf53acea7ee534aa197328a","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/CONTRIBUTING.md","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/CONTRIBUTING.md?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/138fa737b13a13582bf53acea7ee534aa197328a","html":"https://github.com/jayfk/PyGithub/blob/master/CONTRIBUTING.md"}},{"name":"COPYING","path":"COPYING","sha":"94a9ed024d3859793618152ea559a168bbcbb5e2","size":35147,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/COPYING?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/COPYING","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/94a9ed024d3859793618152ea559a168bbcbb5e2","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/COPYING","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/COPYING?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/94a9ed024d3859793618152ea559a168bbcbb5e2","html":"https://github.com/jayfk/PyGithub/blob/master/COPYING"}},{"name":"COPYING.LESSER","path":"COPYING.LESSER","sha":"65c5ca88a67c30becee01c5a8816d964b03862f9","size":7651,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/COPYING.LESSER?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/COPYING.LESSER","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/65c5ca88a67c30becee01c5a8816d964b03862f9","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/COPYING.LESSER","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/COPYING.LESSER?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/65c5ca88a67c30becee01c5a8816d964b03862f9","html":"https://github.com/jayfk/PyGithub/blob/master/COPYING.LESSER"}},{"name":"MAINTAINERS","path":"MAINTAINERS","sha":"f8cbd3bbeba08404099c4bc57135b7d21b9e5616","size":216,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/MAINTAINERS?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/MAINTAINERS","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/f8cbd3bbeba08404099c4bc57135b7d21b9e5616","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/MAINTAINERS","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/MAINTAINERS?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/f8cbd3bbeba08404099c4bc57135b7d21b9e5616","html":"https://github.com/jayfk/PyGithub/blob/master/MAINTAINERS"}},{"name":"MANIFEST.in","path":"MANIFEST.in","sha":"501859533a9b38d0705e5c8cab4380610d574dd7","size":35,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/MANIFEST.in?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/MANIFEST.in","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/501859533a9b38d0705e5c8cab4380610d574dd7","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/MANIFEST.in","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/MANIFEST.in?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/501859533a9b38d0705e5c8cab4380610d574dd7","html":"https://github.com/jayfk/PyGithub/blob/master/MANIFEST.in"}},{"name":"README.md","path":"README.md","sha":"ae065a7ba88a6614cb0a8cdbe5bd58a317654548","size":1570,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/README.md?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/README.md","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/ae065a7ba88a6614cb0a8cdbe5bd58a317654548","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/README.md","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/README.md?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/ae065a7ba88a6614cb0a8cdbe5bd58a317654548","html":"https://github.com/jayfk/PyGithub/blob/master/README.md"}},{"name":"doc","path":"doc","sha":"42cda5799d4f5668c7d59e17c1593debe6410f7f","size":0,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/doc?ref=master","html_url":"https://github.com/jayfk/PyGithub/tree/master/doc","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/trees/42cda5799d4f5668c7d59e17c1593debe6410f7f","download_url":null,"type":"dir","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/doc?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/trees/42cda5799d4f5668c7d59e17c1593debe6410f7f","html":"https://github.com/jayfk/PyGithub/tree/master/doc"}},{"name":"github","path":"github","sha":"357dd749e9f089b6fc1a7437326d75dc2700eb3e","size":0,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/github?ref=master","html_url":"https://github.com/jayfk/PyGithub/tree/master/github","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/trees/357dd749e9f089b6fc1a7437326d75dc2700eb3e","download_url":null,"type":"dir","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/github?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/trees/357dd749e9f089b6fc1a7437326d75dc2700eb3e","html":"https://github.com/jayfk/PyGithub/tree/master/github"}},{"name":"manage.sh","path":"manage.sh","sha":"8ce7c88318a3cc25f368d7a43e69a41b8460e68f","size":2582,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/manage.sh?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/manage.sh","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/8ce7c88318a3cc25f368d7a43e69a41b8460e68f","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/manage.sh","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/manage.sh?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/8ce7c88318a3cc25f368d7a43e69a41b8460e68f","html":"https://github.com/jayfk/PyGithub/blob/master/manage.sh"}},{"name":"python25-requirements.txt","path":"python25-requirements.txt","sha":"322630ee75f32576be6c69b4de9deb73cddc430c","size":11,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/python25-requirements.txt?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/python25-requirements.txt","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/322630ee75f32576be6c69b4de9deb73cddc430c","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/python25-requirements.txt","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/python25-requirements.txt?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/322630ee75f32576be6c69b4de9deb73cddc430c","html":"https://github.com/jayfk/PyGithub/blob/master/python25-requirements.txt"}},{"name":"scripts","path":"scripts","sha":"95e3c1f29331e6de4c3833022fb1a78ef039bb6f","size":0,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/scripts?ref=master","html_url":"https://github.com/jayfk/PyGithub/tree/master/scripts","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/trees/95e3c1f29331e6de4c3833022fb1a78ef039bb6f","download_url":null,"type":"dir","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/scripts?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/trees/95e3c1f29331e6de4c3833022fb1a78ef039bb6f","html":"https://github.com/jayfk/PyGithub/tree/master/scripts"}},{"name":"setup.py","path":"setup.py","sha":"75a4afa35995089741a2089c5356e2b1af3d85cd","size":4094,"url":"https://api.github.com/repos/jayfk/PyGithub/contents/setup.py?ref=master","html_url":"https://github.com/jayfk/PyGithub/blob/master/setup.py","git_url":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/75a4afa35995089741a2089c5356e2b1af3d85cd","download_url":"https://raw.githubusercontent.com/jayfk/PyGithub/master/setup.py","type":"file","_links":{"self":"https://api.github.com/repos/jayfk/PyGithub/contents/setup.py?ref=master","git":"https://api.github.com/repos/jayfk/PyGithub/git/blobs/75a4afa35995089741a2089c5356e2b1af3d85cd","html":"https://github.com/jayfk/PyGithub/blob/master/setup.py"}}]
+
diff --git a/tests/Repository.py b/tests/Repository.py
--- a/tests/Repository.py
+++ b/tests/Repository.py
@@ -523,12 +523,16 @@ def testGetContents(self):
         self.assertEqual(len(self.repo.get_readme().content), 10212)
         self.assertEqual(len(self.repo.get_contents("doc/ReferenceOfClasses.md").content), 38121)
 
-    def testGetContentDir(self):
-
+    def testGetContentsDir(self):
         contents = self.repo.get_contents("")
         self.assertTrue(isinstance(contents, list))
         self.assertEquals(len(contents), 14)
 
+    def testGetContentsDirWithSlash(self):
+        contents = self.repo.get_contents("/")
+        self.assertTrue(isinstance(contents, list))
+        self.assertEquals(len(contents), 14)
+
     def testGetContentsWithRef(self):
         self.assertEqual(len(self.repo.get_readme(ref="refs/heads/topic/ExperimentOnDocumentation").content), 6747)
         self.assertEqual(len(self.repo.get_contents("doc/ReferenceOfClasses.md", ref="refs/heads/topic/ExperimentOnDocumentation").content), 43929)