Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyiceberg/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ def _import_file_io(io_impl: str, properties: Properties) -> FileIO | None:
module_name, class_name = ".".join(path_parts[:-1]), path_parts[-1]
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
if not isinstance(class_, type) or not issubclass(class_, FileIO):
raise ValueError(f"py-io-impl should be a subclass of FileIO, got: {io_impl}")
return class_(properties)
except ModuleNotFoundError:
logger.warning(f"Could not initialize FileIO: {io_impl}", exc_info=logger.isEnabledFor(logging.DEBUG))
Expand Down
2 changes: 2 additions & 0 deletions pyiceberg/io/pyarrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ def _import_retry_strategy(impl: str) -> S3RetryStrategy | None:
module_name, class_name = ".".join(path_parts[:-1]), path_parts[-1]
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
if not isinstance(class_, type) or not issubclass(class_, S3RetryStrategy):
raise ValueError(f"retry-strategy-impl should be a subclass of S3RetryStrategy, got: {impl}")
return class_()
except (ModuleNotFoundError, AttributeError):
warnings.warn(f"Could not initialize S3 retry strategy: {impl}", stacklevel=2)
Expand Down
4 changes: 4 additions & 0 deletions pyiceberg/table/locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ def _import_location_provider(
module_name, class_name = ".".join(path_parts[:-1]), path_parts[-1]
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
if not isinstance(class_, type) or not issubclass(class_, LocationProvider):
raise ValueError(
f"write.py-location-provider.impl should be a subclass of LocationProvider, got: {location_provider_impl}"
)
return class_(table_location, table_properties)
except ModuleNotFoundError:
logger.warning(
Expand Down
5 changes: 5 additions & 0 deletions tests/io/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ def test_import_file_io() -> None:
assert isinstance(_import_file_io(ARROW_FILE_IO, {}), PyArrowFileIO)


def test_import_file_io_wrong_type() -> None:
with pytest.raises(ValueError, match="py-io-impl should be a subclass of FileIO"):
_import_file_io("pyiceberg.table.locations.SimpleLocationProvider", {})


def test_import_file_io_does_not_exist(caplog: Any) -> None:
import logging

Expand Down
6 changes: 6 additions & 0 deletions tests/io/test_pyarrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3309,6 +3309,12 @@ def test_retry_strategy() -> None:
io.new_input("s3://bucket/path/to/file")


def test_retry_strategy_wrong_type() -> None:
io = PyArrowFileIO(properties={S3_RETRY_STRATEGY_IMPL: "pyiceberg.io.FileIO"})
with pytest.raises(ValueError, match="retry-strategy-impl should be a subclass of S3RetryStrategy"):
io.new_input("s3://bucket/path/to/file")


def test_retry_strategy_not_found() -> None:
io = PyArrowFileIO(properties={S3_RETRY_STRATEGY_IMPL: "pyiceberg.DoesNotExist"})
with pytest.warns(UserWarning, match="Could not initialize S3 retry strategy: pyiceberg.DoesNotExist"):
Expand Down
8 changes: 8 additions & 0 deletions tests/table/test_locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ def test_custom_location_provider() -> None:
assert provider.new_data_location("my_file") == "custom_location_provider/my_file"


def test_custom_location_provider_wrong_type() -> None:
with pytest.raises(ValueError, match="write.py-location-provider.impl should be a subclass of LocationProvider"):
load_location_provider(
table_location="table_location",
table_properties={"write.py-location-provider.impl": "pyiceberg.io.FileIO"},
)


def test_custom_location_provider_single_path() -> None:
with pytest.raises(ValueError, match=r"write\.py-location-provider\.impl should be full path"):
load_location_provider(table_location="table_location", table_properties={"write.py-location-provider.impl": "not_found"})
Expand Down
Loading