Add InterpreterPoolExecutor (3.14) (#14008)

This commit is contained in:
Max Muoto
2025-05-12 09:58:29 -07:00
committed by GitHub
parent 81fc4a7b20
commit 8b12b1664b
6 changed files with 248 additions and 28 deletions
@@ -60,17 +60,6 @@ compression.gzip.GzipFile.readinto1
compression.gzip.GzipFile.readinto1
compression.gzip.compress
compression.zstd
concurrent.futures.__all__
concurrent.futures.InterpreterPoolExecutor
concurrent.futures.ThreadPoolExecutor.BROKEN
concurrent.futures.ThreadPoolExecutor.prepare_context
concurrent.futures.interpreter
concurrent.futures.thread.ThreadPoolExecutor.BROKEN
concurrent.futures.thread.ThreadPoolExecutor.prepare_context
concurrent.futures.thread.WorkerContext
concurrent.futures.thread._WorkItem.__init__
concurrent.futures.thread._WorkItem.run
concurrent.futures.thread._worker
ctypes.POINTER
ctypes.byref
ctypes.memoryview_at
@@ -1,7 +1,9 @@
from __future__ import annotations
import sys
from collections.abc import Callable, Iterator
from concurrent.futures import Future, ThreadPoolExecutor, as_completed
from typing import Literal
from typing_extensions import assert_type
@@ -28,3 +30,49 @@ def check_future_invariance() -> None:
fut: Future[Child] = Future()
execute_callback(lambda: Parent(), fut) # type: ignore
assert isinstance(fut.result(), Child)
if sys.version_info >= (3, 14):
def _initializer(x: int) -> None:
pass
def check_interpreter_pool_executor() -> None:
import concurrent.futures.interpreter
from concurrent.futures import InterpreterPoolExecutor
with InterpreterPoolExecutor(initializer=_initializer, initargs=(1,)):
...
with InterpreterPoolExecutor(initializer=_initializer, initargs=("x",)): # type: ignore
...
context = InterpreterPoolExecutor.prepare_context(initializer=_initializer, initargs=(1,), shared={})
worker_context = context[0]()
assert_type(worker_context, concurrent.futures.interpreter.WorkerContext)
resolve_task = context[1]
# Function should enfore that the arguments are correct.
res = resolve_task(_initializer, 1)
assert_type(res, tuple[bytes, Literal["function"]])
# When the function is a script, the arguments should be a string.
str_res = resolve_task("print('Hello, world!')")
assert_type(str_res, tuple[bytes, Literal["script"]])
# When a script is passed, no arguments should be provided.
resolve_task("print('Hello, world!')", 1) # type: ignore
# `WorkerContext.__init__` should accept the result of a resolved task.
concurrent.futures.interpreter.WorkerContext(initdata=res)
# Run should also accept the result of a resolved task.
worker_context.run(res)
def check_thread_worker_context() -> None:
import concurrent.futures.thread
context = concurrent.futures.thread.WorkerContext.prepare(initializer=_initializer, initargs=(1,))
worker_context = context[0]()
assert_type(worker_context, concurrent.futures.thread.WorkerContext)
resolve_task = context[1]
res = resolve_task(_initializer, (1,), {"test": 1})
assert_type(res[1], tuple[int])
assert_type(res[2], dict[str, int])