Repository navigation
feat: enforce binding obligation levels and nested binds_value_of paths - #83
Conversation
|
Claude finished @cmungall's task in 1m 20s —— View job PR #83 review: binding obligation levels and nested
|
- Refactor multi-binding validation into two-pass `_validate_bindings_for_value` so enum membership runs across all bindings before deduplicated existence, `Not4Curation`, and label checks (making `Not4Curation` suppression on hard-rejected terms independent of binding order in the schema) - Precompute `(class, slot) -> range` and normalized `obligation_level` maps in `pre_process` for O(1) per-instance lookups - Introduce `_PathCursor` NamedTuple and deduplicate dict step logic in `_step_segment`; add doctests and absent-field notes on `_extract_targets` - Remove `ENCOURAGED` alias suggestion from YAML schema docs and document absent/`null` field behavior and `severity_overrides` precedence - Add 10 parametrized test cases covering absent/`null` bound fields, `severity_overrides` precedence, binding-order independence, offline unmaterialized dynamic enums under `RECOMMENDED`/`DISCOURAGED`, multivalued leaf list container labels, and partial list fan-out
|
Claude finished @cmungall's task in 1m 7s —— View job Re-review of PR #83 after 763ee1e
The follow-up commit fixes every point from my first review. I found nothing that should block merging. Only small items remain. How the earlier points were handled
Remaining small items (all optional)1.
2. Some state is reset in 3. Keying levels by 4. Behavior to keep in mind: existence checks now run for 5. Wording leftovers
SecurityNothing new. No new exception text reaches messages, so the Test coverageThe new tests cover each gap I listed before: absent/ |
- Reset `bindings_map`, `slot_properties_map`, and `expanded_enums` in `pre_process` so reusing a `BindingValidationPlugin` across schemas starts cleanly - Replace `id(binding)`-keyed obligation level cache with parallel `_slot_binding_levels` indexed alongside `bindings_map` - Remove cross-class fallback in label `range_class` resolution (which could pick an unrelated class's slot range) and scope `_get_binding_range_class` to `target_class` when provided - Document and test that `OPTIONAL` and `EXAMPLE` skip enum membership only while strict existence and label checks still run - Add test covering plugin reuse across schemas and `target_class`-scoped `range_class` lookup
|
Claude finished @cmungall's task in 1m 42s —— View job Re-review of PR #83 after 2d8612b
This commit deals with every optional item from my last review. I found nothing that blocks merging. LGTM. How the earlier items were handled
Remaining small items (all optional)
Code quality, performance, security
Test coverageThe two new tests cover the behavior from my last round: |
Summary
Tightens
BindingValidationPluginto enforce LinkMLEnumBinding.obligation_levelacross all metamodel levels and support multi-levelbinds_value_ofpath resolution with.as the implicit default:.default & multi-levelbinds_value_ofpaths:binds_value_of(or setting./"") binds the slot's own value directly (single or multivalued scalar slots). Non-scalar values at.emit a cleanbinding_validationresult instead of raisingTypeError.term.id,wrapper.term.id) resolve nested objects and track the immediate enclosing dict + its LinkML class sovalidate_labelschecks the right label slot (implements: [rdfs:label],slot_uri, orlabel) and reports the exact nested path.coding.code/coding[*].code, as well as multivalued leaf lists) validates every item; explicit integer indices (extensions.0.value/extensions[0].value) constrain only that element.obligation_levelenforcement:REQUIRED(default when unset):ERRORwhen value is outside enumRECOMMENDED(andENCOURAGEDalias):WARNwhen value is outside enum (without suppressingERRORfromNot4Curationor strict existence/label checks)OPTIONAL/EXAMPLE: skips enum membership (and skips greedy dynamic-enum pre-expansion inpre_processwhen only referenced byOPTIONAL/EXAMPLEbindings)DISCOURAGED:WARNwhen value is inside the enumNot4Curation, and label checks across multiple bindings composed on the same slot (REQUIRED+RECOMMENDED+DISCOURAGED), and respectsseverity_overrides.Test plan
tests/test_binding_obligations_and_nesting.pycovering static/dynamic enums, progressive/greedy caching, all 5 obligation levels, multi-binding composition, scalar.bindings, nested dict paths, list fan-out, and explicit integer indicessrc/linkml_term_validator/plugins/binding_plugin.pydocs/binding-validation.md,docs/bindings-explained.md, anddocs/plugin-reference.md