fix(shaclgen): emit sh:maxCount 0 for zero maximum_cardinality#12
Open
jdsika wants to merge 1 commit into
Open
fix(shaclgen): emit sh:maxCount 0 for zero maximum_cardinality#12jdsika wants to merge 1 commit into
jdsika wants to merge 1 commit into
Conversation
jdsika
added a commit
that referenced
this pull request
May 2, 2026
Apply same fix as fix/shaclgen-maxcount-zero branch to develop. Change truthiness checks to explicit `is not None` comparisons for minimum_cardinality and maximum_cardinality in SHACL generator. See: #12
jdsika
added a commit
that referenced
this pull request
May 2, 2026
Restore shaclgen.py (accidentally emptied) and apply the is-not-None fix for minimum/maximum_cardinality checks. See: #12
abe3f1c to
4f0020c
Compare
7 tasks
3ec940e to
4bc7b3d
Compare
Python truthiness check `if s.maximum_cardinality:` evaluates to False when the value is 0 (an integer), silently skipping sh:maxCount 0 emission. The same bug affected minimum_cardinality and exact_cardinality. Replace all three truthiness checks with explicit `is not None` guards: - `if s.minimum_cardinality is not None:` - `if s.maximum_cardinality is not None:` - `elif s.exact_cardinality is not None:` (two occurrences) Add regression tests: - test_zero_maximum_cardinality_emits_maxcount - test_zero_exact_cardinality_emits_both_counts This is the primary mechanism for suppressing inherited slots on subclasses via slot_usage (OWL maxCardinality 0 pattern). Signed-off-by: Carlo van Driesten <carlo.van-driesten@bmw.de>
ae4b34a to
5544abc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix a Python truthiness bug in the SHACL generator that prevents
sh:maxCount 0andsh:minCount 0from being emitted whenmaximum_cardinality: 0orminimum_cardinality: 0is set in a LinkML schema.Problem
In
shaclgen.py, the cardinality checks use Python truthiness:Since
0evaluates asFalsein Python, settingmaximum_cardinality: 0(which should emitsh:maxCount 0meaning "this property MUST NOT appear") produces no output at all.Root Cause
The condition
if s.maximum_cardinality:fails when the value is0because Python treats0as falsy. The correct check isif s.maximum_cardinality is not None:which distinguishes "not set" from "explicitly set to zero".Fix
Changed both checks to use explicit
is not Nonecomparisons:This matches the pattern already used in the OWL generator (
owlgen.pylines 627-640) for the same attributes.Verification
sh:maxCount 0(means "property must not exist on any conforming node")is not Noneand emitsowl:maxCardinality 0is not Nonefor the same field (line 693)sh:maxCount 0appears in generated outputUse Case
This is needed for modeling class hierarchies where subclasses restrict inherited properties. For example,
slot_usagewithmaximum_cardinality: 0is the idiomatic way in LinkML to express "this inherited slot is not applicable on this subclass" --- but without this fix, the SHACL output silently omits the constraint.Testing
ChildWithZeroMaxCardclass totests/linkml/test_generators/input/shaclgen/cardinality.yamltest_zero_maximum_cardinality_emits_maxcountregression test totest_shaclgen.pyis not Nonecheck)Note on
exact_cardinalityThe
elif s.exact_cardinality:branches (lines 174, 184) have the same truthiness issue for the value0. However,exact_cardinality: 0is semantically degenerate (a list with exactly zero items is the same as a forbidden property) and extremely unlikely in practice. This fix focuses on the common and semantically meaningful case. A follow-up can addressexact_cardinalityif needed.