This commit is contained in:
sltptr 2025-05-17 02:43:53 +00:00 committed by GitHub
commit 52911bf94f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 119 additions and 62 deletions

View file

@ -766,8 +766,8 @@ def get_parser(default_config_files, git_root):
is_config_file=True, is_config_file=True,
metavar="CONFIG_FILE", metavar="CONFIG_FILE",
help=( help=(
"Specify the config file (default: search for .aider.conf.yml in git root, cwd" "Specify the config file (default: searches for .aider.conf.yml then .aider.conf.yaml"
" or home directory)" " in git root, cwd or home directory)"
), ),
).complete = shtab.FILE ).complete = shtab.FILE
# This is a duplicate of the argument in the preparser and is a no-op by this time of # This is a duplicate of the argument in the preparser and is a no-op by this time of

View file

@ -448,6 +448,20 @@ def sanity_check_repo(repo, io):
return False return False
def get_config_file(prefix=None):
conf_files = [
prefix / name if prefix else Path(name)
for name in [".aider.conf.yml", ".aider.conf.yaml"]
if (prefix / name if prefix else Path(name)).exists()
]
if len(conf_files) > 1:
print(
f"Warning: Both .aider.conf.yml and .aider.conf.yaml are present at {prefix}."
f" Defaulting to {prefix}/.aider.conf.yml."
)
return conf_files[0] if conf_files else None
def main(argv=None, input=None, output=None, force_git_root=None, return_coder=False): def main(argv=None, input=None, output=None, force_git_root=None, return_coder=False):
report_uncaught_exceptions() report_uncaught_exceptions()
@ -461,19 +475,22 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
else: else:
git_root = get_git_root() git_root = get_git_root()
conf_fname = Path(".aider.conf.yml") conf_fname = get_config_file()
default_config_files = [] default_config_files = []
try: if conf_fname:
default_config_files += [conf_fname.resolve()] # CWD try:
except OSError: default_config_files += [conf_fname.resolve()] # CWD
pass except OSError:
pass
if git_root: if git_root:
git_conf = Path(git_root) / conf_fname # git root git_conf = get_config_file(Path(git_root)) # git root
if git_conf not in default_config_files: if git_conf and git_conf not in default_config_files:
default_config_files.append(git_conf) default_config_files.append(git_conf.resolve())
default_config_files.append(Path.home() / conf_fname) # homedir home_conf = get_config_file(Path.home()) # home dir
if home_conf and home_conf not in default_config_files:
default_config_files.append(home_conf.resolve())
default_config_files = list(map(str, default_config_files)) default_config_files = list(map(str, default_config_files))
parser = get_parser(default_config_files, git_root) parser = get_parser(default_config_files, git_root)

View file

