File size: 4,270 Bytes
3860419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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