Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 79 additions & 10 deletions Doc/c-api/descriptor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,31 @@ Descriptor Objects
"Descriptors" are objects that describe some attribute of an object. They are
found in the dictionary of type objects.

.. XXX document these!

.. c:function:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset)

Create a new get-set descriptor for extension type *type* from the
:c:type:`PyGetSetDef` structure *getset*.

Get-set descriptors expose attributes implemented by C getter and setter
functions rather than stored directly in the instance. This is the same kind
of descriptor created for entries in :c:member:`~PyTypeObject.tp_getset`, and
it appears in Python as a :class:`types.GetSetDescriptorType` object.

On success, return a :term:`strong reference` to the descriptor. Return
``NULL`` with an exception set on failure.

.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *member)

.. c:function:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *meth)
Create a new member descriptor for extension type *type* from the
:c:type:`PyMemberDef` structure *member*.

Member descriptors expose fields in the type's C struct as Python
attributes. This is the same kind of descriptor created for entries in
:c:member:`~PyTypeObject.tp_members`, and it appears in Python as a
:class:`types.MemberDescriptorType` object.

On success, return a :term:`strong reference` to the descriptor. Return
``NULL`` with an exception set on failure.

.. c:var:: PyTypeObject PyMemberDescr_Type

Expand All @@ -30,22 +48,53 @@ found in the dictionary of type objects.
The type object for get/set descriptor objects created from
:c:type:`PyGetSetDef` structures. These descriptors implement attributes
whose value is computed by C getter and setter functions, and are used
for many built-in type attributes.
for many built-in type attributes. They correspond to
:class:`types.GetSetDescriptorType` objects in Python.


.. c:function:: PyObject* PyDescr_NewMethod(PyTypeObject *type, struct PyMethodDef *meth)

Create a new method descriptor for extension type *type* from the
:c:type:`PyMethodDef` structure *meth*.

Method descriptors expose C functions as methods on a type. This is the same
kind of descriptor created for entries in
:c:member:`~PyTypeObject.tp_methods`, and it appears in Python as a
:class:`types.MethodDescriptorType` object.

On success, return a :term:`strong reference` to the descriptor. Return
``NULL`` with an exception set on failure.

.. c:var:: PyTypeObject PyMethodDescr_Type

The type object for method descriptor objects created from
:c:type:`PyMethodDef` structures. These descriptors expose C functions as
methods on a type, and correspond to :class:`types.MemberDescriptorType`
methods on a type, and correspond to :class:`types.MethodDescriptorType`
objects in Python.


.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *wrapper, void *wrapped)
.. c:struct:: wrapperbase

Describes a slot wrapper used by :c:func:`PyDescr_NewWrapper`.

Each ``wrapperbase`` record stores the Python-visible name and metadata for a
special method implemented by a type slot, together with the wrapper
function used to adapt that slot to Python's calling convention.

.. c:function:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)

Create a new wrapper descriptor for extension type *type* from the
:c:struct:`wrapperbase` structure *base* and the wrapped slot function
pointer
*wrapped*.

Wrapper descriptors expose special methods implemented by type slots. This
is the same kind of descriptor that CPython creates for slot-based special
methods such as ``__repr__`` or ``__add__``, and it appears in Python as a
:class:`types.WrapperDescriptorType` object.

On success, return a :term:`strong reference` to the descriptor. Return
``NULL`` with an exception set on failure.

.. c:var:: PyTypeObject PyWrapperDescr_Type

Expand All @@ -58,6 +107,16 @@ found in the dictionary of type objects.

.. c:function:: PyObject* PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)

Create a new class method descriptor for extension type *type* from the
:c:type:`PyMethodDef` structure *method*.

Class method descriptors expose C methods that receive the class rather than
an instance when accessed. This is the same kind of descriptor created for
``METH_CLASS`` entries in :c:member:`~PyTypeObject.tp_methods`, and it
appears in Python as a :class:`types.ClassMethodDescriptorType` object.

On success, return a :term:`strong reference` to the descriptor. Return
``NULL`` with an exception set on failure.

.. c:function:: int PyDescr_IsData(PyObject *descr)

Expand All @@ -66,8 +125,18 @@ found in the dictionary of type objects.
no error checking.


.. c:function:: PyObject* PyWrapper_New(PyObject *, PyObject *)
.. c:function:: PyObject* PyWrapper_New(PyObject *d, PyObject *self)

Create a new bound wrapper object from the wrapper descriptor *d* and the
instance *self*.

This is the bound form of a wrapper descriptor created by
:c:func:`PyDescr_NewWrapper`. CPython creates these objects when a slot
wrapper is accessed through an instance, and they appear in Python as
:class:`types.MethodWrapperType` objects.

On success, return a :term:`strong reference` to the wrapper object. Return
``NULL`` with an exception set on failure.

.. c:macro:: PyDescr_COMMON

