Skip to content

No way to read a derived property with a default (#178) - #181

Merged
headmeister merged 2 commits into
isi-nmr:masterfrom
gdevenyi:fix/property-get-default
Jul 27, 2026
Merged

No way to read a derived property with a default (#178)#181
headmeister merged 2 commits into
isi-nmr:masterfrom
gdevenyi:fix/property-get-default

Conversation

@gdevenyi

Copy link
Copy Markdown
Contributor

Fixes #178.

dataset.get("TE")           # 4.0, or None where the scan records no echo time
dataset.get("TE", "n/a")    # 4.0, or "n/a"
dataset.get("TEE")          # AttributeError -- a typo does not become the default

The issue's optional distinction is implemented, because it is what makes get safe to reach for: a name no configuration declares still raises, and a property that fails for a reason of its own still raises that reason rather than reporting an absence:

spectroscopy.get("affine")  # UnsupportedDatasetType: ... rather than purely spatial

Telling "declared but unresolved" from "never a property" needs the set of declared names, so _add_property records each name whether or not its recipe resolves (_declared_properties, cleared by unload_properties alongside _properties).

Measured on our corpus

1626 vendor 2dseq reconstructions (PV 5.1 – 360.3.7):

property resolves raises get() == attribute where it resolves default returned where it raises
TE 1563 63 1563 / 1563 63 / 63
TR 1572 54 1572 / 1572 54 / 54
extent, resolution 1591 35 1591 / 1591 35 / 35
imaging_frequency 1588 38 1588 / 1588 38 / 38

get changes nothing where the property resolves. For TE, TR and imaging_frequency the underlying parameter is absent in every raising case, confirming the information content is the same and only the failure mode differs.

Note for review

Dataset.__getitem__ returns a parameter while get returns a property, so d["TE"] raises KeyError where d.get("TE") returns a value. That asymmetry is inherent to naming it get — the docstring says which layer it reads, and get_property would be unambiguous if you prefer it. I kept the name the issue asked for.

Suite: 2112 passed, 12 skipped. The 5 test_affine_agrees_with_the_paravision_nifti_sform failures are the same ones master has.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NuK1cZi8U54WXAdXMmGpzy

A recipe whose conditions do not match, or whose parameters the files do not
contain, leaves its property unset, so an absent property and a misspelled one
are the same AttributeError and neither can be given a default. Which
properties exist is ParaVision-version dependent, so this is the normal case,
not an edge: over the 1626 reconstructions of our corpus that load, TE does not
resolve for 63, TR for 54, extent/resolution for 35, imaging_frequency for 38.

The only workaround is try/except at every access, which also swallows typos
and genuine errors raised by a recipe's cmd -- so a consumer ends up reading
the underlying parameters directly instead, which is the point of having
derived properties at all.

`Dataset.get(name, default=None)` returns the default where the recipe does not
resolve, matching the shape `JCAMPDX.get_value` already establishes for
parameters. A name no configuration declares still raises, so a misspelling
does not quietly become the default, and a property that fails for a reason of
its own -- `affine` on a scan with no image geometry -- still raises that
reason rather than reporting an absence. Telling the two apart needs the set of
declared property names, which `_add_property` now records whether or not the
recipe resolves.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NuK1cZi8U54WXAdXMmGpzy
Copilot AI review requested due to automatic review settings July 26, 2026 18:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@headmeister
headmeister merged commit f29fe2b into isi-nmr:master Jul 27, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No way to read a derived property with a default: absent and misspelled both raise AttributeError

3 participants