import tempfile import pytest from gpt_engineer.core.project_config import ( Config, _GptEngineerAppConfig, _OpenApiConfig, example_config, filter_none, ) def test_config_load(): # write example config to a file with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: f.write(example_config) # load the config from the file config = Config.from_toml(f.name) assert config.paths.base == "./frontend" assert config.paths.src == "./src" assert config.run.build == "npm run build" assert config.run.test == "npm run test" assert config.run.lint == "quick-lint-js" assert config.gptengineer_app assert config.gptengineer_app.project_id == "..." assert config.gptengineer_app.openapi assert ( config.gptengineer_app.openapi[0].url == "https://api.gptengineer.app/openapi.json" ) assert ( config.gptengineer_app.openapi[1].url == "https://some-color-translating-api/openapi.json" ) assert config.to_dict() assert config.to_toml(f.name, save=False) # check that write+read is idempotent assert Config.from_toml(f.name) == config def test_config_defaults(): config = Config() assert config.paths.base is None with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: config.to_toml(f.name) # check that read+write is idempotent assert Config.from_toml(f.name) == config # check that empty (default) config is written as empty string toml_str = config.to_toml(f.name, save=False) assert toml_str == "" def test_config_from_dict(): d = {"gptengineer-app": {"project_id": "..."}} # minimal example config = Config.from_dict(d) assert config.gptengineer_app assert config.gptengineer_app.project_id == "..." config_dict = config.to_dict() # check that the config dict matches the input dict exactly (no keys/defaults added) assert config_dict == d def test_config_from_dict_with_openapi(): # A good test because it has 3 levels of nesting d = { "gptengineer-app": { "project_id": "...", "openapi": [ {"url": "https://api.gptengineer.app/openapi.json"}, ], } } config = Config.from_dict(d) assert config.gptengineer_app assert config.gptengineer_app.project_id == "..." assert config.gptengineer_app.openapi assert ( config.gptengineer_app.openapi[0].url == "https://api.gptengineer.app/openapi.json" ) def test_config_load_partial(): # Loads a partial config, and checks that the rest is not set (i.e. None) example_config = """ [gptengineer-app] project_id = "..." """.strip() with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: f.write(example_config) config = Config.from_toml(f.name) assert config.gptengineer_app assert config.gptengineer_app.project_id == "..." assert config.to_dict() toml_str = config.to_toml(f.name, save=False) assert toml_str == example_config # check that write+read is idempotent assert Config.from_toml(f.name) == config def test_config_update(): example_config = """ [gptengineer-app] project_id = "..." """.strip() with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: f.write(example_config) config = Config.from_toml(f.name) config.gptengineer_app = _GptEngineerAppConfig( project_id="...", openapi=[_OpenApiConfig(url="https://api.gptengineer.app/openapi.json")], ) config.to_toml(f.name) assert Config.from_toml(f.name) == config @pytest.mark.parametrize( "input_dict,expected", [ ({"a": 1, "b": None}, {"a": 1}), ({"a": 1, "b": {"c": None, "d": 2}}, {"a": 1, "b": {"d": 2}}), ({"a": 1, "b": {}}, {"a": 1}), ({"a": 1, "b": {"c": None}}, {"a": 1}), ( {"a": {"b": {"c": None}}, "d": {"e": {"f": 2}}, "g": None}, {"d": {"e": {"f": 2}}}, ), ( {"a": 1, "b": {"c": None, "d": {"e": None, "f": {}}}, "g": {"h": 2}}, {"a": 1, "g": {"h": 2}}, ), ], ) def test_filter_none(input_dict, expected): assert filter_none(input_dict) == expected