Skip to content

Commit 05ec274

Browse files
committed
Merge branch 'master' into long_export-decimal
2 parents 6669b89 + 47c5a0f commit 05ec274

File tree

18 files changed

+158
-58
lines changed

18 files changed

+158
-58
lines changed

Doc/library/ast.rst

Lines changed: 2 additions & 2 deletions
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())],

Doc/library/string.rst

Lines changed: 3 additions & 1 deletion
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

Include/cpython/pystats.h

Lines changed: 6 additions & 0 deletions
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"

Include/internal/pycore_object.h

Lines changed: 5 additions & 0 deletions
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

Lib/_colorize.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ def get_colors(colorize: bool = False) -> ANSIColors:
3232

3333

3434
def can_colorize() -> bool:
35-
if sys.platform == "win32":
36-
try:
37-
import nt
38-
39-
if not nt._supports_virtual_terminal():
40-
return False
41-
except (ImportError, AttributeError):
42-
return False
4335
if not sys.flags.ignore_environment:
4436
if os.environ.get("PYTHON_COLORS") == "0":
4537
return False
@@ -58,6 +50,15 @@ def can_colorize() -> bool:
5850
if not hasattr(sys.stderr, "fileno"):
5951
return False
6052

53+
if sys.platform == "win32":
54+
try:
55+
import nt
56+
57+
if not nt._supports_virtual_terminal():
58+
return False
59+
except (ImportError, AttributeError):
60+
return False
61+
6162
try:
6263
return os.isatty(sys.stderr.fileno())
6364
except io.UnsupportedOperation:

Lib/multiprocessing/resource_tracker.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,14 @@ def ensure_running(self):
155155
# that can make the child die before it registers signal handlers
156156
# for SIGINT and SIGTERM. The mask is unregistered after spawning
157157
# the child.
158+
prev_sigmask = None
158159
try:
159160
if _HAVE_SIGMASK:
160-
signal.pthread_sigmask(signal.SIG_BLOCK, _IGNORED_SIGNALS)
161+
prev_sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, _IGNORED_SIGNALS)
161162
pid = util.spawnv_passfds(exe, args, fds_to_pass)
162163
finally:
163-
if _HAVE_SIGMASK:
164-
signal.pthread_sigmask(signal.SIG_UNBLOCK, _IGNORED_SIGNALS)
164+
if prev_sigmask is not None:
165+
signal.pthread_sigmask(signal.SIG_SETMASK, prev_sigmask)
165166
except:
166167
os.close(w)
167168
raise

Lib/test/_test_multiprocessing.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6044,6 +6044,21 @@ def test_resource_tracker_exit_code(self):
60446044
self._test_resource_tracker_leak_resources(
60456045
cleanup=cleanup,
60466046
)
6047+
@unittest.skipUnless(hasattr(signal, "pthread_sigmask"), "pthread_sigmask is not available")
6048+
def test_resource_tracker_blocked_signals(self):
6049+
#
6050+
# gh-127586: Check that resource_tracker does not override blocked signals of caller.
6051+
#
6052+
from multiprocessing.resource_tracker import ResourceTracker
6053+
signals = {signal.SIGTERM, signal.SIGINT, signal.SIGUSR1}
6054+
6055+
for sig in signals:
6056+
signal.pthread_sigmask(signal.SIG_SETMASK, {sig})
6057+
self.assertEqual(signal.pthread_sigmask(signal.SIG_BLOCK, set()), {sig})
6058+
tracker = ResourceTracker()
6059+
tracker.ensure_running()
6060+
self.assertEqual(signal.pthread_sigmask(signal.SIG_BLOCK, set()), {sig})
6061+
tracker._stop()
60476062

60486063
class TestSimpleQueue(unittest.TestCase):
60496064

Lib/test/support/strace_helper.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def _make_error(reason, details):
104104
return StraceResult(
105105
strace_returncode=-1,
106106
python_returncode=-1,
107-
event_bytes=f"error({reason},details={details}) = -1".encode('utf-8'),
107+
event_bytes= f"error({reason},details={details!r}) = -1".encode('utf-8'),
108108
stdout=res.out if res else b"",
109109
stderr=res.err if res else b"")
110110