@ -406,65 +406,105 @@ class TestMain(TestCase):
self.assertRegex(relevant_output, r"dark_mode:\s+True") self.assertRegex(relevant_output, r"dark_mode:\s+True")
def test_yaml_config_file_loading(self): def test_yaml_config_file_loading(self):
with GitTemporaryDirectory() as git_dir: scenarios = [
git_dir = Path(git_dir) "yml_only", # Test with only .yml files
"yaml_only", # Test with only .yaml files
"both_formats", # Test with both .yml and .yaml files
]
# Create fake home directory for scenario in scenarios:
fake_home = git_dir / "fake_home" with self.subTest(scenario=scenario):
fake_home.mkdir() with GitTemporaryDirectory() as git_dir:
os.environ["HOME"] = str(fake_home) git_dir = Path(git_dir)
# Create subdirectory as current working directory # Create fake home directory
cwd = git_dir / "subdir" fake_home = git_dir / "fake_home"
cwd.mkdir() fake_home.mkdir()
os.chdir(cwd) os.environ["HOME"] = str(fake_home)
# Create .aider.conf.yml files in different locations # Create subdirectory as current working directory
home_config = fake_home / ".aider.conf.yml" cwd = git_dir / "subdir"
git_config = git_dir / ".aider.conf.yml" cwd.mkdir()
cwd_config = cwd / ".aider.conf.yml" os.chdir(cwd)
named_config = git_dir / "named.aider.conf.yml"
cwd_config.write_text("model: gpt-4-32k\nmap-tokens: 4096\n") # Create config files in different locations based on scenario
git_config.write_text("model: gpt-4\nmap-tokens: 2048\n") home_config_yml = fake_home / ".aider.conf.yml"
home_config.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n") home_config_yaml = fake_home / ".aider.conf.yaml"
named_config.write_text("model: gpt-4-1106-preview\nmap-tokens: 8192\n") git_config_yml = git_dir / ".aider.conf.yml"
git_config_yaml = git_dir / ".aider.conf.yaml"
cwd_config_yml = cwd / ".aider.conf.yml"
cwd_config_yaml = cwd / ".aider.conf.yaml"
named_config = git_dir / "named.aider.conf.yml"
with ( # Create files based on the scenario
patch("pathlib.Path.home", return_value=fake_home), if scenario == "yml_only":
patch("aider.coders.Coder.create") as MockCoder, cwd_config_yml.write_text("model: gpt-4-32k\nmap-tokens: 4096\n")
): git_config_yml.write_text("model: gpt-4\nmap-tokens: 2048\n")
# Test loading from specified config file home_config_yml.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n")
main( named_config.write_text("model: gpt-4-1106-preview\nmap-tokens: 8192\n")
["--yes", "--exit", "--config", str(named_config)], elif scenario == "yaml_only":
input=DummyInput(), cwd_config_yaml.write_text("model: gpt-4-32k\nmap-tokens: 4096\n")
output=DummyOutput(), git_config_yaml.write_text("model: gpt-4\nmap-tokens: 2048\n")
) home_config_yaml.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n")
_, kwargs = MockCoder.call_args named_config.write_text("model: gpt-4-1106-preview\nmap-tokens: 8192\n")
self.assertEqual(kwargs["main_model"].name, "gpt-4-1106-preview") else: # both_formats
self.assertEqual(kwargs["map_tokens"], 8192) # Create both formats, with .yaml taking precedence in each directory
cwd_config_yml.write_text("model: gpt-4-32k\nmap-tokens: 4096\n")
cwd_config_yaml.write_text("model: gpt-4-32k\nmap-tokens: 4096\n")
git_config_yml.write_text("model: gpt-4\nmap-tokens: 2048\n")
git_config_yaml.write_text("model: gpt-4\nmap-tokens: 2048\n")
home_config_yml.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n")
home_config_yaml.write_text("model: gpt-3.5-turbo\nmap-tokens: 1024\n")
named_config.write_text("model: gpt-4-1106-preview\nmap-tokens: 8192\n")
# Test loading from current working directory with (
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput()) patch("pathlib.Path.home", return_value=fake_home),
_, kwargs = MockCoder.call_args patch("aider.coders.Coder.create") as MockCoder,
print("kwargs:", kwargs) # Add this line for debugging ):
self.assertIn("main_model", kwargs, "main_model key not found in kwargs") # Test loading from specified config file
self.assertEqual(kwargs["main_model"].name, "gpt-4-32k") main(
self.assertEqual(kwargs["map_tokens"], 4096) ["--yes", "--exit", "--config", str(named_config)],
input=DummyInput(),
output=DummyOutput(),
)
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["main_model"].name, "gpt-4-1106-preview")
self.assertEqual(kwargs["map_tokens"], 8192)
# Test loading from git root # Test loading from current working directory
cwd_config.unlink() main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput()) _, kwargs = MockCoder.call_args
_, kwargs = MockCoder.call_args self.assertIn("main_model", kwargs, "main_model key not found in kwargs")
self.assertEqual(kwargs["main_model"].name, "gpt-4") self.assertEqual(kwargs["main_model"].name, "gpt-4-32k")
self.assertEqual(kwargs["map_tokens"], 2048) self.assertEqual(kwargs["map_tokens"], 4096)
# Test loading from home directory # Test loading from git root by removing cwd config files
git_config.unlink() if scenario == "yml_only":
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput()) cwd_config_yml.unlink()
_, kwargs = MockCoder.call_args elif scenario == "yaml_only":
self.assertEqual(kwargs["main_model"].name, "gpt-3.5-turbo") cwd_config_yaml.unlink()
self.assertEqual(kwargs["map_tokens"], 1024) else: # both_formats
cwd_config_yml.unlink()
cwd_config_yaml.unlink()
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["main_model"].name, "gpt-4")
self.assertEqual(kwargs["map_tokens"], 2048)
# Test loading from home directory by removing git root config files
if scenario == "yml_only":
git_config_yml.unlink()
elif scenario == "yaml_only":
git_config_yaml.unlink()
else: # both_formats
git_config_yml.unlink()
git_config_yaml.unlink()
main(["--yes", "--exit"], input=DummyInput(), output=DummyOutput())
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["main_model"].name, "gpt-3.5-turbo")
self.assertEqual(kwargs["map_tokens"], 1024)
def test_map_tokens_option(self): def test_map_tokens_option(self):
with GitTemporaryDirectory(): with GitTemporaryDirectory():