1
1
import asyncio
2
2
import json
3
3
from dataclasses import dataclass
4
- from typing import Any , Dict , List , Optional , Union
4
+ from typing import Any , cast
5
5
6
6
from aiohttp .client import ClientSession
7
7
8
+ JSON = dict [str , Any ]
9
+
8
10
9
11
@dataclass
10
12
class Builder :
11
13
builderid : int
12
- description : Optional [ str ]
13
- masterids : List [int ]
14
+ description : str | None
15
+ masterids : list [int ]
14
16
name : str
15
- tags : List [str ]
17
+ tags : list [str ]
16
18
17
- def __init__ (self , ** kwargs ) -> None :
19
+ def __init__ (self , ** kwargs : Any ) -> None :
18
20
self .__dict__ .update (** kwargs )
19
21
20
22
def __hash__ (self ) -> int :
@@ -25,15 +27,17 @@ def __hash__(self) -> int:
25
27
class Build :
26
28
id : int
27
29
is_currently_failing : bool
30
+ builderid : int
31
+ builder : Builder | None
28
32
29
- def __init__ (self , ** kwargs ) :
33
+ def __init__ (self , ** kwargs : Any ) -> None :
30
34
self .__dict__ .update (** kwargs )
31
- self .id = kwargs .get ("number" )
32
- self .is_currently_failing = kwargs .get ("currently_failing" )
35
+ self .id = int ( kwargs .get ("number" , - 1 ) )
36
+ self .is_currently_failing = kwargs .get ("currently_failing" , False )
33
37
self .builder = None
34
38
35
- def __eq__ (self , other ) :
36
- return self .id == other .id
39
+ def __eq__ (self , other : object ) -> bool :
40
+ return isinstance ( other , Build ) and self .id == other .id
37
41
38
42
def __hash__ (self ) -> int :
39
43
return hash (self .id )
@@ -52,37 +56,30 @@ async def _fetch_text(self, url: str) -> str:
52
56
async with self ._session .get (url ) as resp :
53
57
return await resp .text ()
54
58
55
- async def _fetch_json (self , url : str ) -> Dict [
56
- str ,
57
- Union [
58
- List [Dict [str , Union [int , bool , str ]]],
59
- Dict [str , int ],
60
- List [Dict [str , Optional [Union [int , List [int ], str , List [str ]]]]],
61
- ],
62
- ]:
63
- return json .loads (await self ._fetch_text (url ))
64
-
65
- async def stable_builders (self , branch : Optional [str ]) -> Dict [int , Builder ]:
59
+ async def _fetch_json (self , url : str ) -> JSON :
60
+ return cast (JSON , json .loads (await self ._fetch_text (url )))
61
+
62
+ async def stable_builders (self , branch : str | None = None ) -> dict [int , Builder ]:
66
63
stable_builders = {
67
64
id : builder
68
65
for (id , builder ) in (await self .all_builders (branch = branch )).items ()
69
66
if "stable" in builder .tags
70
67
}
71
68
return stable_builders
72
69
73
- async def all_builders (self , branch : Optional [ str ] = None ) -> Dict [int , Builder ]:
70
+ async def all_builders (self , branch : str | None = None ) -> dict [int , Builder ]:
74
71
url = "https://buildbot.python.org/all/api/v2/builders"
75
72
if branch is not None :
76
73
url = f"{ url } ?tags__contains={ branch } "
77
- _builders : Dict [str , Any ] = await self ._fetch_json (url )
74
+ _builders : dict [str , Any ] = await self ._fetch_json (url )
78
75
builders = _builders ["builders" ]
79
76
all_builders = {
80
77
builder ["builderid" ]: Builder (** builder ) for builder in builders
81
78
}
82
79
return all_builders
83
80
84
81
async def is_builder_failing_currently (self , builder : Builder ) -> bool :
85
- builds_ : Dict [str , Any ] = await self ._fetch_json (
82
+ builds_ : dict [str , Any ] = await self ._fetch_json (
86
83
f"https://buildbot.python.org/all/api/v2/builds?complete__eq=true"
87
84
f"&&builderid__eq={ builder .builderid } &&order=-complete_at"
88
85
f"&&limit=1"
@@ -95,13 +92,13 @@ async def is_builder_failing_currently(self, builder: Builder) -> bool:
95
92
return True
96
93
return False
97
94
98
- async def get_build (self , builder_id , build_id ) :
95
+ async def get_build (self , builder_id : int , build_id : int ) -> Build :
99
96
data = await self ._fetch_json (
100
97
f"https://buildbot.python.org/all/api/v2/builders/{ builder_id } "
101
98
f"/builds/{ build_id } "
102
99
)
103
100
(build_data ,) = data ["builds" ]
104
- build = Build (** build_data )
101
+ build : Build = Build (** build_data )
105
102
build .builder = (await self .all_builders ())[build .builderid ]
106
103
build .is_currently_failing = await self .is_builder_failing_currently (
107
104
build .builder
@@ -126,7 +123,8 @@ async def get_recent_failures(self, limit: int = 100) -> set[Build]:
126
123
for failure in all_failures :
127
124
failure .builder = stable_builders [failure .builderid ]
128
125
129
- async def _get_missing_info (failure ):
126
+ async def _get_missing_info (failure : Build ) -> None :
127
+ assert failure .builder is not None
130
128
failure .is_currently_failing = await self .is_builder_failing_currently (
131
129
failure .builder
132
130
)
0 commit comments