diff --git a/.gitattributes b/.gitattributes
index 4ed95069442f3d..2bfd4bf9f9b202 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -25,7 +25,7 @@ PC/classicAppCompat.* binary
[attr]noeol -text
Lib/test/cjkencodings/* noeol
-Lib/test/coding20731.py noeol
+Lib/test/tokenizedata/coding20731.py noeol
Lib/test/decimaltestdata/*.decTest noeol
Lib/test/test_email/data/*.txt noeol
Lib/test/test_importlib/resources/data01/* noeol
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 19f6a03745d2d0..4c1fd20ea921b8 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -15,7 +15,7 @@ repos:
- id: check-yaml
- id: end-of-file-fixer
types: [python]
- exclude: Lib/test/coding20731.py
+ exclude: Lib/test/tokenizedata/coding20731.py
- id: trailing-whitespace
types_or: [c, python, rst]
diff --git a/Grammar/python.gram b/Grammar/python.gram
index f88dc2bdd92327..ed0b326fa58642 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -19,8 +19,6 @@ _PyPegen_parse(Parser *p)
result = eval_rule(p);
} else if (p->start_rule == Py_func_type_input) {
result = func_type_rule(p);
- } else if (p->start_rule == Py_fstring_input) {
- result = fstring_rule(p);
}
return result;
@@ -89,7 +87,6 @@ file[mod_ty]: a=[statements] ENDMARKER { _PyPegen_make_module(p, a) }
interactive[mod_ty]: a=statement_newline { _PyAST_Interactive(a, p->arena) }
eval[mod_ty]: a=expressions NEWLINE* ENDMARKER { _PyAST_Expression(a, p->arena) }
func_type[mod_ty]: '(' a=[type_expressions] ')' '->' b=expression NEWLINE* ENDMARKER { _PyAST_FunctionType(a, b, p->arena) }
-fstring[expr_ty]: star_expressions
# GENERAL STATEMENTS
# ==================
@@ -647,20 +644,20 @@ type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ ['
type_param[type_param_ty] (memo):
| a=NAME b=[type_param_bound] { _PyAST_TypeVar(a->v.Name.id, b, EXTRA) }
- | '*' a=NAME colon=":" e=expression {
+ | '*' a=NAME colon=':' e=expression {
RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
? "cannot use constraints with TypeVarTuple"
: "cannot use bound with TypeVarTuple")
}
| '*' a=NAME { _PyAST_TypeVarTuple(a->v.Name.id, EXTRA) }
- | '**' a=NAME colon=":" e=expression {
+ | '**' a=NAME colon=':' e=expression {
RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
? "cannot use constraints with ParamSpec"
: "cannot use bound with ParamSpec")
}
| '**' a=NAME { _PyAST_ParamSpec(a->v.Name.id, EXTRA) }
-type_param_bound[expr_ty]: ":" e=expression { e }
+type_param_bound[expr_ty]: ':' e=expression { e }
# EXPRESSIONS
# -----------
@@ -915,7 +912,7 @@ fstring_middle[expr_ty]:
| fstring_replacement_field
| t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
fstring_replacement_field[expr_ty]:
- | '{' a=(yield_expr | star_expressions) debug_expr="="? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
+ | '{' a=(yield_expr | star_expressions) debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
_PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
| invalid_replacement_field
fstring_conversion[ResultTokenWithMetadata*]:
diff --git a/Include/compile.h b/Include/compile.h
index 3c5acd7209f763..52d0bc76c9fca4 100644
--- a/Include/compile.h
+++ b/Include/compile.h
@@ -10,9 +10,6 @@ extern "C" {
#define Py_eval_input 258
#define Py_func_type_input 345
-/* This doesn't need to match anything */
-#define Py_fstring_input 800
-
#ifndef Py_LIMITED_API
# define Py_CPYTHON_COMPILE_H
# include "cpython/compile.h"
diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py
index c4e5ba2061cffc..043359bbd03f8a 100644
--- a/Lib/asyncio/subprocess.py
+++ b/Lib/asyncio/subprocess.py
@@ -147,15 +147,17 @@ def kill(self):
async def _feed_stdin(self, input):
debug = self._loop.get_debug()
- if input is not None:
- self.stdin.write(input)
- if debug:
- logger.debug(
- '%r communicate: feed stdin (%s bytes)', self, len(input))
try:
+ if input is not None:
+ self.stdin.write(input)
+ if debug:
+ logger.debug(
+ '%r communicate: feed stdin (%s bytes)', self, len(input))
+
await self.stdin.drain()
except (BrokenPipeError, ConnectionResetError) as exc:
- # communicate() ignores BrokenPipeError and ConnectionResetError
+ # communicate() ignores BrokenPipeError and ConnectionResetError.
+ # write() and drain() can raise these exceptions.
if debug:
logger.debug('%r communicate: stdin got %r', self, exc)
diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py
index a8dab1302aabb1..33df65a3081fa7 100644
--- a/Lib/concurrent/futures/process.py
+++ b/Lib/concurrent/futures/process.py
@@ -71,6 +71,11 @@ def __init__(self):
self._reader, self._writer = mp.Pipe(duplex=False)
def close(self):
+ # Please note that we do not take the shutdown lock when
+ # calling clear() (to avoid deadlocking) so this method can
+ # only be called safely from the same thread as all calls to
+ # clear() even if you hold the shutdown lock. Otherwise we
+ # might try to read from the closed pipe.
if not self._closed:
self._closed = True
self._writer.close()
@@ -426,8 +431,12 @@ def wait_result_broken_or_wakeup(self):
elif wakeup_reader in ready:
is_broken = False
- with self.shutdown_lock:
- self.thread_wakeup.clear()
+ # No need to hold the _shutdown_lock here because:
+ # 1. we're the only thread to use the wakeup reader
+ # 2. we're also the only thread to call thread_wakeup.close()
+ # 3. we want to avoid a possible deadlock when both reader and writer
+ # would block (gh-105829)
+ self.thread_wakeup.clear()
return result_item, is_broken, cause
@@ -710,7 +719,10 @@ def __init__(self, max_workers=None, mp_context=None,
# as it could result in a deadlock if a worker process dies with the
# _result_queue write lock still acquired.
#
- # _shutdown_lock must be locked to access _ThreadWakeup.
+ # _shutdown_lock must be locked to access _ThreadWakeup.close() and
+ # .wakeup(). Care must also be taken to not call clear or close from
+ # more than one thread since _ThreadWakeup.clear() is not protected by
+ # the _shutdown_lock
self._executor_manager_thread_wakeup = _ThreadWakeup()
# Create communication channels for the executor
diff --git a/Lib/test/.ruff.toml b/Lib/test/.ruff.toml
index 3bdd472c0acd9a..2d9c9eeae6c0c6 100644
--- a/Lib/test/.ruff.toml
+++ b/Lib/test/.ruff.toml
@@ -22,7 +22,7 @@ extend-exclude = [
"test_capi/test_unicode.py",
"test_ctypes/test_arrays.py",
"test_ctypes/test_functions.py",
- "test_dataclasses.py",
+ "test_dataclasses/__init__.py",
"test_descr.py",
"test_enum.py",
"test_functools.py",
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 044bfc97b8c666..bf5d541af896ca 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -5434,7 +5434,9 @@ def test_nested_startmethod(self):
while not queue.empty():
results.append(queue.get())
- self.assertEqual(results, [2, 1])
+ # gh-109706: queue.put(1) can write into the queue before queue.put(2),
+ # there is no synchronization in the test.
+ self.assertSetEqual(set(results), set([2, 1]))
@unittest.skipIf(sys.platform == "win32",
diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py
index 16ae04191da768..8acce564e61a57 100644
--- a/Lib/test/libregrtest/runtest.py
+++ b/Lib/test/libregrtest/runtest.py
@@ -232,6 +232,7 @@ def iter_tests(self):
SPLITTESTDIRS = {
"test_asyncio",
"test_concurrent_futures",
+ "test_future_stmt",
"test_multiprocessing_fork",
"test_multiprocessing_forkserver",
"test_multiprocessing_spawn",
diff --git a/Lib/test/sgml_input.html b/Lib/test/sgml_input.html
deleted file mode 100644
index f4d2e6cc805e6a..00000000000000
--- a/Lib/test/sgml_input.html
+++ /dev/null
@@ -1,212 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- |
-
-
-
-
- |
-
-
-
-
- |
-
-
-
- |
-
-
-
- |
-
-
- |
-
-
- |
-
-
- |
-
-
- |
- |
-
-
- |
- Metal |
- Cristal |
- Deuterio |
- Energía |
- |
-
-
- |
- 160.636 |
- 3.406 |
- 39.230 |
- -80/3.965 |
- |
-
-
- |
-
-
-
-
-
-
-
- Flotas (max. 9) |
-
-
- Num. |
- Misión |
- Cantidad |
- Comienzo |
- Salida |
- Objetivo |
- Llegada |
- Orden |
-
-
- 1 |
-
- Espionaje
- (F)
- |
- 3 |
- [2:250:6] |
- Wed Aug 9 18:00:02 |
- [2:242:5] |
- Wed Aug 9 18:01:02 |
-
-
- |
-
-
- 2 |
-
- Espionaje
- (V)
- |
- 3 |
- [2:250:6] |
- Wed Aug 9 17:59:55 |
- [2:242:1] |
- Wed Aug 9 18:01:55 |
-
- |
-
-
-
-
-
-