Skip to content

Fix two by_name() edge cases and add case_sensitive and match="contained" options#100

Open
gefleury wants to merge 5 commits into
openMetadataInitiative:pipelinefrom
gefleury:by-name-case-insensitive-and-embedded
Open

Fix two by_name() edge cases and add case_sensitive and match="contained" options#100
gefleury wants to merge 5 commits into
openMetadataInitiative:pipelinefrom
gefleury:by-name-case-insensitive-and-embedded

Conversation

@gefleury

Copy link
Copy Markdown

Four small, independent changes to by_name(), each with its own tests.

Fixes

  • by_name(..., all=True) could return the same instance twice: when an instance's name-like
    properties share a value or when match="contains" reaches it via several keys (bdec073).
  • match="contains" raised TypeError on instances with unset name-like properties, which were
    indexed under a None key (eg ParcellationEntity leaves abbreviation unset) (af66572).

New options

  • case_sensitive (default True, existing behaviour unchanged) (70ce3e8).
    • Uses casefold(), so Unicode variants like "µ"/"μ" also match.
    • Note 1 : it can merge instances differing only in case (covered by a test)
    • Note 2 : with case_sensitive=False, match="equals" can no longer use the dict lookup and
      scans all keys instead, so it drops from O(1) to O(n). That seems acceptable.
  • match="contained", the reverse of "contains": finds instances whose name-like properties are
    substrings of the given string. Motivated by NWB fields like "Mus musculus - House mouse" (056e80e).

Tests
Four tests added to pipeline/tests/test_regressions.py

gefleury added 5 commits July 16, 2026 14:44
by_name(..., all=True) could return the same instance more than once, for two reasons:
- an instance's own name-like properties (including synonyms) sharing a value (e.g. MolecularEntity.propofol)
- match="contains" reaching the same instance via several distinct keys (e.g. searching SovereignState for "FR" matches France via both its "FR" and "FRA" synonyms)

Deduplication preserves the original order, so the first match (all=False) is unaffected.
- hasattr(instance, prop_name) only checks whether the class defines the property, not whether this instance actually set it (every instance shares the same __init__ signature, with unset properties defaulting to None).
- As a result, an unset property (e.g. ParcellationEntity without an abbreviation) was still indexed, leaving None as a  lookup key.
- match="contains" then crashed with TypeError, since `name in key` is invalid when key is None.
- The fix only appends a name-like property to the lookup keys when its value is not None.
- by_name() gains a case_sensitive parameter (default True, preserving current behavior).
- When False, equals/contains comparisons use casefold() instead of lower(), so Unicode variants like the micro sign "µ" and the Greek letter "μ" are also treated as equivalent.
- Case-insensitive matching can merge results from genuinely different instances that only differ by case (e.g. MolecularEntity "pentobarbital" vs "pentobarbital sodium").
- Add tests reusing test_issue0069's License examples with flipped case, plus the MolecularEntity merge case and the Unicode casefold case.
by_name() gains match="contained", the reverse of "contains": finds instances whose name-like properties are substrings of the given string. Useful for NWB files: their fields often combine a canonical name with extra free text (e.g. "Mus musculus - House mouse"), embedding the openMINDS instance name inside a longer, non-canonical string.
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.

1 participant