Skip to content

fix: close remaining #271 type-check gaps in class_expression.restriction - #274

Merged
Demirrr merged 1 commit into
developfrom
worktree-issue-271-type-checks
Aug 24, 2026
Merged

Demirrr merged 1 commit into
developfrom
worktree-issue-271-type-checks

Conversation

@Demirrr

@Demirrr Demirrr commented Aug 24, 2026

Copy link
Copy Markdown
Member

Summary

Follow-up to #272/#273. Audited every OWL-construct constructor for Python-side type checks per #271, and found #272 fixed OWLObjectCardinalityRestriction but left several parallel owlapy.class_expression.restriction constructors unvalidated:

  • OWLObjectSomeValuesFrom / OWLObjectAllValuesFrom: property/filler not checked
  • OWLObjectHasSelf: property not checked
  • OWLObjectHasValue: property/individual not checked
  • OWLDataCardinalityRestriction (backs OWLDataMinCardinality/Max/Exact): cardinality/property not checked -- its OWLObjectCardinalityRestriction sibling already had this from Added initial type checks #272
  • OWLDataSomeValuesFrom / OWLDataAllValuesFrom: property not checked
  • OWLDataHasValue: property/value not checked
  • OWLDatatypeRestriction: datatype/facet restrictions not checked
  • OWLFacetRestriction: facet not checked
  • OWLObjectOneOf / OWLDataOneOf: element checks existed but as a bare, -O-strippable assert; upgraded to raise TypeError for consistency with Added initial type checks #272. This also fixes a latent bug where a one-shot iterable argument was exhausted by the validation loop before being materialized into self._values, silently producing an empty result.

Deliberately left unchanged: owlapy.owl_data_ranges's OWLNaryDataRange/OWLDataComplementOf. I initially added the same strict OWLDataRange check there (the direct analogue of OWLNaryBooleanClassExpression/OWLObjectComplementOf, which #272 did fix), but it broke test_owlapy_nnf.py -- owlapy.utils.nnf.NNF deliberately reuses these two to wrap data-side class expressions (e.g. OWLDataSomeValuesFrom, OWLDataHasValue) during negation, not just genuine OWLDataRange instances. Enforcing strict OWLDataRange there would break NNF's existing, intentional behavior, so I reverted that part rather than force a fix that risks a circular import (owl_data_ranges.py would need to import OWLClassExpression from the class_expression package, which itself imports from owl_data_ranges.py) or subtly changes NNF semantics. Worth a dedicated design discussion if the team wants to tighten this further.

Also checked owlapy/swrl.py (SWRL atom/Rule constructors have no type checks at all) but left that out of scope -- separate, larger piece of work, flagged for a follow-up decision rather than bundled in here.

Test plan

  • ruff check owlapy tests/test_restriction_extra_coverage.py --line-length=200
  • PYTHONPATH=. pytest tests/test_restriction_extra_coverage.py -p no:warnings -q (28 passed, 14 new)
  • PYTHONPATH=. pytest --ignore=tests/test_z_do_last_ebr_retrieval.py -p no:warnings -q (1321 passed, 23 skipped, 1 pre-existing unrelated flaky timing failure in test_rdflib_reasoner_regression.py)
  • Confirmed the test_owlapy_nnf.py regression from the initial owl_data_ranges.py attempt is resolved after reverting that part

🤖 Generated with Claude Code

…tion

#272 fixed OWLObjectCardinalityRestriction but left several parallel
restriction constructors unvalidated: OWLObjectSomeValuesFrom/
OWLObjectAllValuesFrom (property/filler), OWLObjectHasSelf (property),
OWLObjectHasValue (property/individual), OWLDataCardinalityRestriction
(cardinality/property -- its Object-side sibling was already covered),
OWLDataSomeValuesFrom/OWLDataAllValuesFrom (property), OWLDataHasValue
(property/value), OWLDatatypeRestriction (datatype/facet restrictions),
and OWLFacetRestriction (facet). OWLObjectOneOf/OWLDataOneOf's element
checks are upgraded from a bare, -O-strippable assert to raise TypeError,
matching #272's convention; this also fixes a latent bug where a
one-shot iterable argument was exhausted by the validation loop before
being materialized, silently producing an empty result.

owlapy.owl_data_ranges's OWLNaryDataRange/OWLDataComplementOf were
deliberately left unchanged: owlapy.utils.nnf.NNF reuses them to wrap
data-side class expressions (e.g. OWLDataSomeValuesFrom) during
negation, not just genuine OWLDataRange instances -- a strict
OWLDataRange check there breaks NNF, as confirmed by the resulting
test_owlapy_nnf.py failures during development.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Demirrr
Demirrr marked this pull request as ready for review August 24, 2026 09:40
@Demirrr
Demirrr merged commit fee39db into develop Aug 24, 2026
4 checks passed
@Demirrr
Demirrr deleted the worktree-issue-271-type-checks branch August 24, 2026 09:42
phoenix20162016 pushed a commit to phoenix20162016/owlapy that referenced this pull request Sep 13, 2026
…l_data_ranges.py

Follow-up to dice-group#272/dice-group#273/dice-group#274, which audited every OWL-construct constructor
for Python-side type checks but explicitly left two areas open:

- owlapy/swrl.py had no type checks at all (Variable, ClassAtom,
  DataRangeAtom, ObjectPropertyAtom, DataPropertyAtom, SameAsAtom,
  DifferentFromAtom, BuiltInAtom, Rule). Adding checks to BuiltInAtom
  surfaced a latent bug in Atom.from_string's built-in-predicate branch:
  a misplaced `return` inside the arg-conversion loop meant only the
  first argument of a multi-arg built-in was ever converted to a
  DVariable/OWLLiteral, and non-variable args were wrapped as
  OWLNamedIndividual instead of OWLLiteral. Fixed both.

- owlapy/owl_data_ranges.py's OWLNaryDataRange/OWLDataComplementOf were
  deliberately left unchecked in dice-group#274 because owlapy.utils.nnf.NNF
  reuses them to wrap data-side class expressions (e.g.
  OWLDataSomeValuesFrom) during negation, not just genuine OWLDataRange
  instances -- a strict OWLDataRange check broke test_owlapy_nnf.py.
  Validated against OWLPropertyRange instead, the actual common base of
  OWLDataRange and OWLClassExpression already defined in that module,
  which accepts the NNF reuse pattern while still rejecting genuinely
  wrong types (str, int, OWLIndividual, ...).

This closes out the remaining scope of dice-group#271: every Python-Java mapping
now has Python-side type validation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M1RdTi68z3rkZzTohwSZ5F
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