Skip to content

Commit c84a97c

Browse files
authored
Merge pull request #682 from gauge-sh/warnings-errors-notifs-always-stderr
Move all user-facing messages in CLI to stderr
2 parents 74bab4c + c4f0817 commit c84a97c

File tree

4 files changed

+36
-38
lines changed

4 files changed

+36
-38
lines changed

python/tach/cli.py

+28-30
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from tach import __version__, cache, extension, icons
1212
from tach import filesystem as fs
1313
from tach.check_external import check_external
14-
from tach.console import console, console_err
14+
from tach.console import console_err
1515
from tach.constants import CONFIG_FILE_NAME, TOOL_NAME
1616
from tach.errors import (
1717
TachCircularDependencyError,
@@ -61,9 +61,10 @@ def print_unused_dependencies(
6161
"[red bold]Unused Dependencies[/]\n" + f"[yellow]{constraint_messages}[/]"
6262
)
6363
console_err.print(
64-
f"\n[yellow]Remove the unused dependencies from {CONFIG_FILE_NAME}.toml, "
64+
f"\nRemove the unused dependencies from {CONFIG_FILE_NAME}.toml, "
6565
f"or consider running '{TOOL_NAME} sync' to update module configuration and "
66-
f"remove all unused dependencies.[/]\n"
66+
f"remove all unused dependencies.\n",
67+
style="yellow",
6768
)
6869

6970

@@ -95,12 +96,12 @@ def print_no_dependencies_found() -> None:
9596

9697
def print_show_web_suggestion(is_mermaid: bool = False) -> None:
9798
if is_mermaid:
98-
console.print(
99+
console_err.print(
99100
"NOTE: You are generating a Mermaid graph locally representing your module graph. For a remotely hosted visualization, use the '--web' argument.\nTo visualize your graph, you will need to use Mermaid.js: https://mermaid.js.org/config/usage.html\n",
100101
style="cyan",
101102
)
102103
else:
103-
console.print(
104+
console_err.print(
104105
"NOTE: You are generating a DOT file locally representing your module graph. For a remotely hosted visualization, use the '--web' argument.\nTo visualize your graph, you will need a program like GraphViz: https://www.graphviz.org/download/\n",
105106
style="cyan",
106107
)
@@ -110,12 +111,12 @@ def print_generated_module_graph_file(
110111
output_filepath: Path, is_mermaid: bool = False
111112
) -> None:
112113
if is_mermaid:
113-
console.print(
114+
console_err.print(
114115
f"Generated a Mermaid file containing your module graph at '{output_filepath}'",
115116
style="green",
116117
)
117118
else:
118-
console.print(
119+
console_err.print(
119120
f"Generated a DOT file containing your module graph at '{output_filepath}'",
120121
style="green",
121122
)
@@ -568,9 +569,7 @@ def tach_check(
568569
sys.exit(1)
569570

570571
if exit_code == 0 and output_format == "text":
571-
console.print(
572-
f"{icons.SUCCESS} [green]All modules validated![/]", style="green"
573-
)
572+
console_err.print(f"{icons.SUCCESS} All modules validated!", style="green")
574573
sys.exit(exit_code)
575574

576575

@@ -603,9 +602,8 @@ def tach_check_external(
603602
if has_errors:
604603
sys.exit(1)
605604
else:
606-
console.print(
607-
f"{icons.SUCCESS} [green]All external dependencies validated![/]",
608-
style="green",
605+
console_err.print(
606+
f"{icons.SUCCESS} All external dependencies validated!", style="green"
609607
)
610608
sys.exit(0)
611609

@@ -649,9 +647,9 @@ def tach_mod(
649647
if warnings:
650648
console_err.print("\n".join(warnings))
651649
if saved_changes:
652-
console.print(
653-
f"{icons.SUCCESS} [green]Set modules! You may want to run '{TOOL_NAME} sync' "
654-
f"to automatically set boundaries.[/]",
650+
console_err.print(
651+
f"{icons.SUCCESS} Set modules! You may want to run '{TOOL_NAME} sync' "
652+
f"to automatically set boundaries.",
655653
style="green",
656654
)
657655
sys.exit(0)
@@ -681,7 +679,7 @@ def tach_sync(
681679
print(str(e))
682680
sys.exit(1)
683681

684-
console.print(f"{icons.SUCCESS} [green]Synced dependencies.[/]", style="green")
682+
console_err.print(f"{icons.SUCCESS} Synced dependencies.", style="green")
685683
sys.exit(0)
686684

687685

@@ -712,14 +710,14 @@ def tach_install(project_root: Path, target: InstallTarget) -> None:
712710
sys.exit(1)
713711

714712
if installed:
715-
console.print(
716-
f"{icons.SUCCESS} [green]Pre-commit hook installed to '.git/hooks/pre-commit'.[/]",
713+
console_err.print(
714+
f"{icons.SUCCESS} Pre-commit hook installed to '.git/hooks/pre-commit'.",
717715
style="green",
718716
)
719717
sys.exit(0)
720718
else:
721-
console.print(
722-
f"[yellow]Pre-commit hook could not be installed: {warning}[/]",
719+
console_err.print(
720+
f"Pre-commit hook could not be installed: {warning}",
723721
style="yellow",
724722
)
725723
sys.exit(1)
@@ -807,8 +805,8 @@ def tach_show(
807805
)
808806

809807
if is_web and is_mermaid:
810-
console.print(
811-
"[yellow]Passing --web generates a remote graph; ignoring '--mermaid' flag.[/]",
808+
console_err.print(
809+
"Passing --web generates a remote graph; ignoring '--mermaid' flag.",
812810
style="yellow",
813811
)
814812

@@ -830,8 +828,8 @@ def tach_show(
830828
included_paths=included_paths,
831829
)
832830
if result:
833-
console.print("View your dependency graph here:")
834-
console.print(result)
831+
console_err.print("View your dependency graph here:")
832+
console_err.print(result)
835833
sys.exit(0)
836834
else:
837835
sys.exit(1)
@@ -909,12 +907,12 @@ def tach_test(
909907
)
910908
if cached_output.exists:
911909
# Early exit, cached terminal output was found
912-
console.print(
910+
console_err.print(
913911
"============ Cached results found! ============",
914912
style="green",
915913
)
916914
cached_output.replay()
917-
console.print(
915+
console_err.print(
918916
"============ END Cached results ============",
919917
style="green",
920918
)
@@ -1080,7 +1078,7 @@ def main(argv: list[str] = sys.argv[1:]) -> None:
10801078

10811079
latest_version = cache.get_latest_version(project_root)
10821080
if latest_version and current_version_is_behind(latest_version):
1083-
console.print(
1081+
console_err.print(
10841082
f"WARNING: there is a new {TOOL_NAME} version available"
10851083
f" ({__version__} -> {latest_version}). Upgrade to remove this warning.",
10861084
style="yellow",
@@ -1115,7 +1113,7 @@ def main(argv: list[str] = sys.argv[1:]) -> None:
11151113

11161114
# Deprecation warnings
11171115
if project_config.use_regex_matching:
1118-
console.print(
1116+
console_err.print(
11191117
"WARNING: regex matching for exclude paths is deprecated. "
11201118
+ f"Update your exclude paths in {CONFIG_FILE_NAME}.toml to use glob patterns instead, and remove the 'use_regex_matching' setting."
11211119
+ "\n",
@@ -1125,7 +1123,7 @@ def main(argv: list[str] = sys.argv[1:]) -> None:
11251123
project_config.root_module == "ignore"
11261124
and project_config.has_root_module_reference()
11271125
):
1128-
console.print(
1126+
console_err.print(
11291127
"WARNING: root module treatment is set to 'ignore' (default as of 0.23.0), but '<root>' appears in your configuration."
11301128
+ f"\n\nRun '{TOOL_NAME} sync' to remove the root module from your dependencies,"
11311129
+ f" or update 'root_module' in {CONFIG_FILE_NAME}.toml to 'allow' or 'forbid' instead."

python/tests/test_check.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_valid_example_dir(example_dir, capfd):
2424
)
2525
assert exc_info.value.code == 0
2626
captured = capfd.readouterr()
27-
assert SUCCESS in captured.out
27+
assert SUCCESS in captured.err
2828
assert WARNING in captured.err or "WARN" in captured.err
2929

3030

python/tests/test_cli.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ def test_execute_with_config(capfd, mock_check, mock_project_config):
3939
)
4040
captured = capfd.readouterr()
4141
assert sys_exit.value.code == 0
42-
assert "✅" in captured.out
43-
assert "All modules validated!" in captured.out
42+
assert "✅" in captured.err
43+
assert "All modules validated!" in captured.err
4444

4545

4646
def test_invalid_command(capfd):
@@ -63,8 +63,8 @@ def test_execute_with_valid_exclude(capfd, mock_check, mock_project_config):
6363
)
6464
captured = capfd.readouterr()
6565
assert sys_exit.value.code == 0
66-
assert "✅" in captured.out
67-
assert "All modules validated!" in captured.out
66+
assert "✅" in captured.err
67+
assert "All modules validated!" in captured.err
6868

6969

7070
def test_tach_server_with_config(tmp_path, mocker):

python/tests/test_sync.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_valid_example_dir(example_dir, capfd):
2929

3030
assert exc_info.value.code == 0
3131
captured = capfd.readouterr()
32-
assert "✅" in captured.out # success state
32+
assert "✅" in captured.err # success state
3333

3434

3535
def test_distributed_config_dir(example_dir, capfd):
@@ -60,7 +60,7 @@ def test_distributed_config_dir(example_dir, capfd):
6060

6161
assert exc_info.value.code == 0
6262
captured = capfd.readouterr()
63-
assert "✅" in captured.out # success state
63+
assert "✅" in captured.err # success state
6464

6565
project_config = parse_project_config(root=temp_project_root)
6666
assert project_config is not None
@@ -95,7 +95,7 @@ def test_many_features_example_dir(example_dir, capfd):
9595

9696
assert exc_info.value.code == 0
9797
captured = capfd.readouterr()
98-
assert "✅" in captured.out # success state
98+
assert "✅" in captured.err # success state
9999

100100
project_config = parse_project_config(root=temp_project_root)
101101
assert project_config is not None

0 commit comments

Comments
 (0)