@@ -179,9 +179,10 @@ def get_syscalls(code, strace_flags, prelude="", cleanup="",
179179
@cache
180180
def _can_strace():
181181
res = strace_python("import sys; sys.exit(0)", [], check=False)
182-
assert res.events(), "Should have parsed multiple calls"
183-
184-
return res.strace_returncode == 0 and res.python_returncode == 0
182+
if res.strace_returncode == 0 and res.python_returncode == 0:
183+
assert res.events(), "Should have parsed multiple calls"
184+
return True
185+
return False
185186

186187

187188
def requires_strace():

Lib/test/test__colorize.py

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,50 @@ def tearDownModule():
1919
class TestColorizeFunction(unittest.TestCase):
2020
@force_not_colorized
2121
def test_colorized_detection_checks_for_environment_variables(self):
22-
if sys.platform == "win32":
23-
virtual_patching = unittest.mock.patch("nt._supports_virtual_terminal",
24-
return_value=True)
25-
else:
26-
virtual_patching = contextlib.nullcontext()
27-
with virtual_patching:
28-
29-
flags = unittest.mock.MagicMock(ignore_environment=False)
30-
with (unittest.mock.patch("os.isatty") as isatty_mock,
31-
unittest.mock.patch("sys.flags", flags),
32-
unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE)):
33-
isatty_mock.return_value = True
34-
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
35-
self.assertEqual(_colorize.can_colorize(), False)
36-
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
37-
self.assertEqual(_colorize.can_colorize(), True)
38-
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
39-
self.assertEqual(_colorize.can_colorize(), False)
40-
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
22+
flags = unittest.mock.MagicMock(ignore_environment=False)
23+
with (unittest.mock.patch("os.isatty") as isatty_mock,
24+
unittest.mock.patch("sys.stderr") as stderr_mock,
25+
unittest.mock.patch("sys.flags", flags),
26+
unittest.mock.patch("_colorize.can_colorize", ORIGINAL_CAN_COLORIZE),
27+
(unittest.mock.patch("nt._supports_virtual_terminal", return_value=False)
28+
if sys.platform == "win32" else
29+
contextlib.nullcontext()) as vt_mock):
30+
31+
isatty_mock.return_value = True
32+
stderr_mock.fileno.return_value = 2
33+
stderr_mock.isatty.return_value = True
34+
with unittest.mock.patch("os.environ", {'TERM': 'dumb'}):
35+
self.assertEqual(_colorize.can_colorize(), False)
36+
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '1'}):
37+
self.assertEqual(_colorize.can_colorize(), True)
38+
with unittest.mock.patch("os.environ", {'PYTHON_COLORS': '0'}):
39+
self.assertEqual(_colorize.can_colorize(), False)
40+
with unittest.mock.patch("os.environ", {'NO_COLOR': '1'}):
41+
self.assertEqual(_colorize.can_colorize(), False)
42+
with unittest.mock.patch("os.environ",
43+
{'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
44+
self.assertEqual(_colorize.can_colorize(), True)
45+
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
46+
self.assertEqual(_colorize.can_colorize(), True)
47+
with unittest.mock.patch("os.environ",
48+
{'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
49+
self.assertEqual(_colorize.can_colorize(), False)
50+
with unittest.mock.patch("os.environ",
51+
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
52+
self.assertEqual(_colorize.can_colorize(), False)
53+
54+
with unittest.mock.patch("os.environ", {}):
55+
if sys.platform == "win32":
4156
self.assertEqual(_colorize.can_colorize(), False)
42-
with unittest.mock.patch("os.environ",
43-
{'NO_COLOR': '1', "PYTHON_COLORS": '1'}):
57+
58+
vt_mock.return_value = True
4459
self.assertEqual(_colorize.can_colorize(), True)
45-
with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1'}):
60+
else:
4661
self.assertEqual(_colorize.can_colorize(), True)
47-
with unittest.mock.patch("os.environ",
48-
{'FORCE_COLOR': '1', 'NO_COLOR': '1'}):
49-
self.assertEqual(_colorize.can_colorize(), False)
50-
with unittest.mock.patch("os.environ",
51-
{'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}):
52-
self.assertEqual(_colorize.can_colorize(), False)
62+
5363
isatty_mock.return_value = False
54-
with unittest.mock.patch("os.environ", {}):
55-
self.assertEqual(_colorize.can_colorize(), False)
64+
stderr_mock.isatty.return_value = False
65+
self.assertEqual(_colorize.can_colorize(), False)
5666

5767

5868
if __name__ == "__main__":

Lib/test/test_getpath.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,37 @@ def test_explicitly_set_stdlib_dir(self):
832832
actual = getpath(ns, expected)
833833
self.assertEqual(expected, actual)
834834

835+
def test_PYTHONHOME_in_venv(self):
836+
"Make sure prefix/exec_prefix still point to the venv if PYTHONHOME was used."
837+
ns = MockPosixNamespace(
838+
argv0="/venv/bin/python",
839+
PREFIX="/usr",
840+
ENV_PYTHONHOME="/pythonhome",
841+
)
842+
# Setup venv
843+
ns.add_known_xfile("/venv/bin/python")
844+
ns.add_known_file("/venv/pyvenv.cfg", [
845+
r"home = /usr/bin"
846+
])
847+
# Seutup PYTHONHOME
848+
ns.add_known_file("/pythonhome/lib/python9.8/os.py")
849+
ns.add_known_dir("/pythonhome/lib/python9.8/lib-dynload")
850+
851+
expected = dict(
852+
executable="/venv/bin/python",
853+
prefix="/venv",
854+
exec_prefix="/venv",
855+
base_prefix="/pythonhome",
856+
base_exec_prefix="/pythonhome",
857+
module_search_paths_set=1,
858+
module_search_paths=[
859+
"/pythonhome/lib/python98.zip",
860+
"/pythonhome/lib/python9.8",
861+
"/pythonhome/lib/python9.8/lib-dynload",
862+
],
863+
)
864+
actual = getpath(ns, expected)
865+
self.assertEqual(expected, actual)
835866

836867
# ******************************************************************************
837868

0 commit comments

Comments
 (0)