Skip to content

Commit 1a7a274

Browse files
committed
testcode
1 parent 5cb8ee9 commit 1a7a274

File tree

5 files changed

+61
-22
lines changed

5 files changed

+61
-22
lines changed

tests/catalog/test_base.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,18 @@
1616
# under the License.
1717
# pylint:disable=redefined-outer-name
1818

19-
2019
from collections.abc import Generator
2120
from pathlib import PosixPath
2221

2322
import pytest
23+
from pytest_mock import MockFixture
2424

25-
from pyiceberg.catalog import Catalog, load_catalog
25+
from pyiceberg.catalog import Catalog, _get_env_config, load_catalog
2626
from pyiceberg.catalog.memory import InMemoryCatalog
2727
from pyiceberg.io import WAREHOUSE
2828
from pyiceberg.schema import Schema
2929
from pyiceberg.types import NestedField, StringType
30+
from pyiceberg.utils.config import Config
3031

3132

3233
@pytest.fixture
@@ -64,6 +65,20 @@ def test_load_catalog_has_type_and_impl() -> None:
6465
)
6566

6667

68+
def test_get_env_config_is_lazy_and_cached(mocker: MockFixture) -> None:
69+
original_config = _get_env_config()
70+
_get_env_config.cache_clear()
71+
config = Config({"catalog": {"test": {"type": "in-memory"}}})
72+
load_mock = mocker.patch("pyiceberg.catalog.Config.load", return_value=config)
73+
assert _get_env_config() is config
74+
assert _get_env_config() is config
75+
load_mock.assert_called_once()
76+
77+
_get_env_config.cache_clear()
78+
mocker.patch("pyiceberg.catalog.Config.load", return_value=original_config)
79+
assert _get_env_config() is original_config
80+
81+
6782
def test_catalog_repr(catalog: InMemoryCatalog) -> None:
6883
s = repr(catalog)
6984
assert s == "test.in_memory.catalog (<class 'pyiceberg.catalog.memory.InMemoryCatalog'>)"

