-
Notifications
You must be signed in to change notification settings - Fork 3
Add --output-file option to usethis show commands
#1565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
77ba5e5
0713a80
e507212
9634456
1823cc5
3369149
5ed7f37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,36 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| from usethis._backend.dispatch import get_backend | ||
| from usethis._console import plain_print | ||
| from usethis._integrations.project.name import get_project_name | ||
| from usethis._integrations.sonarqube.config import get_sonar_project_properties | ||
|
|
||
| if TYPE_CHECKING: | ||
| from pathlib import Path | ||
|
|
||
|
|
||
| def show_backend(*, output_file: Path | None = None) -> None: | ||
| _output(get_backend().value, output_file=output_file) | ||
|
|
||
|
|
||
| def show_backend() -> None: | ||
| plain_print(get_backend().value) | ||
| def show_name(*, output_file: Path | None = None) -> None: | ||
| _output(get_project_name(), output_file=output_file) | ||
|
|
||
|
|
||
| def show_name() -> None: | ||
| plain_print(get_project_name()) | ||
| def show_sonarqube_config( | ||
| *, project_key: str | None = None, output_file: Path | None = None | ||
| ) -> None: | ||
| _output( | ||
| get_sonar_project_properties(project_key=project_key), output_file=output_file | ||
| ) | ||
|
|
||
|
|
||
| def show_sonarqube_config(*, project_key: str | None = None) -> None: | ||
| plain_print(get_sonar_project_properties(project_key=project_key)) | ||
| def _output(content: str, *, output_file: Path | None = None) -> None: | ||
| if output_file is not None: | ||
| if not content.endswith("\n"): | ||
| content += "\n" | ||
| output_file.write_text(content, encoding="utf-8") | ||
|
Comment on lines
+30
to
+34
|
||
| else: | ||
| plain_print(content) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,22 @@ def test_none_backend(self, tmp_path: Path): | |
| assert result.exit_code == 0, result.output | ||
| assert result.output == "none\n" | ||
|
|
||
| def test_output_file(self, tmp_path: Path): | ||
| # Arrange | ||
| (tmp_path / "uv.lock").touch() | ||
| output_file = tmp_path / "backend.txt" | ||
|
|
||
| # Act | ||
| runner = CliRunner() | ||
| with change_cwd(tmp_path): | ||
| result = runner.invoke_safe( | ||
| app, ["backend", "--output-file", str(output_file)] | ||
| ) | ||
|
|
||
| # Assert | ||
| assert result.exit_code == 0, result.output | ||
| assert output_file.read_text(encoding="utf-8") == "uv\n" | ||
|
Comment on lines
+41
to
+49
|
||
|
|
||
|
|
||
| class TestName: | ||
| def test_output(self, tmp_path: Path): | ||
|
|
@@ -60,6 +76,23 @@ def test_invalid_pyproject(self, tmp_path: Path): | |
| # Assert | ||
| assert result.exit_code == 1, result.output | ||
|
|
||
| def test_output_file(self, tmp_path: Path): | ||
| # Arrange | ||
| path = tmp_path / "fun" | ||
| path.mkdir() | ||
| output_file = path / "name.txt" | ||
|
|
||
| # Act | ||
| runner = CliRunner() | ||
| with change_cwd(path): | ||
| result = runner.invoke_safe( | ||
| app, ["name", "--output-file", str(output_file)] | ||
| ) | ||
|
|
||
| # Assert | ||
| assert result.exit_code == 0, result.output | ||
| assert output_file.read_text(encoding="utf-8") == "fun\n" | ||
|
|
||
|
|
||
| class TestSonarqube: | ||
| def test_runs(self, tmp_path: Path): | ||
|
|
@@ -162,3 +195,64 @@ def test_invalid_pyproject(self, tmp_path: Path): | |
|
|
||
| # Assert | ||
| assert result.exit_code == 1, result.output | ||
|
|
||
| def test_output_file(self, tmp_path: Path): | ||
| # Arrange | ||
| (tmp_path / "pyproject.toml").write_text( | ||
| """ | ||
| [tool.usethis.sonarqube] | ||
| project-key = "fun" | ||
|
|
||
| [tool.coverage.xml.output] | ||
| """ | ||
| ) | ||
| output_file = tmp_path / "sonar-project.properties" | ||
|
|
||
| # Act | ||
| runner = CliRunner() | ||
| with change_cwd(tmp_path): | ||
| result = runner.invoke_safe( | ||
| app, ["sonarqube", "--output-file", str(output_file)] | ||
| ) | ||
|
|
||
| # Assert | ||
| assert result.exit_code == 0, result.output | ||
| content = output_file.read_text(encoding="utf-8") | ||
| assert "sonar.projectKey=fun" in content | ||
|
|
||
| def test_output_file_not_detected_as_existing(self, tmp_path: Path): | ||
| """Using --output-file avoids the redirect problem. | ||
|
|
||
| When using shell redirect (`> file`), the file is created empty before | ||
| the command runs, which causes sonarqube to read that empty file. | ||
| With --output-file, the file is written after generation. | ||
| """ | ||
| # Arrange | ||
| (tmp_path / "pyproject.toml").write_text( | ||
| """ | ||
| [tool.usethis.sonarqube] | ||
| project-key = "fun" | ||
|
|
||
| [tool.coverage.xml.output] | ||
| """ | ||
| ) | ||
| # Simulate what happens with shell redirect: an empty file pre-exists | ||
| output_file = tmp_path / "sonar-project.properties" | ||
| output_file.write_text("", encoding="utf-8") | ||
|
|
||
|
Comment on lines
+223
to
+242
|
||
| # Act | ||
| # Despite sonar-project.properties existing (empty), --output-file | ||
| # still causes the config to be read from that file (by design of | ||
| # get_sonar_project_properties), then overwrites it with that content. | ||
| runner = CliRunner() | ||
| with change_cwd(tmp_path): | ||
| result = runner.invoke_safe( | ||
| app, ["sonarqube", "--output-file", str(output_file)] | ||
| ) | ||
|
|
||
| # Assert | ||
| assert result.exit_code == 0, result.output | ||
| content = output_file.read_text(encoding="utf-8") | ||
| # With --output-file, the file is written after content generation, | ||
| # so even if it was previously empty, it will have the content now | ||
| assert content != "" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doc update implies
--output-fileis only supported forusethis show sonarqube, but the PR adds it to allusethis showsubcommands (backend,name,sonarqube). The reference should either document--output-fileas a sharedusethis showoption or list it under eachusethis show <subcommand>that supports it, to avoid misleading users.