Skip to content

Commit 730f5fd

Browse files
committed
Merge remote-tracking branch 'upstream/main' into return_values
2 parents dad4799 + 5ea052b commit 730f5fd

12 files changed

+322
-102
lines changed

Doc/library/enum.rst

+31-26
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ Data Types
194194

195195
.. method:: EnumType.__getitem__(cls, name)
196196

197-
Returns the Enum member in *cls* matching *name*, or raises an :exc:`KeyError`::
197+
Returns the Enum member in *cls* matching *name*, or raises a :exc:`KeyError`::
198198

199199
>>> Color['BLUE']
200200
<Color.BLUE: 3>
@@ -241,7 +241,7 @@ Data Types
241241

242242
.. note:: Enum member values
243243

244-
Member values can be anything: :class:`int`, :class:`str`, etc.. If
244+
Member values can be anything: :class:`int`, :class:`str`, etc. If
245245
the exact value is unimportant you may use :class:`auto` instances and an
246246
appropriate value will be chosen for you. See :class:`auto` for the
247247
details.
@@ -255,7 +255,7 @@ Data Types
255255
names will also be removed from the completed enumeration. See
256256
:ref:`TimePeriod <enum-time-period>` for an example.
257257

258-
.. method:: Enum.__call__(cls, value, names=None, \*, module=None, qualname=None, type=None, start=1, boundary=None)
258+
.. method:: Enum.__call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
259259

260260
This method is called in two different ways:
261261

@@ -272,8 +272,8 @@ Data Types
272272
:module: The name of the module the new Enum is created in.
273273
:qualname: The actual location in the module where this Enum can be found.
274274
:type: A mix-in type for the new Enum.
275-
:start: The first integer value for the Enum (used by :class:`auto`)
276-
:boundary: How to handle out-of-range values from bit operations (:class:`Flag` only)
275+
:start: The first integer value for the Enum (used by :class:`auto`).
276+
:boundary: How to handle out-of-range values from bit operations (:class:`Flag` only).
277277

278278
.. method:: Enum.__dir__(self)
279279

@@ -315,7 +315,7 @@ Data Types
315315
>>> PowersOfThree.SECOND.value
316316
6
317317

318-
.. method:: Enum.__init_subclass__(cls, \**kwds)
318+
.. method:: Enum.__init_subclass__(cls, **kwds)
319319

320320
A *classmethod* that is used to further configure subsequent subclasses.
321321
By default, does nothing.
@@ -373,7 +373,7 @@ Data Types
373373
.. method:: Enum.__format__(self)
374374

375375
Returns the string used for *format()* and *f-string* calls. By default,
376-
returns :meth:`__str__` returns, but can be overridden::
376+
returns :meth:`__str__` return value, but can be overridden::
377377

378378
>>> class OtherStyle(Enum):
379379
... ALTERNATE = auto()
@@ -552,11 +552,11 @@ Data Types
552552
Using :class:`auto` with :class:`Flag` results in integers that are powers
553553
of two, starting with ``1``.
554554

555-
.. versionchanged:: 3.11 The *repr()* of zero-valued flags has changed. It
555+
.. versionchanged:: 3.11 The *repr()* of zero-valued flags has changed. It
556556
is now::
557557

558-
>>> Color(0) # doctest: +SKIP
559-
<Color: 0>
558+
>>> Color(0) # doctest: +SKIP
559+
<Color: 0>
560560

561561
.. class:: IntFlag
562562

@@ -600,7 +600,7 @@ Data Types
600600
*replacement of existing constants* use-case. :meth:`~object.__format__` was
601601
already :meth:`!int.__format__` for that same reason.
602602

603-
Inversion of a :class:`!IntFlag` now returns a positive value that is the
603+
Inversion of an :class:`!IntFlag` now returns a positive value that is the
604604
union of all flags not in the given flag, rather than a negative value.
605605
This matches the existing :class:`Flag` behavior.
606606

@@ -612,7 +612,7 @@ Data Types
612612
* :meth:`!int.__str__` for :class:`IntEnum` and :class:`IntFlag`
613613
* :meth:`!str.__str__` for :class:`StrEnum`
614614

