574 lines
52 KiB
HTML
574 lines
52 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="color-scheme" content="light dark">
|
||
<title>PEP 688 – Making the buffer protocol accessible in Python | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0688/">
|
||
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
||
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
||
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
||
<meta property="og:title" content='PEP 688 – Making the buffer protocol accessible in Python | peps.python.org'>
|
||
<meta property="og:description" content="This PEP proposes a Python-level API for the buffer protocol, which is currently accessible only to C code. This allows type checkers to evaluate whether objects implement the protocol.">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0688/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="This PEP proposes a Python-level API for the buffer protocol, which is currently accessible only to C code. This allows type checkers to evaluate whether objects implement the protocol.">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 688</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 688 – Making the buffer protocol accessible in Python</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Jelle Zijlstra <jelle.zijlstra at gmail.com></dd>
|
||
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/19756">Discourse thread</a></dd>
|
||
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
||
<dt class="field-even">Type<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
||
<dt class="field-odd">Topic<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="../topic/typing/">Typing</a></dd>
|
||
<dt class="field-even">Created<span class="colon">:</span></dt>
|
||
<dd class="field-even">23-Apr-2022</dd>
|
||
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
|
||
<dd class="field-odd">3.12</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/thread/CX7GPSIYQEL23RXMYL66GAKGP4RLUD7P/" title="Typing-SIG thread">23-Apr-2022</a>,
|
||
<a class="reference external" href="https://discuss.python.org/t/15265" title="Discourse thread">25-Apr-2022</a>,
|
||
<a class="reference external" href="https://discuss.python.org/t/19756" title="Discourse thread">06-Oct-2022</a>,
|
||
<a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/thread/XH5ZK2MSZIQLL62PYZ6I5532SQKKVCBL/" title="Typing-SIG thread">26-Oct-2022</a></dd>
|
||
<dt class="field-odd">Resolution<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="https://discuss.python.org/t/pep-688-making-the-buffer-protocol-accessible-in-python/15265/35">07-Mar-2023</a></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
|
||
<li><a class="reference internal" href="#current-options">Current options</a></li>
|
||
<li><a class="reference internal" href="#kinds-of-buffers">Kinds of buffers</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a><ul>
|
||
<li><a class="reference internal" href="#python-level-buffer-protocol">Python-level buffer protocol</a></li>
|
||
<li><a class="reference internal" href="#inspect-bufferflags"><code class="docutils literal notranslate"><span class="pre">inspect.BufferFlags</span></code></a></li>
|
||
<li><a class="reference internal" href="#collections-abc-buffer"><code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code></a></li>
|
||
<li><a class="reference internal" href="#example">Example</a></li>
|
||
<li><a class="reference internal" href="#equivalent-for-older-python-versions">Equivalent for older Python versions</a></li>
|
||
<li><a class="reference internal" href="#no-special-meaning-for-bytes">No special meaning for <code class="docutils literal notranslate"><span class="pre">bytes</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a><ul>
|
||
<li><a class="reference internal" href="#buffer-and-release-buffer-attributes"><code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> and <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> attributes</a></li>
|
||
<li><a class="reference internal" href="#removal-of-the-bytes-special-case">Removal of the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> special case</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
|
||
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
||
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
||
<li><a class="reference internal" href="#types-buffer"><code class="docutils literal notranslate"><span class="pre">types.Buffer</span></code></a></li>
|
||
<li><a class="reference internal" href="#keep-bytearray-compatible-with-bytes">Keep <code class="docutils literal notranslate"><span class="pre">bytearray</span></code> compatible with <code class="docutils literal notranslate"><span class="pre">bytes</span></code></a></li>
|
||
<li><a class="reference internal" href="#distinguish-between-mutable-and-immutable-buffers">Distinguish between mutable and immutable buffers</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<div class="pep-banner canonical-doc sticky-banner admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>This PEP is a historical document. The up-to-date, canonical documentation can now be found at <a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#python-buffer-protocol" title="(in Python v3.13)"><span>Emulating buffer types</span></a>.</p>
|
||
<p class="close-button">×</p>
|
||
<p>See <a class="pep reference internal" href="../pep-0001/" title="PEP 1 – PEP Purpose and Guidelines">PEP 1</a> for how to propose changes.</p>
|
||
</div>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This PEP proposes a Python-level API for the buffer protocol,
|
||
which is currently accessible only to C code. This allows type
|
||
checkers to evaluate whether objects implement the protocol.</p>
|
||
</section>
|
||
<section id="motivation">
|
||
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
||
<p>The CPython C API provides a versatile mechanism for accessing the
|
||
underlying memory of an object—the <a class="reference external" href="https://docs.python.org/3/c-api/buffer.html">buffer protocol</a>
|
||
introduced in <a class="pep reference internal" href="../pep-3118/" title="PEP 3118 – Revising the buffer protocol">PEP 3118</a>.
|
||
Functions that accept binary data are usually written to handle any
|
||
object implementing the buffer protocol. For example, at the time of writing,
|
||
there are around 130 functions in CPython using the Argument Clinic
|
||
<code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code> type, which accepts the buffer protocol.</p>
|
||
<p>Currently, there is no way for Python code to inspect whether an object
|
||
supports the buffer protocol. Moreover, the static type system
|
||
does not provide a type annotation to represent the protocol.
|
||
This is a <a class="reference external" href="https://github.com/python/typing/issues/593">common problem</a>
|
||
when writing type annotations for code that accepts generic buffers.</p>
|
||
<p>Similarly, it is impossible for a class written in Python to support
|
||
the buffer protocol. A buffer class in
|
||
Python would give users the ability to easily wrap a C buffer object, or to test
|
||
the behavior of an API that consumes the buffer protocol. Granted, this is not
|
||
a particularly common need. However, there has been a
|
||
<a class="reference external" href="https://github.com/python/cpython/issues/58006">CPython feature request</a>
|
||
for supporting buffer classes written in Python that has been open since 2012.</p>
|
||
</section>
|
||
<section id="rationale">
|
||
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
|
||
<section id="current-options">
|
||
<h3><a class="toc-backref" href="#current-options" role="doc-backlink">Current options</a></h3>
|
||
<p>There are two known workarounds for annotating buffer types in
|
||
the type system, but neither is adequate.</p>
|
||
<p>First, the <a class="reference external" href="https://github.com/python/typeshed/blob/2a0fc1b582ef84f7a82c0beb39fa617de2539d3d/stdlib/_typeshed/__init__.pyi#L194">current workaround</a>
|
||
for buffer types in typeshed is a type alias
|
||
that lists well-known buffer types in the standard library, such as
|
||
<code class="docutils literal notranslate"><span class="pre">bytes</span></code>, <code class="docutils literal notranslate"><span class="pre">bytearray</span></code>, <code class="docutils literal notranslate"><span class="pre">memoryview</span></code>, and <code class="docutils literal notranslate"><span class="pre">array.array</span></code>. This
|
||
approach works for the standard library, but it does not extend to
|
||
third-party buffer types.</p>
|
||
<p>Second, the <a class="reference external" href="https://docs.python.org/3.10/library/typing.html#typing.ByteString">documentation</a>
|
||
for <code class="docutils literal notranslate"><span class="pre">typing.ByteString</span></code> currently states:</p>
|
||
<blockquote>
|
||
<div>This type represents the types <code class="docutils literal notranslate"><span class="pre">bytes</span></code>, <code class="docutils literal notranslate"><span class="pre">bytearray</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">memoryview</span></code> of byte sequences.<p>As a shorthand for this type, <code class="docutils literal notranslate"><span class="pre">bytes</span></code> can be used to annotate
|
||
arguments of any of the types mentioned above.</p>
|
||
</div></blockquote>
|
||
<p>Although this sentence has been in the documentation
|
||
<a class="reference external" href="https://github.com/python/cpython/commit/2a19d956ab92fc9084a105cc11292cb0438b322f">since 2015</a>,
|
||
the use of <code class="docutils literal notranslate"><span class="pre">bytes</span></code> to include these other types is not specified
|
||
in any of the typing PEPs. Furthermore, this mechanism has a number of
|
||
problems. It does not include all possible buffer types, and it
|
||
makes the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> type ambiguous in type annotations. After all,
|
||
there are many operations that are valid on <code class="docutils literal notranslate"><span class="pre">bytes</span></code> objects, but
|
||
not on <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> objects, and it is perfectly possible for
|
||
a function to accept <code class="docutils literal notranslate"><span class="pre">bytes</span></code> but not <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> objects.
|
||
A mypy user
|
||
<a class="reference external" href="https://github.com/python/mypy/issues/12643#issuecomment-1105914159">reports</a>
|
||
that this shortcut has caused significant problems for the <code class="docutils literal notranslate"><span class="pre">psycopg</span></code> project.</p>
|
||
</section>
|
||
<section id="kinds-of-buffers">
|
||
<h3><a class="toc-backref" href="#kinds-of-buffers" role="doc-backlink">Kinds of buffers</a></h3>
|
||
<p>The C buffer protocol supports
|
||
<a class="reference external" href="https://docs.python.org/3.10/c-api/buffer.html#buffer-request-types">many options</a>,
|
||
affecting strides, contiguity, and support for writing to the buffer. Some of these
|
||
options would be useful in the type system. For example, typeshed
|
||
currently provides separate type aliases for writable and read-only
|
||
buffers.</p>
|
||
<p>However, in the C buffer protocol, most of these options cannot be
|
||
queried directly on the type object. The only way to figure out
|
||
whether an object supports a particular flag is to actually
|
||
ask for the buffer. For some types, such as <code class="docutils literal notranslate"><span class="pre">memoryview</span></code>,
|
||
the supported flags depend on the instance. As a result, it would
|
||
be difficult to represent support for these flags in the type system.</p>
|
||
</section>
|
||
</section>
|
||
<section id="specification">
|
||
<h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2>
|
||
<section id="python-level-buffer-protocol">
|
||
<h3><a class="toc-backref" href="#python-level-buffer-protocol" role="doc-backlink">Python-level buffer protocol</a></h3>
|
||
<p>We propose to add two Python-level special methods, <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>
|
||
and <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code>. Python
|
||
classes that implement these methods are usable as buffers from C
|
||
code. Conversely, classes implemented in C that support the
|
||
buffer protocol acquire synthesized methods accessible from Python
|
||
code.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method is called to create a buffer from a Python
|
||
object, for example by the <code class="docutils literal notranslate"><span class="pre">memoryview()</span></code> constructor.
|
||
It corresponds to the <code class="docutils literal notranslate"><span class="pre">bf_getbuffer</span></code> C slot.
|
||
The Python signature for this method is
|
||
<code class="docutils literal notranslate"><span class="pre">def</span> <span class="pre">__buffer__(self,</span> <span class="pre">flags:</span> <span class="pre">int,</span> <span class="pre">/)</span> <span class="pre">-></span> <span class="pre">memoryview:</span> <span class="pre">...</span></code>. The method
|
||
must return a <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> object. If the <code class="docutils literal notranslate"><span class="pre">bf_getbuffer</span></code> slot
|
||
is invoked on a Python class with a <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method,
|
||
the interpreter extracts the underlying <code class="docutils literal notranslate"><span class="pre">Py_buffer</span></code> from the
|
||
<code class="docutils literal notranslate"><span class="pre">memoryview</span></code> returned by the method
|
||
and returns it to the C caller. Similarly, if Python code calls the
|
||
<code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method on an instance of a C class that
|
||
implements <code class="docutils literal notranslate"><span class="pre">bf_getbuffer</span></code>, the returned buffer is wrapped in a
|
||
<code class="docutils literal notranslate"><span class="pre">memoryview</span></code> for consumption by Python code.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> method should be called when a caller no
|
||
longer needs the buffer returned by <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>. It corresponds to the
|
||
<code class="docutils literal notranslate"><span class="pre">bf_releasebuffer</span></code> C slot. This is an
|
||
optional part of the buffer protocol.
|
||
The Python signature for this method is
|
||
<code class="docutils literal notranslate"><span class="pre">def</span> <span class="pre">__release_buffer__(self,</span> <span class="pre">buffer:</span> <span class="pre">memoryview,</span> <span class="pre">/)</span> <span class="pre">-></span> <span class="pre">None:</span> <span class="pre">...</span></code>.
|
||
The buffer to be released is wrapped in a <code class="docutils literal notranslate"><span class="pre">memoryview</span></code>. When this
|
||
method is invoked through CPython’s buffer API (for example, through
|
||
calling <code class="docutils literal notranslate"><span class="pre">memoryview.release</span></code> on a <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> returned by
|
||
<code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>), the passed <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> is the same object
|
||
as was returned by <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>. It is
|
||
also possible to call <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> on a C class that
|
||
implements <code class="docutils literal notranslate"><span class="pre">bf_releasebuffer</span></code>.</p>
|
||
<p>If <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> exists on an object,
|
||
Python code that calls <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> directly on the object must
|
||
call <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> on the same object when it is done
|
||
with the buffer. Otherwise, resources used by the object may
|
||
not be reclaimed. Similarly, it is a programming error
|
||
to call <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> without a previous call to
|
||
<code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>, or to call it multiple times for a single call
|
||
to <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>. For objects that implement the C buffer protocol,
|
||
calls to <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> where the argument is not a
|
||
<code class="docutils literal notranslate"><span class="pre">memoryview</span></code> wrapping the same object will raise an exception.
|
||
After a valid call to <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code>, the <code class="docutils literal notranslate"><span class="pre">memoryview</span></code>
|
||
is invalidated (as if its <code class="docutils literal notranslate"><span class="pre">release()</span></code> method had been called),
|
||
and any subsequent calls to <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> with the same
|
||
<code class="docutils literal notranslate"><span class="pre">memoryview</span></code> will raise an exception.
|
||
The interpreter will ensure that misuse
|
||
of the Python API will not break invariants at the C level – for
|
||
example, it will not cause memory safety violations.</p>
|
||
</section>
|
||
<section id="inspect-bufferflags">
|
||
<h3><a class="toc-backref" href="#inspect-bufferflags" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">inspect.BufferFlags</span></code></a></h3>
|
||
<p>To help implementations of <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code>, we add <code class="docutils literal notranslate"><span class="pre">inspect.BufferFlags</span></code>,
|
||
a subclass of <code class="docutils literal notranslate"><span class="pre">enum.IntFlag</span></code>. This enum contains all flags defined in the
|
||
C buffer protocol. For example, <code class="docutils literal notranslate"><span class="pre">inspect.BufferFlags.SIMPLE</span></code> has the same
|
||
value as the <code class="docutils literal notranslate"><span class="pre">PyBUF_SIMPLE</span></code> constant.</p>
|
||
</section>
|
||
<section id="collections-abc-buffer">
|
||
<h3><a class="toc-backref" href="#collections-abc-buffer" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code></a></h3>
|
||
<p>We add a new abstract base classes, <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code>,
|
||
which requires the <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method.
|
||
This class is intended primarily for use in type annotations:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">need_buffer</span><span class="p">(</span><span class="n">b</span><span class="p">:</span> <span class="n">Buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nb">memoryview</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">memoryview</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
|
||
|
||
<span class="n">need_buffer</span><span class="p">(</span><span class="sa">b</span><span class="s2">"xy"</span><span class="p">)</span> <span class="c1"># ok</span>
|
||
<span class="n">need_buffer</span><span class="p">(</span><span class="s2">"xy"</span><span class="p">)</span> <span class="c1"># rejected by static type checkers</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>It can also be used in <code class="docutils literal notranslate"><span class="pre">isinstance</span></code> and <code class="docutils literal notranslate"><span class="pre">issubclass</span></code> checks:</p>
|
||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">collections.abc</span> <span class="kn">import</span> <span class="n">Buffer</span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="sa">b</span><span class="s2">"xy"</span><span class="p">,</span> <span class="n">Buffer</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="nb">issubclass</span><span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="n">Buffer</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="nb">issubclass</span><span class="p">(</span><span class="nb">memoryview</span><span class="p">,</span> <span class="n">Buffer</span><span class="p">)</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="s2">"xy"</span><span class="p">,</span> <span class="n">Buffer</span><span class="p">)</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="nb">issubclass</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">Buffer</span><span class="p">)</span>
|
||
<span class="go">False</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In the typeshed stub files, the class should be defined as a <code class="docutils literal notranslate"><span class="pre">Protocol</span></code>,
|
||
following the precedent of other simple ABCs in <code class="docutils literal notranslate"><span class="pre">collections.abc</span></code> such as
|
||
<code class="docutils literal notranslate"><span class="pre">collections.abc.Iterable</span></code> or <code class="docutils literal notranslate"><span class="pre">collections.abc.Sized</span></code>.</p>
|
||
</section>
|
||
<section id="example">
|
||
<h3><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h3>
|
||
<p>The following is an example of a Python class that implements the
|
||
buffer protocol:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">contextlib</span>
|
||
<span class="kn">import</span> <span class="nn">inspect</span>
|
||
|
||
<span class="k">class</span> <span class="nc">MyBuffer</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="o">=</span> <span class="kc">None</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__buffer__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">flags</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-></span> <span class="nb">memoryview</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">flags</span> <span class="o">!=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">BufferFlags</span><span class="o">.</span><span class="n">FULL_RO</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"Only BufferFlags.FULL_RO supported"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">"Buffer already held"</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="o">=</span> <span class="nb">memoryview</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span>
|
||
|
||
<span class="k">def</span> <span class="nf">__release_buffer__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">view</span><span class="p">:</span> <span class="nb">memoryview</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="ow">is</span> <span class="n">view</span> <span class="c1"># guaranteed to be true</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="o">=</span> <span class="kc">None</span>
|
||
|
||
<span class="k">def</span> <span class="nf">extend</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">"Cannot extend held buffer"</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
|
||
|
||
<span class="n">buffer</span> <span class="o">=</span> <span class="n">MyBuffer</span><span class="p">(</span><span class="sa">b</span><span class="s2">"capybara"</span><span class="p">)</span>
|
||
<span class="k">with</span> <span class="nb">memoryview</span><span class="p">(</span><span class="n">buffer</span><span class="p">)</span> <span class="k">as</span> <span class="n">view</span><span class="p">:</span>
|
||
<span class="n">view</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="s2">"C"</span><span class="p">)</span>
|
||
|
||
<span class="k">with</span> <span class="n">contextlib</span><span class="o">.</span><span class="n">suppress</span><span class="p">(</span><span class="ne">RuntimeError</span><span class="p">):</span>
|
||
<span class="n">buffer</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="sa">b</span><span class="s2">"!"</span><span class="p">)</span> <span class="c1"># raises RuntimeError</span>
|
||
|
||
<span class="n">buffer</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="sa">b</span><span class="s2">"!"</span><span class="p">)</span> <span class="c1"># ok, buffer is no longer held</span>
|
||
|
||
<span class="k">with</span> <span class="nb">memoryview</span><span class="p">(</span><span class="n">buffer</span><span class="p">)</span> <span class="k">as</span> <span class="n">view</span><span class="p">:</span>
|
||
<span class="k">assert</span> <span class="n">view</span><span class="o">.</span><span class="n">tobytes</span><span class="p">()</span> <span class="o">==</span> <span class="sa">b</span><span class="s2">"Capybara!"</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="equivalent-for-older-python-versions">
|
||
<h3><a class="toc-backref" href="#equivalent-for-older-python-versions" role="doc-backlink">Equivalent for older Python versions</a></h3>
|
||
<p>New typing features are usually backported to older Python versions
|
||
in the <a class="reference external" href="https://pypi.org/project/typing-extensions/">typing_extensions</a>
|
||
package. Because the buffer protocol
|
||
is currently accessible only in C, this PEP cannot be fully implemented
|
||
in a pure-Python package like <code class="docutils literal notranslate"><span class="pre">typing_extensions</span></code>. As a temporary
|
||
workaround, an abstract base class <code class="docutils literal notranslate"><span class="pre">typing_extensions.Buffer</span></code>
|
||
will be provided for Python versions
|
||
that do not have <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code> available.</p>
|
||
<p>After this PEP is implemented, inheriting from <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code> will
|
||
not be necessary to indicate that an object supports the buffer protocol.
|
||
However, in older Python versions, it will be necessary to explicitly
|
||
inherit from <code class="docutils literal notranslate"><span class="pre">typing_extensions.Buffer</span></code> to indicate to type checkers that
|
||
a class supports the buffer protocol, since objects supporting the buffer
|
||
protocol will not have a <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method. It is expected that this
|
||
will happen primarily in stub files, because buffer classes are necessarily
|
||
implemented in C code, which cannot have types defined inline.
|
||
For runtime uses, the <code class="docutils literal notranslate"><span class="pre">ABC.register</span></code> API can be used to register
|
||
buffer classes with <code class="docutils literal notranslate"><span class="pre">typing_extensions.Buffer</span></code>.</p>
|
||
</section>
|
||
<section id="no-special-meaning-for-bytes">
|
||
<h3><a class="toc-backref" href="#no-special-meaning-for-bytes" role="doc-backlink">No special meaning for <code class="docutils literal notranslate"><span class="pre">bytes</span></code></a></h3>
|
||
<p>The special case stating that <code class="docutils literal notranslate"><span class="pre">bytes</span></code> may be used as a shorthand
|
||
for other <code class="docutils literal notranslate"><span class="pre">ByteString</span></code> types will be removed from the <code class="docutils literal notranslate"><span class="pre">typing</span></code>
|
||
documentation.
|
||
With <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code> available as an alternative, there will be no good
|
||
reason to allow <code class="docutils literal notranslate"><span class="pre">bytes</span></code> as a shorthand.
|
||
Type checkers currently implementing this behavior
|
||
should deprecate and eventually remove it.</p>
|
||
</section>
|
||
</section>
|
||
<section id="backwards-compatibility">
|
||
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
|
||
<section id="buffer-and-release-buffer-attributes">
|
||
<h3><a class="toc-backref" href="#buffer-and-release-buffer-attributes" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> and <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> attributes</a></h3>
|
||
<p>As the runtime changes in this PEP only add new functionality, there are
|
||
few backwards compatibility concerns.</p>
|
||
<p>However, code that uses a <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> or <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> attribute for
|
||
other purposes may be affected. While all dunders are technically reserved for the
|
||
language, it is still good practice to ensure that a new dunder does not
|
||
interfere with too much existing code, especially widely used packages. A survey
|
||
of publicly accessible code found:</p>
|
||
<ul class="simple">
|
||
<li>PyPy <a class="reference external" href="https://doc.pypy.org/en/latest/__pypy__-module.html#generally-available-functionality">supports</a>
|
||
a <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method with compatible semantics to those proposed in this
|
||
PEP. A PyPy core developer <a class="reference external" href="https://discuss.python.org/t/pep-688-making-the-buffer-protocol-accessible-in-python/15265/34">expressed his support</a>
|
||
for this PEP.</li>
|
||
<li>pyzmq <a class="reference external" href="https://github.com/zeromq/pyzmq/blob/fe18dc55516ef50d168fc02f8550a67ff5b5633d/zmq/backend/cffi/message.py#L190">implements</a>
|
||
a PyPy-compatible <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method.</li>
|
||
<li>mpi4py <a class="reference external" href="https://github.com/mpi4py/mpi4py/blob/453b87d0da37c5914b91afb511b188556dff2a9c/src/mpi4py/typing.py#L66">defines</a>
|
||
a <code class="docutils literal notranslate"><span class="pre">SupportsBuffer</span></code> protocol that would be equivalent to this PEP’s <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code>.</li>
|
||
<li>NumPy used to have an undocumented behavior where it would access a <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> attribute
|
||
(not method) to get an object’s buffer. This was <a class="reference external" href="https://github.com/numpy/numpy/pull/13049">removed</a>
|
||
in 2019 for NumPy 1.17. The behavior would have last worked in NumPy 1.16, which only supported
|
||
Python 3.7 and older. Python 3.7 will have reached its end of life by the time this PEP is expected to
|
||
be implemented.</li>
|
||
</ul>
|
||
<p>Thus, this PEP’s use of the <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> method will improve interoperability with
|
||
PyPy and not interfere with the current versions of any major Python packages.</p>
|
||
<p>No publicly accessible code uses the name <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code>.</p>
|
||
</section>
|
||
<section id="removal-of-the-bytes-special-case">
|
||
<h3><a class="toc-backref" href="#removal-of-the-bytes-special-case" role="doc-backlink">Removal of the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> special case</a></h3>
|
||
<p>Separately, the recommendation to remove the special behavior for
|
||
<code class="docutils literal notranslate"><span class="pre">bytes</span></code> in type checkers does have a backwards compatibility
|
||
impact on their users. An <a class="reference external" href="https://github.com/python/mypy/pull/12661">experiment</a>
|
||
with mypy shows that several major open source projects that use it
|
||
for type checking will see new errors if the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> promotion
|
||
is removed. Many of these errors can be fixed by improving
|
||
the stubs in typeshed, as has already been done for the
|
||
<a class="reference external" href="https://github.com/python/typeshed/pull/7631">builtins</a>,
|
||
<a class="reference external" href="https://github.com/python/typeshed/pull/7677">binascii</a>,
|
||
<a class="reference external" href="https://github.com/python/typeshed/pull/7678">pickle</a>, and
|
||
<a class="reference external" href="https://github.com/python/typeshed/pull/7679">re</a> modules.
|
||
A <a class="reference external" href="https://github.com/python/typeshed/issues/9006">review</a> of all
|
||
usage of <code class="docutils literal notranslate"><span class="pre">bytes</span></code> types in typeshed is in progress.
|
||
Overall, the change improves type safety and makes the type system
|
||
more consistent, so we believe the migration cost is worth it.</p>
|
||
</section>
|
||
</section>
|
||
<section id="how-to-teach-this">
|
||
<h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2>
|
||
<p>We will add notes pointing to <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code> in appropriate places in the
|
||
documentation, such as <a class="reference external" href="https://typing.readthedocs.io/en/latest/">typing.readthedocs.io</a>
|
||
and the <a class="reference external" href="https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html">mypy cheat sheet</a>.
|
||
Type checkers may provide additional pointers in their error messages. For example,
|
||
when they encounter a buffer object being passed to a function that
|
||
is annotated to only accept <code class="docutils literal notranslate"><span class="pre">bytes</span></code>, the error message could include a note suggesting
|
||
the use of <code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code> instead.</p>
|
||
</section>
|
||
<section id="reference-implementation">
|
||
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
|
||
<p>An implementation of this PEP is
|
||
<a class="reference external" href="https://github.com/python/cpython/compare/main...JelleZijlstra:pep688v2?expand=1">available</a>
|
||
in the author’s fork.</p>
|
||
</section>
|
||
<section id="rejected-ideas">
|
||
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
|
||
<section id="types-buffer">
|
||
<h3><a class="toc-backref" href="#types-buffer" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">types.Buffer</span></code></a></h3>
|
||
<p>An earlier version of this PEP proposed adding a new <code class="docutils literal notranslate"><span class="pre">types.Buffer</span></code> type with
|
||
an <code class="docutils literal notranslate"><span class="pre">__instancecheck__</span></code> implemented in C so that <code class="docutils literal notranslate"><span class="pre">isinstance()</span></code> checks can be
|
||
used to check whether a type implements the buffer protocol. This avoids the
|
||
complexity of exposing the full buffer protocol to Python code, while still
|
||
allowing the type system to check for the buffer protocol.</p>
|
||
<p>However, that approach
|
||
does not compose well with the rest of the type system, because <code class="docutils literal notranslate"><span class="pre">types.Buffer</span></code>
|
||
would be a nominal type, not a structural one. For example, there would be no way
|
||
to represent “an object that supports both the buffer protocol and <code class="docutils literal notranslate"><span class="pre">__len__</span></code>”. With
|
||
the current proposal, <code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> is like any other special method, so a
|
||
<code class="docutils literal notranslate"><span class="pre">Protocol</span></code> can be defined combining it with another method.</p>
|
||
<p>More generally, no other part of Python works like the proposed <code class="docutils literal notranslate"><span class="pre">types.Buffer</span></code>.
|
||
The current proposal is more consistent with the rest of the language, where
|
||
C-level slots usually have corresponding Python-level special methods.</p>
|
||
</section>
|
||
<section id="keep-bytearray-compatible-with-bytes">
|
||
<h3><a class="toc-backref" href="#keep-bytearray-compatible-with-bytes" role="doc-backlink">Keep <code class="docutils literal notranslate"><span class="pre">bytearray</span></code> compatible with <code class="docutils literal notranslate"><span class="pre">bytes</span></code></a></h3>
|
||
<p>It has been suggested to remove the special case where <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> is
|
||
always compatible with <code class="docutils literal notranslate"><span class="pre">bytes</span></code>, but keep it for <code class="docutils literal notranslate"><span class="pre">bytearray</span></code>, because
|
||
the two types have very similar interfaces. However, several standard
|
||
library functions (e.g., <code class="docutils literal notranslate"><span class="pre">re.compile</span></code>, <code class="docutils literal notranslate"><span class="pre">socket.getaddrinfo</span></code>, and most
|
||
functions accepting path-like arguments) accept
|
||
<code class="docutils literal notranslate"><span class="pre">bytes</span></code> but not <code class="docutils literal notranslate"><span class="pre">bytearray</span></code>. In most codebases, <code class="docutils literal notranslate"><span class="pre">bytearray</span></code> is also
|
||
not a very common type. We prefer to have users spell out accepted types
|
||
explicitly (or use <code class="docutils literal notranslate"><span class="pre">Protocol</span></code> from <a class="pep reference internal" href="../pep-0544/" title="PEP 544 – Protocols: Structural subtyping (static duck typing)">PEP 544</a> if only a specific set of
|
||
methods is required). This aspect of the proposal was <a class="reference external" href="https://mail.python.org/archives/list/typing-sig@python.org/thread/XH5ZK2MSZIQLL62PYZ6I5532SQKKVCBL/">specifically
|
||
discussed</a>
|
||
on the typing-sig mailing list, without any strong disagreement from the
|
||
typing community.</p>
|
||
</section>
|
||
<section id="distinguish-between-mutable-and-immutable-buffers">
|
||
<h3><a class="toc-backref" href="#distinguish-between-mutable-and-immutable-buffers" role="doc-backlink">Distinguish between mutable and immutable buffers</a></h3>
|
||
<p>The most frequently used distinction within buffer types is
|
||
whether or not the buffer is mutable. Some functions accept only
|
||
mutable buffers (e.g., <code class="docutils literal notranslate"><span class="pre">bytearray</span></code>, some <code class="docutils literal notranslate"><span class="pre">memoryview</span></code> objects),
|
||
others accept all buffers.</p>
|
||
<p>An earlier version of this PEP proposed using the presence of the
|
||
<code class="docutils literal notranslate"><span class="pre">bf_releasebuffer</span></code> slot to determine whether a buffer type is mutable.
|
||
This rule holds for most standard library buffer types, but the relationship
|
||
between mutability and the presence of this slot is not absolute. For
|
||
example, <code class="docutils literal notranslate"><span class="pre">numpy</span></code> arrays are mutable but do not have this slot.</p>
|
||
<p>The current buffer protocol does not provide any way to reliably
|
||
determine whether a buffer type represents a mutable or immutable
|
||
buffer. Therefore, this PEP does not add type system support
|
||
for this distinction.
|
||
The question can be revisited in the future if the buffer protocol
|
||
is enhanced to provide static introspection support.
|
||
A <a class="reference external" href="https://discuss.python.org/t/introspection-and-mutable-xor-shared-semantics-for-pybuffer/20314">sketch</a>
|
||
for such a mechanism exists.</p>
|
||
</section>
|
||
</section>
|
||
<section id="acknowledgments">
|
||
<h2><a class="toc-backref" href="#acknowledgments" role="doc-backlink">Acknowledgments</a></h2>
|
||
<p>Many people have provided useful feedback on drafts of this PEP.
|
||
Petr Viktorin has been particularly helpful in improving my understanding
|
||
of the subtleties of the buffer protocol.</p>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document is placed in the public domain or under the
|
||
CC0-1.0-Universal license, whichever is more permissive.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0688.rst">https://github.com/python/peps/blob/main/peps/pep-0688.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0688.rst">2024-10-17 12:49:39 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
||
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
|
||
<li><a class="reference internal" href="#current-options">Current options</a></li>
|
||
<li><a class="reference internal" href="#kinds-of-buffers">Kinds of buffers</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification">Specification</a><ul>
|
||
<li><a class="reference internal" href="#python-level-buffer-protocol">Python-level buffer protocol</a></li>
|
||
<li><a class="reference internal" href="#inspect-bufferflags"><code class="docutils literal notranslate"><span class="pre">inspect.BufferFlags</span></code></a></li>
|
||
<li><a class="reference internal" href="#collections-abc-buffer"><code class="docutils literal notranslate"><span class="pre">collections.abc.Buffer</span></code></a></li>
|
||
<li><a class="reference internal" href="#example">Example</a></li>
|
||
<li><a class="reference internal" href="#equivalent-for-older-python-versions">Equivalent for older Python versions</a></li>
|
||
<li><a class="reference internal" href="#no-special-meaning-for-bytes">No special meaning for <code class="docutils literal notranslate"><span class="pre">bytes</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a><ul>
|
||
<li><a class="reference internal" href="#buffer-and-release-buffer-attributes"><code class="docutils literal notranslate"><span class="pre">__buffer__</span></code> and <code class="docutils literal notranslate"><span class="pre">__release_buffer__</span></code> attributes</a></li>
|
||
<li><a class="reference internal" href="#removal-of-the-bytes-special-case">Removal of the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> special case</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li>
|
||
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
||
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
||
<li><a class="reference internal" href="#types-buffer"><code class="docutils literal notranslate"><span class="pre">types.Buffer</span></code></a></li>
|
||
<li><a class="reference internal" href="#keep-bytearray-compatible-with-bytes">Keep <code class="docutils literal notranslate"><span class="pre">bytearray</span></code> compatible with <code class="docutils literal notranslate"><span class="pre">bytes</span></code></a></li>
|
||
<li><a class="reference internal" href="#distinguish-between-mutable-and-immutable-buffers">Distinguish between mutable and immutable buffers</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#acknowledgments">Acknowledgments</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0688.rst">Page Source (GitHub)</a>
|
||
</nav>
|
||
</section>
|
||
<script src="../_static/colour_scheme.js"></script>
|
||
<script src="../_static/wrap_tables.js"></script>
|
||
<script src="../_static/sticky_banner.js"></script>
|
||
</body>
|
||
</html> |