Skip to content

Commit 7d1ba28

Browse files
Fix getting release by tag in lazy mode (#3469)
Getting a release by tag cannot return a lazy release. The URL that is used to fetch the release by tag cannot be used for subsequent requests (like getting assets). The URL first has to be turned into the URL that contains the release id. This requires an API call. Supersedes #3468. Fixes #3467. Co-authored-by: Sebastien NICOT <[email protected]>
1 parent 3a17ecf commit 7d1ba28

4 files changed

Lines changed: 70 additions & 6 deletions

File tree

github/Repository.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3672,10 +3672,12 @@ def get_release(self, id: int | str) -> GitRelease:
36723672
assert isinstance(id, (int, str)), id
36733673
if isinstance(id, int):
36743674
url = f"{self.url}/releases/{id}"
3675+
return github.GitRelease.GitRelease(self._requester, url=url)
36753676
else:
36763677
tag = urllib.parse.quote(id, safe="")
36773678
url = f"{self.url}/releases/tags/{tag}"
3678-
return github.GitRelease.GitRelease(self._requester, url=url)
3679+
# a release by tag cannot be lazy, we need to get the url with release id
3680+
return github.GitRelease.GitRelease(self._requester, url=url).complete()
36793681

36803682
def get_latest_release(self) -> GitRelease:
36813683
"""

tests/GitRelease.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,25 @@ def testLazyAttributes(self):
200200
self.assertEqual(id_release.id, 42)
201201
self.assertEqual(id_release.url, "/repos/lazy/repo/releases/42")
202202

203-
id_release = self.g.withLazy(True).get_repo("lazy/repo").get_release("v42")
204-
self.assertEqual(str(id_release), "GitRelease(name=None)")
205-
self.assertEqual(id_release.tag_name, "v42")
206-
self.assertEqual(id_release.url, "/repos/lazy/repo/releases/tags/v42")
207-
208203
def testGetRelease(self):
209204
release_by_id = self.release
210205
release_by_tag = self.repo.get_release(tag)
211206
self.assertEqual(release_by_id, release_by_tag)
212207

208+
def testGetReleaseByTag(self):
209+
release = self.g.get_repo("EnricoMi/PyGithub").get_release("v1.55")
210+
assets = list(release.get_assets())
211+
self.assertEqual(len(assets), 2)
212+
self.assertEqual(assets[0].name, "asset1.md")
213+
self.assertEqual(assets[1].name, "asset2.gz")
214+
215+
def testGetLazyReleaseByTag(self):
216+
release = self.g.withLazy(True).get_repo("EnricoMi/PyGithub").get_release("v1.55")
217+
assets = list(release.get_assets())
218+
self.assertEqual(len(assets), 2)
219+
self.assertEqual(assets[0].name, "asset1.md")
220+
self.assertEqual(assets[1].name, "asset2.gz")
221+
213222
def testGetLatestRelease(self):
214223
latest_release = self.repo.get_latest_release()
215224
self.assertEqual(latest_release.tag_name, tag)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
https
2+
GET
3+
api.github.com
4+
None
5+
/repos/EnricoMi/PyGithub/releases/tags/v1.55
6+
{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
7+
None
8+
200
9+
[('Date', 'Mon, 23 Mar 2026 20:31:36 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"3f4a76a23708f483c60f4df2840f7b5f0ce3b57e1627434b494bd6fb48fb0816"'), ('Last-Modified', 'Thu, 30 Jan 2025 11:12:00 GMT'), ('github-authentication-token-expiration', '2026-05-16 11:52:29 +0200'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-accepted-github-permissions', 'contents=read'), ('x-github-api-version-selected', '2022-11-28'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, 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', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('Transfer-Encoding', 'chunked'), ('Server', 'github.com'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4993'), ('X-RateLimit-Reset', '1774301230'), ('X-RateLimit-Used', '7'), ('X-RateLimit-Resource', 'core'), ('X-GitHub-Request-Id', 'F876:162E:160795EC:1307CB04:69C1A328')]
10+
{"url":"https://api.github.com/repos/EnricoMi/PyGithub/releases/197548596","assets_url":"https://api.github.com/repos/EnricoMi/PyGithub/releases/197548596/assets","upload_url":"https://uploads.github.com/repos/EnricoMi/PyGithub/releases/197548596/assets{?name,label}","html_url":"https://github.com/EnricoMi/PyGithub/releases/tag/v1.55","id":197548596,"author":{"login":"EnricoMi","id":44700269,"node_id":"MDQ6VXNlcjQ0NzAwMjY5","avatar_url":"https://avatars.githubusercontent.com/u/44700269?v=4","gravatar_id":"","url":"https://api.github.com/users/EnricoMi","html_url":"https://github.com/EnricoMi","followers_url":"https://api.github.com/users/EnricoMi/followers","following_url":"https://api.github.com/users/EnricoMi/following{/other_user}","gists_url":"https://api.github.com/users/EnricoMi/gists{/gist_id}","starred_url":"https://api.github.com/users/EnricoMi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EnricoMi/subscriptions","organizations_url":"https://api.github.com/users/EnricoMi/orgs","repos_url":"https://api.github.com/users/EnricoMi/repos","events_url":"https://api.github.com/users/EnricoMi/events{/privacy}","received_events_url":"https://api.github.com/users/EnricoMi/received_events","type":"User","user_view_type":"public","site_admin":false},"node_id":"MDc6UmVsZWFzZTE5NzU0ODU5Ng==","tag_name":"v1.55","target_commitish":"main","name":"Test Release","draft":false,"immutable":false,"prerelease":true,"created_at":"2021-04-26T04:43:40Z","updated_at":"2025-01-30T11:12:00Z","published_at":"2025-01-30T11:12:00Z","assets":[{"url":"https://api.github.com/repos/EnricoMi/PyGithub/releases/assets/224868540","id":224868540,"node_id":"RA_kwDOGpsAJ84NZzi8","name":"asset1.md","label":null,"uploader":{"login":"EnricoMi","id":44700269,"node_id":"MDQ6VXNlcjQ0NzAwMjY5","avatar_url":"https://avatars.githubusercontent.com/u/44700269?v=4","gravatar_id":"","url":"https://api.github.com/users/EnricoMi","html_url":"https://github.com/EnricoMi","followers_url":"https://api.github.com/users/EnricoMi/followers","following_url":"https://api.github.com/users/EnricoMi/following{/other_user}","gists_url":"https://api.github.com/users/EnricoMi/gists{/gist_id}","starred_url":"https://api.github.com/users/EnricoMi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EnricoMi/subscriptions","organizations_url":"https://api.github.com/users/EnricoMi/orgs","repos_url":"https://api.github.com/users/EnricoMi/repos","events_url":"https://api.github.com/users/EnricoMi/events{/privacy}","received_events_url":"https://api.github.com/users/EnricoMi/received_events","type":"User","user_view_type":"public","site_admin":false},"content_type":"text/markdown","state":"uploaded","size":2524,"digest":null,"download_count":39,"created_at":"2025-01-30T11:11:32Z","updated_at":"2025-01-30T11:12:00Z","browser_download_url":"https://github.com/EnricoMi/PyGithub/releases/download/v1.55/asset1.md"},{"url":"https://api.github.com/repos/EnricoMi/PyGithub/releases/assets/224868556","id":224868556,"node_id":"RA_kwDOGpsAJ84NZzjM","name":"asset2.gz","label":null,"uploader":{"login":"EnricoMi","id":44700269,"node_id":"MDQ6VXNlcjQ0NzAwMjY5","avatar_url":"https://avatars.githubusercontent.com/u/44700269?v=4","gravatar_id":"","url":"https://api.github.com/users/EnricoMi","html_url":"https://github.com/EnricoMi","followers_url":"https://api.github.com/users/EnricoMi/followers","following_url":"https://api.github.com/users/EnricoMi/following{/other_user}","gists_url":"https://api.github.com/users/EnricoMi/gists{/gist_id}","starred_url":"https://api.github.com/users/EnricoMi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EnricoMi/subscriptions","organizations_url":"https://api.github.com/users/EnricoMi/orgs","repos_url":"https://api.github.com/users/EnricoMi/repos","events_url":"https://api.github.com/users/EnricoMi/events{/privacy}","received_events_url":"https://api.github.com/users/EnricoMi/received_events","type":"User","user_view_type":"public","site_admin":false},"content_type":"application/gzip","state":"uploaded","size":1199,"digest":null,"download_count":31,"created_at":"2025-01-30T11:11:37Z","updated_at":"2025-01-30T11:12:00Z","browser_download_url":"https://github.com/EnricoMi/PyGithub/releases/download/v1.55/asset2.gz"}],"tarball_url":"https://api.github.com/repos/EnricoMi/PyGithub/tarball/v1.55","zipball_url":"https://api.github.com/repos/EnricoMi/PyGithub/zipball/v1.55","body":"This is a test released used by PyGithub tests."}
11+
12+
https
13+
GET
14+
api.github.com
15+
None
16+
/repos/EnricoMi/PyGithub/releases/197548596/assets
17+
{'Authorization': 'token private_token_removed', 'User-Agent': 'PyGithub/Python'}
18+
None
19+
200
20+
[('Date', 'Mon, 23 Mar 2026 20:31:37 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"02f2c96627cfc5be40bfaaa25813a5dc4b58711b13a846cb8d3c526b81ede7b1"'), ('github-authentication-token-expiration', '2026-05-16 11:52:29 +0200'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-accepted-github-permissions', 'contents=read'), ('x-github-api-version-selected', '2022-11-28'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, 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', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('Transfer-Encoding', 'chunked'), ('Server', 'github.com'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4992'), ('X-RateLimit-Reset', '1774301230'), ('X-RateLimit-Used', '8'), ('X-RateLimit-Resource', 'core'), ('X-GitHub-Request-Id', 'F0E4:1633:B919C6:9A117B:69C1A328')]
21+
[{"url":"https://api.github.com/repos/EnricoMi/PyGithub/releases/assets/224868540","id":224868540,"node_id":"RA_kwDOGpsAJ84NZzi8","name":"asset1.md","label":null,"uploader":{"login":"EnricoMi","id":44700269,"node_id":"MDQ6VXNlcjQ0NzAwMjY5","avatar_url":"https://avatars.githubusercontent.com/u/44700269?v=4","gravatar_id":"","url":"https://api.github.com/users/EnricoMi","html_url":"https://github.com/EnricoMi","followers_url":"https://api.github.com/users/EnricoMi/followers","following_url":"https://api.github.com/users/EnricoMi/following{/other_user}","gists_url":"https://api.github.com/users/EnricoMi/gists{/gist_id}","starred_url":"https://api.github.com/users/EnricoMi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EnricoMi/subscriptions","organizations_url":"https://api.github.com/users/EnricoMi/orgs","repos_url":"https://api.github.com/users/EnricoMi/repos","events_url":"https://api.github.com/users/EnricoMi/events{/privacy}","received_events_url":"https://api.github.com/users/EnricoMi/received_events","type":"User","user_view_type":"public","site_admin":false},"content_type":"text/markdown","state":"uploaded","size":2524,"digest":null,"download_count":39,"created_at":"2025-01-30T11:11:32Z","updated_at":"2025-01-30T11:12:00Z","browser_download_url":"https://github.com/EnricoMi/PyGithub/releases/download/v1.55/asset1.md"},{"url":"https://api.github.com/repos/EnricoMi/PyGithub/releases/assets/224868556","id":224868556,"node_id":"RA_kwDOGpsAJ84NZzjM","name":"asset2.gz","label":null,"uploader":{"login":"EnricoMi","id":44700269,"node_id":"MDQ6VXNlcjQ0NzAwMjY5","avatar_url":"https://avatars.githubusercontent.com/u/44700269?v=4","gravatar_id":"","url":"https://api.github.com/users/EnricoMi","html_url":"https://github.com/EnricoMi","followers_url":"https://api.github.com/users/EnricoMi/followers","following_url":"https://api.github.com/users/EnricoMi/following{/other_user}","gists_url":"https://api.github.com/users/EnricoMi/gists{/gist_id}","starred_url":"https://api.github.com/users/EnricoMi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EnricoMi/subscriptions","organizations_url":"https://api.github.com/users/EnricoMi/orgs","repos_url":"https://api.github.com/users/EnricoMi/repos","events_url":"https://api.github.com/users/EnricoMi/events{/privacy}","received_events_url":"https://api.github.com/users/EnricoMi/received_events","type":"User","user_view_type":"public","site_admin":false},"content_type":"application/gzip","state":"uploaded","size":1199,"digest":null,"download_count":31,"created_at":"2025-01-30T11:11:37Z","updated_at":"2025-01-30T11:12:00Z","browser_download_url":"https://github.com/EnricoMi/PyGithub/releases/download/v1.55/asset2.gz"}]

0 commit comments

Comments
 (0)