615-
Inherit from :class:`!ReprEnum` to keep the :class:`str() <str> / :func:`format`
615+
Inherit from :class:`!ReprEnum` to keep the :class:`str() <str>` / :func:`format`
616616
of the mixed-in data type instead of using the
617617
:class:`Enum`-default :meth:`str() <Enum.__str__>`.
618618

@@ -658,7 +658,7 @@ Data Types
658658
.. attribute:: NAMED_FLAGS
659659

660660
Ensure that any flag groups/masks contain only named flags -- useful when
661-
values are specified instead of being generated by :func:`auto`
661+
values are specified instead of being generated by :func:`auto`::
662662

663663
>>> from enum import Flag, verify, NAMED_FLAGS
664664
>>> @verify(NAMED_FLAGS)
@@ -804,6 +804,11 @@ Utilities and Decorators
804804
* ``THREE = [auto(), -3]`` will *not* work (``<auto instance>, -3`` is used to
805805
create the ``THREE`` enum member)
806806

807+
.. versionchanged:: 3.11.1
808+
809+
In prior versions, ``auto()`` had to be the only thing
810+
on the assignment line to work properly.
811+
807812
``_generate_next_value_`` can be overridden to customize the values used by
808813
*auto*.
809814

@@ -885,23 +890,23 @@ Notes
885890

886891
:class:`IntEnum`, :class:`StrEnum`, and :class:`IntFlag`
887892

888-
These three enum types are designed to be drop-in replacements for existing
889-
integer- and string-based values; as such, they have extra limitations:
893+
These three enum types are designed to be drop-in replacements for existing
894+
integer- and string-based values; as such, they have extra limitations:
890895

891-
- ``__str__`` uses the value and not the name of the enum member
896+
- ``__str__`` uses the value and not the name of the enum member
892897

893-
- ``__format__``, because it uses ``__str__``, will also use the value of
894-
the enum member instead of its name
898+
- ``__format__``, because it uses ``__str__``, will also use the value of
899+
the enum member instead of its name
895900

896-
If you do not need/want those limitations, you can either create your own
897-
base class by mixing in the ``int`` or ``str`` type yourself::
901+
If you do not need/want those limitations, you can either create your own
902+
base class by mixing in the ``int`` or ``str`` type yourself::
898903

899-
>>> from enum import Enum
900-
>>> class MyIntEnum(int, Enum):
901-
... pass
904+
>>> from enum import Enum
905+
>>> class MyIntEnum(int, Enum):
906+
... pass
902907

903908
or you can reassign the appropriate :meth:`str`, etc., in your enum::
904909

905-
>>> from enum import IntEnum
906-
>>> class MyIntEnum(IntEnum):
907-
... __str__ = IntEnum.__str__
910+
>>> from enum import IntEnum
911+
>>> class MyIntEnum(IntEnum):
912+
... __str__ = IntEnum.__str__

Doc/using/configure.rst

+46
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,46 @@
22
Configure Python
33
****************
44

5+
Build Requirements
6+
==================
7+
8+
Features required to build CPython:
9+
10+
* A `C11 <https://en.cppreference.com/w/c/11>`_ compiler. `Optional C11
11+
features
12+
<https://en.wikipedia.org/wiki/C11_(C_standard_revision)#Optional_features>`_
13+
are not required.
14+
15+
* Support for `IEEE 754 <https://en.wikipedia.org/wiki/IEEE_754>`_ floating
16+
point numbers and `floating point Not-a-Number (NaN)
17+
<https://en.wikipedia.org/wiki/NaN#Floating_point>`_.
18+
19+
* Support for threads.
20+
21+
* OpenSSL 1.1.1 or newer for the :mod:`ssl` and :mod:`hashlib` modules.
22+
23+
* On Windows, Microsoft Visual Studio 2017 or later is required.
24+
25+
.. versionchanged:: 3.11
26+
C11 compiler, IEEE 754 and NaN support are now required.
27+
28+
.. versionchanged:: 3.10
29+
OpenSSL 1.1.1 is now required.
30+
31+
.. versionchanged:: 3.7
32+
Thread support and OpenSSL 1.0.2 are now required.
33+
34+
.. versionchanged:: 3.6
35+
Selected C99 features are now required, like ``<stdint.h>`` and ``static
36+
inline`` functions.
37+
38+
.. versionchanged:: 3.5
39+
On Windows, Visual Studio 2015 or later is required.
40+
41+
See also :pep:`7` "Style Guide for C Code" and :pep:`11` "CPython platform
42+
support".
43+
44+
545
.. _configure-options:
646

747
Configure Options
@@ -93,6 +133,12 @@ General Options
93133

94134
See :envvar:`PYTHONCOERCECLOCALE` and the :pep:`538`.
95135

136+
.. cmdoption:: --without-freelists
137+
138+
Disable all freelists except the empty tuple singleton.
139+
140+
.. versionadded:: 3.11
141+
96142
.. cmdoption:: --with-platlibdir=DIRNAME
97143