Expand Down Expand Up @@ -104,9 +173,9 @@ Built-in descriptors
.. c:var:: PyTypeObject PyClassMethodDescr_Type

The type object for C-level class method descriptor objects.
This is the type of the descriptors created for :func:`classmethod` defined in
C extension types, and is the same object as :class:`classmethod`
in Python.
This is the type of the descriptors created for :func:`classmethod` defined
in C extension types, and corresponds to
:class:`types.ClassMethodDescriptorType` objects in Python.


.. c:function:: PyObject *PyClassMethod_New(PyObject *callable)
Expand Down
12 changes: 8 additions & 4 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3735,12 +3735,13 @@ arbitrary binary data.
The separator to search for may be any :term:`bytes-like object`.


.. method:: bytes.replace(old, new, count=-1, /)
bytearray.replace(old, new, count=-1, /)
.. method:: bytes.replace(old, new, /, count=-1)
bytearray.replace(old, new, /, count=-1)

Return a copy of the sequence with all occurrences of subsequence *old*
replaced by *new*. If the optional argument *count* is given, only the
first *count* occurrences are replaced.
replaced by *new*. If *count* is given, only the first *count* occurrences
are replaced. If *count* is not specified or ``-1``, then all occurrences
are replaced.

The subsequence to search for and its replacement may be any
:term:`bytes-like object`.
Expand All @@ -3750,6 +3751,9 @@ arbitrary binary data.
The bytearray version of this method does *not* operate in place - it
always produces a new object, even if no changes were made.

.. versionchanged:: next
*count* is now supported as a keyword argument.


.. method:: bytes.rfind(sub[, start[, end]])
bytearray.rfind(sub[, start[, end]])
Expand Down
1 change: 0 additions & 1 deletion Doc/tools/.nitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# as tested on the CI via check-warnings.py in reusable-docs.yml.
# Keep lines sorted lexicographically to help avoid merge conflicts.

Doc/c-api/descriptor.rst
Doc/c-api/init_config.rst
Doc/c-api/intro.rst
Doc/c-api/stable.rst
Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ Other language changes
respectively.
(Contributed by Sergey B Kirpichev in :gh:`146151`.)

* Allow the *count* argument of :meth:`bytes.replace` to be a keyword.
(Contributed by Stan Ulbrych in :gh:`147856`.)


New modules
===========
Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,13 @@ def test_replace(self):
self.assertEqual(b.replace(b'i', b'a'), b'massassappa')
self.assertEqual(b.replace(b'ss', b'x'), b'mixixippi')

def test_replace_count_keyword(self):
b = self.type2test(b'aa')
self.assertEqual(b.replace(b'a', b'b', count=0), b'aa')
self.assertEqual(b.replace(b'a', b'b', count=1), b'ba')
self.assertEqual(b.replace(b'a', b'b', count=2), b'bb')
self.assertEqual(b.replace(b'a', b'b', count=3), b'bb')

def test_replace_int_error(self):
self.assertRaises(TypeError, self.type2test(b'a b').replace, 32, b'')

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow the *count* argument of :meth:`bytes.replace` to be a keyword.
9 changes: 4 additions & 5 deletions Objects/bytearrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1752,27 +1752,26 @@ bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to)


/*[clinic input]
@permit_long_docstring_body
@critical_section
bytearray.replace

old: Py_buffer
new: Py_buffer
/
count: Py_ssize_t = -1
Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences.
/

Return a copy with all occurrences of substring old replaced by new.

If the optional argument count is given, only the first count occurrences are
replaced.
If count is given, only the first count occurrences are replaced.
If count is not specified or -1, then all occurrences are replaced.
[clinic start generated code]*/

static PyObject *
bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old,
Py_buffer *new, Py_ssize_t count)
/*[clinic end generated code: output=d39884c4dc59412a input=66afec32f4e095e0]*/
/*[clinic end generated code: output=d39884c4dc59412a input=e2591806f954aec3]*/
{
return stringlib_replace((PyObject *)self,
(const char *)old->buf, old->len,
Expand Down
9 changes: 4 additions & 5 deletions Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2403,26 +2403,25 @@ bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to)


/*[clinic input]
@permit_long_docstring_body
bytes.replace

old: Py_buffer
new: Py_buffer
/
count: Py_ssize_t = -1
Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences.
/

Return a copy with all occurrences of substring old replaced by new.

If the optional argument count is given, only the first count occurrences are
replaced.
If count is given, only the first count occurrences are replaced.
If count is not specified or -1, then all occurrences are replaced.
[clinic start generated code]*/

static PyObject *
bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
Py_ssize_t count)
/*[clinic end generated code: output=994fa588b6b9c104 input=8b99a9ab32bc06a2]*/
/*[clinic end generated code: output=994fa588b6b9c104 input=cdf3cf8639297745]*/
{
return stringlib_replace((PyObject *)self,
(const char *)old->buf, old->len,
Expand Down
51 changes: 41 additions & 10 deletions Objects/clinic/bytearrayobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading