Skip to content
Merged
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 docs/docs/in_depth/feature-group-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ def match_feature_group_criteria(cls, feature_name, options, data_access_collect

Do not call `FeatureChainParser.match_configuration_feature_chain_parser` directly from a match hook: it raises on an option value the `PROPERTY_MAPPING` rejects, and an exception out of the hook aborts feature identification for every candidate, not just yours. `match_parser_criteria` turns that rejection into a non-match, and the reason still reaches the user in the "No feature groups found" error.

The options view depends on the caller: feature resolution passes declared (pre-default) options, while filter matching runs after intake and passes the resolved feature's effective (post-default) options merged onto the filter feature's own. Matching logic that reads option values can see different values on the two paths. See [Applying declared defaults](property-mapping.md#applying-declared-defaults).

### 2. PROPERTY_MAPPING Configuration

The `PROPERTY_MAPPING` defines how configuration-based features are validated:
Expand Down
10 changes: 6 additions & 4 deletions docs/docs/in_depth/property-mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,8 @@ For an engine-driven request intake has already run, so the compute-boundary cal
no-op. It carries the work only for direct `FeatureSet` use that bypasses the engine, and there the
collapsing twins raise instead of merging.

Both sites run *after* resolution, so materialization never changes **matching**. It does change
Both sites run *after* resolution, so materialization never changes **resolution matching** (filter
matching runs after intake and does observe materialized values, see below). It does change
how features **group**: intake materialization deliberately canonicalizes default-equivalent twins,
so a feature that passes a declared default explicitly and one that omits it become equal and merge
into a single feature (with a warning naming the duplicated request) instead of computing twice.
Expand All @@ -393,7 +394,7 @@ Which stage sees which view of the options:

| Stage | Options view |
| --- | --- |
| Parse, bind, match, resolve (subtype resolution applies defaults internally) | declared (pre-default) |
| Parse, bind, resolution match, resolve (subtype resolution applies defaults internally) | declared (pre-default) |
| `input_features()` and child option inheritance | declared (pre-default) |
| Splitting, planning, filter matching, `validate_input_features`, compute | effective (post-default) |

Expand All @@ -402,8 +403,9 @@ path the safety net materializes inside `run_calculate_feature`, which is after
`validate_input_features`, not before it.

Filter matching is the one place the same classmethod sees both views: `GlobalFilter` calls
`match_feature_group_criteria` again after intake, so it observes effective options where feature
resolution saw declared ones.
`match_feature_group_criteria` again after intake, passing the filter feature's own options
enriched from the resolved feature's effective ones (`unify_options`), so a key the filter feature
omits arrives materialized where feature resolution saw it declared.

``` python
graph_type = feature.options.get("graph_type") # the declared default when the caller omitted it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@ def match_feature_group_criteria(
variable ``MLODA_ALLOW_FORWARDED_NAME_MISMATCH=1`` downgrades this error to a
warning.

The options view depends on the caller: feature resolution passes declared (pre-default)
options, filter matching a post-intake merge. See ``FeatureGroup.match_feature_group_criteria``.

Args:
feature_name: Feature name to match
options: Options containing configuration
Expand Down
7 changes: 7 additions & 0 deletions mloda/core/abstract_plugins/feature_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,13 @@ def match_feature_group_criteria(
You can disallow them by removing them. However, often you can just use the default.
If you want to implement a concrete implementation, e.g. just accept specific names,
then you can overwrite this function.

The options view depends on the caller. Feature resolution passes declared (pre-default)
options. GlobalFilter matches a filter feature after intake, passing that feature's own
options enriched from the resolved feature's effective (post-default) ones: a key the filter
feature declares itself keeps its declared value, an omitted key arrives materialized.
Matching logic that reads option values can therefore see different values on the two paths.
See ``docs/in_depth/property-mapping.md`` ("Applying declared defaults").
"""

base_feature_name = cls.get_column_base_feature(feature_name)
Expand Down
Loading