Skip to content

Commit a537cc3

Browse files
committed
Merge in the main branch
2 parents d69ec0f + 52d552c commit a537cc3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+896
-406
lines changed

Diff for: Doc/c-api/sequence.rst

+9
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ Sequence Protocol
105105
equivalent to the Python expression ``value in o``.
106106
107107
108+
.. c:function:: int PySequence_In(PyObject *o, PyObject *value)
109+
110+
Alias for :c:func:`PySequence_Contains`.
111+
112+
.. deprecated:: 3.14
113+
The function is :term:`soft deprecated` and should no longer be used to
114+
write new code.
115+
116+
108117
.. c:function:: Py_ssize_t PySequence_Index(PyObject *o, PyObject *value)
109118
110119
Return the first index *i* for which ``o[i] == value``. On error, return

Diff for: Doc/library/ast.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -1807,15 +1807,15 @@ aliases.
18071807

18081808
.. doctest::
18091809

1810-
>>> print(ast.dump(ast.parse("type Alias[**P = (int, str)] = Callable[P, int]"), indent=4))
1810+
>>> print(ast.dump(ast.parse("type Alias[**P = [int, str]] = Callable[P, int]"), indent=4))
18111811
Module(
18121812
body=[
18131813
TypeAlias(
18141814
name=Name(id='Alias', ctx=Store()),
18151815
type_params=[
18161816
ParamSpec(
18171817
name='P',
1818-
default_value=Tuple(
1818+
default_value=List(
18191819
elts=[
18201820
Name(id='int', ctx=Load()),
18211821
Name(id='str', ctx=Load())],

Diff for: Doc/library/itertools.rst

+35-39
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ For instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a
3030
sequence ``f(0), f(1), ...``. The same effect can be achieved in Python
3131
by combining :func:`map` and :func:`count` to form ``map(f, count())``.
3232

33-
These tools and their built-in counterparts also work well with the high-speed
34-
functions in the :mod:`operator` module. For example, the multiplication
35-
operator can be mapped across two vectors to form an efficient dot-product:
36-
``sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))``.
37-
3833

3934
**Infinite iterators:**
4035

@@ -843,12 +838,11 @@ and :term:`generators <generator>` which incur interpreter overhead.
843838

844839
.. testcode::
845840

846-
import collections
847-
import contextlib
848-
import functools
849-
import math
850-
import operator
851-
import random
841+
from collections import deque
842+
from contextlib import suppress
843+
from functools import reduce
844+
from math import sumprod, isqrt
845+
from operator import itemgetter, getitem, mul, neg
852846

853847
def take(n, iterable):
854848
"Return first n items of the iterable as a list."
@@ -863,11 +857,11 @@ and :term:`generators <generator>` which incur interpreter overhead.
863857
"Return function(0), function(1), ..."
864858
return map(function, count(start))
865859

866-
def repeatfunc(func, times=None, *args):
867-
"Repeat calls to func with specified arguments."
860+
def repeatfunc(function, times=None, *args):
861+
"Repeat calls to a function with specified arguments."
868862
if times is None:
869-
return starmap(func, repeat(args))
870-
return starmap(func, repeat(args, times))
863+
return starmap(function, repeat(args))
864+
return starmap(function, repeat(args, times))
871865
872866
def flatten(list_of_lists):
873867
"Flatten one level of nesting."
@@ -885,13 +879,13 @@ and :term:`generators <generator>` which incur interpreter overhead.
885879
def tail(n, iterable):
886880
"Return an iterator over the last n items."
887881
# tail(3, 'ABCDEFG') → E F G
888-
return iter(collections.deque(iterable, maxlen=n))
882+
return iter(deque(iterable, maxlen=n))
889883

890884
def consume(iterator, n=None):
891885
"Advance the iterator n-steps ahead. If n is None, consume entirely."
892886
# Use functions that consume iterators at C speed.
893887
if n is None:
894-
collections.deque(iterator, maxlen=0)
888+
deque(iterator, maxlen=0)
895889
else:
896890
next(islice(iterator, n, n), None)
897891

@@ -919,8 +913,8 @@ and :term:`generators <generator>` which incur interpreter overhead.
919913
# unique_justseen('AAAABBBCCDAABBB') → A B C D A B
920914
# unique_justseen('ABBcCAD', str.casefold) → A B c A D
921915
if key is None:
922-
return map(operator.itemgetter(0), groupby(iterable))
923-
return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
916+
return map(itemgetter(0), groupby(iterable))
917+
return map(next, map(itemgetter(1), groupby(iterable, key)))
924918

925919
def unique_everseen(iterable, key=None):
926920
"Yield unique elements, preserving order. Remember all elements ever seen."
@@ -941,13 +935,14 @@ and :term:`generators <generator>` which incur interpreter overhead.
941935
def unique(iterable, key=None, reverse=False):
942936
"Yield unique elements in sorted order. Supports unhashable inputs."
943937
# unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4]
944-
return unique_justseen(sorted(iterable, key=key, reverse=reverse), key=key)
938+
sequenced = sorted(iterable, key=key, reverse=reverse)
939+
return unique_justseen(sequenced, key=key)
945940

946941
def sliding_window(iterable, n):
947942
"Collect data into overlapping fixed-length chunks or blocks."
948943
# sliding_window('ABCDEFG', 4) → ABCD BCDE CDEF DEFG
949944
iterator = iter(iterable)
950-
window = collections.deque(islice(iterator, n - 1), maxlen=n)
945+
window = deque(islice(iterator, n - 1), maxlen=n)
951946
for x in iterator:
952947
window.append(x)
953948
yield tuple(window)
@@ -981,7 +976,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
981976
"Return all contiguous non-empty subslices of a sequence."
982977
# subslices('ABCD') → A AB ABC ABCD B BC BCD C CD D
983978
slices = starmap(slice, combinations(range(len(seq) + 1), 2))
984-
return map(operator.getitem, repeat(seq), slices)
979+
return map(getitem, repeat(seq), slices)
985980

986981
def iter_index(iterable, value, start=0, stop=None):
987982
"Return indices where a value occurs in a sequence or iterable."
@@ -995,39 +990,40 @@ and :term:`generators <generator>` which incur interpreter overhead.
995990
else:
996991
stop = len(iterable) if stop is None else stop
997992
i = start
998-
with contextlib.suppress(ValueError):
993+
with suppress(ValueError):
999994
while True:
1000995
yield (i := seq_index(value, i, stop))
1001996
i += 1
1002997

1003-
def iter_except(func, exception, first=None):
998+
def iter_except(function, exception, first=None):
1004999
"Convert a call-until-exception interface to an iterator interface."
10051000
# iter_except(d.popitem, KeyError) → non-blocking dictionary iterator
1006-
with contextlib.suppress(exception):
1001+
with suppress(exception):
10071002
if first is not None:
10081003
yield first()
10091004
while True:
1010-
yield func()
1005+
yield function()
10111006

10121007

10131008
The following recipes have a more mathematical flavor:
10141009

10151010
.. testcode::
10161011

10171012
def powerset(iterable):
1013+
"Subsequences of the iterable from shortest to longest."
10181014
# powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)
10191015
s = list(iterable)
10201016
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
10211017

10221018
def sum_of_squares(iterable):
10231019
"Add up the squares of the input values."
10241020
# sum_of_squares([10, 20, 30]) → 1400
1025-
return math.sumprod(*tee(iterable))
1021+
return sumprod(*tee(iterable))
10261022
1027-
def reshape(matrix, cols):
1023+
def reshape(matrix, columns):
10281024
"Reshape a 2-D matrix to have a given number of columns."
10291025
# reshape([(0, 1), (2, 3), (4, 5)], 3) → (0, 1, 2), (3, 4, 5)
1030-
return batched(chain.from_iterable(matrix), cols, strict=True)
1026+
return batched(chain.from_iterable(matrix), columns, strict=True)
10311027

10321028
def transpose(matrix):
10331029
"Swap the rows and columns of a 2-D matrix."
@@ -1038,7 +1034,7 @@ The following recipes have a more mathematical flavor:
10381034
"Multiply two matrices."
10391035
# matmul([(7, 5), (3, 5)], [(2, 5), (7, 9)]) → (49, 80), (41, 60)
10401036
n = len(m2[0])
1041-
return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
1037+
return batched(starmap(sumprod, product(m1, transpose(m2))), n)
10421038

10431039
def convolve(signal, kernel):
10441040
"""Discrete linear convolution of two iterables.
@@ -1059,16 +1055,16 @@ The following recipes have a more mathematical flavor:
10591055
n = len(kernel)
10601056
padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
10611057
windowed_signal = sliding_window(padded_signal, n)
1062-
return map(math.sumprod, repeat(kernel), windowed_signal)
1058+
return map(sumprod, repeat(kernel), windowed_signal)
10631059

10641060
def polynomial_from_roots(roots):
10651061
"""Compute a polynomial's coefficients from its roots.
10661062

10671063
(x - 5) (x + 4) (x - 3) expands to: x³ -4x² -17x + 60
10681064
"""
10691065
# polynomial_from_roots([5, -4, 3]) → [1, -4, -17, 60]
1070-
factors = zip(repeat(1), map(operator.neg, roots))
1071-
return list(functools.reduce(convolve, factors, [1]))
1066+
factors = zip(repeat(1), map(neg, roots))
1067+
return list(reduce(convolve, factors, [1]))
10721068

10731069
def polynomial_eval(coefficients, x):
10741070
"""Evaluate a polynomial at a specific value.
@@ -1081,7 +1077,7 @@ The following recipes have a more mathematical flavor:
10811077
if not n:
10821078
return type(x)(0)
10831079
powers = map(pow, repeat(x), reversed(range(n)))
1084-
return math.sumprod(coefficients, powers)
1080+
return sumprod(coefficients, powers)
10851081

10861082
def polynomial_derivative(coefficients):
10871083
"""Compute the first derivative of a polynomial.
@@ -1092,15 +1088,15 @@ The following recipes have a more mathematical flavor:
10921088
# polynomial_derivative([1, -4, -17, 60]) → [3, -8, -17]
10931089
n = len(coefficients)
10941090
powers = reversed(range(1, n))
1095-
return list(map(operator.mul, coefficients, powers))
1091+
return list(map(mul, coefficients, powers))
10961092

10971093
def sieve(n):
10981094
"Primes less than n."
10991095
# sieve(30) → 2 3 5 7 11 13 17 19 23 29
11001096
if n > 2:
11011097
yield 2
11021098
data = bytearray((0, 1)) * (n // 2)
1103-
for p in iter_index(data, 1, start=3, stop=math.isqrt(n) + 1):
1099+
for p in iter_index(data, 1, start=3, stop=isqrt(n) + 1):
11041100
data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
11051101
yield from iter_index(data, 1, start=3)
11061102

@@ -1109,7 +1105,7 @@ The following recipes have a more mathematical flavor:
11091105
# factor(99) → 3 3 11
11101106
# factor(1_000_000_000_000_007) → 47 59 360620266859
11111107
# factor(1_000_000_000_000_403) → 1000000000000403
1112-
for prime in sieve(math.isqrt(n) + 1):
1108+
for prime in sieve(isqrt(n) + 1):
11131109
while not n % prime:
11141110
yield prime
11151111
n //= prime
@@ -1740,7 +1736,7 @@ The following recipes have a more mathematical flavor:
17401736

17411737
# Old recipes and their tests which are guaranteed to continue to work.
17421738

1743-
def sumprod(vec1, vec2):
1739+
def old_sumprod_recipe(vec1, vec2):
17441740
"Compute a sum of products."
17451741
return sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))
17461742

@@ -1823,7 +1819,7 @@ The following recipes have a more mathematical flavor:
18231819
32
18241820

18251821

1826-
>>> sumprod([1,2,3], [4,5,6])
1822+
>>> old_sumprod_recipe([1,2,3], [4,5,6])
18271823
32
18281824

18291825

Diff for: Doc/library/string.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,9 @@ conversions, trailing zeros are not removed from the result.
409409

410410
.. index:: single: , (comma); in string formatting
411411

412-
The ``','`` option signals the use of a comma for a thousands separator.
412+
The ``','`` option signals the use of a comma for a thousands separator for
413+
floating-point presentation types and for integer presentation type ``'d'``.
414+
For other presentation types, this option is an error.
413415
For a locale aware separator, use the ``'n'`` integer presentation type
414416
instead.
415417

Diff for: Doc/whatsnew/3.14.rst

+10
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,12 @@ New features
10451045
* Add :c:func:`PyUnstable_Object_EnableDeferredRefcount` for enabling
10461046
deferred reference counting, as outlined in :pep:`703`.
10471047

1048+
* The :ref:`Unicode Exception Objects <unicodeexceptions>` C API
1049+
now raises a :exc:`TypeError` if its exception argument is not
1050+
a :exc:`UnicodeError` object.
1051+
(Contributed by Bénédikt Tran in :gh:`127691`.)
1052+
1053+
10481054
Porting to Python 3.14
10491055
----------------------
10501056

@@ -1067,6 +1073,10 @@ Deprecated
10671073
:c:macro:`!isfinite` available from :file:`math.h`
10681074
since C99. (Contributed by Sergey B Kirpichev in :gh:`119613`.)
10691075

1076+
* The previously undocumented function :c:func:`PySequence_In` is :term:`soft deprecated`.
1077+
Use :c:func:`PySequence_Contains` instead.
1078+
(Contributed by Yuki Kobayashi in :gh:`127896`.)
1079+
10701080
.. Add C API deprecations above alphabetically, not here at the end.
10711081
10721082
.. include:: ../deprecations/c-api-pending-removal-in-3.15.rst

Diff for: Include/cpython/pystats.h

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
//
1919
// Define _PY_INTERPRETER macro to increment interpreter_increfs and
2020
// interpreter_decrefs. Otherwise, increment increfs and decrefs.
21+
//
22+
// The number of incref operations counted by `incref` and
23+
// `interpreter_incref` is the number of increment operations, which is
24+
// not equal to the total of all reference counts. A single increment
25+
// operation may increase the reference count of an object by more than
26+
// one. For example, see `_Py_RefcntAdd`.
2127

2228
#ifndef Py_CPYTHON_PYSTATS_H
2329
# error "this header file must not be included directly"

Diff for: Include/internal/pycore_object.h

+5
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ extern void _Py_DecRefTotal(PyThreadState *);
131131
static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
132132
{
133133
if (_Py_IsImmortal(op)) {
134+
_Py_INCREF_IMMORTAL_STAT_INC();
134135
return;
135136
}
136137
#ifdef Py_REF_DEBUG
@@ -159,6 +160,10 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
159160
_Py_atomic_add_ssize(&op->ob_ref_shared, (n << _Py_REF_SHARED_SHIFT));
160161
}
161162
#endif
163+
// Although the ref count was increased by `n` (which may be greater than 1)
164+
// it is only a single increment (i.e. addition) operation, so only 1 refcnt
165+
// increment operation is counted.
166+
_Py_INCREF_STAT_INC();
162167
}
163168
#define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n)
164169

Diff for: Include/internal/pycore_opcode_metadata.h

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)