Skip to content

SCANPY-80 Read ".coveragerc" configuration to exclude files from coverage #234

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

Merged
merged 6 commits into from
Jun 17, 2025

Conversation

maksim-grebeniuk-sonarsource
Copy link
Contributor

@maksim-grebeniuk-sonarsource maksim-grebeniuk-sonarsource commented Jun 17, 2025

SCANPY-80

Part of

Copy link
Contributor

@thomas-serre-sonarsource thomas-serre-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic looks good to me.
I suggested a few changes with some of them which are a matter of taste.

class CoverageRCConfigurationLoader:

@staticmethod
def load(base_dir: pathlib.Path) -> dict[str, str]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor let's rename this function as it's not loading the all coverage file but only the exclusions properties

Suggested change
def load(base_dir: pathlib.Path) -> dict[str, str]:
def load_exclusion_properties(base_dir: pathlib.Path) -> dict[str, str]:

Comment on lines 36 to 40
exclusion_properties = CoverageRCConfigurationLoader.__read_coverage_exclusions_properties(
config_file_path, coverage_properties
)
result_dict.update(exclusion_properties)
return result_dict
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor I would simplify

Suggested change
exclusion_properties = CoverageRCConfigurationLoader.__read_coverage_exclusions_properties(
config_file_path, coverage_properties
)
result_dict.update(exclusion_properties)
return result_dict
exclusion_properties = CoverageRCConfigurationLoader.__read_coverage_exclusions_properties(
config_file_path, coverage_properties
)
return exclusion_properties

def __read_config(config_file_path: pathlib.Path) -> dict[str, Any]:
config_dict: dict[str, Any] = {}
if not config_file_path.exists():
logging.debug(f"Configuration file not found: {config_file_path}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor for coherence with other logs

Suggested change
logging.debug(f"Configuration file not found: {config_file_path}")
logging.debug(f"Coverage file not found: {config_file_path}")

Comment on lines 52 to 53

# Iterate over sections and options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
# Iterate over sections and options

return config_dict

@staticmethod
def __read_coverage_exclusions_properties(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor as this function is not reading from the file but only extracting patterns

Suggested change
def __read_coverage_exclusions_properties(
def __extract_coverage_exclusion_patterns(

Comment on lines 64 to 75
@staticmethod
def __read_coverage_exclusions_properties(
config_file_path: pathlib.Path, coverage_properties: dict[str, Any]
) -> dict[str, Any]:
result_dict: dict[str, Any] = {}
if "run" not in coverage_properties:
logging.debug(f"The run key was not found in {config_file_path}")
return result_dict

if "omit" not in coverage_properties["run"]:
logging.debug(f"The run.omit key was not found in {config_file_path}")
return result_dict
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@staticmethod
def __read_coverage_exclusions_properties(
config_file_path: pathlib.Path, coverage_properties: dict[str, Any]
) -> dict[str, Any]:
result_dict: dict[str, Any] = {}
if "run" not in coverage_properties:
logging.debug(f"The run key was not found in {config_file_path}")
return result_dict
if "omit" not in coverage_properties["run"]:
logging.debug(f"The run.omit key was not found in {config_file_path}")
return result_dict
@staticmethod
def __extract_coverage_exclusion_patterns(coverage_properties: dict[str, Any]) -> dict[str, Any]:
result_dict: dict[str, Any] = {}
if "run" not in coverage_properties or "omit" not in coverage_properties["run"]:
logging.debug(f"Coverage file has no exclusion properties")
return result_dict

Comment on lines 81 to 82
result_dict["sonar.coverage.exclusions"] = translated_exclusions
return result_dict
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't find it relevant in a loader file to build the options that should be passed to the scanner. I think this function should only return the exclusion patterns, so only a string, and the dict should be built outside. Moreover, the dict will always have only one key which seems overkill :) I'd suggest to build the dictionnary in the load function

Suggested change
result_dict["sonar.coverage.exclusions"] = translated_exclusions
return result_dict
return translated_exclusions

Copy link

Copy link
Contributor

@thomas-serre-sonarsource thomas-serre-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the modifications !

@maksim-grebeniuk-sonarsource maksim-grebeniuk-sonarsource marked this pull request as ready for review June 17, 2025 14:02
@maksim-grebeniuk-sonarsource maksim-grebeniuk-sonarsource merged commit 8f21b82 into master Jun 17, 2025
17 checks passed
@maksim-grebeniuk-sonarsource maksim-grebeniuk-sonarsource deleted the SCANPY-80 branch June 17, 2025 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants