diff --git a/src/snowflake/cli/api/console/console.py b/src/snowflake/cli/api/console/console.py index 79031d23a7..94c80c9cc9 100644 --- a/src/snowflake/cli/api/console/console.py +++ b/src/snowflake/cli/api/console/console.py @@ -29,10 +29,6 @@ INDENTATION_LEVEL: int = 2 -class CliConsoleNestingProhibitedError(RuntimeError): - """CliConsole phase nesting not allowed.""" - - class CliConsole(AbstractConsole): """An utility for displaying intermediate output. @@ -70,28 +66,21 @@ def _format_message(self, message: str, output: Output) -> Text: @contextmanager def phase(self, enter_message: str, exit_message: Optional[str] = None): """A context manager for organising steps into logical group.""" - if self.in_phase: - raise CliConsoleNestingProhibitedError("Only one phase allowed at a time.") - if self._extra_indent > 0: - raise CliConsoleNestingProhibitedError( - "Phase cannot be used in an indented block." - ) - self._print(self._format_message(enter_message, Output.PHASE)) - self._in_phase = True + self._extra_indent += 1 try: yield self.step finally: - self._in_phase = False + self._extra_indent -= 1 if exit_message: self._print(self._format_message(exit_message, Output.PHASE)) @contextmanager def indented(self): """ - A context manager for temporarily indenting messages and warnings. Phases and steps cannot be used in indented blocks, - but multiple indented blocks can be nested (use sparingly). + A context manager for temporarily indenting messages and warnings. + Multiple indented blocks can be nested (use sparingly). """ self._extra_indent += 1 try: @@ -104,10 +93,6 @@ def step(self, message: str): If called within a phase, the output will be indented. """ - if self._extra_indent > 0: - raise CliConsoleNestingProhibitedError( - "Step cannot be used in an indented block." - ) text = self._format_message(message, Output.STEP) self._print(text) diff --git a/tests/api/console/test_cli_console_output.py b/tests/api/console/test_cli_console_output.py index c79dc9b0ee..589b9f35a2 100644 --- a/tests/api/console/test_cli_console_output.py +++ b/tests/api/console/test_cli_console_output.py @@ -20,7 +20,6 @@ import pytest from snowflake.cli.api.console.console import ( CliConsole, - CliConsoleNestingProhibitedError, ) @@ -74,12 +73,22 @@ def test_error_messages(cli_console, capsys): assert_output_matches("42\n 73\n ops\nOPS\n", capsys) -def test_phase_nesting_not_allowed(cli_console): +def test_phase_nesting(cli_console, capsys): with cli_console.phase("Enter 1"): - with pytest.raises(CliConsoleNestingProhibitedError): - with cli_console.phase("Enter 2"): + with cli_console.phase("Enter 2"): + with cli_console.phase("Enter 3"): pass + expected_output = dedent( + f"""\ + Enter 1 + Enter 2 + Enter 3 + """ + ) + + assert_output_matches(expected_output, capsys) + def test_phase_is_cleaned_up_on_exception(cli_console): with pytest.raises(RuntimeError): @@ -91,18 +100,38 @@ def test_phase_is_cleaned_up_on_exception(cli_console): pass -def test_phase_cannot_be_indented(cli_console): +def test_phase_inside_indented(cli_console, capsys): + cli_console.step("Outside of Indent") with cli_console.indented(): - with pytest.raises(CliConsoleNestingProhibitedError): - with cli_console.phase("Enter"): - pass + cli_console.step("Step In Indent") + with cli_console.phase("Phase In Indent"): + cli_console.step("Step In Indent + Phase") + expected_output = dedent( + f"""\ + Outside of Indent + Step In Indent + Phase In Indent + Step In Indent + Phase + """ + ) -def test_step_cannot_be_indented(cli_console): + assert_output_matches(expected_output, capsys) + + +def test_step_inside_indented(cli_console, capsys): + cli_console.step("Outside of Indent") with cli_console.indented(): - with pytest.raises(CliConsoleNestingProhibitedError): - with cli_console.step("Operation"): - pass + cli_console.step("Operation") + + expected_output = dedent( + f"""\ + Outside of Indent + Operation + """ + ) + + assert_output_matches(expected_output, capsys) def test_indented(cli_console, capsys): diff --git a/tests_integration/nativeapp/test_validate.py b/tests_integration/nativeapp/test_validate.py index 6a3efadabb..c435f069a9 100644 --- a/tests_integration/nativeapp/test_validate.py +++ b/tests_integration/nativeapp/test_validate.py @@ -144,3 +144,37 @@ def test_nativeapp_validate_with_post_deploy_hooks( with nativeapp_teardown(project_dir=Path(temp_dir)): result = runner.invoke_with_connection(["app", "validate"]) assert result.exit_code == 0, result.output + + +@pytest.mark.integration +def test_nativeapp_validate_with_artifacts_processor( + nativeapp_teardown, runner, temp_dir +): + ProjectV2Factory( + pdf__entities=dict( + pkg=ApplicationPackageEntityModelFactory( + identifier="myapp_pkg", + artifacts=[ + "setup.sql", + "README.md", + "manifest.yml", + # just needs to have the templates processor to nest phases + {"src": "app/*", "dest": "./", "processors": ["templates"]}, + ], + ), + app=ApplicationEntityModelFactory( + identifier="myapp", + fromm__target="pkg", + ), + ), + files={ + "setup.sql": "CREATE OR ALTER VERSIONED SCHEMA core;", + "README.md": "\n", + "manifest.yml": "\n", + "app/dummy_file.md": "\n", + }, + ) + + with nativeapp_teardown(project_dir=Path(temp_dir)): + result = runner.invoke_with_connection(["app", "validate"]) + assert result.exit_code == 0, result.output