|
14 | 14 | # KIND, either express or implied. See the License for the |
15 | 15 | # specific language governing permissions and limitations |
16 | 16 | # under the License. |
| 17 | +from __future__ import annotations |
| 18 | + |
17 | 19 | import time |
18 | 20 | from collections import defaultdict |
19 | 21 | from enum import Enum |
20 | | -from typing import Any, DefaultDict, Dict, List, Mapping, Optional |
| 22 | +from typing import TYPE_CHECKING, Any, DefaultDict, Dict, Iterable, List, Mapping, Optional |
21 | 23 |
|
22 | 24 | from pydantic import Field, PrivateAttr, model_serializer |
23 | 25 |
|
24 | 26 | from pyiceberg.io import FileIO |
25 | 27 | from pyiceberg.manifest import DataFile, DataFileContent, ManifestFile, read_manifest_list |
26 | 28 | from pyiceberg.partitioning import UNPARTITIONED_PARTITION_SPEC, PartitionSpec |
27 | 29 | from pyiceberg.schema import Schema |
| 30 | + |
| 31 | +if TYPE_CHECKING: |
| 32 | + from pyiceberg.table.metadata import TableMetadata |
28 | 33 | from pyiceberg.typedef import IcebergBaseModel |
29 | 34 |
|
30 | 35 | ADDED_DATA_FILES = "added-data-files" |
@@ -412,3 +417,12 @@ def _update_totals(total_property: str, added_property: str, removed_property: s |
412 | 417 | def set_when_positive(properties: Dict[str, str], num: int, property_name: str) -> None: |
413 | 418 | if num > 0: |
414 | 419 | properties[property_name] = str(num) |
| 420 | + |
| 421 | + |
| 422 | +def ancestors_of(current_snapshot: Optional[Snapshot], table_metadata: TableMetadata) -> Iterable[Snapshot]: |
| 423 | + """Get the ancestors of and including the given snapshot.""" |
| 424 | + if current_snapshot: |
| 425 | + yield current_snapshot |
| 426 | + if current_snapshot.parent_snapshot_id is not None: |
| 427 | + if parent := table_metadata.snapshot_by_id(current_snapshot.parent_snapshot_id): |
| 428 | + yield from ancestors_of(parent, table_metadata) |
0 commit comments