Skip to content

feat(gen-shacl): add --message-template for sh:message on property shapes#10

Open
jdsika wants to merge 1 commit intofeat/generators-default-languagefrom
feat/shaclgen-validation-messages
Open

feat(gen-shacl): add --message-template for sh:message on property shapes#10
jdsika wants to merge 1 commit intofeat/generators-default-languagefrom
feat/shaclgen-validation-messages

Conversation

@jdsika
Copy link
Copy Markdown

@jdsika jdsika commented Apr 25, 2026

Summary

Adds a --message-template CLI option to gen-shacl that generates sh:message literals on every SHACL property shape from a user-supplied template string. This enables SHACL validators (e.g. pyshacl) to produce human-friendly error messages identifying the specific constraint that was violated.

Depends on: #9 (--default-language flag)

Problem

LinkML's SHACL generator currently produces property shapes without sh:message. When SHACL validation fails, the error report contains only technical details (focus node, result path, constraint component) but no human-readable explanation. Users must manually trace the violation back to the source shape.

The SHACL specification (§2.1.5) explicitly supports sh:message for this purpose:

"Values of sh:message are either xsd:string literals or literals with a language tag."

Usage

gen-shacl --message-template '{class}.{name}: {title}' schema.yaml
gen-shacl --message-template 'Validation of {name} failed!' --default-language en schema.yaml

Supported placeholders

Placeholder Description Example
{name} Slot name (underscore-separated LinkML identifier) has_speed
{title} Slot title (human-readable), falls back to name Has Speed
{class} Enclosing class name Vehicle
{path} Property IRI http://example.org/hasSpeed

Changes

gen-shacl (shaclgen.py)

  • New message_template field with __post_init__ whitespace normalisation
  • Template expansion after sh:name / sh:description emission
  • Uses prop_pv_text for language tag support when combined with --default-language (sh:message gets language tag per SHACL §2.1.5)
  • Invalid/positional placeholders and format specs raise ValueError with helpful message (catches KeyError, IndexError, ValueError)
  • Empty and whitespace-only templates normalised to None (no sh:message emitted)
  • New --message-template Click CLI option

Tests (10 new)

  • Basic template with {name}, {title}, {class}, {path}
  • Title/class placeholder expansion
  • Backward compatibility (no template = no sh:message)
  • Invalid placeholder raises ValueError
  • Positional placeholder {0} raises ValueError
  • Format spec {name:d} raises ValueError
  • Empty string normalised to no emission
  • Whitespace-only normalised to no emission
  • Combined with --default-language (sh:message gets @en tag)

Backward compatibility

  • Default is None — existing behaviour is completely unchanged
  • Empty strings and whitespace-only values normalised to None

Standards compliance

Standard Requirement Status
SHACL §2.1.5 sh:message accepts xsd:string or rdf:langString
SHACL Core sh:message is non-validating metadata for error reports
pyshacl Preserves @lang tag on sh:resultMessage in reports ✅ Verified

Testing

  • 39 SHACL tests pass (22 existing + 7 C1 + 10 C2), 0 skipped
  • 3 rounds of adversarial review completed with 0 open bugs

@jdsika jdsika force-pushed the feat/shaclgen-validation-messages branch from ab3a0ff to 0f541b2 Compare April 26, 2026 12:51
@jdsika jdsika force-pushed the feat/generators-default-language branch from 0f263f0 to c3751dd Compare April 26, 2026 12:51
…apes

Add a --message-template CLI option to gen-shacl that generates
sh:message literals on every property shape from a user-supplied
template string.

Supported placeholders:
- {name}  - slot name (underscore-separated LinkML identifier)
- {title} - slot title (human-readable), falls back to name
- {class} - enclosing class name
- {path}  - property IRI

Example usage:
  gen-shacl --message-template 'Validation of {name} failed!' schema.yaml

This enables SHACL validators (e.g. pyshacl) to produce human-friendly
error messages identifying the specific constraint that was violated.

Changes:
- New message_template field on ShaclGenerator dataclass
- Template expansion after sh:name / sh:description emission
- Uses prop_pv_text for language tag support when combined with
  --default-language (sh:message gets language tag per SHACL 2.1.5)
- Invalid/positional placeholders and format specs raise ValueError
  with helpful message (catches KeyError, IndexError, ValueError)
- Empty and whitespace-only templates normalised to None (no emission)
- New --message-template Click CLI option
- 10 new tests: basic, title/class placeholders, backward-compat,
  invalid/positional/format-spec errors, empty/whitespace, combined

Signed-off-by: Carlo van Driesten <carlo.van-driesten@bmw.de>
@jdsika jdsika force-pushed the feat/generators-default-language branch from c3751dd to 06ac9fc Compare April 26, 2026 13:19
@jdsika jdsika force-pushed the feat/shaclgen-validation-messages branch from 0f541b2 to 39e9d7d Compare April 26, 2026 13:19
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