Files
RustPython/Lib
Jeong, YunWon f24b2570a9 Implement PEP 688 and rework the buffer protocol around managed exports (#8523)
* Implement PEP 688 __buffer__ and __release_buffer__

A Python class could not export a buffer: the slot machinery had no
bf_getbuffer or bf_releasebuffer, and every consumer acquired buffers as
PyBUF_FULL_RO through a module of PyBUF_* constants.

Add both slots. PyBuffer::release now runs a Python __release_buffer__
before the exporter's own release, once per acquisition, which PyBuffer
tracks with an `acquired` flag that clones do not inherit. An export made
by a Python __buffer__ is held by a _buffer_wrapper payload that counts its
exports and drops the returned memoryview with the last one, and the view
handed to __release_buffer__ is a _buffer_window that owns no export, so
releasing it inside the hook is inert instead of re-entering it.

Replace the PyBUF_* constants with a BufferFlags bitflags type whose
composite requests are supersets of the simpler ones, so `contains` answers
the REQ_* questions, and pass the request to PyBuffer::from_object. Each
consumer now asks for what its counterpart asks for: y* arguments for
SIMPLE, w* for WRITABLE, BytesIO.write for CONTIG_RO, bytes(), bytearray()
and memoryview() for FULL_RO. memoryview checks the request in
memory_getbuf, and array.array and mmap.mmap expose __release_buffer__.

Test buffer support with PyObject::check_buffer (PyObject_CheckBuffer)
instead of attempting an acquisition, so an exception raised by __buffer__
is no longer reported as the object not being bytes-like, and a __buffer__
with side effects runs once. PyBytesInner becomes a y* conversion as a
result: bytes and bytearray methods no longer accept iterables of ints, and
find, index, count and __contains__ take the arguments
parse_args_finds_byte and bytes_contains describe.

A view exports its start offset in the descriptor rather than in its
window, which fixes a panic when collecting from a negative-stride view.

BytesIO.write rechecks closed after acquiring its buffer, which __buffer__
can close in between.

Assisted-by: Claude Code:claude-opus-5

* Rework the buffer protocol around managed exports and view offsets

Give `PyBuffer` the `_PyManagedBufferObject` shape: one `bf_getbuffer`
acquisition is shared by every handle taken from it, cloning takes another
share instead of re-acquiring, and the exporter's release runs once when the
last share goes away. Remove `retain`, the unsafe `drop_without_release`, the
three `impl Drop`s and the `ManuallyDrop` that stood in for this. Add
`abort_acquisition` so a failed request does not run `bf_releasebuffer`.

Move the view start into `BufferDescriptor::offset`, the `Py_buffer.buf`
analogue, and drop the separate `start` fields on `PyMemoryView` and
`PyBufferWrapper`. Slicing goes through `SaturatedSlice::adjust_indices_start`,
which reproduces `PySlice_AdjustIndices` and keeps the adjusted start.

Fix `zip_eq` to take its contiguous fast path only when both last dimensions
are contiguous, and make `for_each_segment` and `zip_eq` handle zero-length and
zero-dimensional views.

Add `BufferDescriptor::projected` so a request without `PyBUF_ND`,
`PyBUF_STRIDES` or `PyBUF_FORMAT` receives a correspondingly reduced
descriptor, and reject a request without `PyBUF_INDIRECT` against an exporter
that has suboffsets.

Copy the source first in `memoryview` slice assignment when both sides reach
the same root exporter.

Hold the export across the resize in `bytearray.extend`, take `y*` in
`marshal.loads`, stop probing the buffer protocol in `FsPath`, rewrite `ord`
over the concrete string types, fold `array`'s buffer slot into one
`slot_as_buffer`, take `w*`/`y*` in `_overlapped`, and thread the new `offset`
field through the `_ctypes` descriptors.

Assisted-by: Claude

* Re-check a memoryview after a conversion and tighten cast and release

`pack_single` and `unpack_single` addressed the buffer with a position taken
before `__index__` ran, so releasing the view from that conversion read or wrote
outside the exporter's storage, panicking when it had also shrunk. Check the
released flag again once the conversion is done, as `CHECK_RELEASED_AGAIN` does.

Reject a cast to a format that is not a single native format character with an
optional `@` in front of it. An empty format reached a division by its item size
of zero. get_native_fmtchar

Report a second `__release_buffer__` on the same view as a `ValueError` rather
than accepting it, and check that the view belongs to the object first; the
silent case is a view that exports nothing. wrap_releasebuffer

Compare against another memoryview by reading its view where it lies instead of
acquiring a buffer from it, so the restricted view handed to
`__release_buffer__` compares equal rather than unequal in one direction only.
memory_richcompare

Name the type in the unraisable an exception from `__release_buffer__` reports,
as `releasebuffer_call_python` does, instead of reporting the exporter object.

Assisted-by: Claude

* Re-check the destination of a memoryview slice assignment

Acquiring the source runs `__buffer__`, which can release the destination view,
so check the released flag again once the source is in hand and before the
structures are compared, as `copy_single` does.

Build the sliced destination as a view that counts as no export, the way a
`Py_buffer dest = *view` copy does. Holding one kept the exporter unresizable
for the length of the assignment, so a source that released the view and then
resized the exporter met a `BufferError` instead of the assignment reporting the
released view.

Assisted-by: Claude

* Answer the memoryview contiguity getsets with the layout

`f_contiguous` reported the row-major answer for one dimension and False
for any more, so a view laid out both ways, such as one of shape (1, 8),
reported False while `check_buffer_request` accepted a `F_CONTIGUOUS`
request on it. `contiguous` answered row-major order alone.

Move the Fortran-order test from `PyMemoryView` to `BufferDescriptor`,
next to the row-major one it differs from only in iteration order, and
answer all three getsets with it.

Assisted-by: Claude
2026-08-16 21:32:29 +09:00
..
2026-06-12 11:10:50 +09:00
2026-05-17 20:54:56 +09:00
2026-06-15 11:21:28 +09:00
2026-05-12 00:42:54 +09:00
2026-01-20 15:29:05 +09:00
2026-01-17 19:21:11 +09:00
2026-05-12 20:52:36 +09:00
2026-06-15 11:20:13 +09:00
2026-06-15 11:19:40 +09:00
2026-06-15 11:19:40 +09:00
2026-05-20 23:09:50 +09:00
2025-03-20 14:28:26 +09:00
2025-03-10 11:43:53 +09:00
2026-02-02 01:20:23 +09:00
2025-01-11 18:48:27 +09:00
2025-03-10 11:43:53 +09:00
2025-03-10 23:13:32 -07:00
2026-02-13 13:55:05 +09:00
2026-02-24 01:07:30 +00:00
2026-01-30 19:21:10 +09:00
2026-02-02 01:20:23 +09:00
2026-02-28 12:09:59 +09:00
2026-01-31 10:11:58 +09:00
2025-04-21 20:45:06 -07:00
2026-01-24 00:24:12 +09:00
2026-02-18 00:43:49 +09:00
2026-02-24 01:07:30 +00:00
2026-01-30 16:38:36 +02:00
2026-02-08 20:36:35 +09:00
2026-01-26 10:40:22 +09:00
2026-02-11 16:47:03 +09:00
2025-04-30 14:33:52 +09:00
2026-01-30 07:48:29 +09:00
2026-02-08 16:35:56 +09:00
2026-02-08 16:35:56 +09:00
2026-02-14 21:40:04 +09:00
2026-02-15 21:04:32 +09:00
2026-05-12 20:53:24 +09:00
2026-02-13 14:13:30 +09:00
2026-02-09 12:56:53 +09:00
2026-02-14 18:19:57 +02:00
2026-01-21 20:14:30 +09:00
2026-01-25 00:18:55 +09:00
2026-03-01 14:51:54 +09:00
2026-01-23 23:57:31 +09:00
2026-06-11 13:36:30 +09:00
2026-05-17 19:49:42 +09:00
2026-03-03 20:00:50 +09:00
2026-03-12 18:08:56 +09:00
2026-02-13 20:24:57 +09:00
2026-02-06 01:14:55 +09:00
2026-05-12 20:51:02 +09:00
2025-07-25 10:50:17 +09:00
2026-02-13 18:07:25 +09:00
2026-02-04 18:32:45 +09:00
2026-05-17 19:49:09 +09:00
…
2026-01-21 15:10:40 +09:00
2026-05-12 20:51:46 +09:00
2025-04-21 21:11:42 -07:00
2025-07-17 00:04:12 +09:00
2024-04-26 01:39:02 +09:00
2026-05-12 00:43:34 +09:00
2026-05-12 20:51:57 +09:00
2026-05-13 19:52:56 +09:00
2024-03-22 14:54:02 +09:00
2024-03-22 14:54:02 +09:00
2026-03-01 11:36:46 +09:00
2026-02-14 09:18:09 +09:00
2026-02-11 18:01:41 +09:00
2026-01-21 03:05:05 +09:00
2026-01-30 19:13:59 +02:00
…
2026-05-12 20:53:11 +09:00
2026-01-22 08:02:43 +09:00
2026-03-10 11:28:16 +09:00
2026-03-04 05:38:58 +09:00
2026-06-03 18:36:37 +09:00
2026-06-15 11:20:13 +09:00
2026-06-15 11:20:13 +09:00
2026-06-02 18:00:54 +09:00
2026-02-13 13:42:22 +09:00
2026-01-30 19:21:10 +09:00
2026-03-05 17:25:59 +09:00

Standard Library for RustPython

This directory contains all of the Python files that make up the standard library for RustPython.

Most of these files are copied over from the CPython repository (the 3.7 branch), with slight modifications to allow them to work under RustPython. The current goal is to complete the standard library with as few modifications as possible. Current modifications are just temporary workarounds for bugs/missing feature within the RustPython implementation.

The first big module we are targeting is unittest, so we can leverage the CPython test suite.