|
17 | 17 |
|
18 | 18 | import base64 |
19 | 19 | import datetime as py_datetime |
| 20 | +import importlib |
20 | 21 | import struct |
| 22 | +import types |
21 | 23 | from abc import ABC, abstractmethod |
22 | 24 | from enum import IntEnum |
23 | 25 | from functools import singledispatch |
|
28 | 30 | import mmh3 |
29 | 31 | from pydantic import Field, PositiveInt, PrivateAttr |
30 | 32 |
|
| 33 | +from pyiceberg.exceptions import NotInstalledError |
31 | 34 | from pyiceberg.expressions import ( |
32 | 35 | BoundEqualTo, |
33 | 36 | BoundGreaterThan, |
|
106 | 109 | TRUNCATE_PARSER = ParseNumberFromBrackets(TRUNCATE) |
107 | 110 |
|
108 | 111 |
|
| 112 | +def _try_import(module_name: str, extras_name: Optional[str] = None) -> types.ModuleType: |
| 113 | + try: |
| 114 | + return importlib.import_module(module_name) |
| 115 | + except ImportError: |
| 116 | + if extras_name: |
| 117 | + msg = f'{module_name} needs to be installed. pip install "pyiceberg[{extras_name}]"' |
| 118 | + else: |
| 119 | + msg = f"{module_name} needs to be installed." |
| 120 | + raise NotInstalledError(msg) from None |
| 121 | + |
| 122 | + |
109 | 123 | def _transform_literal(func: Callable[[L], L], lit: Literal[L]) -> Literal[L]: |
110 | 124 | """Small helper to upwrap the value from the literal, and wrap it again.""" |
111 | 125 | return literal(func(lit.value)) |
@@ -382,8 +396,7 @@ def __repr__(self) -> str: |
382 | 396 | return f"BucketTransform(num_buckets={self._num_buckets})" |
383 | 397 |
|
384 | 398 | def pyarrow_transform(self, source: IcebergType) -> "Callable[[pa.Array], pa.Array]": |
385 | | - from pyiceberg_core import transform as pyiceberg_core_transform |
386 | | - |
| 399 | + pyiceberg_core_transform = _try_import("pyiceberg_core", extras_name="pyiceberg-core").transform |
387 | 400 | return _pyiceberg_transform_wrapper(pyiceberg_core_transform.bucket, self._num_buckets) |
388 | 401 |
|
389 | 402 | @property |
@@ -509,9 +522,8 @@ def __repr__(self) -> str: |
509 | 522 | return "YearTransform()" |
510 | 523 |
|
511 | 524 | def pyarrow_transform(self, source: IcebergType) -> "Callable[[pa.Array], pa.Array]": |
512 | | - import pyarrow as pa |
513 | | - from pyiceberg_core import transform as pyiceberg_core_transform |
514 | | - |
| 525 | + pa = _try_import("pyarrow") |
| 526 | + pyiceberg_core_transform = _try_import("pyiceberg_core", extras_name="pyiceberg-core").transform |
515 | 527 | return _pyiceberg_transform_wrapper(pyiceberg_core_transform.year, expected_type=pa.int32()) |
516 | 528 |
|
517 | 529 |
|
@@ -570,8 +582,8 @@ def __repr__(self) -> str: |
570 | 582 | return "MonthTransform()" |
571 | 583 |
|
572 | 584 | def pyarrow_transform(self, source: IcebergType) -> "Callable[[pa.Array], pa.Array]": |
573 | | - import pyarrow as pa |
574 | | - from pyiceberg_core import transform as pyiceberg_core_transform |
| 585 | + pa = _try_import("pyarrow") |
| 586 | + pyiceberg_core_transform = _try_import("pyiceberg_core", extras_name="pyiceberg-core").transform |
575 | 587 |
|
576 | 588 | return _pyiceberg_transform_wrapper(pyiceberg_core_transform.month, expected_type=pa.int32()) |
577 | 589 |
|
@@ -639,8 +651,8 @@ def __repr__(self) -> str: |
639 | 651 | return "DayTransform()" |
640 | 652 |
|
641 | 653 | def pyarrow_transform(self, source: IcebergType) -> "Callable[[pa.Array], pa.Array]": |
642 | | - import pyarrow as pa |
643 | | - from pyiceberg_core import transform as pyiceberg_core_transform |
| 654 | + pa = _try_import("pyarrow", extras_name="pyarrow") |
| 655 | + pyiceberg_core_transform = _try_import("pyiceberg_core", extras_name="pyiceberg-core").transform |
644 | 656 |
|
645 | 657 | return _pyiceberg_transform_wrapper(pyiceberg_core_transform.day, expected_type=pa.int32()) |
646 | 658 |
|
@@ -692,7 +704,7 @@ def __repr__(self) -> str: |
692 | 704 | return "HourTransform()" |
693 | 705 |
|
694 | 706 | def pyarrow_transform(self, source: IcebergType) -> "Callable[[pa.Array], pa.Array]": |
695 | | - from pyiceberg_core import transform as pyiceberg_core_transform |
| 707 | + pyiceberg_core_transform = _try_import("pyiceberg_core", extras_name="pyiceberg-core").transform |
696 | 708 |
|
697 | 709 | return _pyiceberg_transform_wrapper(pyiceberg_core_transform.hour) |
698 | 710 |
|
@@ -915,7 +927,7 @@ def __repr__(self) -> str: |
915 | 927 | return f"TruncateTransform(width={self._width})" |
916 | 928 |
|
917 | 929 | def pyarrow_transform(self, source: IcebergType) -> "Callable[[pa.Array], pa.Array]": |
918 | | - from pyiceberg_core import transform as pyiceberg_core_transform |
| 930 | + pyiceberg_core_transform = _try_import("pyiceberg_core", extras_name="pyiceberg-core").transform |
919 | 931 |
|
920 | 932 | return _pyiceberg_transform_wrapper(pyiceberg_core_transform.truncate, self._width) |
921 | 933 |
|
|
0 commit comments