From 249109ba9a14aef66887267191092d3e8e58d8a4 Mon Sep 17 00:00:00 2001 From: "John-Mason P. Shackelford" Date: Fri, 31 May 2024 16:16:35 -0400 Subject: [PATCH] All AIDER_* environment vars may now be placed within .env --- .pre-commit-config.yaml | 2 +- aider/args.py | 20 +++++++++- aider/main.py | 13 ++++--- aider/tests/test_main.py | 80 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 95b449726..9222c3e25 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ repos: - - repo: https://github.com/pycqa/isort + - repo: https://github.com/PyCQA/isort rev: 5.12.0 hooks: - id: isort diff --git a/aider/args.py b/aider/args.py index 070905bb4..4b0b1bccb 100644 --- a/aider/args.py +++ b/aider/args.py @@ -12,6 +12,21 @@ from aider.args_formatter import MarkdownHelpFormatter, YamlHelpFormatter from .dump import dump # noqa: F401 +def default_env_file(git_root): + return os.path.join(git_root, ".env") if git_root else ".env" + + +def get_preparser(git_root): + parser = configargparse.ArgumentParser(add_help=False) + parser.add_argument( + "--env-file", + metavar="ENV_FILE", + default=default_env_file(git_root), + help="Specify the .env file to load (default: .env in git root)", + ) + return parser + + def get_parser(default_config_files, git_root): parser = configargparse.ArgumentParser( description="aider is GPT powered coding in your terminal", @@ -184,11 +199,12 @@ def get_parser(default_config_files, git_root): " max_chat_history_tokens." ), ) - default_env_file = os.path.join(git_root, ".env") if git_root else ".env" + # This is a duplicate of the argument in the preparser and is a no-op by this time of + # argument parsing, but it's here so that the help is displayed as expected. group.add_argument( "--env-file", metavar="ENV_FILE", - default=default_env_file, + default=default_env_file(git_root), help="Specify the .env file to load (default: .env in git root)", ) diff --git a/aider/main.py b/aider/main.py index c4d211fc7..f1da79066 100644 --- a/aider/main.py +++ b/aider/main.py @@ -10,7 +10,7 @@ from prompt_toolkit.enums import EditingMode from streamlit.web import cli from aider import __version__, models, utils -from aider.args import get_parser +from aider.args import get_parser, get_preparser from aider.coders import Coder from aider.commands import SwitchModel from aider.io import InputOutput @@ -129,7 +129,7 @@ def format_settings(parser, args): for arg, val in sorted(vars(args).items()): if val: val = scrub_sensitive_info(args, str(val)) - show += f" - {arg}: {val}\n" + show += f" - {arg}: {val}\n" # noqa: E221 return show @@ -225,6 +225,12 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F default_config_files.append(Path.home() / conf_fname) # homedir default_config_files = list(map(str, default_config_files)) + preparser = get_preparser(git_root) + pre_args, _ = preparser.parse_known_args() + + # Load the .env file specified in the arguments + load_dotenv(pre_args.env_file) + parser = get_parser(default_config_files, git_root) args = parser.parse_args(argv) @@ -320,9 +326,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F cmd_line = scrub_sensitive_info(args, cmd_line) io.tool_output(cmd_line, log_only=True) - if args.env_file: - load_dotenv(args.env_file) - if args.anthropic_api_key: os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key diff --git a/aider/tests/test_main.py b/aider/tests/test_main.py index d319a78dd..001551a28 100644 --- a/aider/tests/test_main.py +++ b/aider/tests/test_main.py @@ -237,3 +237,83 @@ class TestMain(TestCase): main(["--message", test_message]) args, kwargs = MockInputOutput.call_args self.assertEqual(args[1], None) + + def test_dark_mode_sets_code_theme(self): + # Mock Coder.create to capture the configuration + with patch("aider.coders.Coder.create") as MockCoder: + main(["--dark-mode", "--no-git"], input=DummyInput(), output=DummyOutput()) + # Ensure Coder.create was called + MockCoder.assert_called_once() + # Check if the code_theme setting is for dark mode + _, kwargs = MockCoder.call_args + self.assertEqual(kwargs["code_theme"], "monokai") + + def test_light_mode_sets_code_theme(self): + # Mock Coder.create to capture the configuration + with patch("aider.coders.Coder.create") as MockCoder: + main(["--light-mode", "--no-git"], input=DummyInput(), output=DummyOutput()) + # Ensure Coder.create was called + MockCoder.assert_called_once() + # Check if the code_theme setting is for light mode + _, kwargs = MockCoder.call_args + self.assertEqual(kwargs["code_theme"], "default") + + def test_env_file_flag_read(self): + # Create a temporary .env file + env_file_path = Path(self.tempdir) / ".env.test" + env_content = "TEST_ENV_VAR=12345" + env_file_path.write_text(env_content) + + # Run the main function with the --env-file flag + main( + ["--env-file", str(env_file_path), "--no-git"], input=DummyInput(), output=DummyOutput() + ) + + # Check if the environment variable is loaded + self.assertEqual(os.getenv("TEST_ENV_VAR"), "12345") + + def test_default_env_file_read(self): + # Create a temporary .env file + env_file_path = Path(self.tempdir) / ".env" + env_content = "TEST_ENV_VAR=12345" + env_file_path.write_text(env_content) + + # Run the main function with the --env-file flag + main(["--no-git"], input=DummyInput(), output=DummyOutput()) + + # Check if the environment variable is loaded + self.assertEqual(os.getenv("TEST_ENV_VAR"), "12345") + + def test_env_file_flag_sets_automatic_variable(self): + # Create a temporary .env file with custom settings + env_file_path = Path(self.tempdir) / ".env.test" + env_content = "AIDER_DARK_MODE=True" + env_file_path.write_text(env_content) + + # Mock the InputOutput to capture the configuration + with patch("aider.coders.Coder.create") as MockCoder: + main( + ["--env-file", str(env_file_path), "--no-git"], + input=DummyInput(), + output=DummyOutput(), + ) + # Ensure Coder.create was called + MockCoder.assert_called_once() + # Check if the color settings are for dark mode + _, kwargs = MockCoder.call_args + self.assertEqual(kwargs["code_theme"], "monokai") + + def test_default_env_file_sets_automatic_variable(self): + # Create a default .env file in the temporary directory + env_file_path = Path(self.tempdir) / ".env" + env_content = "AIDER_DARK_MODE=True" + env_file_path.write_text(env_content) + + # Mock the InputOutput to capture the configuration + with patch("aider.coders.Coder.create") as MockCoder: + main(["--no-git"], input=DummyInput(), output=DummyOutput()) + # Ensure Coder.create was called + MockCoder.assert_called_once() + # Check if the color settings are for dark mode + _, kwargs = MockCoder.call_args + self.assertEqual(kwargs["code_theme"], "monokai")