@@ -309,7 +309,16 @@ def migrate_config_from_pre_commit(self) -> None:
309309 self .print_how_to_use ()
310310
311311 def get_active_config_file_managers (self ) -> set [KeyValueFileManager ]:
312- """Get relative paths to all active configuration files."""
312+ """Get file managers for all active configuration files.
313+
314+ Active configuration files are just those that we expect to use based on our
315+ strategy for deciding on relevant files: this is a combination of the resolution
316+ methodology associated with the tool, and hard-coded preferences for certain
317+ files.
318+
319+ Most commonly, this will just be a single file manager. The active config files
320+ themselves do not necessarily exist yet.
321+ """
313322 config_spec = self .get_config_spec ()
314323 resolution = config_spec .resolution
315324 return self ._get_active_config_file_managers_from_resolution (
@@ -428,8 +437,14 @@ def _add_config_item(
428437 ) -> bool :
429438 """Add a specific configuration item using specified file managers.
430439
431- Returns whether any config was added. Config might not be added in some cases
432- where it's conditional and not applicable based on the current project state.
440+ Args:
441+ config_item: The configuration item to add.
442+ file_managers: The set of (active) file managers to consider for adding the
443+ config.
444+
445+ Returns:
446+ Whether any config was added. Config might not be added in some cases where
447+ it's conditional and not applicable based on the current project state.
433448 """
434449 # This is mostly a helper method for `add_configs`.
435450
@@ -440,45 +455,61 @@ def _add_config_item(
440455 for file_manager in file_managers
441456 if file_manager .path in config_item .paths
442457 ]
443-
458+ # Validate the filter is not empty
444459 if not used_file_managers :
445460 if config_item .applies_to_all :
446461 msg = f"No active config file managers found for one of the '{ self .name } ' config items."
447462 raise NotImplementedError (msg )
448463 else :
449464 # Early exit; this config item is not managed by any active files
450- # so it's optional, effectively.
465+ # and explicitly declares itself not-applicable-to-all-files, so it's
466+ # optional, effectively. See docs for ConfigItem.applies_to_all to
467+ # understand the motivation for this better.
451468 return False
452469
470+ # Now, filter the config entries associated with the item to just those
471+ # relevant to the active file managers
472+ # Usually, there will only be one such entry (since there is usually one entry
473+ # per file manager)
453474 config_entries = [
454475 config_item
455476 for relative_path , config_item in config_item .root .items ()
456477 if relative_path
457478 in {file_manager .relative_path for file_manager in used_file_managers }
458479 ]
480+ # Validate the filter is not empty
459481 if not config_entries :
460482 msg = f"No config entries found for one of the '{ self .name } ' config items."
461483 raise NotImplementedError (msg )
484+
485+ # Focus on the one entry
462486 if len (config_entries ) != 1 :
463487 msg = (
464488 "Adding config is not yet supported for the case of multiple "
465489 "active config files."
466490 )
467491 raise NotImplementedError (msg )
468-
469492 (entry ,) = config_entries
470493
471494 if isinstance (entry .get_value (), NoConfigValue ):
472495 # No value to add, so skip this config item.
473496 return False
474497
475- # N.B. we wait to create files until after all `return False` lines to avoid
498+ # Create the config files if they don't exist yet.
499+ # N.B. we wait to do this until after all `return False` lines to avoid
476500 # creating empty files unnecessarily.
477501 for file_manager in used_file_managers :
478502 if not (file_manager .path .exists () and file_manager .path .is_file ()):
479503 tick_print (f"Writing '{ file_manager .relative_path } '." )
480504 file_manager .path .touch (exist_ok = True )
481505
506+ # Try and identify which file manager to use for adding the config, based on
507+ # where existing config is located and our priority order
508+ # The idea is that the config is located at a given key sequence (e.g.
509+ # ["tool", "ruff", "line-length"]), and we we will look for existing config
510+ # using at least a shared subset of those e.g. ["tool", "ruff"], and
511+ # preferentially add to the highest-priority file manager which already has
512+ # config at that shared key sequence.
482513 shared_keys = []
483514 for key in entry .keys :
484515 shared_keys .append (key )
@@ -490,7 +521,6 @@ def _add_config_item(
490521 if not new_file_managers :
491522 break
492523 used_file_managers = new_file_managers
493-
494524 # Now, use the highest-priority file manager to add the config
495525 (used_file_manager , * _ ) = used_file_managers
496526
0 commit comments