mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
gh-136380: Fix import behavior for concurrent.futures.InterpreterPoolExecutor
(#136381)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-authored-by: Peter Bierma <zintensitydev@gmail.com> Co-authored-by: sobolevn <mail@sobolevn.me>
This commit is contained in:
parent
ba9c198630
commit
490eea0281
3 changed files with 62 additions and 17 deletions
|
@ -17,7 +17,7 @@ from concurrent.futures._base import (FIRST_COMPLETED,
|
|||
wait,
|
||||
as_completed)
|
||||
|
||||
__all__ = (
|
||||
__all__ = [
|
||||
'FIRST_COMPLETED',
|
||||
'FIRST_EXCEPTION',
|
||||
'ALL_COMPLETED',
|
||||
|
@ -29,10 +29,18 @@ __all__ = (
|
|||
'Executor',
|
||||
'wait',
|
||||
'as_completed',
|
||||
'InterpreterPoolExecutor',
|
||||
'ProcessPoolExecutor',
|
||||
'ThreadPoolExecutor',
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
try:
|
||||
import _interpreters
|
||||
except ImportError:
|
||||
_interpreters = None
|
||||
|
||||
if _interpreters:
|
||||
__all__.append('InterpreterPoolExecutor')
|
||||
|
||||
|
||||
def __dir__():
|
||||
|
@ -43,22 +51,15 @@ def __getattr__(name):
|
|||
global ProcessPoolExecutor, ThreadPoolExecutor, InterpreterPoolExecutor
|
||||
|
||||
if name == 'ProcessPoolExecutor':
|
||||
from .process import ProcessPoolExecutor as pe
|
||||
ProcessPoolExecutor = pe
|
||||
return pe
|
||||
from .process import ProcessPoolExecutor
|
||||
return ProcessPoolExecutor
|
||||
|
||||
if name == 'ThreadPoolExecutor':
|
||||
from .thread import ThreadPoolExecutor as te
|
||||
ThreadPoolExecutor = te
|
||||
return te
|
||||
from .thread import ThreadPoolExecutor
|
||||
return ThreadPoolExecutor
|
||||
|
||||
if name == 'InterpreterPoolExecutor':
|
||||
try:
|
||||
from .interpreter import InterpreterPoolExecutor as ie
|
||||
except ModuleNotFoundError:
|
||||
ie = InterpreterPoolExecutor = None
|
||||
else:
|
||||
InterpreterPoolExecutor = ie
|
||||
return ie
|
||||
if _interpreters and name == 'InterpreterPoolExecutor':
|
||||
from .interpreter import InterpreterPoolExecutor
|
||||
return InterpreterPoolExecutor
|
||||
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
|
|
@ -2,7 +2,9 @@ import asyncio
|
|||
import contextlib
|
||||
import io
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
import time
|
||||
import unittest
|
||||
from concurrent.futures.interpreter import BrokenInterpreterPool
|
||||
|
@ -457,6 +459,45 @@ class InterpreterPoolExecutorTest(
|
|||
# Weak references don't cross between interpreters.
|
||||
raise unittest.SkipTest('not applicable')
|
||||
|
||||
@support.requires_subprocess()
|
||||
def test_import_interpreter_pool_executor(self):
|
||||
# Test the import behavior normally if _interpreters is unavailable.
|
||||
code = textwrap.dedent("""
|
||||
import sys
|
||||
# Set it to None to emulate the case when _interpreter is unavailable.
|
||||
sys.modules['_interpreters'] = None
|
||||
from concurrent import futures
|
||||
|
||||
try:
|
||||
futures.InterpreterPoolExecutor
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
print('AttributeError not raised!', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from concurrent.futures import InterpreterPoolExecutor
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print('ImportError not raised!', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
from concurrent.futures import *
|
||||
|
||||
if 'InterpreterPoolExecutor' in globals():
|
||||
print('InterpreterPoolExecutor should not be imported!',
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
""")
|
||||
|
||||
cmd = [sys.executable, '-c', code]
|
||||
p = subprocess.run(cmd, capture_output=True)
|
||||
self.assertEqual(p.returncode, 0, p.stderr.decode())
|
||||
self.assertEqual(p.stdout.decode(), '')
|
||||
self.assertEqual(p.stderr.decode(), '')
|
||||
|
||||
|
||||
class AsyncioTest(InterpretersMixin, testasyncio_utils.TestCase):
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Raises :exc:`AttributeError` when accessing
|
||||
:class:`concurrent.futures.InterpreterPoolExecutor` and subinterpreters are
|
||||
not available.
|
Loading…
Add table
Add a link
Reference in a new issue