Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 22 additions & 27 deletions Lib/shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,29 @@
import fnmatch
import collections
import errno
import importlib

try:
import zlib
del zlib
_ZLIB_SUPPORTED = True
except ImportError:
_ZLIB_SUPPORTED = False

try:
import bz2
del bz2
_BZ2_SUPPORTED = True
except ImportError:
_BZ2_SUPPORTED = False

try:
import lzma
del lzma
_LZMA_SUPPORTED = True
except ImportError:
_LZMA_SUPPORTED = False

try:
from compression import zstd
del zstd
_ZSTD_SUPPORTED = True
except ImportError:
_ZSTD_SUPPORTED = False
def _compression_module_supported(module_name):
set_lazy_imports = getattr(sys, "set_lazy_imports", None)
try:
if set_lazy_imports is None:
importlib.import_module(module_name)
return True

lazy_imports_mode = sys.get_lazy_imports()
set_lazy_imports("normal")
importlib.import_module(module_name)
except ImportError:
return False
finally:
if set_lazy_imports is not None:
set_lazy_imports(lazy_imports_mode)
return True

_ZLIB_SUPPORTED = _compression_module_supported("zlib")
_BZ2_SUPPORTED = _compression_module_supported("bz2")
_LZMA_SUPPORTED = _compression_module_supported("lzma")
_ZSTD_SUPPORTED = _compression_module_supported("compression.zstd")

_WINDOWS = os.name == 'nt'
posix = nt = None
Expand Down
22 changes: 22 additions & 0 deletions Lib/test/test_shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from test import support
from test.support import os_helper
from test.support.os_helper import TESTFN, FakePath
from test.support.script_helper import assert_python_ok

TESTFN2 = TESTFN + "2"
TESTFN_SRC = TESTFN + "_SRC"
Expand Down Expand Up @@ -2177,6 +2178,27 @@ def test_unpack_archive_gztar(self):
def test_unpack_archive_bztar(self):
self.check_unpack_tarball('bztar')

@support.requires_subprocess()
def test_bz2_support_probe_is_eager_under_lazy_imports(self):
module_dir = self.mkdtemp()
create_file(
(module_dir, 'bz2.py'),
'import _bz2\n'
'SENTINEL = True\n',
)
create_file(
(module_dir, '_bz2.py'),
'raise ImportError("missing _bz2 backend")\n',
)
code = f"""
import sys
sys.path.insert(0, {module_dir!r})
import shutil
print(shutil._BZ2_SUPPORTED)
"""
proc = assert_python_ok('-X', 'lazy_imports=all', '-S', '-c', code)
self.assertEqual(proc.out.strip(), b'False')

@support.requires_zstd()
def test_unpack_archive_zstdtar(self):
self.check_unpack_tarball('zstdtar')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Make :mod:`shutil` probe compression-module support eagerly even when Python is
started with ``-X lazy_imports=all``. This fixes cases where
``shutil._BZ2_SUPPORTED`` could be reported as ``True`` even though the
underlying ``_bz2`` extension is unavailable.
Loading