Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/usethis/_integrations/sonarqube/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class _NonstandardPythonVersionError(Exception):
"""Raised when a non-standard Python version is detected."""


def get_sonar_project_properties() -> str:
def get_sonar_project_properties() -> str: # noqa: PLR0912
"""Get contents for (or from) the sonar-project.properties file."""
path = usethis_config.cpd() / "sonar-project.properties"
if path.exists() and path.is_file():
Expand Down Expand Up @@ -59,6 +59,7 @@ def get_sonar_project_properties() -> str:
]
except (FileNotFoundError, KeyError):
exclusions = []
# TypeAdapter(list).validate_python() ensures we have a list and returns a new list
exclusions = TypeAdapter(list).validate_python(exclusions)
for exclusion in exclusions:
TypeAdapter(str).validate_python(exclusion)
Expand All @@ -77,6 +78,9 @@ def get_sonar_project_properties() -> str:
source_dir_str = get_source_dir_str()
if source_dir_str == ".":
sources = "./"
# When using flat layout, exclude tests directory to avoid double indexing
if "tests/*" not in exclusions:
exclusions.insert(0, "tests/*")
else:
sources = f"./{source_dir_str}"

Expand Down
45 changes: 44 additions & 1 deletion tests/usethis/_integrations/sonarqube/test_sonarqube_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def test_different_python_version(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=false
sonar.exclusions=tests/*
"""
)

Expand Down Expand Up @@ -128,6 +129,7 @@ def test_no_pin_python(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=false
sonar.exclusions=tests/*
"""
)

Expand Down Expand Up @@ -157,6 +159,7 @@ def test_different_project_key(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=false
sonar.exclusions=tests/*
"""
)

Expand Down Expand Up @@ -189,6 +192,7 @@ def test_set_verbose_true(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=true
sonar.exclusions=tests/*
"""
)

Expand Down Expand Up @@ -235,6 +239,7 @@ def test_patch_version_ignored(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=false
sonar.exclusions=tests/*
"""
)

Expand Down Expand Up @@ -271,7 +276,7 @@ def test_exclusions(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=false
sonar.exclusions=**/Dockerfile, src/notebooks/**/*
sonar.exclusions=tests/*, **/Dockerfile, src/notebooks/**/*
"""
)

Expand Down Expand Up @@ -302,6 +307,7 @@ def test_different_coverage_file_location(self, tmp_path: Path):
sonar.tests=./tests
sonar.python.coverage.reportPaths=./test-reports/cov.xml
sonar.verbose=false
sonar.exclusions=tests/*
"""
)

Expand All @@ -318,6 +324,43 @@ def test_missing_coverage_file_location_error(self, tmp_path: Path):
with pytest.raises(CoverageReportConfigNotFoundError):
get_sonar_project_properties()

def test_flat_layout_exclusions_already_has_tests(self, tmp_path: Path):
# When using flat layout and tests/* is already in exclusions,
# it should not be added again.

with change_cwd(tmp_path), PyprojectTOMLManager():
# Arrange
uv_python_pin("3.12")
ensure_pyproject_toml()
PyprojectTOMLManager().set_value(
keys=["tool", "usethis", "sonarqube", "project-key"], value="foobar"
)
PyprojectTOMLManager().set_value(
keys=["tool", "usethis", "sonarqube", "exclusions"],
value=["tests/*", "**/Dockerfile"],
)
PyprojectTOMLManager().set_value(
keys=["tool", "coverage", "xml", "output"], value="coverage.xml"
)

# Act
result = get_sonar_project_properties()

# Assert
assert (
result
== """\
sonar.projectKey=foobar
sonar.language=py
sonar.python.version=3.12
sonar.sources=./
sonar.tests=./tests
sonar.python.coverage.reportPaths=coverage.xml
sonar.verbose=false
sonar.exclusions=tests/*, **/Dockerfile
"""
)


class TestValidateProjectKey:
def test_valid(self):
Expand Down
Loading