Pygithub: Branch object is missing most attributes and methods

Created on 17 Aug 2018  ·  11Comments  ·  Source: PyGithub/PyGithub

I'm playing around with this library with the hopes that I can automate things on our Github Enterprise. One of the first things I need to do is to set branch protections for our repos. However, when I initiate a Branch object from a test repository (that already had branch protections set, mind you), the only attribute it has assigned is "name", and most of the methods listed in the documentation don't exist on the object:

import github
github.enable_console_debug_logging()
Github = github.Github

Github("myuser",
'mycreds',
base_url="https://ghe.workworkwork.com/api/v3")

master = g.get_user("myuser").get_repo('cookbook1').get_branch('master')
print master
print master.protection_url

The output:

...
GET https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/branches/master {'Authorization': 'Basic (login and password removed)', 'User-Agent': 'PyGithub/Python'} None ==> 200 {'status': '200 OK', 'content-length': '2925', 'x-github-media-type': 'github.v3', 'x-content-type-options': 'nosniff', 'content-security-policy': "default-src 'none'", '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': '0ec6f4e8-2355-41dc-859d-0e7076a294b1', 'strict-transport-security': 'max-age=31536000; includeSubdomains', 'vary': 'Accept, Authorization, Cookie, X-GitHub-OTP', 'server': 'GitHub.com', 'access-control-allow-origin': '*', 'etag': '"965449c848ed3319d7e028c2a587f414"', 'x-xss-protection': '1; mode=block', 'cache-control': 'private, max-age=60, s-maxage=60', 'date': 'Thu, 16 Aug 2018 23:41:19 GMT', 'x-frame-options': 'deny', 'x-oauth-scopes': 'admin:org_hook, admin:pre_receive_hook, admin:repo_hook, repo', 'content-type': 'application/json; charset=utf-8', 'x-accepted-oauth-scopes': ''} {"name":"master","commit":{"sha":"3548233b67c8ec4cad703ff947fa0ba022df7c66","commit":{"author":{"name":"Garrett Anderson","email":"[email protected]","date":"2018-08-16T18:44:44Z"},"committer":{"name":"GitHub Enterprise","email":"[email protected]","date":"2018-08-16T18:44:44Z"},"message":"Merge pull request #8 from myuser/newfork\n\nwhat","tree":{"sha":"44b3a300094b2ccbbfb79ea7df5f82e627c12b42","url":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/git/trees/44b3a300094b2ccbbfb79ea7df5f82e627c12b42"},"url":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/git/commits/3548233b67c8ec4cad703ff947fa0ba022df7c66","comment_count":0},"url":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/commits/3548233b67c8ec4cad703ff947fa0ba022df7c66","html_url":"https://ghe.workworkwork.com/myuser/cookbook1/commit/3548233b67c8ec4cad703ff947fa0ba022df7c66","comments_url":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/commits/3548233b67c8ec4cad703ff947fa0ba022df7c66/comments","author":{"login":"myuser","id":593,"avatar_url":"https://ghe.workworkwork.com/avatars/u/593?","gravatar_id":"","url":"https://ghe.workworkwork.com/api/v3/users/myuser","html_url":"https://ghe.workworkwork.com/myuser","followers_url":"https://ghe.workworkwork.com/api/v3/users/myuser/followers","following_url":"https://ghe.workworkwork.com/api/v3/users/myuser/following{/other_user}","gists_url":"https://ghe.workworkwork.com/api/v3/users/myuser/gists{/gist_id}","starred_url":"https://ghe.workworkwork.com/api/v3/users/myuser/starred{/owner}{/repo}","subscriptions_url":"https://ghe.workworkwork.com/api/v3/users/myuser/subscriptions","organizations_url":"https://ghe.workworkwork.com/api/v3/users/myuser/orgs","repos_url":"https://ghe.workworkwork.com/api/v3/users/myuser/repos","events_url":"https://ghe.workworkwork.com/api/v3/users/myuser/events{/privacy}","received_events_url":"https://ghe.workworkwork.com/api/v3/users/myuser/received_events","type":"User","site_admin":true},"committer":null,"parents":[{"sha":"067642113fe45ee77160ee28cafc4870f2c06b6a","url":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/commits/067642113fe45ee77160ee28cafc4870f2c06b6a","html_url":"https://ghe.workworkwork.com/myuser/cookbook1/commit/067642113fe45ee77160ee28cafc4870f2c06b6a"},{"sha":"3a9479c605617a9035cd986a4bf77880ac5dde64","url":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/commits/3a9479c605617a9035cd986a4bf77880ac5dde64","html_url":"https://ghe.workworkwork.com/myuser/cookbook1/commit/3a9479c605617a9035cd986a4bf77880ac5dde64"}]},"_links":{"self":"https://ghe.workworkwork.com/api/v3/repos/myuser/cookbook1/branches/master","html":"https://ghe.workworkwork.com/myuser/cookbook1/tree/master"}}

Branch(name="master")

AttributeError: 'Branch' object has no attribute 'protection_url'

There aren't any of the methods there either:

print master.get_required_status_checks()
OUTPUT:
AttributeError: 'Branch' object has no attribute 'get_required_status_checks'

Or this attribute:

print master.protection
OUTPUT:
return self._protected.value
AttributeError: 'Branch' object has no attribute '_protected'

The object looks like this:

print dir(master)
OUTPUT:
['CHECK_AFTER_INIT_FLAG', '_GithubObject__makeSimpleAttribute', '_GithubObject__makeSimpleListAttribute', '_GithubObject__makeTransformedAttribute', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_commit', '_completeIfNeeded', '_headers', '_initAttributes', '_makeBoolAttribute', '_makeClassAttribute', '_makeDatetimeAttribute', '_makeDictAttribute', '_makeDictOfStringsToClassesAttribute', '_makeIntAttribute', '_makeListOfClassesAttribute', '_makeListOfIntsAttribute', '_makeListOfListOfStringsAttribute', '_makeListOfStringsAttribute', '_makeStringAttribute', '_makeTimestampAttribute', '_name', '_parentUrl', '_rawData', '_requester', '_storeAndUseAttributes', '_useAttributes', 'commit', 'contexts', 'enforcement_level', 'etag', 'get__repr__', 'last_modified', 'name', 'protected', 'raw_data', 'raw_headers', 'setCheckAfterInitFlag']

It looks like the object isn't being created properly.

bug stale

Most helpful comment

I hit this issue when developing the branch protection code -- Repository.get_branches() does return a list
of branches, but GitHub does not return enough information for the methods on Branch to be useful. If you want to utilise the protection features you must call Repository.get_branch('name').

All 11 comments

What PyGithub version are you using? Note that #790 is only recently merged in but not released yet.

I'm using PyGithub-1.40 and Github Enterprise 2.8.6.
https://github.com/PyGithub/PyGithub/pull/790 definitely looks promising, although my company's GHE version is a little out of date, so I'm not sure if the API changes affect it.

UPDATE: in the process of testing the latest master

Looks like the latest merge fixed the issues of missing attributes and methods, but it seems to be incompatible with my version of the API:

master = g.get_user("ganderson").get_repo('cookbook1').get_branch('master')
print master.protection_url
master.get_protection()

OUTPUT:

None
Traceback (most recent call last):
  File "test_pygithub.py", line 12, in <module>
    master.get_protection()
  File "/Users/me/tmp/ghe-python/venv/lib/python2.7/site-packages/github/Branch.py", line 102, in get_protection
    self.protection_url
  File "/Users/me/tmp/ghe-python/venv/lib/python2.7/site-packages/github/Requester.py", line 260, in requestJsonAndCheck
    return self.__check(*self.requestJson(verb, url, parameters, headers, input, self.__customConnection(url)))
  File "/Users/me/tmp/ghe-python/venv/lib/python2.7/site-packages/github/Requester.py", line 276, in __customConnection
    if not url.startswith("/"):
AttributeError: 'NoneType' object has no attribute 'startswith'

This appears to be a separate issue, so I'll close this ticket. Thank you.

Do raise a new issue if the master breaks.

This also seems broken for me on 1.43.2 on standard api.github.com

I have 2 branches that are protected but the Branch objects never get the protection_url set.

The protection URL doesnt get set and results in errors for anything that uses it to build URLs.

[
  {
    "name": "develop",
    "commit": {
      "sha": "XXXX",
      "url": "https://api.github.com/repos/X/X/commits/X"
    }
  },
  {
    "name": "master",
    "commit": {
      "sha": "X",
      "url": "https://api.github.com/repos/X/X/commits/X"
    }
  }
]

If i curl using branches?protected=true it then returns the protection_url in the payload.

[
  {
    "name": "develop",
    "commit": {
      "sha": "X",
      "url": "https://api.github.com/repos/X/X/commits/X"
    },
    "protected": true,
    "protection": {
      "enabled": true,
      "required_status_checks": {
        "enforcement_level": "off",
        "contexts": [

        ]
      }
    },
    "protection_url": "https://api.github.com/repos/X/X/branches/develop/protection"
  },
  {
    "name": "master",
    "commit": {
      "sha": "X",
      "url": "https://api.github.com/repos/X/X/commits/X"
    },
    "protected": true,
    "protection": {
      "enabled": true,
      "required_status_checks": {
        "enforcement_level": "off",
        "contexts": [

        ]
      }
    },
    "protection_url": "https://api.github.com/repos/X/X/branches/master/protection"
  }
]

I'm reopening the issue on behalf of the last commenter

Can you try get single branch with get_branch("master")? I think the issue might be the current get_branches method does not support the protected parameter.

I spent a bit of time debugging this issue and raised a bug against the GitHub v3 API.

https://github.com/dear-github/dear-github/issues/325

I hit this issue when developing the branch protection code -- Repository.get_branches() does return a list
of branches, but GitHub does not return enough information for the methods on Branch to be useful. If you want to utilise the protection features you must call Repository.get_branch('name').

I hit this issue when developing the branch protection code -- Repository.get_branches() does return a list
of branches, but GitHub does not return enough information for the methods on Branch to be useful. If you want to utilise the protection features you must call Repository.get_branch('name').

Thanks, I hit this issue today, this workaround saved me a lot of time and frustration!

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BBI-YggyKing picture BBI-YggyKing  ·  5Comments

surajjacob picture surajjacob  ·  4Comments

kodeshpa picture kodeshpa  ·  3Comments

psychemedia picture psychemedia  ·  5Comments

xpdable picture xpdable  ·  5Comments