1111
1212# SPDX-License-Identifier: BSD-3-Clause
1313
14+ from __future__ import annotations
15+
1416import functools
1517import re
1618import shlex
2426from datetime import datetime , timedelta , timezone
2527from pathlib import Path
2628from subprocess import CompletedProcess
27- from typing import Callable , NamedTuple , Optional
29+ from typing import Any , Callable , NamedTuple , NoReturn , Optional
2830
2931import __main__
3032import rich .traceback
4143rich .traceback .install ()
4244
4345
46+ def validate_stage_name (stage_name : str ) -> None :
47+ """
48+ Validate a stage name.
49+
50+ Ensure a stage name consists of only lowercase letters. This is
51+ both to simplify implementation details within the
52+ :class:`StagedScript` class, and to provide the best user experience
53+ for users of your :class:`StagedScript` subclasses.
54+
55+ Args:
56+ stage_name: The name of the stage.
57+
58+ Raises:
59+ ValueError: If the stage name is invalid.
60+ """
61+ if not re .match ("^[a-z]+$" , stage_name ):
62+ message = (
63+ f"Stage name { stage_name !r} must contain only lowercase letters."
64+ )
65+ raise ValueError (message )
66+
67+
4468class StagedScript :
4569 """
4670 The base class for all staged scripts.
@@ -121,7 +145,7 @@ def __init__(
121145 console_force_terminal : Optional [bool ] = None ,
122146 console_log_path : bool = True ,
123147 print_commands : bool = True ,
124- ):
148+ ) -> None :
125149 """
126150 Initialize a :class:`StagedScript` object.
127151
@@ -145,7 +169,7 @@ def __init__(
145169 and optionally pass in additional arguments.
146170 """
147171 for stage in stages :
148- self . _validate_stage_name (stage )
172+ validate_stage_name (stage )
149173 self .args = Namespace ()
150174 self .commands_executed : list [str ] = []
151175 self .console = Console (
@@ -163,29 +187,6 @@ def __init__(
163187 self .stages_to_run : set [str ] = set ()
164188 self .start_time = datetime .now (tz = timezone .utc )
165189
166- @staticmethod
167- def _validate_stage_name (stage_name : str ) -> None :
168- """
169- Validate the stage name.
170-
171- Ensure the stage name consists of only lowercase letters. This
172- is both to simplify implementation details within the class, and
173- to provide the best user experience for users of your
174- :class:`StagedScript` subclasses.
175-
176- Args:
177- stage_name: The name of the stage.
178-
179- Raises:
180- ValueError: If the stage name is invalid.
181- """
182- if not re .match ("^[a-z]+$" , stage_name ):
183- message = (
184- f"Stage name { stage_name !r} must contain only lowercase "
185- "letters."
186- )
187- raise ValueError (message )
188-
189190 #
190191 # The `stage` decorator.
191192 #
@@ -243,13 +244,11 @@ def stage(stage_name: str, heading: str) -> Callable:
243244 heading: A heading message to print indicating what will
244245 happen in the stage.
245246 """
246- __class__ ._validate_stage_name ( # type: ignore[name-defined]
247- stage_name
248- )
247+ validate_stage_name (stage_name )
249248
250249 def decorator (func : Callable ) -> Callable :
251250 def get_phase_method ( # noqa: D417
252- self ,
251+ self , # noqa: ANN001
253252 method_name : str ,
254253 ) -> Callable :
255254 """
@@ -274,9 +273,9 @@ def get_phase_method( # noqa: D417
274273 )
275274
276275 def run_retryable_phases ( # noqa: D417
277- self ,
278- * args ,
279- ** kwargs ,
276+ self , # noqa: ANN001
277+ * args : Any , # noqa: ANN401
278+ ** kwargs : Any , # noqa: ANN401
280279 ) -> None :
281280 """
282281 Run the retryable phases.
@@ -311,7 +310,7 @@ def run_retryable_phases( # noqa: D417
311310 get_phase_method (self , "_end_stage" )()
312311
313312 @functools .wraps (func )
314- def wrapper (self , * args , ** kwargs ) -> None :
313+ def wrapper (self , * args : Any , ** kwargs : Any ) -> None : # noqa: ANN001, ANN401
315314 """
316315 Turn a function into a stage.
317316
@@ -365,7 +364,6 @@ def _run_pre_stage_actions(self) -> None:
365364 were met before attempting the stage, and erroring out
366365 appropriately if not.
367366 """
368- pass
369367
370368 def _begin_stage (self , heading : str ) -> None :
371369 """
@@ -495,7 +493,6 @@ def _run_post_stage_actions(self) -> None:
495493 were met before moving on, and erroring out appropriately if
496494 not.
497495 """
498- pass
499496
500497 def _prepare_to_retry_stage (self , retry_state : RetryCallState ) -> None :
501498 """
@@ -762,7 +759,7 @@ def parse_args(self, argv: list[str]) -> None:
762759 ]:
763760 setattr (self , retry_arg , getattr (self .args , retry_arg , None ))
764761
765- def raise_parser_error (self , message ) :
762+ def raise_parser_error (self , message : str ) -> NoReturn :
766763 """
767764 Raise a parser error.
768765
@@ -791,7 +788,7 @@ def run(
791788 * ,
792789 pretty_print : bool = False ,
793790 print_command : Optional [bool ] = None ,
794- ** kwargs ,
791+ ** kwargs : Any , # noqa: ANN401
795792 ) -> CompletedProcess :
796793 """
797794 Run a command in the underlying shell.
@@ -1023,8 +1020,6 @@ class RetryStage(TryAgain):
10231020 that a stage should be retried.
10241021 """
10251022
1026- pass
1027-
10281023
10291024class HelpFormatter (
10301025 ArgumentDefaultsHelpFormatter , RawDescriptionHelpFormatter
@@ -1036,5 +1031,3 @@ class HelpFormatter(
10361031 treats the description as raw text (doesn't do any automatic
10371032 formatting) and shows default values of arguments.
10381033 """
1039-
1040- pass
0 commit comments