Skip to content

Add guardrails for LinkML's compatibility constraints - #108

Merged
ericprud merged 4 commits into
masterfrom
compat-guardrails
Sep 24, 2026
Merged

ericprud merged 4 commits into
masterfrom
compat-guardrails

Conversation

@ericprud

@ericprud ericprud commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

LinkML asked that PyShEx releases not break compatibility, keep up with current Python versions, and not add unexpected heavyweight dependencies. This PR adds automated checks for all three.

What's added

  • tests/test_contract freezes the public API: signatures, exports, CLI options and exit codes. It also replays the exact calls of the known PyPI clients, linkml and jupyter-rdfify 1.0.4. The tests are self-contained, so they also run against the built wheel.
  • tests/test_policy checks the runtime dependency closure in uv.lock against an allowlist. It rejects version caps and requires imports to match declared dependencies. It keeps Python versions consistent across classifiers, the CI matrix and tox, and flags a CPython release left unsupported for more than 90 days.
  • .github/scripts/api_compat.py diffs the API against the previous release with griffe. A break needs the breaking-change label on the PR, or a major version bump at release (minor while 0.x).
  • New CI jobs:
    • policy runs the pre-commit hooks and the API diff.
    • downstream installs this tree with the latest linkml and jupyter-rdfify in one resolution and runs their usage.
    • python-next is a non-blocking early warning for the next Python release.
    • A weekly schedule runs the whole workflow.
  • The release workflow now verifies the built wheel before publishing.
  • Pre-commit hooks are installed with uvx pre-commit install.

Fixes

  • CI push trigger now targets master; it previously targeted main, so pushes to master never ran CI.
  • Added py314 to tox env_list.
  • Added pytest config so a checked-out shexTest submodule doesn't break test collection.

Findings not addressed here

  • The existing codespell step checks nothing, because tox runs codespell ''.
  • Validation bug: { ex:knows . * ; ex:knows . + } accepts a node with no ex:knows triples.
  • Python 3.15.0b1 crashes importing chardet's compiled extension, which comes in via pyshexc. pyjsg also uses a typing call that 3.15 disallows.
  • Undeclared imports: pyshex imports rdflib, pyjsg and jsonasobj but doesn't declare them. It declares chardet and urllib3 but never imports them. The tests record these as known exceptions.

After rebasing on #109 and #105

  • Current uv: the pinned uv is now 0.12.18. The old pin made the "3.14" jobs run a 3.14 beta.
  • python-next: a failure now shows as a warning rather than a red check.
  • Windows: the policy tests now read files as UTF-8.
  • API check: it uses griffe's Python API and ignores "attribute value changed" reports, which flag refactorings rather than interface changes.
  • pyshexc from a fork: EXTENDS validation with feasibility-pruned partition search #105 installs pyshexc from a fork through [tool.uv.sources]. The policy tests allow this by name on pull requests. The release workflow sets PYSHEX_RELEASE_CHECK=1, which refuses it, so nothing can be published until that pyshexc is on PyPI.

🤖 Generated with Claude Code

Eric Prud'hommeaux and others added 4 commits September 24, 2026 01:36
LinkML asks that PyShEx releases not break compatibility, keep up with
current Python, and not add unexpected heavyweight dependencies.

- tests/test_contract: freeze the public API and the call patterns of
  known clients (linkml, jupyter-rdfify 1.0.4); run the real clients
  when installed.
- tests/test_policy: runtime dependency allowlist from uv.lock, no
  version caps, imports match declared deps, Python versions consistent
  across classifiers/CI/tox and current with CPython releases.
- .github/scripts/api_compat.py: griffe API diff against the previous
  release; breaks need a 'breaking-change' PR label or a major (0.x:
  minor) version bump.
- CI: policy, downstream and python-next jobs; weekly schedule; run on
  pushes to master (was 'main'). Release workflow verifies the built
  wheel before publishing.
- pre-commit hooks for the lockfile, contract/policy tests and API diff.
- pytest config so a checked-out shexTest submodule doesn't break
  collection; add py314 to tox env_list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…res as warnings

uv 0.7.13 predates Python 3.14.0, so every '3.14' job ran 3.14.0b2,
and it fetched Python builds from an old release URL that failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…m PyPI

- Windows' default code page broke parsing pyshex sources and TOML.
- New check: runtime packages in uv.lock must come from the PyPI
  registry. [tool.uv.sources] git/path overrides don't reach published
  wheels, so CI would test different code than users install.
- SKIP_EXTERNAL_URLS=false no longer disables the network check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- api_compat: use griffe's API and ignore "attribute value changed",
  which flags refactored right-hand sides of instance attributes
  (ShapeAssociation.nodeSelector) rather than interface changes. Also
  fixes old-version loading: load_git must not get search_paths=".".
- Dependency policy: pyshexc comes from a fork via [tool.uv.sources]
  until the EXTENDS grammar is released. Allow it by name on pull
  requests; the release workflow sets PYSHEX_RELEASE_CHECK=1 and refuses
  any non-PyPI runtime source, since wheels resolve from PyPI.
- chardet is now imported (schema_loader's safe reader).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ericprud
ericprud merged commit 7b1ecce into master Sep 24, 2026
15 checks passed
@ericprud
ericprud deleted the compat-guardrails branch September 24, 2026 21:10
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