4
4
5
5
Original code by Pablo Galindo
6
6
"""
7
+ from __future__ import annotations
7
8
8
9
import argparse
9
10
import asyncio
23
24
import urllib .request
24
25
from dataclasses import dataclass
25
26
from shelve import DbfilenameShelf
26
- from typing import Callable , Iterator , List , Optional
27
+ from typing import Any , Callable , Generator , Iterator
27
28
28
29
import aiohttp
29
30
import gnupg
33
34
34
35
import release as release_mod
35
36
import sbom
36
- from buildbotapi import BuildBotAPI
37
+ from buildbotapi import BuildBotAPI , Builder
37
38
38
39
API_KEY_REGEXP = re .compile (r"(?P<major>\w+):(?P<minor>\w+)" )
39
40
@@ -184,7 +185,7 @@ class Task:
184
185
function : Callable [[DbfilenameShelf ], None ]
185
186
description : str
186
187
187
- def __call__ (self , db : DbfilenameShelf ) -> None :
188
+ def __call__ (self , db : DbfilenameShelf ) -> Any :
188
189
return getattr (self , "function" )(db )
189
190
190
191
@@ -195,13 +196,13 @@ class ReleaseException(Exception):
195
196
class ReleaseDriver :
196
197
def __init__ (
197
198
self ,
198
- tasks : List [Task ],
199
+ tasks : list [Task ],
199
200
* ,
200
201
release_tag : release_mod .Tag ,
201
202
git_repo : str ,
202
203
api_key : str ,
203
204
ssh_user : str ,
204
- first_state : Optional [ Task ] = None ,
205
+ first_state : Task | None = None ,
205
206
) -> None :
206
207
self .tasks = tasks
207
208
dbfile = pathlib .Path .home () / ".python_release"
@@ -212,7 +213,7 @@ def __init__(
212
213
self .db .close ()
213
214
self .db = shelve .open (str (dbfile ), "n" )
214
215
215
- self .current_task : Optional [ Task ] = first_state
216
+ self .current_task : Task | None = first_state
216
217
self .completed_tasks = self .db .get ("completed_tasks" , [])
217
218
self .remaining_tasks = iter (tasks [len (self .completed_tasks ) :])
218
219
if self .db .get ("gpg_key" ):
@@ -282,7 +283,7 @@ def cd(path: str) -> Iterator[None]:
282
283
283
284
284
285
@contextlib .contextmanager
285
- def supress_print ():
286
+ def supress_print () -> Generator [ None , None , None ] :
286
287
print_func = builtins .print
287
288
builtins .print = lambda * args , ** kwargs : None
288
289
yield
@@ -333,8 +334,10 @@ def check_ssh_connection(db: DbfilenameShelf) -> None:
333
334
334
335
335
336
def check_buildbots (db : DbfilenameShelf ) -> None :
336
- async def _check ():
337
- async def _get_builder_status (buildbot_api , the_builder ):
337
+ async def _check () -> set [Builder ]:
338
+ async def _get_builder_status (
339
+ buildbot_api : BuildBotAPI , the_builder : Builder
340
+ ) -> tuple [Builder , bool ]:
338
341
return the_builder , await buildbot_api .is_builder_failing_currently (
339
342
the_builder
340
343
)
@@ -567,7 +570,7 @@ def build_sbom_artifacts(db):
567
570
568
571
569
572
class MySFTPClient (paramiko .SFTPClient ):
570
- def put_dir (self , source , target , progress = None ):
573
+ def put_dir (self , source : str , target : str , progress : Any = None ) -> None :
571
574
for item in os .listdir (source ):
572
575
if os .path .isfile (os .path .join (source , item )):
573
576
progress .text (item )
@@ -581,7 +584,7 @@ def put_dir(self, source, target, progress=None):
581
584
progress = progress ,
582
585
)
583
586
584
- def mkdir (self , path , mode = 511 , ignore_existing = False ):
587
+ def mkdir (self , path : str , mode : int = 511 , ignore_existing : bool = False ) -> None :
585
588
try :
586
589
super ().mkdir (path , mode )
587
590
except OSError :
@@ -609,7 +612,7 @@ def upload_files_to_server(db: DbfilenameShelf) -> None:
609
612
610
613
shutil .rmtree (artifacts_path / f"Python-{ db ['release' ]} " , ignore_errors = True )
611
614
612
- def upload_subdir (subdir ) :
615
+ def upload_subdir (subdir : str ) -> None :
613
616
with contextlib .suppress (OSError ):
614
617
ftp_client .mkdir (str (destination / subdir ))
615
618
with alive_bar (len (tuple ((artifacts_path / subdir ).glob ("**/*" )))) as progress :
@@ -636,7 +639,7 @@ def place_files_in_download_folder(db: DbfilenameShelf) -> None:
636
639
source = f"/home/psf-users/{ db ['ssh_user' ]} /{ db ['release' ]} "
637
640
destination = f"/srv/www.python.org/ftp/python/{ db ['release' ].normalized ()} "
638
641
639
- def execute_command (command ) :
642
+ def execute_command (command : str ) -> None :
640
643
channel = client .get_transport ().open_session ()
641
644
channel .exec_command (command )
642
645
if channel .recv_exit_status () != 0 :
@@ -655,7 +658,7 @@ def execute_command(command):
655
658
source = f"/home/psf-users/{ db ['ssh_user' ]} /{ db ['release' ]} "
656
659
destination = f"/srv/www.python.org/ftp/python/doc/{ release_tag } "
657
660
658
- def execute_command (command ) :
661
+ def execute_command (command : str ) -> None :
659
662
channel = client .get_transport ().open_session ()
660
663
channel .exec_command (command )
661
664
if channel .recv_exit_status () != 0 :
@@ -690,7 +693,7 @@ def upload_docs_to_the_docs_server(db: DbfilenameShelf) -> None:
690
693
691
694
shutil .rmtree (artifacts_path / f"Python-{ db ['release' ]} " , ignore_errors = True )
692
695
693
- def upload_subdir (subdir ) :
696
+ def upload_subdir (subdir : str ) -> None :
694
697
with contextlib .suppress (OSError ):
695
698
ftp_client .mkdir (str (destination / subdir ))
696
699
with alive_bar (len (tuple ((artifacts_path / subdir ).glob ("**/*" )))) as progress :
@@ -719,7 +722,7 @@ def unpack_docs_in_the_docs_server(db: DbfilenameShelf) -> None:
719
722
source = f"/home/psf-users/{ db ['ssh_user' ]} /{ db ['release' ]} "
720
723
destination = f"/srv/docs.python.org/release/{ release_tag } "
721
724
722
- def execute_command (command ) :
725
+ def execute_command (command : str ) -> None :
723
726
channel = client .get_transport ().open_session ()
724
727
channel .exec_command (command )
725
728
if channel .recv_exit_status () != 0 :
@@ -926,8 +929,6 @@ def modify_the_release_to_the_prerelease_pages(db: DbfilenameShelf) -> None:
926
929
927
930
928
931
def post_release_merge (db : DbfilenameShelf ) -> None :
929
- release_tag : release_mod .Tag = db ["release" ]
930
-
931
932
subprocess .check_call (
932
933
["git" , "fetch" , "--all" ],
933
934
cwd = db ["git_repo" ],
@@ -1031,7 +1032,7 @@ def is_mirror(repo: pathlib.Path, remote: str) -> bool:
1031
1032
1032
1033
1033
1034
def push_to_local_fork (db : DbfilenameShelf ) -> None :
1034
- def _push_to_local (dry_run = False ):
1035
+ def _push_to_local (dry_run : bool = False ) -> None :
1035
1036
git_command = ["git" , "push" ]
1036
1037
if dry_run :
1037
1038
git_command .append ("--dry-run" )
@@ -1057,7 +1058,7 @@ def _push_to_local(dry_run=False):
1057
1058
def push_to_upstream (db : DbfilenameShelf ) -> None :
1058
1059
release_tag : release_mod .Tag = db ["release" ]
1059
1060
1060
- def _push_to_upstream (dry_run = False ):
1061
+ def _push_to_upstream (dry_run : bool = False ) -> None :
1061
1062
branch = f"{ release_tag .major } .{ release_tag .minor } "
1062
1063
git_command = ["git" , "push" ]
1063
1064
if dry_run :
@@ -1112,7 +1113,7 @@ def main() -> None:
1112
1113
1113
1114
parser = argparse .ArgumentParser (description = "Process some integers." )
1114
1115
1115
- def _release_type (release ) :
1116
+ def _release_type (release : str ) -> str :
1116
1117
if not RELEASE_REGEXP .match (release ):
1117
1118
raise argparse .ArgumentTypeError ("Invalid release string" )
1118
1119
return release
@@ -1132,7 +1133,7 @@ def _release_type(release):
1132
1133
type = str ,
1133
1134
)
1134
1135
1135
- def _api_key (api_key ) :
1136
+ def _api_key (api_key : str ) -> str :
1136
1137
if not API_KEY_REGEXP .match (api_key ):
1137
1138
raise argparse .ArgumentTypeError (
1138
1139
"Invalid api key format. It must be on the form USER:API_KEY"
0 commit comments