|
19 | 19 | import math |
20 | 20 | import threading |
21 | 21 | from abc import ABC, abstractmethod |
22 | | -from collections.abc import Iterator |
| 22 | +from collections.abc import Callable, Iterator |
23 | 23 | from copy import copy |
24 | 24 | from enum import Enum |
25 | 25 | from types import TracebackType |
@@ -883,6 +883,40 @@ def fetch_manifest_entry(self, io: FileIO, discard_deleted: bool = True) -> list |
883 | 883 | if not discard_deleted or entry.status != ManifestEntryStatus.DELETED |
884 | 884 | ] |
885 | 885 |
|
| 886 | + def prune_manifest_entry( |
| 887 | + self, io: FileIO, partition_filter: Callable[[DataFile], bool], metrics_evaluator: Callable[[DataFile], bool] |
| 888 | + ) -> list[ManifestEntry]: |
| 889 | + """ |
| 890 | + Read manifest entries, applying partition and metrics evaluator during deserialization. |
| 891 | +
|
| 892 | + Unlike fetch_manifest_entry followed by a separate filer pass, this fuses filtering |
| 893 | + into the deserialization loop, avoiding the intermediate list allocation for |
| 894 | + non-matching entries. |
| 895 | +
|
| 896 | + Args: |
| 897 | + io: The FileIO to fetch the file. |
| 898 | + partition_filter: Evaluates the entry's partition data. |
| 899 | + metrics_evaluator: Evaluates the entry's column-level metrics. |
| 900 | +
|
| 901 | + Returns: |
| 902 | + An Iterator of manifest entries matching both filters. |
| 903 | + """ |
| 904 | + input_file = io.new_input(self.manifest_path) |
| 905 | + with AvroFile[ManifestEntry]( |
| 906 | + input_file, |
| 907 | + MANIFEST_ENTRY_SCHEMAS[DEFAULT_READ_VERSION], |
| 908 | + read_types={-1: ManifestEntry, 2: DataFile}, |
| 909 | + read_enums={0: ManifestEntryStatus, 101: DataFileContent}, |
| 910 | + ) as reader: |
| 911 | + result = [] |
| 912 | + for entry in reader: |
| 913 | + if entry.status != ManifestEntryStatus.DELETED: |
| 914 | + _inherit_from_manifest(entry, self) |
| 915 | + if partition_filter(entry.data_file) and metrics_evaluator(entry.data_file): |
| 916 | + result.append(entry) |
| 917 | + |
| 918 | + return result |
| 919 | + |
886 | 920 | def __eq__(self, other: Any) -> bool: |
887 | 921 | """Return the equality of two instances of the ManifestFile class.""" |
888 | 922 | return self.manifest_path == other.manifest_path if isinstance(other, ManifestFile) else False |
|
0 commit comments