Skip to content

Commit

Permalink
remove limitation on nested phases/steps (#1843)
Browse files Browse the repository at this point in the history
* remove limitation on nested phases/steps

* remove unused error

* add integ test for validate with artifacts processor

* rename tests for clarity and add one more nested phase for deep nesting

* make phase in indent test more robust
  • Loading branch information
sfc-gh-mchok authored Nov 14, 2024
1 parent 5ae3d6b commit 86359a5
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 31 deletions.
23 changes: 4 additions & 19 deletions src/snowflake/cli/api/console/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand All @@ -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)

Expand Down
53 changes: 41 additions & 12 deletions tests/api/console/test_cli_console_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import pytest
from snowflake.cli.api.console.console import (
CliConsole,
CliConsoleNestingProhibitedError,
)


Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand Down
34 changes: 34 additions & 0 deletions tests_integration/nativeapp/test_validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 86359a5

Please sign in to comment.