Skip to content

feat(bindings): add UNDEFINED sentinels for unbound binding values - #78

Merged
david-debest merged 3 commits into
mainfrom
75-feat/sentinel-values
Oct 19, 2026
Merged

david-debest merged 3 commits into
mainfrom
75-feat/sentinel-values

Conversation

@david-debest

Copy link
Copy Markdown
Contributor

Fixes #75

What

The Knowledge Engine has no optional values in bindings. This adds two sentinels that serialize to <http://www.knowledge-engine.eu/mapper/undefined>:

Sentinel Type Use for
UNDEFINED URIRef Uri fields
UNDEFINED_LITERAL single member of enum UndefinedLiteral Literal[T], Datatype-annotated and RdfLiteral fields
  • Incoming bindings with the URI deserialize to the sentinel that matches the field type (check with is), never to None.
  • Using the wrong sentinel for a field type raises a ValidationError, and pyright flags it too.
  • None is not converted automatically; dump_result_binding() still rejects it.
  • In dump_partial_binding() and matches_with, the sentinels are concrete values, not wildcards.

Why an enum for literals

Pyright accepts an enum member in literal fields and narrows it away. For a Literal[int] field, x is not None and x is not UNDEFINED_LITERAL narrows to int. A URIRef sentinel can't be narrowed like that.

Typing change: literal field hints are now T | UndefinedLiteral | None. Pyright will flag code that only checks for None before using a literal value.

The enum branch is Strict(), so a bare URI string (no <>) is not turned into the sentinel.

Docs

README (API section and examples table), examples/README.md, CONTEXT.md, and a new examples/13-undefined_values.py.

Testing

  • uv run pytest: all tests pass, including new sentinel tests in tests/test_bindings.py.
  • Typing checked with pyright 1.1.414 against the package; it isn't part of the project tooling.
  • The example handler was called directly; it was not run against a live KE.

Related

david-debest and others added 2 commits October 19, 2026 15:57
The Knowledge Engine has no optional values in bindings, so a variable
without a value previously could not be sent from a BindingModel.

Add two sentinels that serialize to
<http://www.knowledge-engine.eu/mapper/undefined>: UNDEFINED (a URIRef)
for Uri fields and UNDEFINED_LITERAL (an enum member) for Literal,
Datatype and RdfLiteral fields. The enum lets pyright accept the
sentinel in literal fields and narrow it away with an `is` check.
Incoming bindings deserialize to the sentinel matching the field type;
using the wrong sentinel for a field raises a ValidationError.

Fixes #75

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@david-debest david-debest self-assigned this Oct 19, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@david-debest
david-debest merged commit 485a84b into main Oct 19, 2026
3 checks passed
david-debest added a commit that referenced this pull request Oct 27, 2026
Covers models missed in the first pass and those added by #78 and #79.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@david-debest
david-debest deleted the 75-feat/sentinel-values branch October 27, 2026 14:32
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.

Add handling of sentinel values

1 participant