Skip to content

docs(bindings): recommend explicit None defaults for pyright - #80

Merged
david-debest merged 5 commits into
mainfrom
77-fix/pyright-binding-defaults
Oct 27, 2026
Merged

david-debest merged 5 commits into
mainfrom
77-fix/pyright-binding-defaults

Conversation

@david-debest

@david-debest david-debest commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #77

What

Pyright only recognises assigned defaults, so it ignores Field(default=None) inside the Uri / Literal[T] / RdfLiteral aliases and reports all binding model fields as required. This PR documents = None as the recommended pattern and applies it:

The runtime default stays, so existing code without = None keeps working.

Options explored (none work with pyright 1.1.414)

  • __init__(self, **data) on BindingModel: pyright still synthesizes a typed __init__ for each subclass.
  • Custom ModelMetaclass subclass with its own dataclass_transform: same result. dataclass_transform has no "all fields optional" option, and defaults in Annotated are never considered.
  • Hiding BindingModel from type checkers via TYPE_CHECKING: rejected because it loses field-name and type checking.

Testing

  • uv run pytest and ruff: all pass.
  • uvx pyright@1.1.414 examples tests/test_bindings.py: no "Argument(s) missing" errors left. The 27 remaining errors are tests that deliberately pass N3 strings, rdflib.Literal values or the wrong UNDEFINED sentinel (from feat(bindings): add UNDEFINED sentinels for unbound binding values #78) to typed fields to check runtime validation. That is a separate typing limitation and out of scope here.
  • pyright is not added to project tooling.

Follow-ups (not in this PR)

  • AskAnswerKnowledgeInteraction / PostReactKnowledgeInteraction.prefixes have the same root cause (Field(default_factory=dict) inside Annotated). Pyright reports prefixes as missing in 5 test call sites.
  • knowledge_mapper/__init__.py has no __all__. Because the package ships py.typed, downstream pyright users get reportPrivateImportUsage on every public import (from knowledge_mapper import BindingModel, ...).

david-debest and others added 2 commits October 19, 2026 16:09
Pyright ignores Field(default=None) inside Annotated and reports every
BindingModel field as required. No library-side change makes pyright
see the default, so document `= None` and use it in examples and tests.

Fixes #77

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@david-debest david-debest self-assigned this Oct 27, 2026
david-debest and others added 3 commits October 27, 2026 14:31
…g-defaults

# Conflicts:
#	tests/test_bindings.py
Ruff 0.17 formats Python code blocks in Markdown, so the long binding
field lines in README and CONTEXT are shortened.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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 merged commit e5057ec into main Oct 27, 2026
3 checks passed
@david-debest
david-debest deleted the 77-fix/pyright-binding-defaults 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.

Pyright reports BindingModel fields as required despite None default

1 participant