Skip to content

release: 0.29.1 - #6151

Draft
davidhewitt wants to merge 43 commits into
release-0.29from
release-0.29.1
Draft

release: 0.29.1#6151
davidhewitt wants to merge 43 commits into
release-0.29from
release-0.29.1

Conversation

davidhewitt and others added 6 commits June 21, 2026 21:46
Signed-off-by: person93 <person93.person93@gmail.com>
…_MEMBERS` fail with address sanitizer (#6145)

* PyHeapType_GET_MEMBERS: cast etype to *mut u8

* PyObject_GET_WEAKREFS_LISTPTR: cast o to *mut u8

* Add newsfragement entry

* fix newsfragement entry

* Use byte_offset instead of casting

* PyObject_GET_WEAKREFS_LISTPTR: link from CPython
* fix typos & add spell check

* add typos to dependency-groups

* uvx ruff format .
chirizxc and others added 12 commits July 4, 2026 20:38
* fix: compile with PyPy when nightly feature is enabled

* add changelog

* add check-nightly

* Update .github/workflows/ci.yml

---------

Co-authored-by: David Hewitt <mail@davidhewitt.dev>
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Commits](actions/checkout@v6.0.3...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* ci: update / clean up wasm build

* drop `--quiet`

* fix CC variable conflict

* switch wasm jobs to uv

* debug

* fix `test-wasm` path
Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v5...v6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Updates the requirements on [codspeed-criterion-compat](https://github.com/CodSpeedHQ/codspeed-rust) to permit the latest version.
- [Release notes](https://github.com/CodSpeedHQ/codspeed-rust/releases)
- [Commits](CodSpeedHQ/codspeed-rust@v4.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: codspeed-criterion-compat
  dependency-version: 5.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Update nox command for generating lcov file for vscode plugin for coverage visualization.
* fix lifetime of return value in `PyClassGuardMutSuper::as_super`

* newsfragment
@codspeed-hq

codspeed-hq Bot commented Jul 4, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 16.51%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

#### 🎉 Hooray! `codspeed-rust` just leveled up to 5.0.1!

A heads-up, this is a breaking change and it might affect your current performance baseline a bit. But here's the exciting part - it's packed with new, cool features and promises improved result stability 🥳!
Curious about what's new? Visit our releases page to delve into all the awesome details about this new version.

⚡ 10 improved benchmarks
✅ 116 untouched benchmarks

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation extract_u128_small 1,171.7 ns 986.1 ns +18.82%
Simulation extract_u128_zero 1.2 µs 1 µs +18.28%
Simulation extract_i128_small_pos 1.2 µs 1 µs +17.77%
Simulation extract_i128_zero 1.3 µs 1.1 µs +17.28%
Simulation extract_u128_u32_max 1.3 µs 1.1 µs +17.05%
Simulation extract_i128_small_neg 1.3 µs 1.1 µs +16.75%
Simulation extract_u128_u64_max 1.4 µs 1.2 µs +15.46%
Simulation extract_u128_max 1.4 µs 1.2 µs +15.07%
Simulation extract_i128_pos_max 1.5 µs 1.3 µs +14.38%
Simulation extract_i128_neg_min 1.5 µs 1.3 µs +14.35%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing release-0.29.1 (8663a9a) with release-0.29 (646a38d)1

Open in CodSpeed

Footnotes

  1. No successful run was found on release-0.29 (0f90242) during the generation of this report, so e69ae19 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@ngoldbaum

Copy link
Copy Markdown
Contributor

I just opened #6192. The first commit there should be backported here.

@bschoenmaeckers

Copy link
Copy Markdown
Member

Could you also include the fix in #6154?

rewitt94 and others added 5 commits July 29, 2026 15:05
* update `PySet_GET_SIZE` and similar for free-threaded Python

* split `cpython` portion of `setobject.h` off
* Fix #[pyclass(dict)] leak on Python 3.11 and 3.12

* apply review suggestion

* Don't use sys.getallocatedblocks in test

* add release note

* fix clippy

* apply David's suggestions

* Apply David's suggestion with cfg_select
* Fix compilation with GraalPy 3.13

* Exclude mypy from optional-dependencies on GraalPy

* Add GraalPy to check-all
bschoenmaeckers and others added 4 commits July 29, 2026 15:12
…6252)

Nightly rustdoc's `rustdoc::invalid-html-tags` lint gained an
"improperly nested Markdown paragraph" check, which broke the
netlify-build CI job (`nox -s check-guide` runs `cargo doc` with
`-Dwarnings`).

The warning box on `PyModule::from_code` contained a blank doc line
before `</pre></div>`. A blank line terminates a CommonMark HTML block,
so the closing tags landed in a separate block from the tags they close.

Keep the markup on contiguous doc lines so it forms a single HTML block.
This also drops a stray `//` (rather than `///`) line, which was silently
omitting content from the rendered docs.