98144
Python library directory name (default is ``lib``).

Doc/whatsnew/3.11.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -2131,7 +2131,7 @@ Build Changes
21312131
(Contributed by Dong-hee Na and Brett Holman in :issue:`44340`.)
21322132

21332133
* Freelists for object structs can now be disabled. A new :program:`configure`
2134-
option :option:`!--without-freelists` can be used to disable all freelists
2134+
option :option:`--without-freelists` can be used to disable all freelists
21352135
except empty tuple singleton.
21362136
(Contributed by Christian Heimes in :issue:`45522`.)
21372137

Include/internal/pycore_object.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, PyObject *);
373373
* match.
374374
*
375375
* Third party code unintentionally rely on problematic fpcasts. The call
376-
* trampoline mitigates common occurences of bad fpcasts on Emscripten.
376+
* trampoline mitigates common occurrences of bad fpcasts on Emscripten.
377377
*/
378378
#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
379379
#define _PyCFunction_TrampolineCall(meth, self, args) \

Lib/test/test_cmd_line_script.py

+3
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,9 @@ def test_nonexisting_script(self):
753753
self.assertNotEqual(proc.returncode, 0)
754754

755755
@unittest.skipUnless(os.path.exists('/dev/fd/0'), 'requires /dev/fd platform')
756+
@unittest.skipIf(sys.platform.startswith("freebsd") and
757+
os.stat("/dev").st_dev == os.stat("/dev/fd").st_dev,
758+
"Requires fdescfs mounted on /dev/fd on FreeBSD")
756759
def test_script_as_dev_fd(self):
757760
# GH-87235: On macOS passing a non-trivial script to /dev/fd/N can cause
758761
# problems because all open /dev/fd/N file descriptors share the same

Lib/test/test_struct.py

+48-15
Original file line numberDiff line numberDiff line change
@@ -723,23 +723,56 @@ def test_issue35714(self):
723723
struct.calcsize(s)
724724

725725
@support.cpython_only
726-
def test_issue45034_unsigned(self):
727-
_testcapi = import_helper.import_module('_testcapi')
728-
error_msg = f'ushort format requires 0 <= number <= {_testcapi.USHRT_MAX}'
729-
with self.assertRaisesRegex(struct.error, error_msg):
730-
struct.pack('H', 70000) # too large
731-
with self.assertRaisesRegex(struct.error, error_msg):
732-
struct.pack('H', -1) # too small
726+
def test_issue98248(self):
727+
def test_error_msg(prefix, int_type, is_unsigned):
728+
fmt_str = prefix + int_type
729+
size = struct.calcsize(fmt_str)
730+
if is_unsigned:
731+
max_ = 2 ** (size * 8) - 1
732+
min_ = 0
733+
else:
734+
max_ = 2 ** (size * 8 - 1) - 1
735+
min_ = -2 ** (size * 8 - 1)
736+
error_msg = f"'{int_type}' format requires {min_} <= number <= {max_}"
737+
for number in [int(-1e50), min_ - 1, max_ + 1, int(1e50)]:
738+
with self.subTest(format_str=fmt_str, number=number):
739+
with self.assertRaisesRegex(struct.error, error_msg):
740+
struct.pack(fmt_str, number)
741+
error_msg = "required argument is not an integer"
742+
not_number = ""
743+
with self.subTest(format_str=fmt_str, number=not_number):
744+
with self.assertRaisesRegex(struct.error, error_msg):
745+
struct.pack(fmt_str, not_number)
746+
747+
for prefix in '@=<>':
748+
for int_type in 'BHILQ':
749+
test_error_msg(prefix, int_type, True)
750+
for int_type in 'bhilq':
751+
test_error_msg(prefix, int_type, False)
752+
753+
int_type = 'N'
754+
test_error_msg('@', int_type, True)
755+
756+
int_type = 'n'
757+
test_error_msg('@', int_type, False)
733758

734759
@support.cpython_only
735-
def test_issue45034_signed(self):
736-
_testcapi = import_helper.import_module('_testcapi')
737-
error_msg = f'short format requires {_testcapi.SHRT_MIN} <= number <= {_testcapi.SHRT_MAX}'
738-
with self.assertRaisesRegex(struct.error, error_msg):
739-
struct.pack('h', 70000) # too large
740-
with self.assertRaisesRegex(struct.error, error_msg):
741-
struct.pack('h', -70000) # too small
742-
760+
def test_issue98248_error_propagation(self):
761+
class Div0:
762+
def __index__(self):
763+
1 / 0
764+
765+
def test_error_propagation(fmt_str):
766+
with self.subTest(format_str=fmt_str, exception="ZeroDivisionError"):
767+
with self.assertRaises(ZeroDivisionError):
768+
struct.pack(fmt_str, Div0())
769+
770+
for prefix in '@=<>':
771+
for int_type in 'BHILQbhilq':
772+
test_error_propagation(prefix + int_type)
773+
774+
test_error_propagation('N')
775+
test_error_propagation('n')
743776

