mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
* 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
126 lines
2.7 KiB
JSON
126 lines
2.7 KiB
JSON
// See: https://github.com/streetsidesoftware/cspell/tree/master/packages/cspell
|
|
{
|
|
"version": "0.2",
|
|
"import": [
|
|
"@cspell/dict-en_us/cspell-ext.json",
|
|
// "@cspell/dict-cpp/cspell-ext.json",
|
|
"@cspell/dict-python/cspell-ext.json",
|
|
"@cspell/dict-rust/cspell-ext.json",
|
|
"@cspell/dict-win32/cspell-ext.json",
|
|
"@cspell/dict-shell/cspell-ext.json",
|
|
],
|
|
"allowCompoundWords": true,
|
|
// language - current active spelling language
|
|
"language": "en",
|
|
// dictionaries - list of the names of the dictionaries to use
|
|
"dictionaries": [
|
|
"cpython", // Sometimes keeping same terms with cpython is easy
|
|
"python-more", // Python API terms not listed in python
|
|
"rust-more", // Rust API terms not listed in rust
|
|
"rustpython", // RustPython derive macros and internal terms
|
|
"en_US",
|
|
"softwareTerms",
|
|
"c",
|
|
"cpp",
|
|
"python",
|
|
"rust",
|
|
"shell",
|
|
"win32"
|
|
],
|
|
// dictionaryDefinitions - this list defines any custom dictionaries to use
|
|
"dictionaryDefinitions": [
|
|
{
|
|
"name": "cpython",
|
|
"path": "./.cspell.dict/cpython.txt"
|
|
},
|
|
{
|
|
"name": "python-more",
|
|
"path": "./.cspell.dict/python-more.txt"
|
|
},
|
|
{
|
|
"name": "rust-more",
|
|
"path": "./.cspell.dict/rust-more.txt"
|
|
},
|
|
{
|
|
"name": "rustpython",
|
|
"path": "./.cspell.dict/rustpython.txt"
|
|
}
|
|
],
|
|
"ignorePaths": [
|
|
"**/__pycache__/**",
|
|
"target/**",
|
|
"Lib/**",
|
|
"crates/host_env/**"
|
|
],
|
|
// words - list of words to be always considered correct
|
|
// (compound words like pyarg, baseclass, microbenchmark are handled by allowCompoundWords)
|
|
"words": [
|
|
"aiterable",
|
|
"alnum",
|
|
"csock",
|
|
"coro",
|
|
"contig",
|
|
"Crnl",
|
|
"dedentations",
|
|
"dedents",
|
|
"deduped",
|
|
"deoptimized",
|
|
"deoptimize",
|
|
"emscripten",
|
|
"excs",
|
|
"fdigits",
|
|
"flufl",
|
|
"fnfe",
|
|
"fsdefault",
|
|
"ifexp",
|
|
"implicits",
|
|
"inity",
|
|
"interps",
|
|
"jitted",
|
|
"jitting",
|
|
"kwonly",
|
|
"lossily",
|
|
"mcache",
|
|
"oparg",
|
|
"opargs",
|
|
"pointee",
|
|
"pyc",
|
|
"qmark",
|
|
"reborrow",
|
|
"reborrows",
|
|
"reparenting",
|
|
"reraises",
|
|
"reraising",
|
|
"significand",
|
|
"summands",
|
|
"TESTFN",
|
|
"TZPATH",
|
|
"unraisable",
|
|
"wasi",
|
|
"weaked",
|
|
// unix
|
|
"posixshmem",
|
|
"shm",
|
|
"CLOEXEC",
|
|
"endgrent",
|
|
"gethrvtime",
|
|
"getrusage",
|
|
"sigaction",
|
|
"WRLCK",
|
|
// win32
|
|
"IFEXEC"
|
|
],
|
|
// flagWords - list of words to be always considered incorrect
|
|
"flagWords": [
|
|
],
|
|
"ignoreRegExpList": [
|
|
],
|
|
// languageSettings - allow for per programming language configuration settings.
|
|
"languageSettings": [
|
|
{
|
|
"languageId": "python",
|
|
"locale": "en"
|
|
}
|
|
]
|
|
}
|