Skip to content

Validate change/variable targets against the model they reference - #168

Open
jcschaff wants to merge 2 commits into
biosimulators:devfrom
jcschaff:fix/setvalue-target-validated-against-wrong-model
Open

Validate change/variable targets against the model they reference#168
jcschaff wants to merge 2 commits into
biosimulators:devfrom
jcschaff:fix/setvalue-target-validated-against-wrong-model

Conversation

@jcschaff

@jcschaff jcschaff commented Aug 6, 2026

Copy link
Copy Markdown
Member

Fixes #167.

validate_doc reports valid repeatedTask setValue targets as invalid, because the XPath is evaluated against the last <model> in the document rather than the model the change references.

Cause

model_etrees is built in for model in doc.models: (L131, rebound at L229). Three later validate_target(...) calls then read model_etrees.get(model, None) — the leaked loop variable, which by then is always the last model — where they mean the model belonging to the change or variable being validated:

line context now passes
359 repeated-task change variable model_etrees.get(variable.model, None)
509 repeated-task setValue change target model_etrees.get(change.model, None)
551 setValue variable model_etrees.get(variable.model, None)

Every other argument at those call sites already comes from change.model / variable.model — only the etree was taken from the stale name. That is why the message names a model that was never searched, and the element it claims is missing is plainly present in the named model's source.

L190 and L1408 also read model_etrees.get(model, ...) but use genuine loop variables; they are untouched.

Test

test_validate_repeated_task_xpaths_use_the_referenced_model validates one document twice, swapping only the order of two models in doc.models. The change references the same model and carries the same target both times, so both orderings must be valid.

On dev the new test fails in one ordering with exactly the reported message:

AssertionError: Lists differ: [['Task `task2` is invalid.', ...
-  'does not match any elements of model `model1`.']]]]]]]] : unexpected errors with model order ['model1', 'model2']

and passes in the other — the ordering alone decides it. With the fix both orderings pass.

The existing repeated-task fixtures (BIOMD0000000297_repeat_*.sedml) all have a single model, where the leaked variable happens to equal the correct one, which is why this went unnoticed.

Verification

tests/sedml/ run against this branch versus the same clone with only the validation.py change reverted:

failures
without fix 4 — 3 pre-existing + the new test
with fix 3 — the 3 pre-existing only

The 3 pre-existing failures (test_validate_model_with_language, test_get_parameters_variables_for_simulation, test_build_combine_archive_for_model_xpp_with_plot) are missing optional dependencies in my environment — ModuleNotFoundError: No module named 'libcellml' and XPP — and fail identically before and after. Nothing else changes.

Deliberately not included

Two adjacent points raised in #167 are left out, since they are behaviour calls rather than clear bugs and I did not want to bundle them:

  • L551 passes model_change=change.model and change.model.has_structural_changes() where its sibling at L359 uses variable.model. Since the target validated there is variable.target, variable.model looks right, but it can turn warnings into errors for some documents.
  • Model.has_structural_changes() returns True for ModelAttributeChange, contradicting its docstring (add/replace/remove only). This is what demotes genuine XPath misses to warnings for any model carrying changes, so it masked half of this bug — but tightening it would surface errors in documents that validate today.

Happy to fold either in, or open them separately, whichever you prefer.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SvqmME7MkRUNEYje5HpiLt

`validate_doc` builds `model_etrees` in `for model in doc.models:`, then three
later `validate_target(...)` calls read `model_etrees.get(model, None)` - the
leaked loop variable, which by then is always the last model in the document -
where they mean the model belonging to the change or variable being validated.

Every other argument at those call sites already comes from `change.model` /
`variable.model`; only the etree was taken from the stale name, so the error
names a model that was never searched:

    XPath `...parameter[@id='pA']/@value` does not match any elements of
    model `modelA`.

reported for a target that does resolve against modelA's source.

The two other readers of `model_etrees.get(model, ...)`, at L190 and L1408,
use genuine loop variables and are left alone.

Fixes biosimulators#167
Validates one document twice, swapping only the order of two models in
`doc.models`. The setValue references the same model and carries the same
target both times, so both orderings must be valid; before the previous
commit the ordering alone decided it.

The existing repeated-task fixtures all have a single model, where the leaked
variable happens to equal the right model - which is why this went unnoticed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

SED-ML validation checks setValue/change targets against the last model in the document instead of the referenced model

1 participant