You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by gi...@apache.org on 2026/09/07 06:25:52 UTC
(iceberg-python) branch main updated: fix: treat a .pyiceberg.yaml without a mapping as no config (#3915)
This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-python.git
The following commit(s) were added to refs/heads/main by this push:
new 75b74cfca fix: treat a .pyiceberg.yaml without a mapping as no config (#3915)
75b74cfca is described below
commit 75b74cfca0d0491e94c12c9da978eeb0bc05698a
Author: jackylee <qc...@gmail.com>
AuthorDate: Mon Sep 7 06:13:04 2026 +0000
fix: treat a .pyiceberg.yaml without a mapping as no config (#3915)
`_load_yaml` passed `strictyaml.load(...).data` straight to
`_lowercase_dictionary_keys`. For an empty or comment-only document that
value is a `str`, not a mapping, so the call raised
`AttributeError: 'str' object has no attribute 'items'`.
`Config()` runs at import time, so commenting out the file made
`import pyiceberg.catalog` fail with an error naming neither YAML nor the
file. Return `None` instead, which the annotated return type already allows
and which the caller already handles as "keep looking".
Co-authored-by: Claude Code <no...@anthropic.com>
---
pyiceberg/utils/config.py | 3 +++
tests/utils/test_config.py | 17 +++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/pyiceberg/utils/config.py b/pyiceberg/utils/config.py
index ab9b549d2..2b5baafa5 100644
--- a/pyiceberg/utils/config.py
+++ b/pyiceberg/utils/config.py
@@ -79,6 +79,9 @@ class Config:
with open(path, encoding=UTF8) as f:
yml_str = f.read()
file_config = strictyaml.load(yml_str).data
+ if not isinstance(file_config, dict):
+ # An empty or comment-only document parses as a string
+ return None
file_config_lowercase = _lowercase_dictionary_keys(file_config)
return file_config_lowercase
return None
diff --git a/tests/utils/test_config.py b/tests/utils/test_config.py
index 5cd6a7203..309821023 100644
--- a/tests/utils/test_config.py
+++ b/tests/utils/test_config.py
@@ -183,3 +183,20 @@ def test_config_lookup_order(
assert (
result["catalog"]["default"]["uri"] if result else None # type: ignore
) == expected_result, f"Unexpected configuration result. Expected: {expected_result}, Actual: {result}"
+
+
+@pytest.mark.parametrize("content", ["", "\n", "# only a comment\n"])
+def test_from_configuration_files_without_a_mapping(
+ monkeypatch: pytest.MonkeyPatch, tmp_path_factory: pytest.TempPathFactory, content: str
+) -> None:
+ """A file that holds no mapping should be treated as absent."""
+ pyiceberg_home = str(tmp_path_factory.mktemp("pyiceberg_home"))
+ empty_dir = str(tmp_path_factory.mktemp("empty"))
+ with open(os.path.join(pyiceberg_home, ".pyiceberg.yaml"), "w", encoding=UTF8) as file:
+ file.write(content)
+
+ monkeypatch.setenv("PYICEBERG_HOME", pyiceberg_home)
+ monkeypatch.setattr(os.path, "expanduser", lambda _: empty_dir)
+ monkeypatch.chdir(empty_dir)
+
+ assert Config()._from_configuration_files() is None