55
66from typing_extensions import assert_never
77
8+ from usethis ._config import usethis_config
89from usethis ._config_file import DotRuffTOMLManager , RuffTOMLManager
910from usethis ._console import box_print , tick_print
1011from usethis ._integrations .ci .bitbucket .anchor import (
@@ -297,12 +298,12 @@ def get_bitbucket_steps(self) -> list[BitbucketStep]:
297298
298299 return steps
299300
300- def select_rules (self , rules : list [Rule ]) -> None :
301+ def select_rules (self , rules : list [Rule ]) -> bool :
301302 """Add Ruff rules to the project."""
302303 rules = sorted (set (rules ) - set (self .get_selected_rules ()))
303304
304305 if not rules :
305- return
306+ return False
306307
307308 rules_str = ", " .join ([f"'{ rule } '" for rule in rules ])
308309 s = "" if len (rules ) == 1 else "s"
@@ -315,12 +316,14 @@ def select_rules(self, rules: list[Rule]) -> None:
315316 keys = self ._get_select_keys (file_manager )
316317 file_manager .extend_list (keys = keys , values = rules )
317318
318- def ignore_rules (self , rules : list [Rule ]) -> None :
319+ return True
320+
321+ def ignore_rules (self , rules : list [Rule ]) -> bool :
319322 """Ignore Ruff rules in the project."""
320323 rules = sorted (set (rules ) - set (self .get_ignored_rules ()))
321324
322325 if not rules :
323- return
326+ return False
324327
325328 rules_str = ", " .join ([f"'{ rule } '" for rule in rules ])
326329 s = "" if len (rules ) == 1 else "s"
@@ -333,12 +336,14 @@ def ignore_rules(self, rules: list[Rule]) -> None:
333336 keys = self ._get_ignore_keys (file_manager )
334337 file_manager .extend_list (keys = keys , values = rules )
335338
336- def unignore_rules (self , rules : list [str ]) -> None :
339+ return True
340+
341+ def unignore_rules (self , rules : list [str ]) -> bool :
337342 """Unignore Ruff rules in the project."""
338343 rules = list (set (rules ) & set (self .get_ignored_rules ()))
339344
340345 if not rules :
341- return
346+ return False
342347
343348 rules_str = ", " .join ([f"'{ rule } '" for rule in rules ])
344349 s = "" if len (rules ) == 1 else "s"
@@ -350,13 +355,14 @@ def unignore_rules(self, rules: list[str]) -> None:
350355 )
351356 keys = self ._get_ignore_keys (file_manager )
352357 file_manager .remove_from_list (keys = keys , values = rules )
358+ return True
353359
354- def deselect_rules (self , rules : list [Rule ]) -> None :
360+ def deselect_rules (self , rules : list [Rule ]) -> bool :
355361 """Ensure Ruff rules are not selected in the project."""
356362 rules = list (set (rules ) & set (self .get_selected_rules ()))
357363
358364 if not rules :
359- return
365+ return False
360366
361367 rules_str = ", " .join ([f"'{ rule } '" for rule in rules ])
362368 s = "" if len (rules ) == 1 else "s"
@@ -368,6 +374,7 @@ def deselect_rules(self, rules: list[Rule]) -> None:
368374 )
369375 keys = self ._get_select_keys (file_manager )
370376 file_manager .remove_from_list (keys = keys , values = rules )
377+ return True
371378
372379 def get_selected_rules (self ) -> list [Rule ]:
373380 """Get the Ruff rules selected in the project."""
@@ -397,8 +404,14 @@ def ignore_rules_in_glob(self, rules: list[Rule], *, glob: str) -> None:
397404 if not rules :
398405 return
399406
407+ rules_str = ", " .join ([f"'{ rule } '" for rule in rules ])
408+ s = "" if len (rules ) == 1 else "s"
409+
400410 (file_manager ,) = self .get_active_config_file_managers ()
401411 ensure_managed_file_exists (file_manager )
412+ tick_print (
413+ f"Ignoring { self .name } rule{ s } { rules_str } for '{ glob } ' in '{ file_manager .name } '."
414+ )
402415 keys = self ._get_per_file_ignore_keys (file_manager , glob = glob )
403416 file_manager .extend_list (keys = keys , values = rules )
404417
@@ -407,9 +420,19 @@ def apply_rule_config(self, rule_config: RuleConfig) -> None:
407420
408421 Note, this will add both managed and unmanaged config.
409422 """
410- self .select_rules (rule_config .get_all_selected ())
411- self .ignore_rules (rule_config .get_all_ignored ())
412- self .ignore_rules_in_glob (rule_config .tests_unmanaged_ignored , glob = "tests/**" )
423+ is_selected = self .select_rules (rule_config .get_all_selected ())
424+ is_ignored = self .ignore_rules (rule_config .get_all_ignored ())
425+
426+ # We don't want to spam the user with verbose messages about per-file ignores.
427+ # On the other hand, if we haven't displayed any messages at all, we need to
428+ # avoid a misleading silence, which would imply we haven't modified a file.
429+ # This is probably a workaround until there is more sophisticated support for
430+ # verbosity control.
431+ # https://github.com/usethis-python/usethis-python/issues/884
432+ with usethis_config .set (alert_only = is_selected or is_ignored ):
433+ self .ignore_rules_in_glob (
434+ rule_config .tests_unmanaged_ignored , glob = "tests/**"
435+ )
413436
414437 def remove_rule_config (self , rule_config : RuleConfig ) -> None :
415438 """Remove the Ruff rules associated with a rule config from the project.
0 commit comments