Claude-Session: https://claude.ai/code/session_0176PdmBb2j8euHTFEv4huzz

Co-authored-by: Claude <noreply@anthropic.com>
@ngoldbaum

Copy link
Copy Markdown
Contributor

I just pushed backports for all the merged PRs listed in the description. I backported a few more PRs than the ones listed to get CI passing. I also had to do manual fixes for Python 3.8 compat and pinning ruff.

jonasdedden and others added 14 commits July 31, 2026 14:03
… is `cfg`-ed out (#6255)

The `,` separating two elements of an introspection list was written
unconditionally as soon as the element was not the first one, even when
the elements before it were all behind a `#[cfg]` that is disabled. A
`#[pymodule]` whose first member is `cfg`-ed out therefore serialized its
member list as `[,"..."]`, and since `find_introspection_chunks_in_*`
propagates the parse error, one such module makes `pyo3-introspection`
fail to read the *whole* extension — no stubs at all.

This is reachable in `pyo3_pytests` as it ships: `pyfunctions` has
`#[cfg(feature = "experimental-async")] use super::with_async;` as its
first member, so building it with `experimental-inspect` but without
`experimental-async` produces a binary `pyo3-introspection` refuses:

    Failed to parse introspection chunk: "{...,\"members\":[,\"134042...

`nox -s test-introspection` never catches it because it always enables
both features together.

The separator is now gated behind an `any(..)` of the `cfg`s of all the
elements before the one it precedes, on top of that element's own. The
two cases that look like they need special handling fall out of `cfg`
syntax instead: `any()` is false, so the first element gets no separator,
and `all()` is true, so an element that is always compiled in makes every
later separator unconditional too.

Verified in both the `abi3` and non-`abi3` configurations, for a `cfg`-ed
out first member, middle member and last member.

`experimental-inspect`: cover `cfg`-ed out `#[pymodule]` members in `pytests`

`nox -s test-introspection` builds `pytests` with `experimental-async`
and `experimental-inspect` together, so the only `cfg`-ed out member the
crate has as it ships is always compiled in and no CI run ever exercised
a `#[pymodule]` member list with a hole in it -- which is how the invalid
JSON fixed two commits ago went unnoticed.

`pyfunctions` gains a first and a last member behind `#[cfg(any())]`,
which is never true. This changes neither the module at runtime nor the
checked-in stubs, but it makes every introspection run walk the path
where an element is removed, and a regression there fails loudly:
`pyo3-introspection` refuses the whole extension and the session never
reaches the stub comparison.

Rename
* fix: register in-place sequence operations in distinct slots

* docs: add newsfragment for PR 6260
…g an instance of an extension type (#6224)

* pycell: decref the reference to the type held by the instance when deallocating the instance

* add newsfragment

* fix type being decrefed and add tests

* check type is heap type before forcing decref and use the type system to encode the decref of the type,

* remove useless import

* address last comment

* clippy fix

* proper gating to make clippy happy

* improve release notes

* remove separate type decref for types with free list

* disable reference based count tests on free threaded builds

* cfg out macro helper used only in test that are cfg out on free threaded build
* fix: return error for oversized time durations

* docs: add time duration overflow news fragment
…-endian (#6150)

* fix 3.15+ `append_to_inittab` on platforms which aren't 64-bit little-endian

* fix test conditional code

* fix missing import

* newsfragment

* implement legacy slots in terms of new slots

* don't build module def slots on abi3t

* promote constants to statics

* fix test
…Generator and ConvertField (#6277)

* Remove IMPLEMENTS_INTOPYOBJECT from PyClassGetterGenerator and ConvertField

Unused, enables to remove IsIntoPyObject traity

* Fix UI tests
…d magic methods (#6239)

* fix: emit positional-only arguments for slot-backed magic methods

`experimental-inspect` emitted the arguments of magic methods as
positional-or-keyword, but the slot wrappers CPython installs for type
slots reject keyword arguments entirely, e.g. `__eq__` is exposed as
`($self, value, /)`. `mypy.stubtest` therefore reported every such
method as inconsistent with the runtime.

`PythonSignature` already distinguishes positional-only, positional-or-
keyword and keyword-only parameters, so record the truth when the
signature is built rather than teaching introspection a new mode: set
`positional_only_parameters`, the same assignment a trailing `/` in
`#[pyo3(signature = ...)]` performs, now factored into
`make_all_parameters_positional_only`. Introspection is untouched.

`SlotDef::arguments_are_positional_only` is the single source of truth.
It excludes the `TpNew`/`TpInit` calling conventions, since `__new__` and
`__init__` are called with `args`/`kwargs` and keep the signature
declared in Rust. `__call__` behaves the same way, so this ends up being
exactly the set of magic methods for which `#[pyo3(signature = ...)]` is
allowed.

Writing to the spec's signature is inert for codegen: `impl_arg_params`
is reached from the slot path only for `TpNew`/`TpInit`, and
`__text_signature__` is rejected on every magic method but `__new__`.
Runtime text signatures are unchanged.

The parameter of the comparison dunders synthesized by `#[pyclass(eq)]`
and `#[pyclass(ord)]` is also renamed from `other` to `value` to match
the name CPython uses in the `tp_richcompare` slot wrappers.

Closes #6235

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Proper newsfragments name

* Address review comments

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ame (#6254)

* `experimental-inspect`: introspect `#[pyfunction]` under its Python name

`impl_wrap_pyfunction` passed `func.sig.ident`, the Rust identifier, as
the function name in the introspection data. `#[pyfunction(name = "x")]`
was therefore declared in the stubs under a name the module does not have
at runtime:

    #[pyfunction(name = "solve")]
    fn rust_solve() -> usize { 42 }

generated `def rust_solve() -> int: ...` for a module exporting `solve`.

`pytests` gains a renamed `#[pyfunction]` so the checked-in stubs cover it.

`experimental-inspect`: pin the renamed `#[pyfunction]` to its Python name

The preceding commit checks the name a renamed `#[pyfunction]` is
declared under in the checked-in stubs, but nothing checks that this is
the name the module actually exports -- which is the invariant the bug
broke. Assert both from Python.

Also drop that commit's mention of `__all__`: the stub generator never
emits one, so only the declaration has to use the Python name.

`experimental-inspect`: drop the newsfragment suffix

The `.1` suffix distinguished this fragment from the one of the `cfg`
separator fix, which now lives on its own branch. Both still need
renumbering to their real pull request.

Rename

* Rename
… indentation (#6270)

* fix(inspect): don't pad blank docstring lines with the body indentation

`class_stubs` and `function_stubs` re-indent each docstring line into the
body by writing the indentation and then the line. For an empty line — a
paragraph break, which every non-trivial docstring has — that leaves a line
consisting only of spaces.

A 1200-line stub generated for a real project came out with 95 of them, all
flagged `W293` by ruff and flake8. It is not fixable downstream: the file is
generated, so any hand edit is reverted by the next run, and the formatter's
autofix is classified unsafe inside a string literal.

The three nested-indentation sites used `str::replace('\\n', "\\n    ")`, which
has the same problem for any nested element whose body contains a blank line.
Both now go through `push_indented`/`push_docstring`, which leave an empty line
empty. Indentation of non-empty lines is unchanged, so the checked-in
`pytests/stubs/*.pyi` are untouched.

* Rename
* pyo3-introspection Fixes wheel publishing

- The artifact directory was wrong during publishing
- Validate wheels after build
- Remove license files that were not properly included in source wheels (the `License: MIT OR Apache-2.0` metadata line is still there)

* Properly install uvx

---------

Co-authored-by: David Hewitt <mail@davidhewitt.dev>
* add an AI contributions policy

* drop extra word

* typo

* reword to be more direct and forbid use of AI on easy issues

* signpost to contributing guide on pull request template

Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com>

---------

Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.