Skip to main content

Include/internal/pycore_bytes_methods.h

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_bytes_methods.h

Declares the _Py_bytes_* family of functions that are shared between bytesobj and bytearrayobj. Neither type duplicates its method implementations; instead both reference a common method table and call into Objects/bytes_methods.c. The split is deliberate: the public header Include/cpython/bytesobject.h exposes only the Python-level API, while this internal header gives other C translation units access to the raw helpers without pulling in the full PyBytesObject struct layout.

The key consumers are Objects/bytesobject.c (which owns bytes_methods at line 2664) and Objects/bytearrayobject.c (which mirrors it with its own method table that delegates to the same _Py_bytes_* implementations). String-template headers in Objects/stringlib/ -- find.h, split.h, transmogrify.h, partition.h, and fastsearch.h -- are the actual implementations instantiated by a set of #define macros before each #include. The pycore_bytes_methods.h declarations let all callers agree on the shared signatures without seeing those templates.

Map

LinesSymbolRolegopy
1-20_Py_bytes_lower, _Py_bytes_upper, _Py_bytes_title, _Py_bytes_capitalize, _Py_bytes_swapcaseCase-conversion helpers; operate on a raw const char * + Py_ssize_t pair.not yet ported
21-40_Py_bytes_find, _Py_bytes_rfind, _Py_bytes_index, _Py_bytes_rindex, _Py_bytes_countSubstring search and count with [start:end] slice arguments.objects/bytes_methods_wrap.go (as Find, RFind, Index, RIndex, Count)
41-55_Py_bytes_split, _Py_bytes_rsplit, _Py_bytes_splitlines, _Py_bytes_partition, _Py_bytes_rpartitionSplitting and partitioning family.objects/bytes_methods_wrap.go (as Split, RSplit, SplitLines, Partition, RPartition)
56-70_Py_bytes_strip, _Py_bytes_lstrip, _Py_bytes_rstrip, _Py_bytes_maketransStrip family and translation-table builder.objects/bytes_methods_wrap.go (as Strip, LStrip, RStrip, MakeBytesTrans)
71-80_Py_bytes_isalpha, _Py_bytes_isdigit, _Py_bytes_isspace, _Py_bytes_islower, _Py_bytes_isupper, _Py_bytes_istitlePredicate methods; each returns PyObject * (True or False).not yet ported

Reading

Declaration convention (lines 1 to 40)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_bytes_methods.h#L1-40

Every helper follows the same C signature shape: the first two arguments are the receiver byte array (const char *, Py_ssize_t), followed by the Python argument objects already converted by Argument Clinic. The functions return PyObject * (new reference) rather than raw C primitives so the calling method table entry can return them directly to the interpreter:

PyObject* _Py_bytes_find(const char *str, Py_ssize_t len,
PyObject *args);
PyObject* _Py_bytes_count(const char *str, Py_ssize_t len,
PyObject *args);
PyObject* _Py_bytes_split(const char *str, Py_ssize_t len,
PyObject *args);

Both bytes.find and bytearray.find in their respective method tables produce wrappers that extract self->ob_val and Py_SIZE(self), then call the same _Py_bytes_find. The duplication that would otherwise exist across the two type implementations is eliminated entirely.

Template instantiation in Objects/stringlib/ (referenced by lines 21 to 55)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_bytes_methods.h#L21-55

The implementations of _Py_bytes_find, _Py_bytes_split, and their siblings are not written in bytes_methods.c as ordinary functions. Instead Objects/bytesobject.c sets a block of #define macros -- STRINGLIB_CHAR, STRINGLIB_LEN, STRINGLIB_NEW, STRINGLIB_ISSPACE and so on -- that parameterize the shared templates, then #includes them:

/* In Objects/bytesobject.c, before each stringlib include: */
#define STRINGLIB_CHAR char
#define STRINGLIB_ISSPACE Py_ISSPACE
#define STRINGLIB_ISLINEBREAK(c) ((c) == '\n' || (c) == '\r')
#define STRINGLIB_NEW PyBytes_FromStringAndSize
#define STRINGLIB_LEN PyBytes_GET_SIZE
...
#include "stringlib/fastsearch.h"
#include "stringlib/split.h"
#include "stringlib/find.h"
#include "stringlib/partition.h"
#include "stringlib/transmogrify.h"

Objects/bytearrayobject.c repeats the pattern with STRINGLIB_NEW pointing to PyByteArray_FromStringAndSize and STRINGLIB_LEN to PyByteArray_GET_SIZE. The two translation units thus each compile a separate copy of the template code, tuned to their own allocation and size macros, while sharing the declaration contract from pycore_bytes_methods.h.

_Py_bytes_maketrans and the 256-byte table contract (lines 56 to 70)

cpython 3.14 @ ab2d84fe1023/Include/internal/pycore_bytes_methods.h#L56-70

_Py_bytes_maketrans is the only helper in this header that is not a template instantiation. It lives entirely in Objects/bytes_methods.c and builds a 256-element bytes object that maps frm[i] to to[i] for every pair, leaving all other byte values as identity:

PyObject *
_Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to)
{
Py_ssize_t n = frm->len;
if (n != to->len) {
PyErr_SetString(PyExc_ValueError,
"maketrans arguments must have same length");
return NULL;
}
/* Build a 256-byte identity table first. */
char *buf;
PyObject *res = PyBytes_FromStringAndSize(NULL, 256);
...
buf = PyBytes_AS_STRING(res);
for (int i = 0; i < 256; i++) buf[i] = (char)i;
for (Py_ssize_t i = 0; i < n; i++)
buf[((const unsigned char *)frm->buf)[i]] =
((const unsigned char *)to->buf)[i];
return res;
}

The resulting object is passed straight to _Py_bytes_translate (the underlying implementation of bytes.translate), which indexes the table once per input byte. Both bytes.maketrans and bytearray.maketrans call this single C function.

gopy mirror

objects/bytes_methods_wrap.go covers the search, split, strip, pad, hex, and translation methods. The file applies the same receiver/helper split as CPython: raw []byte helpers (clampBytesSlice, splitWhitespace, stripPredicate, padFill, hexDigit) are package-level functions; the *Bytes methods (Find, Split, Strip, Translate, MakeBytesTrans, etc.) wrap them exactly as CPython's method-table entries wrap _Py_bytes_*. The case- conversion methods (Lower, Upper, Title, Capitalize, Swapcase) and the Is* predicates are not yet ported.

CPython 3.14 changes

The header and Objects/bytes_methods.c have been stable in structure since Python 3.0. In 3.12 the Argument Clinic machinery was applied to most bytes/bytearray methods, replacing hand-written argument parsing with generated code; the _Py_bytes_* signatures themselves did not change. No structural changes affect this header in 3.14.