mirror of https://github.com/python/cpython
bpo-39939: Add str.removeprefix and str.removesuffix (GH-18939)
Added str.removeprefix and str.removesuffix methods and corresponding bytes, bytearray, and collections.UserString methods to remove affixes from a string if present. See PEP 616 for a full description.
This commit is contained in:
parent
39652cd8bd
commit
a81849b031
|
@ -1549,6 +1549,33 @@ expression support in the :mod:`re` module).
|
||||||
interpreted as in slice notation.
|
interpreted as in slice notation.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: str.removeprefix(prefix, /)
|
||||||
|
|
||||||
|
If the string starts with the *prefix* string, return
|
||||||
|
``string[len(prefix):]``. Otherwise, return a copy of the original
|
||||||
|
string::
|
||||||
|
|
||||||
|
>>> 'TestHook'.removeprefix('Test')
|
||||||
|
'Hook'
|
||||||
|
>>> 'BaseTestCase'.removeprefix('Test')
|
||||||
|
'BaseTestCase'
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
.. method:: str.removesuffix(suffix, /)
|
||||||
|
|
||||||
|
If the string ends with the *suffix* string and that *suffix* is not empty,
|
||||||
|
return ``string[:-len(suffix)]``. Otherwise, return a copy of the
|
||||||
|
original string::
|
||||||
|
|
||||||
|
>>> 'MiscTests'.removesuffix('Tests')
|
||||||
|
'Misc'
|
||||||
|
>>> 'TmpDirMixin'.removesuffix('Tests')
|
||||||
|
'TmpDirMixin'
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. method:: str.encode(encoding="utf-8", errors="strict")
|
.. method:: str.encode(encoding="utf-8", errors="strict")
|
||||||
|
|
||||||
Return an encoded version of the string as a bytes object. Default encoding
|
Return an encoded version of the string as a bytes object. Default encoding
|
||||||
|
@ -1831,6 +1858,14 @@ expression support in the :mod:`re` module).
|
||||||
>>> 'www.example.com'.lstrip('cmowz.')
|
>>> 'www.example.com'.lstrip('cmowz.')
|
||||||
'example.com'
|
'example.com'
|
||||||
|
|
||||||
|
See :meth:`str.removeprefix` for a method that will remove a single prefix
|
||||||
|
string rather than all of a set of characters. For example::
|
||||||
|
|
||||||
|
>>> 'Arthur: three!'.lstrip('Arthur: ')
|
||||||
|
'ee!'
|
||||||
|
>>> 'Arthur: three!'.removeprefix('Arthur: ')
|
||||||
|
'three!'
|
||||||
|
|
||||||
|
|
||||||
.. staticmethod:: str.maketrans(x[, y[, z]])
|
.. staticmethod:: str.maketrans(x[, y[, z]])
|
||||||
|
|
||||||
|
@ -1911,6 +1946,13 @@ expression support in the :mod:`re` module).
|
||||||
>>> 'mississippi'.rstrip('ipz')
|
>>> 'mississippi'.rstrip('ipz')
|
||||||
'mississ'
|
'mississ'
|
||||||
|
|
||||||
|
See :meth:`str.removesuffix` for a method that will remove a single suffix
|
||||||
|
string rather than all of a set of characters. For example::
|
||||||
|
|
||||||
|
>>> 'Monty Python'.rstrip(' Python')
|
||||||
|
'M'
|
||||||
|
>>> 'Monty Python'.removesuffix(' Python')
|
||||||
|
'Monty'
|
||||||
|
|
||||||
.. method:: str.split(sep=None, maxsplit=-1)
|
.. method:: str.split(sep=None, maxsplit=-1)
|
||||||
|
|
||||||
|
@ -2591,6 +2633,50 @@ arbitrary binary data.
|
||||||
Also accept an integer in the range 0 to 255 as the subsequence.
|
Also accept an integer in the range 0 to 255 as the subsequence.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: bytes.removeprefix(prefix, /)
|
||||||
|
bytearray.removeprefix(prefix, /)
|
||||||
|
|
||||||
|
If the binary data starts with the *prefix* string, return
|
||||||
|
``bytes[len(prefix):]``. Otherwise, return a copy of the original
|
||||||
|
binary data::
|
||||||
|
|
||||||
|
>>> b'TestHook'.removeprefix(b'Test')
|
||||||
|
b'Hook'
|
||||||
|
>>> b'BaseTestCase'.removeprefix(b'Test')
|
||||||
|
b'BaseTestCase'
|
||||||
|
|
||||||
|
The *prefix* may be any :term:`bytes-like object`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The bytearray version of this method does *not* operate in place -
|
||||||
|
it always produces a new object, even if no changes were made.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: bytes.removesuffix(suffix, /)
|
||||||
|
bytearray.removesuffix(suffix, /)
|
||||||
|
|
||||||
|
If the binary data ends with the *suffix* string and that *suffix* is
|
||||||
|
not empty, return ``bytes[:-len(suffix)]``. Otherwise, return a copy of
|
||||||
|
the original binary data::
|
||||||
|
|
||||||
|
>>> b'MiscTests'.removesuffix(b'Tests')
|
||||||
|
b'Misc'
|
||||||
|
>>> b'TmpDirMixin'.removesuffix(b'Tests')
|
||||||
|
b'TmpDirMixin'
|
||||||
|
|
||||||
|
The *suffix* may be any :term:`bytes-like object`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The bytearray version of this method does *not* operate in place -
|
||||||
|
it always produces a new object, even if no changes were made.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. method:: bytes.decode(encoding="utf-8", errors="strict")
|
.. method:: bytes.decode(encoding="utf-8", errors="strict")
|
||||||
bytearray.decode(encoding="utf-8", errors="strict")
|
bytearray.decode(encoding="utf-8", errors="strict")
|
||||||
|
|
||||||
|
@ -2841,7 +2927,14 @@ produce new objects.
|
||||||
b'example.com'
|
b'example.com'
|
||||||
|
|
||||||
The binary sequence of byte values to remove may be any
|
The binary sequence of byte values to remove may be any
|
||||||
:term:`bytes-like object`.
|
:term:`bytes-like object`. See :meth:`~bytes.removeprefix` for a method
|
||||||
|
that will remove a single prefix string rather than all of a set of
|
||||||
|
characters. For example::
|
||||||
|
|
||||||
|
>>> b'Arthur: three!'.lstrip(b'Arthur: ')
|
||||||
|
b'ee!'
|
||||||
|
>>> b'Arthur: three!'.removeprefix(b'Arthur: ')
|
||||||
|
b'three!'
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -2890,7 +2983,14 @@ produce new objects.
|
||||||
b'mississ'
|
b'mississ'
|
||||||
|
|
||||||
The binary sequence of byte values to remove may be any
|
The binary sequence of byte values to remove may be any
|
||||||
:term:`bytes-like object`.
|
:term:`bytes-like object`. See :meth:`~bytes.removesuffix` for a method
|
||||||
|
that will remove a single suffix string rather than all of a set of
|
||||||
|
characters. For example::
|
||||||
|
|
||||||
|
>>> b'Monty Python'.rstrip(b' Python')
|
||||||
|
b'M'
|
||||||
|
>>> b'Monty Python'.removesuffix(b' Python')
|
||||||
|
b'Monty'
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,16 @@ Merge (``|``) and update (``|=``) operators have been added to the built-in
|
||||||
:class:`dict` class. See :pep:`584` for a full description.
|
:class:`dict` class. See :pep:`584` for a full description.
|
||||||
(Contributed by Brandt Bucher in :issue:`36144`.)
|
(Contributed by Brandt Bucher in :issue:`36144`.)
|
||||||
|
|
||||||
|
PEP 616: New removeprefix() and removesuffix() string methods
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
:meth:`str.removeprefix(prefix)<str.removeprefix>` and
|
||||||
|
:meth:`str.removesuffix(suffix)<str.removesuffix>` have been added
|
||||||
|
to easily remove an unneeded prefix or a suffix from a string. Corresponding
|
||||||
|
``bytes``, ``bytearray``, and ``collections.UserString`` methods have also been
|
||||||
|
added. See :pep:`616` for a full description. (Contributed by Dennis Sweeney in
|
||||||
|
:issue:`18939`.)
|
||||||
|
|
||||||
|
|
||||||
Other Language Changes
|
Other Language Changes
|
||||||
======================
|
======================
|
||||||
|
|
|
@ -1239,6 +1239,14 @@ class UserString(_collections_abc.Sequence):
|
||||||
if isinstance(sub, UserString):
|
if isinstance(sub, UserString):
|
||||||
sub = sub.data
|
sub = sub.data
|
||||||
return self.data.count(sub, start, end)
|
return self.data.count(sub, start, end)
|
||||||
|
def removeprefix(self, prefix, /):
|
||||||
|
if isinstance(prefix, UserString):
|
||||||
|
prefix = prefix.data
|
||||||
|
return self.__class__(self.data.removeprefix(prefix))
|
||||||
|
def removesuffix(self, suffix, /):
|
||||||
|
if isinstance(suffix, UserString):
|
||||||
|
suffix = suffix.data
|
||||||
|
return self.__class__(self.data.removesuffix(suffix))
|
||||||
def encode(self, encoding='utf-8', errors='strict'):
|
def encode(self, encoding='utf-8', errors='strict'):
|
||||||
encoding = 'utf-8' if encoding is None else encoding
|
encoding = 'utf-8' if encoding is None else encoding
|
||||||
errors = 'strict' if errors is None else errors
|
errors = 'strict' if errors is None else errors
|
||||||
|
|
|
@ -682,6 +682,42 @@ class BaseTest:
|
||||||
self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
|
self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
|
||||||
self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
|
self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
|
||||||
|
|
||||||
|
def test_removeprefix(self):
|
||||||
|
self.checkequal('am', 'spam', 'removeprefix', 'sp')
|
||||||
|
self.checkequal('spamspam', 'spamspamspam', 'removeprefix', 'spam')
|
||||||
|
self.checkequal('spam', 'spam', 'removeprefix', 'python')
|
||||||
|
self.checkequal('spam', 'spam', 'removeprefix', 'spider')
|
||||||
|
self.checkequal('spam', 'spam', 'removeprefix', 'spam and eggs')
|
||||||
|
|
||||||
|
self.checkequal('', '', 'removeprefix', '')
|
||||||
|
self.checkequal('', '', 'removeprefix', 'abcde')
|
||||||
|
self.checkequal('abcde', 'abcde', 'removeprefix', '')
|
||||||
|
self.checkequal('', 'abcde', 'removeprefix', 'abcde')
|
||||||
|
|
||||||
|
self.checkraises(TypeError, 'hello', 'removeprefix')
|
||||||
|
self.checkraises(TypeError, 'hello', 'removeprefix', 42)
|
||||||
|
self.checkraises(TypeError, 'hello', 'removeprefix', 42, 'h')
|
||||||
|
self.checkraises(TypeError, 'hello', 'removeprefix', 'h', 42)
|
||||||
|
self.checkraises(TypeError, 'hello', 'removeprefix', ("he", "l"))
|
||||||
|
|
||||||
|
def test_removesuffix(self):
|
||||||
|
self.checkequal('sp', 'spam', 'removesuffix', 'am')
|
||||||
|
self.checkequal('spamspam', 'spamspamspam', 'removesuffix', 'spam')
|
||||||
|
self.checkequal('spam', 'spam', 'removesuffix', 'python')
|
||||||
|
self.checkequal('spam', 'spam', 'removesuffix', 'blam')
|
||||||
|
self.checkequal('spam', 'spam', 'removesuffix', 'eggs and spam')
|
||||||
|
|
||||||
|
self.checkequal('', '', 'removesuffix', '')
|
||||||
|
self.checkequal('', '', 'removesuffix', 'abcde')
|
||||||
|
self.checkequal('abcde', 'abcde', 'removesuffix', '')
|
||||||
|
self.checkequal('', 'abcde', 'removesuffix', 'abcde')
|
||||||
|
|
||||||
|
self.checkraises(TypeError, 'hello', 'removesuffix')
|
||||||
|
self.checkraises(TypeError, 'hello', 'removesuffix', 42)
|
||||||
|
self.checkraises(TypeError, 'hello', 'removesuffix', 42, 'h')
|
||||||
|
self.checkraises(TypeError, 'hello', 'removesuffix', 'h', 42)
|
||||||
|
self.checkraises(TypeError, 'hello', 'removesuffix', ("lo", "l"))
|
||||||
|
|
||||||
def test_capitalize(self):
|
def test_capitalize(self):
|
||||||
self.checkequal(' hello ', ' hello ', 'capitalize')
|
self.checkequal(' hello ', ' hello ', 'capitalize')
|
||||||
self.checkequal('Hello ', 'Hello ','capitalize')
|
self.checkequal('Hello ', 'Hello ','capitalize')
|
||||||
|
|
|
@ -665,7 +665,7 @@ plain ol' Python and is guaranteed to be available.
|
||||||
|
|
||||||
>>> import builtins
|
>>> import builtins
|
||||||
>>> tests = doctest.DocTestFinder().find(builtins)
|
>>> tests = doctest.DocTestFinder().find(builtins)
|
||||||
>>> 810 < len(tests) < 830 # approximate number of objects with docstrings
|
>>> 816 < len(tests) < 836 # approximate number of objects with docstrings
|
||||||
True
|
True
|
||||||
>>> real_tests = [t for t in tests if len(t.examples) > 0]
|
>>> real_tests = [t for t in tests if len(t.examples) > 0]
|
||||||
>>> len(real_tests) # objects that actually have doctests
|
>>> len(real_tests) # objects that actually have doctests
|
||||||
|
|
|
@ -1660,6 +1660,7 @@ Hisao Suzuki
|
||||||
Kalle Svensson
|
Kalle Svensson
|
||||||
Andrew Svetlov
|
Andrew Svetlov
|
||||||
Paul Swartz
|
Paul Swartz
|
||||||
|
Dennis Sweeney
|
||||||
Al Sweigart
|
Al Sweigart
|
||||||
Sviatoslav Sydorenko
|
Sviatoslav Sydorenko
|
||||||
Thenault Sylvain
|
Thenault Sylvain
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Added str.removeprefix and str.removesuffix methods and corresponding
|
||||||
|
bytes, bytearray, and collections.UserString methods to remove affixes
|
||||||
|
from a string if present.
|
||||||
|
See :pep:`616` for a full description.
|
||||||
|
Patch by Dennis Sweeney.
|
|
@ -1181,6 +1181,71 @@ bytearray_endswith(PyByteArrayObject *self, PyObject *args)
|
||||||
return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
return _Py_bytes_endswith(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
bytearray.removeprefix as bytearray_removeprefix
|
||||||
|
|
||||||
|
prefix: Py_buffer
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a bytearray with the given prefix string removed if present.
|
||||||
|
|
||||||
|
If the bytearray starts with the prefix string, return
|
||||||
|
bytearray[len(prefix):]. Otherwise, return a copy of the original
|
||||||
|
bytearray.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix)
|
||||||
|
/*[clinic end generated code: output=6cabc585e7f502e0 input=968aada38aedd262]*/
|
||||||
|
{
|
||||||
|
const char *self_start = PyByteArray_AS_STRING(self);
|
||||||
|
Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
|
||||||
|
const char *prefix_start = prefix->buf;
|
||||||
|
Py_ssize_t prefix_len = prefix->len;
|
||||||
|
|
||||||
|
if (self_len >= prefix_len
|
||||||
|
&& memcmp(self_start, prefix_start, prefix_len) == 0)
|
||||||
|
{
|
||||||
|
return PyByteArray_FromStringAndSize(self_start + prefix_len,
|
||||||
|
self_len - prefix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyByteArray_FromStringAndSize(self_start, self_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
bytearray.removesuffix as bytearray_removesuffix
|
||||||
|
|
||||||
|
suffix: Py_buffer
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a bytearray with the given suffix string removed if present.
|
||||||
|
|
||||||
|
If the bytearray ends with the suffix string and that suffix is not
|
||||||
|
empty, return bytearray[:-len(suffix)]. Otherwise, return a copy of
|
||||||
|
the original bytearray.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix)
|
||||||
|
/*[clinic end generated code: output=2bc8cfb79de793d3 input=c1827e810b2f6b99]*/
|
||||||
|
{
|
||||||
|
const char *self_start = PyByteArray_AS_STRING(self);
|
||||||
|
Py_ssize_t self_len = PyByteArray_GET_SIZE(self);
|
||||||
|
const char *suffix_start = suffix->buf;
|
||||||
|
Py_ssize_t suffix_len = suffix->len;
|
||||||
|
|
||||||
|
if (self_len >= suffix_len
|
||||||
|
&& memcmp(self_start + self_len - suffix_len,
|
||||||
|
suffix_start, suffix_len) == 0)
|
||||||
|
{
|
||||||
|
return PyByteArray_FromStringAndSize(self_start,
|
||||||
|
self_len - suffix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyByteArray_FromStringAndSize(self_start, self_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
bytearray.translate
|
bytearray.translate
|
||||||
|
@ -2203,6 +2268,8 @@ bytearray_methods[] = {
|
||||||
BYTEARRAY_POP_METHODDEF
|
BYTEARRAY_POP_METHODDEF
|
||||||
BYTEARRAY_REMOVE_METHODDEF
|
BYTEARRAY_REMOVE_METHODDEF
|
||||||
BYTEARRAY_REPLACE_METHODDEF
|
BYTEARRAY_REPLACE_METHODDEF
|
||||||
|
BYTEARRAY_REMOVEPREFIX_METHODDEF
|
||||||
|
BYTEARRAY_REMOVESUFFIX_METHODDEF
|
||||||
BYTEARRAY_REVERSE_METHODDEF
|
BYTEARRAY_REVERSE_METHODDEF
|
||||||
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
|
{"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, _Py_rfind__doc__},
|
||||||
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
|
{"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, _Py_rindex__doc__},
|
||||||
|
|
|
@ -2182,6 +2182,81 @@ bytes_replace_impl(PyBytesObject *self, Py_buffer *old, Py_buffer *new,
|
||||||
|
|
||||||
/** End DALKE **/
|
/** End DALKE **/
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
bytes.removeprefix as bytes_removeprefix
|
||||||
|
|
||||||
|
prefix: Py_buffer
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a bytes object with the given prefix string removed if present.
|
||||||
|
|
||||||
|
If the bytes starts with the prefix string, return bytes[len(prefix):].
|
||||||
|
Otherwise, return a copy of the original bytes.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_removeprefix_impl(PyBytesObject *self, Py_buffer *prefix)
|
||||||
|
/*[clinic end generated code: output=f006865331a06ab6 input=0c93bac817a8502c]*/
|
||||||
|
{
|
||||||
|
const char *self_start = PyBytes_AS_STRING(self);
|
||||||
|
Py_ssize_t self_len = PyBytes_GET_SIZE(self);
|
||||||
|
const char *prefix_start = prefix->buf;
|
||||||
|
Py_ssize_t prefix_len = prefix->len;
|
||||||
|
|
||||||
|
if (self_len >= prefix_len
|
||||||
|
&& prefix_len > 0
|
||||||
|
&& memcmp(self_start, prefix_start, prefix_len) == 0)
|
||||||
|
{
|
||||||
|
return PyBytes_FromStringAndSize(self_start + prefix_len,
|
||||||
|
self_len - prefix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyBytes_CheckExact(self)) {
|
||||||
|
Py_INCREF(self);
|
||||||
|
return (PyObject *)self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyBytes_FromStringAndSize(self_start, self_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
bytes.removesuffix as bytes_removesuffix
|
||||||
|
|
||||||
|
suffix: Py_buffer
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a bytes object with the given suffix string removed if present.
|
||||||
|
|
||||||
|
If the bytes ends with the suffix string and that suffix is not empty,
|
||||||
|
return bytes[:-len(prefix)]. Otherwise, return a copy of the original
|
||||||
|
bytes.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix)
|
||||||
|
/*[clinic end generated code: output=d887d308e3242eeb input=9f4e1da8c637bbf1]*/
|
||||||
|
{
|
||||||
|
const char *self_start = PyBytes_AS_STRING(self);
|
||||||
|
Py_ssize_t self_len = PyBytes_GET_SIZE(self);
|
||||||
|
const char *suffix_start = suffix->buf;
|
||||||
|
Py_ssize_t suffix_len = suffix->len;
|
||||||
|
|
||||||
|
if (self_len >= suffix_len
|
||||||
|
&& suffix_len > 0
|
||||||
|
&& memcmp(self_start + self_len - suffix_len,
|
||||||
|
suffix_start, suffix_len) == 0)
|
||||||
|
{
|
||||||
|
return PyBytes_FromStringAndSize(self_start,
|
||||||
|
self_len - suffix_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PyBytes_CheckExact(self)) {
|
||||||
|
Py_INCREF(self);
|
||||||
|
return (PyObject *)self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PyBytes_FromStringAndSize(self_start, self_len);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytes_startswith(PyBytesObject *self, PyObject *args)
|
bytes_startswith(PyBytesObject *self, PyObject *args)
|
||||||
|
@ -2421,6 +2496,8 @@ bytes_methods[] = {
|
||||||
BYTES_MAKETRANS_METHODDEF
|
BYTES_MAKETRANS_METHODDEF
|
||||||
BYTES_PARTITION_METHODDEF
|
BYTES_PARTITION_METHODDEF
|
||||||
BYTES_REPLACE_METHODDEF
|
BYTES_REPLACE_METHODDEF
|
||||||
|
BYTES_REMOVEPREFIX_METHODDEF
|
||||||
|
BYTES_REMOVESUFFIX_METHODDEF
|
||||||
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
|
{"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, _Py_rfind__doc__},
|
||||||
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
|
{"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, _Py_rindex__doc__},
|
||||||
STRINGLIB_RJUST_METHODDEF
|
STRINGLIB_RJUST_METHODDEF
|
||||||
|
|
|
@ -38,6 +38,86 @@ bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
return bytearray_copy_impl(self);
|
return bytearray_copy_impl(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bytearray_removeprefix__doc__,
|
||||||
|
"removeprefix($self, prefix, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return a bytearray with the given prefix string removed if present.\n"
|
||||||
|
"\n"
|
||||||
|
"If the bytearray starts with the prefix string, return\n"
|
||||||
|
"bytearray[len(prefix):]. Otherwise, return a copy of the original\n"
|
||||||
|
"bytearray.");
|
||||||
|
|
||||||
|
#define BYTEARRAY_REMOVEPREFIX_METHODDEF \
|
||||||
|
{"removeprefix", (PyCFunction)bytearray_removeprefix, METH_O, bytearray_removeprefix__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytearray_removeprefix_impl(PyByteArrayObject *self, Py_buffer *prefix);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytearray_removeprefix(PyByteArrayObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer prefix = {NULL, NULL};
|
||||||
|
|
||||||
|
if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PyBuffer_IsContiguous(&prefix, 'C')) {
|
||||||
|
_PyArg_BadArgument("removeprefix", "argument", "contiguous buffer", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = bytearray_removeprefix_impl(self, &prefix);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for prefix */
|
||||||
|
if (prefix.obj) {
|
||||||
|
PyBuffer_Release(&prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bytearray_removesuffix__doc__,
|
||||||
|
"removesuffix($self, suffix, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return a bytearray with the given suffix string removed if present.\n"
|
||||||
|
"\n"
|
||||||
|
"If the bytearray ends with the suffix string and that suffix is not\n"
|
||||||
|
"empty, return bytearray[:-len(suffix)]. Otherwise, return a copy of\n"
|
||||||
|
"the original bytearray.");
|
||||||
|
|
||||||
|
#define BYTEARRAY_REMOVESUFFIX_METHODDEF \
|
||||||
|
{"removesuffix", (PyCFunction)bytearray_removesuffix, METH_O, bytearray_removesuffix__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytearray_removesuffix(PyByteArrayObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer suffix = {NULL, NULL};
|
||||||
|
|
||||||
|
if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PyBuffer_IsContiguous(&suffix, 'C')) {
|
||||||
|
_PyArg_BadArgument("removesuffix", "argument", "contiguous buffer", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = bytearray_removesuffix_impl(self, &suffix);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for suffix */
|
||||||
|
if (suffix.obj) {
|
||||||
|
PyBuffer_Release(&suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(bytearray_translate__doc__,
|
PyDoc_STRVAR(bytearray_translate__doc__,
|
||||||
"translate($self, table, /, delete=b\'\')\n"
|
"translate($self, table, /, delete=b\'\')\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -1011,4 +1091,4 @@ bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
return bytearray_sizeof_impl(self);
|
return bytearray_sizeof_impl(self);
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=508dce79cf2dffcc input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=b2919f76709e48dc input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -526,6 +526,85 @@ exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bytes_removeprefix__doc__,
|
||||||
|
"removeprefix($self, prefix, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return a bytes object with the given prefix string removed if present.\n"
|
||||||
|
"\n"
|
||||||
|
"If the bytes starts with the prefix string, return bytes[len(prefix):].\n"
|
||||||
|
"Otherwise, return a copy of the original bytes.");
|
||||||
|
|
||||||
|
#define BYTES_REMOVEPREFIX_METHODDEF \
|
||||||
|
{"removeprefix", (PyCFunction)bytes_removeprefix, METH_O, bytes_removeprefix__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_removeprefix_impl(PyBytesObject *self, Py_buffer *prefix);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_removeprefix(PyBytesObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer prefix = {NULL, NULL};
|
||||||
|
|
||||||
|
if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PyBuffer_IsContiguous(&prefix, 'C')) {
|
||||||
|
_PyArg_BadArgument("removeprefix", "argument", "contiguous buffer", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = bytes_removeprefix_impl(self, &prefix);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for prefix */
|
||||||
|
if (prefix.obj) {
|
||||||
|
PyBuffer_Release(&prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(bytes_removesuffix__doc__,
|
||||||
|
"removesuffix($self, suffix, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return a bytes object with the given suffix string removed if present.\n"
|
||||||
|
"\n"
|
||||||
|
"If the bytes ends with the suffix string and that suffix is not empty,\n"
|
||||||
|
"return bytes[:-len(prefix)]. Otherwise, return a copy of the original\n"
|
||||||
|
"bytes.");
|
||||||
|
|
||||||
|
#define BYTES_REMOVESUFFIX_METHODDEF \
|
||||||
|
{"removesuffix", (PyCFunction)bytes_removesuffix, METH_O, bytes_removesuffix__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_removesuffix_impl(PyBytesObject *self, Py_buffer *suffix);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bytes_removesuffix(PyBytesObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer suffix = {NULL, NULL};
|
||||||
|
|
||||||
|
if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PyBuffer_IsContiguous(&suffix, 'C')) {
|
||||||
|
_PyArg_BadArgument("removesuffix", "argument", "contiguous buffer", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = bytes_removesuffix_impl(self, &suffix);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for suffix */
|
||||||
|
if (suffix.obj) {
|
||||||
|
PyBuffer_Release(&suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(bytes_decode__doc__,
|
PyDoc_STRVAR(bytes_decode__doc__,
|
||||||
"decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n"
|
"decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -755,4 +834,4 @@ skip_optional_pos:
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=ca60dfccf8d51e88 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=220388917d7bf751 input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -754,6 +754,77 @@ exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(unicode_removeprefix__doc__,
|
||||||
|
"removeprefix($self, prefix, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return a str with the given prefix string removed if present.\n"
|
||||||
|
"\n"
|
||||||
|
"If the string starts with the prefix string, return string[len(prefix):].\n"
|
||||||
|
"Otherwise, return a copy of the original string.");
|
||||||
|
|
||||||
|
#define UNICODE_REMOVEPREFIX_METHODDEF \
|
||||||
|
{"removeprefix", (PyCFunction)unicode_removeprefix, METH_O, unicode_removeprefix__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_removeprefix_impl(PyObject *self, PyObject *prefix);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_removeprefix(PyObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *prefix;
|
||||||
|
|
||||||
|
if (!PyUnicode_Check(arg)) {
|
||||||
|
_PyArg_BadArgument("removeprefix", "argument", "str", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (PyUnicode_READY(arg) == -1) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
prefix = arg;
|
||||||
|
return_value = unicode_removeprefix_impl(self, prefix);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(unicode_removesuffix__doc__,
|
||||||
|
"removesuffix($self, suffix, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Return a str with the given suffix string removed if present.\n"
|
||||||
|
"\n"
|
||||||
|
"If the string ends with the suffix string and that suffix is not empty,\n"
|
||||||
|
"return string[:-len(suffix)]. Otherwise, return a copy of the original\n"
|
||||||
|
"string.");
|
||||||
|
|
||||||
|
#define UNICODE_REMOVESUFFIX_METHODDEF \
|
||||||
|
{"removesuffix", (PyCFunction)unicode_removesuffix, METH_O, unicode_removesuffix__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_removesuffix_impl(PyObject *self, PyObject *suffix);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_removesuffix(PyObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *suffix;
|
||||||
|
|
||||||
|
if (!PyUnicode_Check(arg)) {
|
||||||
|
_PyArg_BadArgument("removesuffix", "argument", "str", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (PyUnicode_READY(arg) == -1) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
suffix = arg;
|
||||||
|
return_value = unicode_removesuffix_impl(self, suffix);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(unicode_rjust__doc__,
|
PyDoc_STRVAR(unicode_rjust__doc__,
|
||||||
"rjust($self, width, fillchar=\' \', /)\n"
|
"rjust($self, width, fillchar=\' \', /)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -1232,4 +1303,4 @@ unicode_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
{
|
{
|
||||||
return unicode_sizeof_impl(self);
|
return unicode_sizeof_impl(self);
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=e4ed33400979c7e8 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=b91233f3722643be input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -12789,6 +12789,61 @@ unicode_replace_impl(PyObject *self, PyObject *old, PyObject *new,
|
||||||
return replace(self, old, new, count);
|
return replace(self, old, new, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
str.removeprefix as unicode_removeprefix
|
||||||
|
|
||||||
|
prefix: unicode
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a str with the given prefix string removed if present.
|
||||||
|
|
||||||
|
If the string starts with the prefix string, return string[len(prefix):].
|
||||||
|
Otherwise, return a copy of the original string.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_removeprefix_impl(PyObject *self, PyObject *prefix)
|
||||||
|
/*[clinic end generated code: output=f1e5945e9763bcb9 input=27ec40b99a37eb88]*/
|
||||||
|
{
|
||||||
|
int match = tailmatch(self, prefix, 0, PY_SSIZE_T_MAX, -1);
|
||||||
|
if (match == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
return PyUnicode_Substring(self, PyUnicode_GET_LENGTH(prefix),
|
||||||
|
PyUnicode_GET_LENGTH(self));
|
||||||
|
}
|
||||||
|
return unicode_result_unchanged(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
str.removesuffix as unicode_removesuffix
|
||||||
|
|
||||||
|
suffix: unicode
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a str with the given suffix string removed if present.
|
||||||
|
|
||||||
|
If the string ends with the suffix string and that suffix is not empty,
|
||||||
|
return string[:-len(suffix)]. Otherwise, return a copy of the original
|
||||||
|
string.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_removesuffix_impl(PyObject *self, PyObject *suffix)
|
||||||
|
/*[clinic end generated code: output=d36629e227636822 input=12cc32561e769be4]*/
|
||||||
|
{
|
||||||
|
int match = tailmatch(self, suffix, 0, PY_SSIZE_T_MAX, +1);
|
||||||
|
if (match == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
return PyUnicode_Substring(self, 0, PyUnicode_GET_LENGTH(self)
|
||||||
|
- PyUnicode_GET_LENGTH(suffix));
|
||||||
|
}
|
||||||
|
return unicode_result_unchanged(self);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
unicode_repr(PyObject *unicode)
|
unicode_repr(PyObject *unicode)
|
||||||
{
|
{
|
||||||
|
@ -14105,6 +14160,8 @@ static PyMethodDef unicode_methods[] = {
|
||||||
UNICODE_UPPER_METHODDEF
|
UNICODE_UPPER_METHODDEF
|
||||||
{"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__},
|
{"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__},
|
||||||
{"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__},
|
{"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__},
|
||||||
|
UNICODE_REMOVEPREFIX_METHODDEF
|
||||||
|
UNICODE_REMOVESUFFIX_METHODDEF
|
||||||
UNICODE_ISASCII_METHODDEF
|
UNICODE_ISASCII_METHODDEF
|
||||||
UNICODE_ISLOWER_METHODDEF
|
UNICODE_ISLOWER_METHODDEF
|
||||||
UNICODE_ISUPPER_METHODDEF
|
UNICODE_ISUPPER_METHODDEF
|
||||||
|
|
Loading…
Reference in New Issue