tests/catalog/test_rest.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,18 +1887,18 @@ def test_catalog_from_environment_variables(catalog_config_mock: mock.Mock, rest
18871887

18881888

18891889
@mock.patch.dict(os.environ, EXAMPLE_ENV)
1890-
@mock.patch("pyiceberg.catalog._ENV_CONFIG.get_catalog_config")
1891-
def test_catalog_from_environment_variables_override(catalog_config_mock: mock.Mock, rest_mock: Mocker) -> None:
1890+
def test_catalog_from_environment_variables_override(rest_mock: Mocker) -> None:
18921891
rest_mock.get(
18931892
"https://other-service.io/api/v1/config",
18941893
json={"defaults": {}, "overrides": {}},
18951894
status_code=200,
18961895
)
18971896
env_config: RecursiveDict = Config._from_environment_variables({})
1898-
1899-
catalog_config_mock.return_value = cast(RecursiveDict, env_config.get("catalog")).get("production")
1900-
catalog = cast(RestCatalog, load_catalog("production", uri="https://other-service.io/api"))
1901-
assert catalog.uri == "https://other-service.io/api"
1897+
mock_env_config = mock.Mock()
1898+
mock_env_config.get_catalog_config.return_value = cast(RecursiveDict, env_config.get("catalog")).get("production")
1899+
with mock.patch("pyiceberg.catalog._get_env_config", return_value=mock_env_config):
1900+
catalog = cast(RestCatalog, load_catalog("production", uri="https://other-service.io/api"))
1901+
assert catalog.uri == "https://other-service.io/api"
19021902

19031903

19041904
def test_catalog_from_parameters_empty_env(rest_mock: Mocker) -> None:

tests/cli/test_console.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@
3939
def test_missing_uri(mocker: MockFixture, empty_home_dir_path: str) -> None:
4040
# mock to prevent parsing ~/.pyiceberg.yaml or {PYICEBERG_HOME}/.pyiceberg.yaml
4141
mocker.patch.dict(os.environ, values={"HOME": empty_home_dir_path, "PYICEBERG_HOME": empty_home_dir_path})
42-
mocker.patch("pyiceberg.catalog._ENV_CONFIG", return_value=Config())
42+
mocker.patch("pyiceberg.catalog._get_env_config", return_value=Config())
4343

4444
runner = CliRunner()
4545
result = runner.invoke(run, ["list"])
4646

4747
assert result.exit_code == 1
48-
assert result.output == "Could not initialize catalog with the following properties: {}\n"
48+
assert "URI missing, please provide using --uri" in result.output
4949

5050

5151
def test_hive_catalog_missing_uri_shows_helpful_error(mocker: MockFixture) -> None:
5252
mock_env_config = mocker.MagicMock()
5353
mock_env_config.get_catalog_config.return_value = {"type": "hive"}
54-
mocker.patch("pyiceberg.catalog._ENV_CONFIG", mock_env_config)
54+
mocker.patch("pyiceberg.catalog._get_env_config", return_value=mock_env_config)
5555

5656
runner = CliRunner()
5757
result = runner.invoke(run, ["--catalog", "my_hive_catalog", "list"])

tests/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ def _isolate_pyiceberg_config() -> None:
122122
from pyiceberg.utils.config import Config
123123

124124
with mock.patch.object(Config, "_from_configuration_files", return_value=None):
125-
_catalog_module._ENV_CONFIG = Config()
125+
_catalog_module._get_env_config.cache_clear()
126+
_catalog_module._get_env_config()
126127

127128

128129
def pytest_addoption(parser: pytest.Parser) -> None:

tests/utils/test_config.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,30 @@
2828

2929

3030
def test_config() -> None:
31-
"""To check if all the file lookups go well without any mocking"""
31+
"""Config() should be a pure empty container and perform no implicit IO."""
3232
assert Config()
33+
assert Config().config == {}
34+
35+
36+
def test_config_does_not_load_implicitly() -> None:
37+
with (
38+
mock.patch.object(Config, "_from_configuration_files") as from_files_mock,
39+
mock.patch.object(Config, "_from_environment_variables") as from_env_mock,
40+
):
41+
Config()
42+
43+
from_files_mock.assert_not_called()
44+
from_env_mock.assert_not_called()
3345

3446

3547
@mock.patch.dict(os.environ, EXAMPLE_ENV)
3648
def test_from_environment_variables() -> None:
37-
assert Config().get_catalog_config("production") == {"uri": "https://service.io/api"}
49+
assert Config.load().get_catalog_config("production") == {"uri": "https://service.io/api"}
3850

3951

4052
@mock.patch.dict(os.environ, EXAMPLE_ENV)
4153
def test_from_environment_variables_uppercase() -> None:
42-
assert Config().get_catalog_config("PRODUCTION") == {"uri": "https://service.io/api"}
54+
assert Config.load().get_catalog_config("PRODUCTION") == {"uri": "https://service.io/api"}
4355

4456

4557
@mock.patch.dict(
@@ -50,7 +62,7 @@ def test_from_environment_variables_uppercase() -> None:
5062
},
5163
)
5264
def test_fix_nested_objects_from_environment_variables() -> None:
53-
assert Config().get_catalog_config("PRODUCTION") == {
65+
assert Config.load().get_catalog_config("PRODUCTION") == {
5466
"s3.region": "eu-north-1",
5567
"s3.access-key-id": "username",
5668
}
@@ -59,7 +71,7 @@ def test_fix_nested_objects_from_environment_variables() -> None:
5971
@mock.patch.dict(os.environ, EXAMPLE_ENV)
6072
@mock.patch.dict(os.environ, {"PYICEBERG_CATALOG__DEVELOPMENT__URI": "https://dev.service.io/api"})
6173
def test_list_all_known_catalogs() -> None:
62-
catalogs = Config().get_known_catalogs()
74+
catalogs = Config.load().get_known_catalogs()
6375
assert "production" in catalogs
6476
assert "development" in catalogs
6577

@@ -71,7 +83,7 @@ def test_from_configuration_files(tmp_path_factory: pytest.TempPathFactory) -> N
7183
file.write(yaml_str)
7284

7385
os.environ["PYICEBERG_HOME"] = config_path
74-
assert Config().get_catalog_config("production") == {"uri": "https://service.io/api"}
86+
assert Config.load().get_catalog_config("production") == {"uri": "https://service.io/api"}
7587

7688

7789
def test_lowercase_dictionary_keys() -> None:
@@ -95,13 +107,13 @@ def test_from_configuration_files_get_typed_value(tmp_path_factory: pytest.TempP
95107

96108
os.environ["PYICEBERG_HOME"] = config_path
97109
with pytest.raises(ValueError):
98-
Config().get_bool("max-workers")
110+
Config.load().get_bool("max-workers")
99111

100112
with pytest.raises(ValueError):
101-
Config().get_int("legacy-current-snapshot-id")
113+
Config.load().get_int("legacy-current-snapshot-id")
102114

103-
assert Config().get_bool("legacy-current-snapshot-id")
104-
assert Config().get_int("max-workers") == 4
115+
assert Config.load().get_bool("legacy-current-snapshot-id")
116+
assert Config.load().get_int("max-workers") == 4
105117

106118

107119
@pytest.mark.parametrize(
@@ -183,3 +195,14 @@ def create_config_file(path: str, uri: str | None) -> None:
183195
assert (
184196
result["catalog"]["default"]["uri"] if result else None # type: ignore
185197
) == expected_result, f"Unexpected configuration result. Expected: {expected_result}, Actual: {result}"
198+
199+
200+
def test_load_reads_file_and_environment_once(monkeypatch: pytest.MonkeyPatch) -> None:
201+
monkeypatch.setenv("PYICEBERG_CATALOG__PRODUCTION__URI", "https://env.service.io/api")
202+
with mock.patch.object(
203+
Config, "_from_configuration_files", return_value={"catalog": {"production": {"type": "rest"}}}
204+
) as files_mock:
205+
config = Config.load()
206+
207+
files_mock.assert_called_once()
208+
assert config.get_catalog_config("production") == {"type": "rest", "uri": "https://env.service.io/api"}

0 commit comments

Comments
 (0)