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
2 changes: 1 addition & 1 deletion conf/run_linters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ if [[ "${linters_to_run}" == *"flake8"* ]]; then
echo "===> Running flake8"
rm -f "${FLAKE8_REPORT}"
# See .flake8 file for settings
flake8 --config "${CONF_DIR}/.flake8" "${ROOT_DIR}" | tee "${FLAKE8_REPORT}"
flake8 --config "${CONF_DIR}/.flake8" --exclude test/gen "${ROOT_DIR}" | tee "${FLAKE8_REPORT}"
fi

if [[ "${localbuild}" = "true" ]]; then
Expand Down
66 changes: 51 additions & 15 deletions sonar/qualityprofiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,11 +393,15 @@ def to_json(self, export_settings: types.ConfigSettings) -> types.ObjectJsonRepr
json_data.pop("isBuiltIn", None)
json_data["rules"] = []
for rule in self.rules().values():
data = {k: v for k, v in rule.export(full).items() if k not in ("isTemplate", "templateKey", "language", "tags", "severities")}
data = {
k: v for k, v in rule.export(full).items() if k not in ("isTemplate", "templateKey", "language", "tags", "severities", "impacts")
}
if self.rule_is_prioritized(rule.key):
data["prioritized"] = True
if self.rule_has_custom_severities(rule.key):
data["severities"] = self.rule_impacts(rule.key, substitute_with_default=True)
if self.rule_has_custom_severity(rule.key):
data["severity"] = self.rule_severity(rule.key, substitute_with_default=True)
if self.rule_has_custom_impacts(rule.key):
data["impacts"] = {k: v for k, v in self.rule_impacts(rule.key, substitute_with_default=True).items() if v != c.DEFAULT}
json_data["rules"].append({"key": rule.key, **data})
json_data["permissions"] = self.permissions().export(export_settings)
return util.remove_nones(util.filter_export(json_data, _IMPORTABLE_PROPERTIES, full))
Expand All @@ -422,21 +426,32 @@ def api_params(self, op: str = c.GET) -> types.ApiParams:
return operations[op] if op in operations else operations[c.GET]

def rule_impacts(self, rule_key: str, substitute_with_default: bool = True) -> dict[str, str]:
"""Returns the severities of a rule in the quality profile
"""Returns the impacts of a rule in the quality profile

:param str rule_key: The rule key to get severities for
:return: The severities of the rule in the quality profile
:return: The impacts of the rule in the quality profile
:rtype: dict[str, str]
"""
return rules.Rule.get_object(self.endpoint, rule_key).impacts(self.key, substitute_with_default=substitute_with_default)

def __process_rules_diff(self, rule_set: dict[str:str]) -> dict[str:str]:
def rule_severity(self, rule_key: str, substitute_with_default: bool = True) -> str:
"""Returns the severity of a rule in the quality profile

:param str rule_key: The rule key to get severities for
:return: The severity
:rtype: str
"""
return rules.Rule.get_object(self.endpoint, rule_key).rule_severity(self.key, substitute_with_default=substitute_with_default)

def __process_rules_diff(self, rule_set: dict[str, str]) -> list[dict[str, str]]:
diff_rules = {}
for rule in rule_set:
r_key = rule["key"]
diff_rules[r_key] = {}
if self.rule_has_custom_severities(r_key):
diff_rules[r_key]["severities"] = self.rule_impacts(r_key, substitute_with_default=True)
if self.rule_has_custom_severity(r_key):
diff_rules[r_key]["severity"] = self.rule_severity(r_key, substitute_with_default=True)
if self.rule_has_custom_impacts(r_key):
diff_rules[r_key]["impacts"] = {k: v for k, v in self.rule_impacts(r_key, substitute_with_default=True).items() if v != c.DEFAULT}
if self.rule_is_prioritized(r_key):
diff_rules[r_key]["prioritized"] = True
if (params := self.rule_custom_params(r_key)) is not None:
Expand Down Expand Up @@ -500,23 +515,44 @@ def used_by_project(self, project: object) -> bool:
"""
return project.key in self.projects()

def rule_has_custom_severities(self, rule_key: str) -> bool:
"""Checks whether the rule has a custom severity in the quality profile
def rule_has_custom_impacts(self, rule_key: str) -> bool:
"""Checks whether the rule has custom impacts in the quality profile

:param str rule_key: The rule key to check
:return: Whether the rule has a some custom impacts in the quality profile
"""
if self.endpoint.is_sonarcloud():
return False
rule = rules.Rule.get_object(self.endpoint, rule_key)
impacts = rule.impacts(quality_profile_id=self.key, substitute_with_default=True)
has_custom = any(sev != c.DEFAULT for sev in impacts.values())
log.debug(
"Checking if rule %s has custom impacts in %s: %s - result %s",
rule_key,
str(self),
str(impacts),
has_custom,
)
return has_custom

def rule_has_custom_severity(self, rule_key: str) -> bool:
"""Checks whether the rule has custom impacts in the quality profile

:param str rule_key: The rule key to check
:return: Whether the rule has a some custom severities in the quality profile
:return: Whether the rule has a some custom severity in the quality profile
"""
if self.endpoint.is_sonarcloud():
return False
rule = rules.Rule.get_object(self.endpoint, rule_key)
sev = rule.rule_severity(quality_profile_id=self.key, substitute_with_default=True)
log.debug(
"Checking if rule %s has custom severities in %s: %s - result %s",
"Checking if rule %s has custom impacts in %s: %s - result %s",
rule_key,
str(self),
str(rule.impacts(quality_profile_id=self.key, substitute_with_default=True)),
any(sev != c.DEFAULT for sev in rule.impacts(quality_profile_id=self.key, substitute_with_default=True).values()),
sev,
sev != c.DEFAULT,
)
return any(sev != c.DEFAULT for sev in rule.impacts(quality_profile_id=self.key, substitute_with_default=True).values())
return sev != c.DEFAULT

def rule_is_prioritized(self, rule_key: str) -> bool:
"""Checks whether the rule is prioritized in the quality profile
Expand Down
14 changes: 13 additions & 1 deletion sonar/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ def impacts(self, quality_profile_id: Optional[str] = None, substitute_with_defa
"""Returns the rule clean code attributes"""
found_qp = None
if quality_profile_id:
self.refresh()
if "actives" not in self.sq_json:
self.refresh()
found_qp = next((qp for qp in self.sq_json.get("actives", []) if quality_profile_id and qp["qProfile"] == quality_profile_id), None)
if not found_qp:
return self._impacts if len(self._impacts) > 0 else {TYPE_TO_QUALITY[self.type]: self.severity}
Expand All @@ -361,6 +362,17 @@ def impacts(self, quality_profile_id: Optional[str] = None, substitute_with_defa
else:
return qp_impacts

def rule_severity(self, quality_profile_id: Optional[str] = None, substitute_with_default: bool = True) -> str:
"""Returns the severity, potentially customized in a QP"""
found_qp = None
if quality_profile_id:
if "actives" not in self.sq_json:
self.refresh()
found_qp = next((qp for qp in self.sq_json.get("actives", []) if quality_profile_id and qp["qProfile"] == quality_profile_id), None)
if not found_qp:
return c.DEFAULT if substitute_with_default else self.severity
return c.DEFAULT if substitute_with_default and found_qp["severity"] == self.severity else found_qp["severity"]

def __get_quality_profile_data(self, quality_profile_id: str) -> Optional[dict[str, str]]:
if not quality_profile_id:
return None
Expand Down