From 5f7b06329b07dfdc8a773889bf5c9ee8c910ac59 Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:20:35 -0600 Subject: [PATCH 1/8] test: Rename test fixtures Remove acronyms for clarity. --- test/test_staged_script.py | 110 ++++++++++--------- test/test_staged_script_advanced_subclass.py | 32 +++--- test/test_staged_script_basic_subclass.py | 26 +++-- 3 files changed, 88 insertions(+), 80 deletions(-) diff --git a/test/test_staged_script.py b/test/test_staged_script.py index ea47394..a715be0 100644 --- a/test/test_staged_script.py +++ b/test/test_staged_script.py @@ -15,7 +15,7 @@ @pytest.fixture() -def ds() -> StagedScript: +def script() -> StagedScript: """Create a :class:`StagedScript` object to be used by tests.""" staged_script = StagedScript(set()) staged_script.console = Console(log_time=False, log_path=False) @@ -23,12 +23,12 @@ def ds() -> StagedScript: def test_print_dry_run_message( - ds: StagedScript, capsys: pytest.CaptureFixture + script: StagedScript, capsys: pytest.CaptureFixture ) -> None: """Test the :func:`print_dry_run_message` method.""" message = "dry run message" expected = f"DRY-RUN MODE: {message}" - ds.print_dry_run_message(message) + script.print_dry_run_message(message) captured = capsys.readouterr() assert expected in captured.out @@ -51,30 +51,36 @@ def test_validate_stage_name_raises(stage_name: str) -> None: StagedScript._validate_stage_name(stage_name) -def test__begin_stage(ds: StagedScript, capsys: pytest.CaptureFixture) -> None: +def test__begin_stage( + script: StagedScript, capsys: pytest.CaptureFixture +) -> None: """Test the :func:`_begin_stage` method.""" message = "begin stage" - ds._begin_stage(message) + script._begin_stage(message) captured = capsys.readouterr() assert message in captured.out - assert ds.stage_start_time is not None + assert script.stage_start_time is not None -def test__end_stage(ds: StagedScript, capsys: pytest.CaptureFixture) -> None: +def test__end_stage( + script: StagedScript, capsys: pytest.CaptureFixture +) -> None: """Test the :func:`_end_stage` method.""" stage_name = "test" - ds.current_stage = stage_name - ds.stage_start_time = datetime.now(tz=timezone.utc) - ds._end_stage() + script.current_stage = stage_name + script.stage_start_time = datetime.now(tz=timezone.utc) + script._end_stage() captured = capsys.readouterr() - assert stage_name in [_.stage for _ in ds.durations] + assert stage_name in [_.stage for _ in script.durations] assert "duration:" in captured.out - assert str(ds.durations[-1].duration) in captured.out + assert str(script.durations[-1].duration) in captured.out -def test__skip_stage(ds: StagedScript, capsys: pytest.CaptureFixture) -> None: +def test__skip_stage( + script: StagedScript, capsys: pytest.CaptureFixture +) -> None: """Test the :func:`_skip_stage` method.""" - ds._skip_stage() + script._skip_stage() captured = capsys.readouterr() assert "Skipping this stage." in captured.out @@ -84,18 +90,18 @@ def test__skip_stage(ds: StagedScript, capsys: pytest.CaptureFixture) -> None: def test__handle_stage_retry_error( mock_Retrying: MagicMock, retry_attempts: int, - ds: StagedScript, + script: StagedScript, capsys: pytest.CaptureFixture, ) -> None: """Test the :func:`_handle_stage_retry_error` method.""" - ds.current_stage = "test" - ds.test_retry_attempts = retry_attempts + script.current_stage = "test" + script.test_retry_attempts = retry_attempts retry = mock_Retrying() retry.statistics = { "delay_since_first_attempt": 1234, "attempt_number": retry_attempts, } - ds._handle_stage_retry_error(retry) + script._handle_stage_retry_error(retry) captured = capsys.readouterr() if retry_attempts == 0: assert captured.out == "" @@ -113,14 +119,14 @@ def test__handle_stage_retry_error( @patch("tenacity.RetryCallState") def test__prepare_to_retry_stage( mock_RetryCallState: MagicMock, - ds: StagedScript, + script: StagedScript, capsys: pytest.CaptureFixture, ) -> None: """Test the :func:`_prepare_to_retry_stage` method.""" - ds.current_stage = "test" + script.current_stage = "test" retry_state = mock_RetryCallState() retry_state.__repr__ = lambda self: "mock_RetryCallState.__repr__" - ds._prepare_to_retry_stage(retry_state) + script._prepare_to_retry_stage(retry_state) captured = capsys.readouterr() for text in [ "Preparing to retry the 'test' stage...", @@ -130,10 +136,10 @@ def test__prepare_to_retry_stage( def test_get_timing_report( - ds: StagedScript, capsys: pytest.CaptureFixture + script: StagedScript, capsys: pytest.CaptureFixture ) -> None: """Test the :func:`_get_timing_report` method.""" - ds.durations = [ + script.durations = [ StageDuration( "first", timedelta(hours=1, minutes=2, seconds=3, microseconds=4) @@ -143,11 +149,11 @@ def test_get_timing_report( timedelta(hours=4, minutes=3, seconds=2, microseconds=1) ) ] # yapf: disable - ds.console.print(ds._get_timing_report()) + script.console.print(script._get_timing_report()) captured = capsys.readouterr() - for stage in [_.stage for _ in ds.durations]: + for stage in [_.stage for _ in script.durations]: assert stage in captured.out - for duration in [_.duration for _ in ds.durations]: + for duration in [_.duration for _ in script.durations]: assert str(duration) in captured.out assert "Total" in captured.out @@ -165,18 +171,18 @@ def test_get_timing_report( ], ) def test_pretty_print_command( - command: str, expected: str, ds: StagedScript + command: str, expected: str, script: StagedScript ) -> None: """Test the :func:`pretty_print_command` method.""" - assert ds.pretty_print_command(command) == expected + assert script.pretty_print_command(command) == expected -def test_parse_args(ds: StagedScript) -> None: +def test_parse_args(script: StagedScript) -> None: """Test the :func:`parse_args` method.""" - ds.stages = {"first", "second", "third"} - ds.parse_args(shlex.split("--dry-run --stage first third")) - assert ds.dry_run is True - assert ds.stages_to_run == {"first", "third"} + script.stages = {"first", "second", "third"} + script.parse_args(shlex.split("--dry-run --stage first third")) + assert script.dry_run is True + assert script.stages_to_run == {"first", "third"} @pytest.mark.parametrize("print_commands", [True, False]) @@ -184,34 +190,34 @@ def test_parse_args(ds: StagedScript) -> None: def test_run( mock_run: MagicMock, print_commands: bool, # noqa: FBT001 - ds: StagedScript, + script: StagedScript, capsys: pytest.CaptureFixture, ) -> None: """Test the :func:`run` method.""" command = "echo 'hello world'" mock_run.return_value = CompletedProcess(args=command, returncode=0) - ds.print_commands = print_commands - ds.run(command) + script.print_commands = print_commands + script.run(command) captured = capsys.readouterr() if print_commands: assert f"Executing: {command}" in captured.out else: assert f"Executing: {command}" not in captured.out - assert command in ds.commands_executed + assert command in script.commands_executed @patch("subprocess.run") def test_run_override_print_commands( - mock_run: MagicMock, ds: StagedScript, capsys: pytest.CaptureFixture + mock_run: MagicMock, script: StagedScript, capsys: pytest.CaptureFixture ) -> None: """Ensure :func:`run` prints the command executed when appropriate.""" command = "echo 'hello world'" mock_run.return_value = CompletedProcess(args=command, returncode=0) - ds.run(command, print_command=False) + script.run(command, print_command=False) captured = capsys.readouterr() assert f"Executing: {command}" not in captured.out - ds.print_commands = False - ds.run(command, print_command=True) + script.print_commands = False + script.run(command, print_command=True) captured = capsys.readouterr() assert f"Executing: {command}" in captured.out @@ -235,14 +241,14 @@ def test_print_script_execution_summary( mock_get_pretty_command_line_invocation: MagicMock, extras: dict[str, str] | None, script_success: bool, # noqa: FBT001 - ds: StagedScript, + script: StagedScript, capsys: pytest.CaptureFixture, ) -> None: """Test the :func:`print_script_execution_summary` method.""" mock_get_pretty_command_line_invocation.return_value = ( "command line invocation" ) - ds.durations = [ + script.durations = [ StageDuration( "first", timedelta(hours=1, minutes=2, seconds=3, microseconds=4) @@ -252,12 +258,12 @@ def test_print_script_execution_summary( timedelta(hours=4, minutes=3, seconds=2, microseconds=1) ) ] # yapf: disable - ds.commands_executed = ["foo", "bar", "baz"] - ds.script_success = script_success + script.commands_executed = ["foo", "bar", "baz"] + script.script_success = script_success if extras is None: - ds.print_script_execution_summary() + script.print_script_execution_summary() else: - ds.print_script_execution_summary(extra_sections=extras) + script.print_script_execution_summary(extra_sections=extras) captured = capsys.readouterr() headings = [ "Ran the following", @@ -267,9 +273,9 @@ def test_print_script_execution_summary( ] details = ( [mock_get_pretty_command_line_invocation.return_value] - + ds.commands_executed - + [_.stage for _ in ds.durations] - + [str(_.duration) for _ in ds.durations] + + script.commands_executed + + [_.stage for _ in script.durations] + + [str(_.duration) for _ in script.durations] + ["Success" if script_success else "Failure"] ) # yapf: disable if extras is not None: @@ -280,7 +286,7 @@ def test_print_script_execution_summary( def test_raise_parser_error( - ds: StagedScript, capsys: pytest.CaptureFixture + script: StagedScript, capsys: pytest.CaptureFixture ) -> None: """Test the :func:`raise_parser_error` method.""" error_message = ( @@ -289,7 +295,7 @@ def test_raise_parser_error( "lines." ) with pytest.raises(SystemExit): - ds.raise_parser_error(error_message) + script.raise_parser_error(error_message) captured = capsys.readouterr() expected = [*error_message.split(), "usage:", "--dry-run", "--stage"] for term in expected: diff --git a/test/test_staged_script_advanced_subclass.py b/test/test_staged_script_advanced_subclass.py index a4d3310..92272ee 100644 --- a/test/test_staged_script_advanced_subclass.py +++ b/test/test_staged_script_advanced_subclass.py @@ -56,7 +56,7 @@ def _prepare_to_retry_stage(self, retry_state: RetryCallState) -> None: @pytest.fixture() -def mas() -> MyAdvancedScript: +def script() -> MyAdvancedScript: """Create a :class:`MyAdvancedScript` object to be used by tests.""" my_advanced_script = MyAdvancedScript({"test"}) my_advanced_script.console = Console(log_time=False, log_path=False) @@ -103,7 +103,7 @@ def test_stage( # noqa: PLR0913 custom_skip_stage: bool, # noqa: FBT001 custom_end_stage: bool, # noqa: FBT001 custom_post_stage: bool, # noqa: FBT001 - mas: MyAdvancedScript, + script: MyAdvancedScript, capsys: pytest.CaptureFixture, ) -> None: """ @@ -111,29 +111,29 @@ def test_stage( # noqa: PLR0913 This case does not include retrying the stage. """ - mas.parse_args([]) - mas.stages_to_run = stages_to_run + script.parse_args([]) + script.stages_to_run = stages_to_run if custom_pre_stage: - mas._run_pre_stage_actions_test = lambda: print( + script._run_pre_stage_actions_test = lambda: print( "inside '_run_pre_stage_actions_test' function" ) if custom_begin_stage: - mas._begin_stage_test = lambda heading: print( + script._begin_stage_test = lambda heading: print( "inside '_begin_stage_test' function" ) if custom_skip_stage: - mas._skip_stage_test = lambda: print( + script._skip_stage_test = lambda: print( "inside '_skip_stage_test' function" ) if custom_end_stage: - mas._end_stage_test = lambda: print( + script._end_stage_test = lambda: print( "inside '_end_stage_test' function" ) if custom_post_stage: - mas._run_post_stage_actions_test = lambda: print( + script._run_post_stage_actions_test = lambda: print( "inside '_run_post_stage_actions_test' function" ) - mas.run_test() + script.run_test() captured = capsys.readouterr() index = 0 phases = [ @@ -160,7 +160,7 @@ def test_stage_retry( custom_prepare_to_retry: bool, # noqa: FBT001 custom_handle_retry_error: bool, # noqa: FBT001 retry_attempts: int, - mas: MyAdvancedScript, + script: MyAdvancedScript, capsys: pytest.CaptureFixture, ) -> None: """ @@ -168,17 +168,17 @@ def test_stage_retry( This case includes retrying the stage. """ - mas.parse_args(shlex.split(f"--test-retry-attempts {retry_attempts}")) - mas.stages_to_run = {"test"} + script.parse_args(shlex.split(f"--test-retry-attempts {retry_attempts}")) + script.stages_to_run = {"test"} if custom_prepare_to_retry: - mas._prepare_to_retry_stage_test = lambda retry_state: print( + script._prepare_to_retry_stage_test = lambda retry_state: print( "inside '_prepare_to_retry_stage_test' function" ) if custom_handle_retry_error: - mas._handle_stage_retry_error_test = lambda retry: print( + script._handle_stage_retry_error_test = lambda retry: print( "inside '_handle_stage_retry_error_test' function" ) - mas.run_test(retry=True) + script.run_test(retry=True) captured = capsys.readouterr() index = 0 phases = [ diff --git a/test/test_staged_script_basic_subclass.py b/test/test_staged_script_basic_subclass.py index f81cad2..1c50bc7 100644 --- a/test/test_staged_script_basic_subclass.py +++ b/test/test_staged_script_basic_subclass.py @@ -34,7 +34,7 @@ def run_bad_stage(self, *, error: bool) -> None: @pytest.fixture() -def mbs() -> MyBasicScript: +def script() -> MyBasicScript: """Create a :class:`MyBasicScript` object to be used by tests.""" my_basic_script = MyBasicScript({"good", "bad"}) my_basic_script.console = Console(log_time=False, log_path=False) @@ -43,12 +43,14 @@ def mbs() -> MyBasicScript: @pytest.mark.parametrize("stages_to_run", [{"good"}, set()]) def test_good_stage( - stages_to_run: set[str], mbs: MyBasicScript, capsys: pytest.CaptureFixture + stages_to_run: set[str], + script: MyBasicScript, + capsys: pytest.CaptureFixture, ) -> None: """Ensure the good stage runs to completion.""" - mbs.parse_args([]) - mbs.stages_to_run = stages_to_run - mbs.run_good_stage() + script.parse_args([]) + script.stages_to_run = stages_to_run + script.run_good_stage() captured = capsys.readouterr() # Ensure `_begin_stage()` is called. @@ -67,7 +69,7 @@ def test_good_stage( @pytest.mark.parametrize("error", [True, False]) def test_bad_stage( error: bool, # noqa: FBT001 - mbs: MyBasicScript, + script: MyBasicScript, capsys: pytest.CaptureFixture, ) -> None: """ @@ -76,15 +78,15 @@ def test_bad_stage( If there's no error, it runs to completion; otherwise it bugs out in the stage body, but still runs the end-stage actions. """ - mbs.parse_args([]) - mbs.stages_to_run = {"bad"} + script.parse_args([]) + script.stages_to_run = {"bad"} if error: with pytest.raises(RuntimeError) as e: - mbs.run_bad_stage(error=error) + script.run_bad_stage(error=error) msg = e.value.args[0] assert "Something went wrong." in msg else: - mbs.run_bad_stage(error=error) + script.run_bad_stage(error=error) captured = capsys.readouterr() # Ensure `_begin_stage()` is called. @@ -101,9 +103,9 @@ def test_bad_stage( @pytest.mark.parametrize("stage", ["good", "bad"]) -def test_parser_retry_options(stage: str, mbs: MyBasicScript) -> None: +def test_parser_retry_options(stage: str, script: MyBasicScript) -> None: """Ensure the stage retry options are present.""" - help_text = mbs.parser.format_help() + help_text = script.parser.format_help() assert f"--{stage}-retry-attempts" in help_text assert f"--{stage}-retry-delay" in help_text assert f"--{stage}-retry-timeout" in help_text From 27233514efb2797f8f8fe8e561d9377bbb9677e3 Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:21:49 -0600 Subject: [PATCH 2/8] test: Rename tests The convention is to name tests `test_`, but these tests accidentally omitted the leading underscore. --- test/test_staged_script.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_staged_script.py b/test/test_staged_script.py index a715be0..de6cb7a 100644 --- a/test/test_staged_script.py +++ b/test/test_staged_script.py @@ -33,7 +33,7 @@ def test_print_dry_run_message( assert expected in captured.out -def test_validate_stage_name() -> None: +def test__validate_stage_name() -> None: """Test the :func:`validate_stage_name` method.""" StagedScript._validate_stage_name("valid") @@ -42,7 +42,7 @@ def test_validate_stage_name() -> None: "stage_name", ["Uppercase", "spa ces", "hyphen-ated", "under_scores"] ) # yapf: disable -def test_validate_stage_name_raises(stage_name: str) -> None: +def test__validate_stage_name_raises(stage_name: str) -> None: """Ensure :func:`validate_stage_name` raises an exception when needed.""" with pytest.raises( ValueError, @@ -135,7 +135,7 @@ def test__prepare_to_retry_stage( assert text in captured.out -def test_get_timing_report( +def test__get_timing_report( script: StagedScript, capsys: pytest.CaptureFixture ) -> None: """Test the :func:`_get_timing_report` method.""" From 86f5cfeb2886f25a3cef9dd7035e635748038a9d Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:24:07 -0600 Subject: [PATCH 3/8] chore: Remove YAPF comments No longer needed after switching from YAPF to Ruff. --- staged_script/staged_script.py | 19 ++++++++++--------- test/test_staged_script.py | 27 +++++++++++---------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/staged_script/staged_script.py b/staged_script/staged_script.py index 2b370f3..62e71e0 100644 --- a/staged_script/staged_script.py +++ b/staged_script/staged_script.py @@ -699,7 +699,7 @@ def _end_stage_test(self) -> None: stage_duration = datetime.now(tz=timezone.utc) - self.stage_start_time self.durations.append( StageDuration(self.current_stage, stage_duration) - ) # yapf: disable + ) self.console.log( f"`{self.current_stage}` stage duration: {stage_duration!s}" ) @@ -862,9 +862,11 @@ def pretty_print_command(self, command: str, indent: int = 4) -> str: args = shlex.split(command) lines = [args.pop(0)] while args: - if (not self._current_arg_is_long_flag(args) - or self._next_arg_is_flag(args) - or len(args) == 1): # yapf: disable + if ( + not self._current_arg_is_long_flag(args) + or self._next_arg_is_flag(args) + or len(args) == 1 + ): lines.append(args.pop(0)) else: lines.append( @@ -887,9 +889,9 @@ def print_dry_run_message(self, message: str, *, indent: int = 0) -> None: self.console.log( Padding( Panel(f"DRY-RUN MODE: {message}", style="yellow"), - (0, 0, 0, indent) + (0, 0, 0, indent), ) - ) # yapf: disable + ) def print_heading(self, message: str, *, color: str = "cyan") -> None: """ @@ -904,9 +906,8 @@ def print_heading(self, message: str, *, color: str = "cyan") -> None: self.console.log(Panel(f"[bold]{message}", style=color)) def print_script_execution_summary( - self, - extra_sections: dict[str, str] | None = None - ) -> None: # yapf: disable + self, extra_sections: dict[str, str] | None = None + ) -> None: """ Print a summary of everything that was done by the script. diff --git a/test/test_staged_script.py b/test/test_staged_script.py index de6cb7a..0f66ad6 100644 --- a/test/test_staged_script.py +++ b/test/test_staged_script.py @@ -39,9 +39,8 @@ def test__validate_stage_name() -> None: @pytest.mark.parametrize( - "stage_name", - ["Uppercase", "spa ces", "hyphen-ated", "under_scores"] -) # yapf: disable + "stage_name", ["Uppercase", "spa ces", "hyphen-ated", "under_scores"] +) def test__validate_stage_name_raises(stage_name: str) -> None: """Ensure :func:`validate_stage_name` raises an exception when needed.""" with pytest.raises( @@ -141,14 +140,12 @@ def test__get_timing_report( """Test the :func:`_get_timing_report` method.""" script.durations = [ StageDuration( - "first", - timedelta(hours=1, minutes=2, seconds=3, microseconds=4) + "first", timedelta(hours=1, minutes=2, seconds=3, microseconds=4) ), StageDuration( - "second", - timedelta(hours=4, minutes=3, seconds=2, microseconds=1) - ) - ] # yapf: disable + "second", timedelta(hours=4, minutes=3, seconds=2, microseconds=1) + ), + ] script.console.print(script._get_timing_report()) captured = capsys.readouterr() for stage in [_.stage for _ in script.durations]: @@ -250,14 +247,12 @@ def test_print_script_execution_summary( ) script.durations = [ StageDuration( - "first", - timedelta(hours=1, minutes=2, seconds=3, microseconds=4) + "first", timedelta(hours=1, minutes=2, seconds=3, microseconds=4) ), StageDuration( - "second", - timedelta(hours=4, minutes=3, seconds=2, microseconds=1) - ) - ] # yapf: disable + "second", timedelta(hours=4, minutes=3, seconds=2, microseconds=1) + ), + ] script.commands_executed = ["foo", "bar", "baz"] script.script_success = script_success if extras is None: @@ -277,7 +272,7 @@ def test_print_script_execution_summary( + [_.stage for _ in script.durations] + [str(_.duration) for _ in script.durations] + ["Success" if script_success else "Failure"] - ) # yapf: disable + ) if extras is not None: headings += list(extras.keys()) details += list(extras.values()) From e1836e31a7c56d33d77b8c1736d147d279105e17 Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:28:18 -0600 Subject: [PATCH 4/8] test: Fix imports for unit/integration tests --- test/__init__.py | 7 +++++++ test/test_staged_script.py | 5 +---- test/test_staged_script_advanced_subclass.py | 2 +- test/test_staged_script_basic_subclass.py | 2 +- test/test_staged_script_registered_stages.py | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 test/__init__.py diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..a629140 --- /dev/null +++ b/test/__init__.py @@ -0,0 +1,7 @@ +""" +Create the ``test`` package. + +This ``__init__.py`` file creates the ``test`` package, such that tests +can relative-import from modules in the sibling ``staged_script`` +directory. +""" diff --git a/test/test_staged_script.py b/test/test_staged_script.py index 0f66ad6..8e56325 100644 --- a/test/test_staged_script.py +++ b/test/test_staged_script.py @@ -8,10 +8,7 @@ import pytest from rich.console import Console -from python.staged_script.staged_script.staged_script import ( - StagedScript, - StageDuration, -) +from staged_script import StagedScript, StageDuration @pytest.fixture() diff --git a/test/test_staged_script_advanced_subclass.py b/test/test_staged_script_advanced_subclass.py index 92272ee..aaee3be 100644 --- a/test/test_staged_script_advanced_subclass.py +++ b/test/test_staged_script_advanced_subclass.py @@ -6,7 +6,7 @@ from rich.console import Console from tenacity import RetryCallState, Retrying, TryAgain -from python.staged_script.staged_script.staged_script import StagedScript +from staged_script import StagedScript class MyAdvancedScript(StagedScript): diff --git a/test/test_staged_script_basic_subclass.py b/test/test_staged_script_basic_subclass.py index 1c50bc7..64f3dc5 100644 --- a/test/test_staged_script_basic_subclass.py +++ b/test/test_staged_script_basic_subclass.py @@ -3,7 +3,7 @@ import pytest from rich.console import Console -from python.staged_script.staged_script.staged_script import StagedScript +from staged_script import StagedScript class MyBasicScript(StagedScript): diff --git a/test/test_staged_script_registered_stages.py b/test/test_staged_script_registered_stages.py index d9b843b..910f3ec 100644 --- a/test/test_staged_script_registered_stages.py +++ b/test/test_staged_script_registered_stages.py @@ -1,6 +1,6 @@ """Integration tests for retry options.""" -from python.staged_script.staged_script.staged_script import StagedScript +from staged_script import StagedScript class MyScript(StagedScript): From b23355399007e17f023750d33a46020b33b817fb Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:32:01 -0600 Subject: [PATCH 5/8] refactor: Reduce setup file Remove the guts of the `setup.py` file so it just uses the `pyproject.toml` under the hood. --- setup.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/setup.py b/setup.py index 2f71641..9c2bbdb 100644 --- a/setup.py +++ b/setup.py @@ -4,18 +4,7 @@ To install, simply ``python3 -m pip install .`` in the repository root. """ -from setuptools import setup +import setuptools -setup( - name="staged-script", - version="1.0.0", - description=( - "A base class to inherit from when building scripts that are " - "subdivided into a series of stages." - ), - packages=["staged_script"], - scripts=[], - python_requires=">=3.10", - tests_require=["pytest==7.1.1"], - install_requires=["rich==12.5.1"], -) +if __name__ == "__main__": + setuptools.setup() From f42f22d4a8e2dc553ffe2ec0df039078ffb45772 Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:33:19 -0600 Subject: [PATCH 6/8] chore: Add version to __init__.py --- staged_script/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/staged_script/__init__.py b/staged_script/__init__.py index acaa161..3037fcc 100644 --- a/staged_script/__init__.py +++ b/staged_script/__init__.py @@ -20,3 +20,4 @@ "StageDuration", "lazy_property", ] +__version__ = "1.0.0" From b0c22fcc011cb77ffada7d8614f63e435774818e Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 17:39:12 -0600 Subject: [PATCH 7/8] docs: Add copyright/license text to source files --- setup.py | 6 ++++++ staged_script/__init__.py | 6 ++++++ staged_script/staged_script.py | 6 ++++++ test/__init__.py | 6 ++++++ test/test_staged_script.py | 6 ++++++ test/test_staged_script_advanced_subclass.py | 6 ++++++ test/test_staged_script_basic_subclass.py | 6 ++++++ test/test_staged_script_registered_stages.py | 6 ++++++ 8 files changed, 48 insertions(+) diff --git a/setup.py b/setup.py index 9c2bbdb..cc43b2a 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,12 @@ To install, simply ``python3 -m pip install .`` in the repository root. """ +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + import setuptools if __name__ == "__main__": diff --git a/staged_script/__init__.py b/staged_script/__init__.py index 3037fcc..09a3ea4 100644 --- a/staged_script/__init__.py +++ b/staged_script/__init__.py @@ -5,6 +5,12 @@ and functions. """ +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + from .staged_script import ( StagedScript, HelpFormatter, diff --git a/staged_script/staged_script.py b/staged_script/staged_script.py index 62e71e0..74ea598 100644 --- a/staged_script/staged_script.py +++ b/staged_script/staged_script.py @@ -5,6 +5,12 @@ your own staged scripts, along with some helpers. """ +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + import functools import re import shlex diff --git a/test/__init__.py b/test/__init__.py index a629140..207222e 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -5,3 +5,9 @@ can relative-import from modules in the sibling ``staged_script`` directory. """ + +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause diff --git a/test/test_staged_script.py b/test/test_staged_script.py index 8e56325..db5becb 100644 --- a/test/test_staged_script.py +++ b/test/test_staged_script.py @@ -1,5 +1,11 @@ """Unit tests for ``staged-script``.""" +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + import shlex from datetime import datetime, timedelta, timezone from subprocess import CompletedProcess diff --git a/test/test_staged_script_advanced_subclass.py b/test/test_staged_script_advanced_subclass.py index aaee3be..c43ee7a 100644 --- a/test/test_staged_script_advanced_subclass.py +++ b/test/test_staged_script_advanced_subclass.py @@ -1,5 +1,11 @@ """Integration tests for an advanced ``staged-script`` use case.""" +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + import shlex import pytest diff --git a/test/test_staged_script_basic_subclass.py b/test/test_staged_script_basic_subclass.py index 64f3dc5..c742b74 100644 --- a/test/test_staged_script_basic_subclass.py +++ b/test/test_staged_script_basic_subclass.py @@ -1,5 +1,11 @@ """Integration tests for a basic ``StagedScript`` use case.""" +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + import pytest from rich.console import Console diff --git a/test/test_staged_script_registered_stages.py b/test/test_staged_script_registered_stages.py index 910f3ec..5fbb7ce 100644 --- a/test/test_staged_script_registered_stages.py +++ b/test/test_staged_script_registered_stages.py @@ -1,5 +1,11 @@ """Integration tests for retry options.""" +# © 2024 National Technology & Engineering Solutions of Sandia, LLC +# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the +# U.S. Government retains certain rights in this software. + +# SPDX-License-Identifier: BSD-3-Clause + from staged_script import StagedScript From 4dbf516b868d68471e7eb0e79d835b832743d6a2 Mon Sep 17 00:00:00 2001 From: "Jason M. Gates" Date: Thu, 9 May 2024 18:15:15 -0600 Subject: [PATCH 8/8] chore: Ignore mypy warnings Temporarily disable these warnings until there's time to revisit and address them. --- test/test_staged_script.py | 2 +- test/test_staged_script_advanced_subclass.py | 28 +++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/test/test_staged_script.py b/test/test_staged_script.py index db5becb..4f5b3c9 100644 --- a/test/test_staged_script.py +++ b/test/test_staged_script.py @@ -97,7 +97,7 @@ def test__handle_stage_retry_error( ) -> None: """Test the :func:`_handle_stage_retry_error` method.""" script.current_stage = "test" - script.test_retry_attempts = retry_attempts + script.test_retry_attempts = retry_attempts # type: ignore[attr-defined] retry = mock_Retrying() retry.statistics = { "delay_since_first_attempt": 1234, diff --git a/test/test_staged_script_advanced_subclass.py b/test/test_staged_script_advanced_subclass.py index c43ee7a..15f2351 100644 --- a/test/test_staged_script_advanced_subclass.py +++ b/test/test_staged_script_advanced_subclass.py @@ -120,24 +120,24 @@ def test_stage( # noqa: PLR0913 script.parse_args([]) script.stages_to_run = stages_to_run if custom_pre_stage: - script._run_pre_stage_actions_test = lambda: print( - "inside '_run_pre_stage_actions_test' function" + script._run_pre_stage_actions_test = ( # type: ignore[attr-defined] + lambda: print("inside '_run_pre_stage_actions_test' function") ) if custom_begin_stage: - script._begin_stage_test = lambda heading: print( - "inside '_begin_stage_test' function" + script._begin_stage_test = ( # type: ignore[attr-defined] + lambda heading: print("inside '_begin_stage_test' function") ) if custom_skip_stage: - script._skip_stage_test = lambda: print( + script._skip_stage_test = lambda: print( # type: ignore[attr-defined] "inside '_skip_stage_test' function" ) if custom_end_stage: - script._end_stage_test = lambda: print( + script._end_stage_test = lambda: print( # type: ignore[attr-defined] "inside '_end_stage_test' function" ) if custom_post_stage: - script._run_post_stage_actions_test = lambda: print( - "inside '_run_post_stage_actions_test' function" + script._run_post_stage_actions_test = ( # type: ignore[attr-defined] + lambda: print("inside '_run_post_stage_actions_test' function") ) script.run_test() captured = capsys.readouterr() @@ -177,12 +177,16 @@ def test_stage_retry( script.parse_args(shlex.split(f"--test-retry-attempts {retry_attempts}")) script.stages_to_run = {"test"} if custom_prepare_to_retry: - script._prepare_to_retry_stage_test = lambda retry_state: print( - "inside '_prepare_to_retry_stage_test' function" + script._prepare_to_retry_stage_test = ( # type: ignore[attr-defined] + lambda retry_state: print( + "inside '_prepare_to_retry_stage_test' function" + ) ) if custom_handle_retry_error: - script._handle_stage_retry_error_test = lambda retry: print( - "inside '_handle_stage_retry_error_test' function" + script._handle_stage_retry_error_test = ( # type: ignore[attr-defined] + lambda retry: print( + "inside '_handle_stage_retry_error_test' function" + ) ) script.run_test(retry=True) captured = capsys.readouterr()