744777
class UnpackIteratorTest(unittest.TestCase):
745778
"""

Lib/test/test_subprocess.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2832,7 +2832,7 @@ def test_close_fds(self):
28322832

28332833
@unittest.skipIf(sys.platform.startswith("freebsd") and
28342834
os.stat("/dev").st_dev == os.stat("/dev/fd").st_dev,
2835-
"Requires fdescfs mounted on /dev/fd on FreeBSD.")
2835+
"Requires fdescfs mounted on /dev/fd on FreeBSD")
28362836
def test_close_fds_when_max_fd_is_lowered(self):
28372837
"""Confirm that issue21618 is fixed (may fail under valgrind)."""
28382838
fd_status = support.findfile("fd_status.py", subdir="subprocessdata")

Lib/test/test_unittest/test_result.py

+56
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,62 @@ def get_exc_info():
275275
self.assertEqual(len(dropped), 1)
276276
self.assertIn("raise self.failureException(msg)", dropped[0])
277277

278+
def test_addFailure_filter_traceback_frames_chained_exception_self_loop(self):
279+
class Foo(unittest.TestCase):
280+
def test_1(self):
281+
pass
282+
283+
def get_exc_info():
284+
try:
285+
loop = Exception("Loop")
286+
loop.__cause__ = loop
287+
loop.__context__ = loop
288+
raise loop
289+
except:
290+
return sys.exc_info()
291+
292+
exc_info_tuple = get_exc_info()
293+
294+
test = Foo('test_1')
295+
result = unittest.TestResult()
296+
result.startTest(test)
297+
result.addFailure(test, exc_info_tuple)
298+
result.stopTest(test)
299+
300+
formatted_exc = result.failures[0][1]
301+
self.assertEqual(formatted_exc.count("Exception: Loop\n"), 1)
302+
303+
def test_addFailure_filter_traceback_frames_chained_exception_cycle(self):
304+
class Foo(unittest.TestCase):
305+
def test_1(self):
306+
pass
307+
308+
def get_exc_info():
309+
try:
310+
# Create two directionally opposed cycles
311+
# __cause__ in one direction, __context__ in the other
312+
A, B, C = Exception("A"), Exception("B"), Exception("C")
313+
edges = [(C, B), (B, A), (A, C)]
314+
for ex1, ex2 in edges:
315+
ex1.__cause__ = ex2
316+
ex2.__context__ = ex1
317+
raise C
318+
except:
319+
return sys.exc_info()
320+
321+
exc_info_tuple = get_exc_info()
322+
323+
test = Foo('test_1')
324+
result = unittest.TestResult()
325+
result.startTest(test)
326+
result.addFailure(test, exc_info_tuple)
327+
result.stopTest(test)
328+
329+
formatted_exc = result.failures[0][1]
330+
self.assertEqual(formatted_exc.count("Exception: A\n"), 1)
331+
self.assertEqual(formatted_exc.count("Exception: B\n"), 1)
332+
self.assertEqual(formatted_exc.count("Exception: C\n"), 1)
333+
278334
# "addError(test, err)"
279335
# ...
280336
# "Called when the test case test raises an unexpected exception err

Lib/unittest/result.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ def _clean_tracebacks(self, exctype, value, tb, test):
196196
ret = None
197197
first = True
198198
excs = [(exctype, value, tb)]
199+
seen = {id(value)} # Detect loops in chained exceptions.
199200
while excs:
200201
(exctype, value, tb) = excs.pop()
201202
# Skip test runner traceback levels
@@ -214,8 +215,9 @@ def _clean_tracebacks(self, exctype, value, tb, test):
214215

215216
if value is not None:
216217
for c in (value.__cause__, value.__context__):
217-
if c is not None:
218+
if c is not None and id(c) not in seen:
218219
excs.append((type(c), c, c.__traceback__))
220+
seen.add(id(c))
219221
return ret
220222

221223
def _is_relevant_tb_level(self, tb):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Provide informative error messages in :func:`struct.pack` when its integral arguments are not in range.

0 commit comments

Comments
 (0)