|
16 | 16 | LocalOutputNode, |
17 | 17 | LocalTransformationNode, |
18 | 18 | ) |
| 19 | +from feast.infra.compute_engines.utils import ENTITY_TS_ALIAS |
19 | 20 | from feast.repo_config import MaterializationConfig |
20 | 21 |
|
21 | 22 | backend = PandasBackend() |
@@ -78,6 +79,55 @@ def test_local_filter_node(): |
78 | 79 | assert result.data.num_rows == 3 |
79 | 80 |
|
80 | 81 |
|
| 82 | +@pytest.mark.parametrize("backend_name", ["pandas", "polars"]) |
| 83 | +@pytest.mark.parametrize( |
| 84 | + "ttl, expected_values", |
| 85 | + [(None, [20, 30, 40]), (timedelta(minutes=2), [20, 30])], |
| 86 | +) |
| 87 | +def test_local_filter_node_point_in_time(backend_name, ttl, expected_values): |
| 88 | + if backend_name == "polars": |
| 89 | + pytest.importorskip("polars") |
| 90 | + from feast.infra.compute_engines.backends.factory import BackendFactory |
| 91 | + |
| 92 | + # Rows as they look after the join with the entity dataframe: one row is |
| 93 | + # newer than the entity timestamp and one is older than the 2 minute TTL. |
| 94 | + joined_df = pd.DataFrame( |
| 95 | + { |
| 96 | + "entity_id": [1, 1, 2, 2], |
| 97 | + "value": [10, 20, 30, 40], |
| 98 | + "event_timestamp": [ |
| 99 | + now + timedelta(minutes=1), |
| 100 | + now - timedelta(minutes=1), |
| 101 | + now, |
| 102 | + now - timedelta(minutes=5), |
| 103 | + ], |
| 104 | + ENTITY_TS_ALIAS: [now] * 4, |
| 105 | + } |
| 106 | + ) |
| 107 | + context = create_context( |
| 108 | + node_outputs={"source": ArrowTableValue(pa.Table.from_pandas(joined_df))} |
| 109 | + ) |
| 110 | + |
| 111 | + filter_node = LocalFilterNode( |
| 112 | + name="filter", |
| 113 | + backend=BackendFactory.from_name(backend_name), |
| 114 | + ttl=ttl, |
| 115 | + column_info=ColumnInfo( |
| 116 | + join_keys=["entity_id"], |
| 117 | + feature_cols=["value"], |
| 118 | + ts_col="event_timestamp", |
| 119 | + created_ts_col=None, |
| 120 | + ), |
| 121 | + ) |
| 122 | + filter_node.add_input(MagicMock()) |
| 123 | + filter_node.inputs[0].name = "source" |
| 124 | + |
| 125 | + result = filter_node.execute(context) |
| 126 | + assert isinstance(result, ArrowTableValue) |
| 127 | + assert set(joined_df.columns) <= set(result.data.column_names) |
| 128 | + assert result.data.column("value").to_pylist() == expected_values |
| 129 | + |
| 130 | + |
81 | 131 | def test_local_aggregation_node(): |
82 | 132 | context = create_context( |
83 | 133 | node_outputs={"source": ArrowTableValue(pa.Table.from_pandas(sample_df))} |
|
0 commit comments