Skip to content

Restore stubtest and release-tag wheel publishing - #237

Merged
lelit merged 3 commits into
python-rapidjson:masterfrom
espressolee:fix/master-ci-release-readiness
Aug 23, 2026
Merged

lelit merged 3 commits into
python-rapidjson:masterfrom
espressolee:fix/master-ci-release-readiness

Conversation

@espressolee

Copy link
Copy Markdown
Contributor

Summary

Restore the two failing parts of the current master workflow:

  • align the bundled stubs with the C extension types as checked by mypy 2.1;
  • run the workflow for v* tags and publish wheels only after the test, debug,
    and wheel jobs have succeeded.

Addresses #157.

Why

The latest exact-master workflow, run
28846305296
at 00e9a146e958d42f84c81dcfdf39572280ecf01f, failed in two independent
places:

  1. stubtest rapidjson reported 19 errors after the test requirements moved to
    mypy 2.1. The C extension constructors are implemented in tp_new, while
    the stubs described them as __init__; Decoder and Encoder are also
    runtime disjoint bases.
  2. The upload job ran on an ordinary master push while the package version
    was still 1.23, so PyPI rejected the first wheel with 400 File already exists.

The old upload condition also used github.event.ref, and the workflow only
selected branch pushes, so a release tag could not reach the job even if the
condition were re-enabled.

Changes

Typing stubs

  • Describe Decoder, Encoder, RawJSON, and Validator construction with
    __new__, matching their C tp_new implementations.
  • Mark Decoder and Encoder with @disjoint_base. This preserves valid
    single inheritance while rejecting the same incompatible-layout multiple
    inheritance that fails at runtime.
  • Keep the stubs consumable by the branch's older mypy 1.16 through a narrow
    attr-defined compatibility ignore on the new typing extension import.

Release workflow

  • Trigger on v* tag pushes as well as master branch pushes.
  • Use github.ref for the release-tag predicate.
  • Skip publishing on pull requests and ordinary branch pushes.
  • Require tests, debug-tests, and the complete wheel matrix to succeed
    before publishing.

PR #235 contains a related upload guard on the free-threaded branch. This
change targets the currently failing master release path and additionally
restores the missing tag trigger and validation dependencies.

Verification

Based on 00e9a146e958d42f84c81dcfdf39572280ecf01f, candidate head
e5663ec092e79cbbb4e00937de6d71b3fa35c7c1:

  • mypy 2.1 stubtest: 19 baseline errors -> Success: no issues found;
  • mypy 1.16 stubtest: pass;
  • type fixtures: Decoder/Encoder single inheritance accepted; incompatible
    combined inheritance rejected;
  • runtime fixture: the same single/multiple-inheritance behavior;
  • pytest -q tests: 929 passed, 17 skipped, 2 xfailed;
  • actionlint -ignore SC2046: pass (SC2046 is the pre-existing
    $(which python3) warning);
  • workflow truth table: PR and master push do not publish; v1.24 does;
    other branches and non-v* tags do not trigger;
  • git diff --check: pass.

One local macOS/Python 3.13.12 doctest has a pre-existing final-digit float
representation difference. It reproduced identically on unmodified master;
the exact Linux workflow above passed all 274 doctests. No documentation or
runtime source is changed here.

No tag or real PyPI publication has been attempted from this branch.

(Developed with AI assistance; the log analysis, runtime checks, and test runs
were executed and verified by me.)

@lelit

lelit commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Thank you. Can you explain why this is marked as draft? Everything seems reasonable here, albeit I still do not understand the difference between the predicate on upload-wheels (as it was before your change) and the one I use on pglast ... maybe you can enlight me on that too?

@espressolee
espressolee marked this pull request as ready for review August 23, 2026 14:21
#

import typing as t
from typing_extensions import disjoint_base # type: ignore[attr-defined]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this requires adding typing-extensions to the requirements.txt, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch. CI was receiving it transitively through mypy, which is why the exact-head run passed, but the stub now imports disjoint_base directly and needs an explicit typing-extensions dependency. I added typing-extensions==4.16.0 to requirements-test.txt (requirements.txt includes that file) in 98dd717. Local verification: stubtest found no issues in 1 module; pytest reported 929 passed, 17 skipped, and 2 xfailed; pip check is clean. The new exact-head CI is starting now.

@espressolee

Copy link
Copy Markdown
Contributor Author

I used the draft state only as a temporary review-readiness marker while the exact-head CI completed and I rechecked the release trigger. There is no known unfinished work in the PR; the checks are green, and I have now marked it ready for review.

On the predicate: for a push event, the pglast form and this PR's form are effectively equivalent. github.event.ref and github.ref both contain the full pushed ref, such as refs/tags/v1.2.3. The material difference is the workflow trigger, not that field:

  • pglast has on: [push, pull_request], so every tag push starts the workflow and the job-level predicate can evaluate true.
  • python-rapidjson previously had only push.branches: [master]. With a branch filter defined and no push.tags filter, a tag push does not start the workflow, so upload_wheels never reaches its if expression.

This PR adds tags: ['v*'] to the push trigger. The job-level condition then remains defense in depth, limiting publication to a v* tag push. I used github.ref because it is the standard workflow context here, not because it changes the predicate's behavior.

The other release-path change is that upload_wheels now needs tests, debug-tests, and build_wheels, so publication waits for all three gates rather than only the wheel matrix.

@lelit

lelit commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Great, TIL! 😉

@lelit
lelit merged commit b283f49 into python-rapidjson:master Aug 23, 2026
9 checks passed
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.

2 participants