Repository navigation
Expand file tree
/
Copy pathgithub.py
More file actions
120 lines (85 loc) · 2.62 KB
/
Copy pathgithub.py
File metadata and controls
120 lines (85 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# -*- coding: utf-8 -*-
"""
Created on Sun Aug 2 15:53:05 2026
@author: mark
"""
import re
from dataclasses import dataclass
import requests
# Base URL for the GitHub REST API
GITHUB_API = "https://api.github.com"
# ----------------------------------------------------------------------
# Asset Object
# ----------------------------------------------------------------------
@dataclass
class GithubAsset:
"""
Represents a downloadable file from a GitHub release.
"""
name: str
download_url: str
size: int
# ----------------------------------------------------------------------
# Release Object
# ----------------------------------------------------------------------
@dataclass
class GithubRelease:
"""
Represents the latest GitHub release.
"""
tag: str
name: str
published: str
assets: list[GithubAsset]
# ----------------------------------------------------------------------
# Exception
# ----------------------------------------------------------------------
class GithubError(Exception):
pass
# ----------------------------------------------------------------------
# GitHub Client
# ----------------------------------------------------------------------
class GithubClient:
def __init__(self, timeout=30):
self.timeout = timeout
def latest_release(self, repository: str) -> GithubRelease:
"""
Download information about the latest release.
"""
url = f"{GITHUB_API}/repos/{repository}/releases/latest"
response = requests.get(url, timeout=self.timeout)
if response.status_code != 200:
raise GithubError(
f"GitHub returned HTTP {response.status_code}"
)
data = response.json()
assets = []
for asset in data.get("assets", []):
assets.append(
GithubAsset(
name=asset["name"],
download_url=asset["browser_download_url"],
size=asset["size"]
)
)
return GithubRelease(
tag=data["tag_name"],
name=data["name"],
published=data["published_at"],
assets=assets
)
def find_asset(
self,
release: GithubRelease,
regex: str
) -> GithubAsset:
"""
Search the release for an asset matching the supplied regex.
"""
pattern = re.compile(regex)
for asset in release.assets:
if pattern.match(asset.name):
return asset
raise GithubError(
f"No asset matched '{regex}'"
)