From 6bd56d7ed04d434fc662d1a7f3f91a6a0b9fd881 Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 10:37:04 +0000 Subject: [PATCH 01/14] Inital make zlib test required on platforms other than wasi, remove wrong comments, add news/whatsnew entries --- Doc/whatsnew/3.14.rst | 6 ++++++ Lib/encodings/zlib_codec.py | 2 +- Lib/test/test_zlib.py | 9 ++++++++- .../Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst | 2 ++ configure.ac | 2 +- 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 05221a8edf4066..7540bb3b9c7bbd 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1310,6 +1310,12 @@ Build changes * GNU Autoconf 2.72 is now required to generate :file:`configure`. (Contributed by Erlend Aasland in :gh:`115765`.) +* zlib is now officially required to build CPython. + It is still technically possible to build CPython without it for special needs, like bootstrapping. + Such builds are not supported, but we can accept pull requests to keep them working. + As an exception, zlib is not required on WASI. + (Contributed by Stan Ulbrych in :gh:`xxxxxx`.) + .. _whatsnew314-pep761: PEP 761: Discontinuation of PGP signatures diff --git a/Lib/encodings/zlib_codec.py b/Lib/encodings/zlib_codec.py index 95908a4b4a13a1..25acfba1c01483 100644 --- a/Lib/encodings/zlib_codec.py +++ b/Lib/encodings/zlib_codec.py @@ -6,7 +6,7 @@ """ import codecs -import zlib # this codec needs the optional zlib module ! +import zlib ### Codec APIs diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index 4d97fe56f3a094..da9e289cf78b85 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -8,8 +8,15 @@ import sys from test.support import bigmemtest, _1G, _4G, is_s390x +# Building CPython without zlib is not supported except WASI. +# +# Anyone who wants build CPython this way should be prepared to patch it, +# but the core team may help getting those patches to the main branch +# (as that’s the place where multiple third parties can cooperate). +# +# For tests to pass without zlib, this file needs to be removed. -zlib = import_helper.import_module('zlib') +zlib = import_helper.import_module('zlib', required_on=('linux', 'android', 'ios', 'darwin', 'win32', 'cygwin')) requires_Compress_copy = unittest.skipUnless( hasattr(zlib.compressobj(), "copy"), diff --git a/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst b/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst new file mode 100644 index 00000000000000..64303a8ad29742 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst @@ -0,0 +1,2 @@ +Make zlib required to build CPython with the exception of WASI. +(Contributed by Stan Ulbrych in :gh:`xxxxxx`.) diff --git a/configure.ac b/configure.ac index 234ae90616af62..84ee473392fb20 100644 --- a/configure.ac +++ b/configure.ac @@ -5323,7 +5323,7 @@ if test "$ac_cv_have_lchflags" = yes ; then fi dnl Check for compression libraries -AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy]) +AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy; zlib 1.2.0 (2003) added inflateCopy.]) dnl detect zlib from Emscripten emport PY_CHECK_EMSCRIPTEN_PORT([ZLIB], [-sUSE_ZLIB]) From 0f1090b55c71ca4ca213158dc23148e0e31fa738 Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 10:49:29 +0000 Subject: [PATCH 02/14] Make zlib default in binascii, update news/whatsnew with pr no --- Doc/whatsnew/3.14.rst | 2 +- ...5-02-19-00-00-00.gh-issue-91246.ahsgd3.rst | 2 +- Modules/binascii.c | 16 +++++++------ PCbuild/pythoncore.vcxproj | 4 +--- configure | 24 ++++++------------- configure.ac | 13 +++++----- pyconfig.h.in | 3 ++- 7 files changed, 27 insertions(+), 37 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 7540bb3b9c7bbd..4e7ef3293b6ad1 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1314,7 +1314,7 @@ Build changes It is still technically possible to build CPython without it for special needs, like bootstrapping. Such builds are not supported, but we can accept pull requests to keep them working. As an exception, zlib is not required on WASI. - (Contributed by Stan Ulbrych in :gh:`xxxxxx`.) + (Contributed by Stan Ulbrych in :gh:`130297`.) .. _whatsnew314-pep761: diff --git a/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst b/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst index 64303a8ad29742..c6868c15903aef 100644 --- a/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst +++ b/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst @@ -1,2 +1,2 @@ Make zlib required to build CPython with the exception of WASI. -(Contributed by Stan Ulbrych in :gh:`xxxxxx`.) +(Contributed by Stan Ulbrych in :gh:`130297`.) diff --git a/Modules/binascii.c b/Modules/binascii.c index 6bb01d148b6faa..839b193b866302 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -60,7 +60,7 @@ #include "Python.h" #include "pycore_long.h" // _PyLong_DigitValue #include "pycore_strhex.h" // _Py_strhex_bytes_with_sep() -#ifdef USE_ZLIB_CRC32 +#ifndef NO_ZLIB_CRC32 # include "zlib.h" #endif @@ -616,7 +616,7 @@ binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc) return PyLong_FromUnsignedLong(crc); } -#ifndef USE_ZLIB_CRC32 +#ifdef NO_ZLIB_CRC32 /* Crc - 32 BIT ANSI X3.66 CRC checksum files Also known as: ISO 3307 **********************************************************************| @@ -749,7 +749,7 @@ internal_crc32(const unsigned char *bin_data, Py_ssize_t len, unsigned int crc) result = (crc ^ 0xFFFFFFFF); return result & 0xffffffff; } -#endif /* USE_ZLIB_CRC32 */ +#endif /* NO_ZLIB_CRC32 */ /*[clinic input] binascii.crc32 -> unsigned_int @@ -765,9 +765,11 @@ static unsigned int binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc) /*[clinic end generated code: output=52cf59056a78593b input=bbe340bc99d25aa8]*/ -#ifdef USE_ZLIB_CRC32 +#ifndef NO_ZLIB_CRC32 /* This is the same as zlibmodule.c zlib_crc32_impl. It exists in two - * modules for historical reasons. */ + * modules for historical reasons. They should be consolidated in the future + * once WASI supports zlib. + */ { /* Releasing the GIL for very small buffers is inefficient and may lower performance */ @@ -798,7 +800,7 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc) } return crc & 0xffffffff; } -#else /* USE_ZLIB_CRC32 */ +#else /* NO_ZLIB_CRC32 */ { const unsigned char *bin_data = data->buf; Py_ssize_t len = data->len; @@ -815,7 +817,7 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc) return internal_crc32(bin_data, len, crc); } } -#endif /* USE_ZLIB_CRC32 */ +#endif /* NO_ZLIB_CRC32 */ /*[clinic input] binascii.b2a_hex diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 9ebf58ae8a9bc4..b963c6b4cff495 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -457,9 +457,7 @@ - - USE_ZLIB_CRC32;%(PreprocessorDefinitions) - + diff --git a/configure b/configure index 453b0123ded0a4..742238a1a24953 100755 --- a/configure +++ b/configure @@ -21450,20 +21450,6 @@ fi - - - if test "$ac_sys_system" = "Emscripten" -a -z "$ZLIB_CFLAGS" -a -z "$ZLIB_LIBS" -then : - - ZLIB_CFLAGS="-sUSE_ZLIB" - ZLIB_LIBS="-sUSE_ZLIB" - -fi - - - - - pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib >= 1.2.0" >&5 printf %s "checking for zlib >= 1.2.0... " >&6; } @@ -21604,6 +21590,8 @@ then : ZLIB_CFLAGS=${ZLIB_CFLAGS-""} ZLIB_LIBS=${ZLIB_LIBS-"-lz"} + BINASCII_CFLAGS="$ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" py_check_lib_save_LIBS=$LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 printf %s "checking for inflateCopy in -lz... " >&6; } @@ -21751,6 +21739,8 @@ then : ZLIB_CFLAGS=${ZLIB_CFLAGS-""} ZLIB_LIBS=${ZLIB_LIBS-"-lz"} + BINASCII_CFLAGS="$ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" py_check_lib_save_LIBS=$LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 printf %s "checking for inflateCopy in -lz... " >&6; } @@ -21825,11 +21815,11 @@ printf "%s\n" "yes" >&6; } fi -if test "x$have_zlib" = xyes +if test "x$have_zlib" = xno then : - BINASCII_CFLAGS="-DUSE_ZLIB_CRC32 $ZLIB_CFLAGS" - BINASCII_LIBS="$ZLIB_LIBS" + BINASCII_CFLAGS="-DNO_ZLIB_CRC32" + BINASCII_LIBS="" fi diff --git a/configure.ac b/configure.ac index 84ee473392fb20..e68cf92dc3e71f 100644 --- a/configure.ac +++ b/configure.ac @@ -5325,9 +5325,6 @@ fi dnl Check for compression libraries AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy; zlib 1.2.0 (2003) added inflateCopy.]) -dnl detect zlib from Emscripten emport -PY_CHECK_EMSCRIPTEN_PORT([ZLIB], [-sUSE_ZLIB]) - PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ have_zlib=yes dnl zlib 1.2.0 (2003) added inflateCopy @@ -5342,15 +5339,17 @@ PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ AS_VAR_IF([have_zlib], [yes], [ ZLIB_CFLAGS=${ZLIB_CFLAGS-""} ZLIB_LIBS=${ZLIB_LIBS-"-lz"} + BINASCII_CFLAGS="$ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" PY_CHECK_LIB([z], [inflateCopy], [AC_DEFINE([HAVE_ZLIB_COPY], [1])]) ]) ]) ]) -dnl binascii can use zlib for optimized crc32. -AS_VAR_IF([have_zlib], [yes], [ - BINASCII_CFLAGS="-DUSE_ZLIB_CRC32 $ZLIB_CFLAGS" - BINASCII_LIBS="$ZLIB_LIBS" +dnl wasi does not support zlib +AS_VAR_IF([have_zlib], [no], [ + BINASCII_CFLAGS="-DNO_ZLIB_CRC32" + BINASCII_LIBS="" ]) dnl detect bzip2 from Emscripten emport diff --git a/pyconfig.h.in b/pyconfig.h.in index 4295b4f5ea5fbd..ee4cac2ce8472a 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1609,7 +1609,8 @@ /* Define to 1 if you have the 'writev' function. */ #undef HAVE_WRITEV -/* Define if the zlib library has inflateCopy */ +/* Define if the zlib library has inflateCopy; zlib 1.2.0 (2003) added + inflateCopy. */ #undef HAVE_ZLIB_COPY /* Define to 1 if you have the header file. */ From 89d2d5fa82b772ee6147ba9430ecda0810499bba Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 11:12:55 +0000 Subject: [PATCH 03/14] Update test_zlib and configure --- Lib/test/test_zlib.py | 8 +++++++- configure | 26 ++++++++++++++++---------- configure.ac | 26 +++++++++++++++++--------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index da9e289cf78b85..b8f35c59bedaa4 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -7,6 +7,7 @@ import random import sys from test.support import bigmemtest, _1G, _4G, is_s390x +import importlib # Building CPython without zlib is not supported except WASI. # @@ -16,7 +17,12 @@ # # For tests to pass without zlib, this file needs to be removed. -zlib = import_helper.import_module('zlib', required_on=('linux', 'android', 'ios', 'darwin', 'win32', 'cygwin')) +try: + zlib = importlib.import_module('zlib') +except ImportError as msg: + if sys.platform.startswith('wasi'): + raise unittest.SkipTest(str(msg)) + raise ImportError("Building CPython without zlib is not supported") requires_Compress_copy = unittest.skipUnless( hasattr(zlib.compressobj(), "copy"), diff --git a/configure b/configure index 742238a1a24953..5dc67de0db5354 100755 --- a/configure +++ b/configure @@ -21590,8 +21590,6 @@ then : ZLIB_CFLAGS=${ZLIB_CFLAGS-""} ZLIB_LIBS=${ZLIB_LIBS-"-lz"} - BINASCII_CFLAGS="$ZLIB_CFLAGS" - BINASCII_LIBS="$ZLIB_LIBS" py_check_lib_save_LIBS=$LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 printf %s "checking for inflateCopy in -lz... " >&6; } @@ -21739,8 +21737,6 @@ then : ZLIB_CFLAGS=${ZLIB_CFLAGS-""} ZLIB_LIBS=${ZLIB_LIBS-"-lz"} - BINASCII_CFLAGS="$ZLIB_CFLAGS" - BINASCII_LIBS="$ZLIB_LIBS" py_check_lib_save_LIBS=$LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inflateCopy in -lz" >&5 printf %s "checking for inflateCopy in -lz... " >&6; } @@ -21810,18 +21806,28 @@ else printf "%s\n" "yes" >&6; } have_zlib=yes - printf "%s\n" "#define HAVE_ZLIB_COPY 1" >>confdefs.h + printf "%s\n" "#define HAVE_ZLIB_COPY 1" >>confdefs.h fi +case $ac_sys_system in #( + WASI) : -if test "x$have_zlib" = xno -then : + BINASCII_CFLAGS="-DNO_ZLIB_CRC32" + BINASCII_LIBS="" + ;; #( + *) : - BINASCII_CFLAGS="-DNO_ZLIB_CRC32" - BINASCII_LIBS="" + if test "$have_zlib" != "yes"; then + as_fn_error $? "zlib.h and libz are required. Install your OS's zlib-devel or zlib1g-dev equivalent library or get it from https://zlib.net/." "$LINENO" 5 + fi + BINASCII_CFLAGS="$ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" -fi + ;; #( + *) : + ;; +esac diff --git a/configure.ac b/configure.ac index e68cf92dc3e71f..c803bf9e9f530c 100644 --- a/configure.ac +++ b/configure.ac @@ -5327,7 +5327,6 @@ AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy; zlib PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ have_zlib=yes - dnl zlib 1.2.0 (2003) added inflateCopy AC_DEFINE([HAVE_ZLIB_COPY], [1]) ], [ WITH_SAVE_ENV([ @@ -5339,18 +5338,27 @@ PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [ AS_VAR_IF([have_zlib], [yes], [ ZLIB_CFLAGS=${ZLIB_CFLAGS-""} ZLIB_LIBS=${ZLIB_LIBS-"-lz"} - BINASCII_CFLAGS="$ZLIB_CFLAGS" - BINASCII_LIBS="$ZLIB_LIBS" PY_CHECK_LIB([z], [inflateCopy], [AC_DEFINE([HAVE_ZLIB_COPY], [1])]) ]) ]) ]) - -dnl wasi does not support zlib -AS_VAR_IF([have_zlib], [no], [ - BINASCII_CFLAGS="-DNO_ZLIB_CRC32" - BINASCII_LIBS="" -]) +dnl temporarily throw only errors on builds other than wasi until wasi supports zlib +AS_CASE([$ac_sys_system], + [WASI], [ + BINASCII_CFLAGS="-DNO_ZLIB_CRC32" + BINASCII_LIBS="" + ], + [*], [ + if test "$have_zlib" != "yes"; then + AC_MSG_ERROR([m4_normalize([ + zlib.h and libz are required. Install your OS's zlib-devel or + zlib1g-dev equivalent library or get it from https://zlib.net/. + ])]) + fi + BINASCII_CFLAGS="$ZLIB_CFLAGS" + BINASCII_LIBS="$ZLIB_LIBS" + ] +) dnl detect bzip2 from Emscripten emport PY_CHECK_EMSCRIPTEN_PORT([BZIP2], [-sUSE_BZIP2]) From 57d35206dd34c1190a58362977946183ffb99b78 Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 12:29:20 +0000 Subject: [PATCH 04/14] Remove fancy error messages for zlib import errors Co-authored-by: Gregory P. Smith --- Lib/shutil.py | 20 +++++--------------- Lib/tarfile.py | 16 +++++----------- Lib/zipfile/__init__.py | 14 +++----------- Lib/zipimport.py | 7 +------ 4 files changed, 14 insertions(+), 43 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py index 510ae8c6f22d59..090325647cc328 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -11,12 +11,6 @@ import collections import errno -try: - import zlib - del zlib - _ZLIB_SUPPORTED = True -except ImportError: - _ZLIB_SUPPORTED = False try: import bz2 @@ -1000,7 +994,7 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, """ if compress is None: tar_compression = '' - elif _ZLIB_SUPPORTED and compress == 'gzip': + elif compress == 'gzip': tar_compression = 'gz' elif _BZ2_SUPPORTED and compress == 'bzip2': tar_compression = 'bz2' @@ -1121,10 +1115,9 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, "uncompressed tar file"), } -if _ZLIB_SUPPORTED: - _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')], - "gzip'ed tar-file") - _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file") +_ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')], + "gzip'ed tar-file") +_ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file") if _BZ2_SUPPORTED: _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], @@ -1345,12 +1338,9 @@ def _unpack_tarfile(filename, extract_dir, *, filter=None): _UNPACK_FORMATS = { 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"), + 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), } -if _ZLIB_SUPPORTED: - _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [], - "gzip'ed tar-file") - if _BZ2_SUPPORTED: _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [], "bzip2'ed tar-file") diff --git a/Lib/tarfile.py b/Lib/tarfile.py index a0fab46b24e249..5523ab3598e3bc 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -364,10 +364,7 @@ def __init__(self, name, mode, comptype, fileobj, bufsize, try: if comptype == "gz": - try: - import zlib - except ImportError: - raise CompressionError("zlib module is not available") from None + import zlib self.zlib = zlib self.crc = zlib.crc32(b"") if mode == "r": @@ -2697,13 +2694,10 @@ def next(self): except SubsequentHeaderError as e: raise ReadError(str(e)) from None except Exception as e: - try: - import zlib - if isinstance(e, zlib.error): - raise ReadError(f'zlib error: {e}') from None - else: - raise e - except ImportError: + import zlib + if isinstance(e, zlib.error): + raise ReadError(f'zlib error: {e}') from None + else: raise e break diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index b8b496ad9471f4..c8b5bcdc05d179 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -14,12 +14,8 @@ import threading import time -try: - import zlib # We may need its compression method - crc32 = zlib.crc32 -except ImportError: - zlib = None - crc32 = binascii.crc32 +import zlib +crc32 = zlib.crc32 try: import bz2 # We may need its compression method @@ -771,12 +767,8 @@ def decompress(self, data): } def _check_compression(compression): - if compression == ZIP_STORED: + if compression in (ZIP_STORED, ZIP_DEFLATED): pass - elif compression == ZIP_DEFLATED: - if not zlib: - raise RuntimeError( - "Compression requires the (missing) zlib module") elif compression == ZIP_BZIP2: if not bz2: raise RuntimeError( diff --git a/Lib/zipimport.py b/Lib/zipimport.py index 444c9dd11d8672..70e0988ba3b258 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -604,9 +604,7 @@ def _read_directory(archive): _importing_zlib = False -# Return the zlib.decompress function object, or NULL if zlib couldn't -# be imported. The function is cached when found, so subsequent calls -# don't import zlib again. +# Return the zlib.decompress function object or raise an import error. def _get_decompress_func(): global _importing_zlib if _importing_zlib: @@ -618,9 +616,6 @@ def _get_decompress_func(): _importing_zlib = True try: from zlib import decompress - except Exception: - _bootstrap._verbose_message('zipimport: zlib UNAVAILABLE') - raise ZipImportError("can't decompress data; zlib not available") finally: _importing_zlib = False From be513cba989da280d5610ca21cfab4d1219b3bc8 Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 13:38:07 +0000 Subject: [PATCH 05/14] Add skips --- Lib/test/support/__init__.py | 6 +++-- Lib/test/test_bdb.py | 16 +++++++++++++ Lib/test/test_cmd_line_script.py | 34 +++++++++++++++++++++++++++ Lib/test/test_ensurepip.py | 2 ++ Lib/test/test_eof.py | 2 ++ Lib/test/test_gc.py | 3 ++- Lib/test/test_importlib/__init__.py | 4 ++++ Lib/test/test_inspect/test_inspect.py | 3 ++- Lib/test/test_modulefinder.py | 17 ++++++++++++++ Lib/test/test_pdb.py | 6 ++++- Lib/test/test_pkgutil.py | 8 +++++-- Lib/test/test_pydoc/test_pydoc.py | 7 +++++- Lib/test/test_reprlib.py | 9 ++++++- Lib/test/test_runpy.py | 19 +++++++++++++++ Lib/test/test_shutil.py | 6 ++++- Lib/test/test_source_encoding.py | 3 ++- Lib/test/test_super.py | 3 ++- Lib/test/test_support.py | 2 ++ Lib/test/test_tokenize.py | 4 ++-- Lib/test/test_zipapp.py | 4 ++++ Lib/test/test_zipimport.py | 9 +++---- Lib/test/test_zoneinfo/__init__.py | 4 ++++ 22 files changed, 153 insertions(+), 18 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index f31d98bf731d67..140c8bb00a8a93 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -497,8 +497,10 @@ def requires_zlib(reason='requires zlib'): try: import zlib except ImportError: - zlib = None - return unittest.skipUnless(zlib, reason) + if sys.platform.startswith('wasi'): + zlib = None + return unittest.skipUnless(zlib, reason) + raise def requires_gzip(reason='requires gzip'): try: diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index f15dae13eb384e..74b69b0a7018f9 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -60,6 +60,7 @@ from test.support import import_helper from test.support import os_helper from test.support import patch_list +from test.support import requires_zlib class BdbException(Exception): pass @@ -634,6 +635,7 @@ def test_next(self): with TracerRun(self) as tracer: tracer.runcall(tfunc_main) + @requires_zlib def test_next_over_import(self): code = """ def main(): @@ -729,6 +731,7 @@ def test_until_in_caller_frame(self): tracer.runcall(tfunc_main) @patch_list(sys.meta_path) + @requires_zlib def test_skip(self): # Check that tracing is skipped over the import statement in # 'tfunc_import()'. @@ -789,6 +792,7 @@ def test_bp_on_non_existent_module(self): with TracerRun(self) as tracer: self.assertRaises(BdbError, tracer.runcall, tfunc_import) + @requires_zlib def test_bp_after_last_statement(self): code = """ def main(): @@ -802,6 +806,7 @@ def main(): with TracerRun(self) as tracer: self.assertRaises(BdbError, tracer.runcall, tfunc_import) + @requires_zlib def test_temporary_bp(self): code = """ def func(): @@ -853,6 +858,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_bp_condition(self): code = """ def func(a): @@ -873,6 +879,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_bp_exception_on_condition_evaluation(self): code = """ def func(a): @@ -892,6 +899,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_bp_ignore_count(self): code = """ def func(): @@ -913,6 +921,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_ignore_count_on_disabled_bp(self): code = """ def func(): @@ -940,6 +949,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_clear_two_bp_on_same_line(self): code = """ def func(): @@ -1030,6 +1040,7 @@ def test_run_step(self): with TracerRun(self) as tracer: tracer.run(compile(textwrap.dedent(code), '', 'exec')) + @requires_zlib def test_runeval_step(self): # Test bdb 'runeval'. code = """ @@ -1053,6 +1064,7 @@ def main(): class IssuesTestCase(BaseTestCase): """Test fixed bdb issues.""" + @requires_zlib def test_step_at_return_with_no_trace_in_caller(self): # Issue #13183. # Check that the tracer does step into the caller frame when the @@ -1083,6 +1095,7 @@ def func(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_next_until_return_in_generator(self): # Issue #16596. # Check that set_next(), set_until() and set_return() do not treat the @@ -1124,6 +1137,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_next_command_in_generator_for_loop(self): # Issue #16596. code = """ @@ -1155,6 +1169,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_next_command_in_generator_with_subiterator(self): # Issue #16596. code = """ @@ -1186,6 +1201,7 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) + @requires_zlib def test_return_command_in_generator_with_subiterator(self): # Issue #16596. code = """ diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index 53dc9b1a7effb5..65a6bcd6242677 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -19,6 +19,8 @@ make_pkg, make_script, make_zip_pkg, make_zip_script, assert_python_ok, assert_python_failure, spawn_python, kill_python) +from Lib.test.support import requires_zlib + verbose = support.verbose example_args = ['test1', 'test2', 'test3'] @@ -220,6 +222,7 @@ def test_repl_stderr_flush(self): def test_repl_stderr_flush_separate_stderr(self): self.check_repl_stderr_flush(True) + @requires_zlib def test_basic_script(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') @@ -228,6 +231,7 @@ def test_basic_script(self): importlib.machinery.SourceFileLoader, expected_cwd=script_dir) + @requires_zlib def test_script_abspath(self): # pass the script using the relative path, expect the absolute path # in __file__ @@ -240,6 +244,7 @@ def test_script_abspath(self): script_dir, None, importlib.machinery.SourceFileLoader) + @requires_zlib def test_script_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') @@ -250,6 +255,7 @@ def test_script_compiled(self): pyc_file, script_dir, None, importlib.machinery.SourcelessFileLoader) + @requires_zlib def test_directory(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -257,6 +263,7 @@ def test_directory(self): script_dir, '', importlib.machinery.SourceFileLoader) + @requires_zlib def test_directory_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -272,6 +279,7 @@ def test_directory_error(self): msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) + @requires_zlib def test_zipfile(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -279,6 +287,7 @@ def test_zipfile(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) + @requires_zlib def test_zipfile_compiled_timestamp(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -289,6 +298,7 @@ def test_zipfile_compiled_timestamp(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) + @requires_zlib def test_zipfile_compiled_checked_hash(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -299,6 +309,7 @@ def test_zipfile_compiled_checked_hash(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) + @requires_zlib def test_zipfile_compiled_unchecked_hash(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -309,6 +320,7 @@ def test_zipfile_compiled_unchecked_hash(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) + @requires_zlib def test_zipfile_error(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'not_main') @@ -316,6 +328,7 @@ def test_zipfile_error(self): msg = "can't find '__main__' module in %r" % zip_name self._check_import_error(zip_name, msg) + @requires_zlib def test_module_in_package(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -326,6 +339,7 @@ def test_module_in_package(self): importlib.machinery.SourceFileLoader, cwd=script_dir) + @requires_zlib def test_module_in_package_in_zipfile(self): with os_helper.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') @@ -341,6 +355,7 @@ def test_module_in_subpackage_in_zipfile(self): zipimport.zipimporter, PYTHONPATH=zip_name, cwd=script_dir) + @requires_zlib def test_package(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -351,6 +366,7 @@ def test_package(self): importlib.machinery.SourceFileLoader, cwd=script_dir) + @requires_zlib def test_package_compiled(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -364,6 +380,7 @@ def test_package_compiled(self): importlib.machinery.SourcelessFileLoader, cwd=script_dir) + @requires_zlib def test_package_error(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -372,6 +389,7 @@ def test_package_error(self): "be directly executed") self._check_import_error(["-m", "test_pkg"], msg, cwd=script_dir) + @requires_zlib def test_package_recursion(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -383,6 +401,7 @@ def test_package_recursion(self): "be directly executed") self._check_import_error(["-m", "test_pkg"], msg, cwd=script_dir) + @requires_zlib def test_issue8202(self): # Make sure package __init__ modules see "-m" in sys.argv0 while # searching for the module to execute @@ -415,6 +434,7 @@ def test_issue8202_dash_c_file_ignored(self): expected = "sys.path[0]==%r" % '' self.assertIn(expected.encode('utf-8'), out) + @requires_zlib def test_issue8202_dash_m_file_ignored(self): # Make sure a "-m" file in the current directory # does not alter the value of sys.path[0] @@ -461,6 +481,7 @@ def check_dash_m_failure(self, *args): self.assertEqual(rc, 1) return err + @requires_zlib def test_dash_m_error_code_is_one(self): # If a module is invoked with the -m command line flag # and results in an error that the return code to the @@ -515,6 +536,7 @@ def test_hint_when_triying_to_import_a_py_file(self): self.assertIn(b"Try using 'asyncio' instead " b"of 'asyncio.py' as the module name", err) + @requires_zlib def test_dash_m_init_traceback(self): # These were wrapped in an ImportError and tracebacks were # suppressed; see Issue 14285 @@ -539,6 +561,7 @@ def test_dash_m_main_traceback(self): self.assertIn(b'Exception in __main__ module', err) self.assertIn(b'Traceback', err) + @requires_zlib def test_pep_409_verbiage(self): # Make sure PEP 409 syntax properly suppresses # the context of an exception @@ -557,6 +580,7 @@ def test_pep_409_verbiage(self): self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) + @requires_zlib def test_non_ascii(self): # Apple platforms deny the creation of a file with an invalid UTF-8 name. # Windows allows creating a name with an arbitrary bytes name, but @@ -586,6 +610,7 @@ def test_non_ascii(self): 'stdout=%r stderr=%r' % (stdout, stderr)) self.assertEqual(0, rc) + @requires_zlib def test_issue20500_exit_with_exception_value(self): script = textwrap.dedent("""\ import sys @@ -604,6 +629,7 @@ def test_issue20500_exit_with_exception_value(self): text = stderr.decode('ascii') self.assertEqual(text.rstrip(), "some text") + @requires_zlib def test_syntaxerror_unindented_caret_position(self): script = "1 + 1 = 2\n" with os_helper.temp_dir() as script_dir: @@ -613,6 +639,7 @@ def test_syntaxerror_unindented_caret_position(self): # Confirm that the caret is located under the '=' sign self.assertIn("\n ^^^^^\n", text) + @requires_zlib def test_syntaxerror_indented_caret_position(self): script = textwrap.dedent("""\ if True: @@ -636,6 +663,7 @@ def test_syntaxerror_indented_caret_position(self): self.assertNotIn("\f", text) self.assertIn("\n 1 + 1 = 2\n ^^^^^\n", text) + @requires_zlib def test_syntaxerror_multi_line_fstring(self): script = 'foo = f"""{}\nfoo"""\n' with os_helper.temp_dir() as script_dir: @@ -650,6 +678,7 @@ def test_syntaxerror_multi_line_fstring(self): ], ) + @requires_zlib def test_syntaxerror_invalid_escape_sequence_multi_line(self): script = 'foo = """\\q"""\n' with os_helper.temp_dir() as script_dir: @@ -666,6 +695,7 @@ def test_syntaxerror_invalid_escape_sequence_multi_line(self): ], ) + @requires_zlib def test_syntaxerror_null_bytes(self): script = "x = '\0' nothing to see here\n';import os;os.system('echo pwnd')\n" with os_helper.temp_dir() as script_dir: @@ -678,6 +708,7 @@ def test_syntaxerror_null_bytes(self): ], ) + @requires_zlib def test_syntaxerror_null_bytes_in_multiline_string(self): scripts = ["\n'''\nmultilinestring\0\n'''", "\nf'''\nmultilinestring\0\n'''"] # Both normal and f-strings with os_helper.temp_dir() as script_dir: @@ -701,6 +732,7 @@ def test_source_lines_are_shown_when_running_source(self): b'ZeroDivisionError: division by zero'] self.assertEqual(stderr.splitlines(), expected_lines) + @requires_zlib def test_syntaxerror_does_not_crash(self): script = "nonlocal x\n" with os_helper.temp_dir() as script_dir: @@ -712,6 +744,7 @@ def test_syntaxerror_does_not_crash(self): 'SyntaxError: nonlocal declaration not allowed at module level\n', ), text) + @requires_zlib def test_consistent_sys_path_for_direct_execution(self): # This test case ensures that the following all give the same # sys.path configuration: @@ -743,6 +776,7 @@ def test_consistent_sys_path_for_direct_execution(self): out_by_dir_isolated = kill_python(p).decode().splitlines() self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name) + @requires_zlib def test_consistent_sys_path_for_module_execution(self): # This test case ensures that the following both give the same # sys.path configuration: diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py index 6d3c91b0b6d9f9..672838a665535a 100644 --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -11,6 +11,8 @@ import ensurepip import ensurepip._uninstall +if sys.platform == "wasm": + unittest.skip("zlib unavailable") class TestPackages(unittest.TestCase): def touch(self, directory, filename): diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py index 582e5b6de6e687..6cb2a6f991e6bc 100644 --- a/Lib/test/test_eof.py +++ b/Lib/test/test_eof.py @@ -6,6 +6,7 @@ from test.support import os_helper from test.support import script_helper from test.support import warnings_helper +from test.support import requires_zlib import unittest class EOFTestCase(unittest.TestCase): @@ -45,6 +46,7 @@ def test_EOFS(self): self.assertEqual(cm.exception.offset, 5) @force_not_colorized + @requires_zlib def test_EOFS_with_file(self): expect = ("(, line 1)") with os_helper.temp_dir() as temp_dir: diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index b5140057a69d36..4e676fad615d10 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -8,7 +8,7 @@ from test.support.import_helper import import_module from test.support.os_helper import temp_dir, TESTFN, unlink from test.support.script_helper import assert_python_ok, make_script -from test.support import threading_helper, gc_threshold +from test.support import threading_helper, gc_threshold, requires_zlib import gc import sys @@ -752,6 +752,7 @@ def __del__(self): rc, out, err = assert_python_ok('-c', code) self.assertEqual(out.strip(), b'__del__ called') + @requires_zlib def test_gc_ordinary_module_at_shutdown(self): # Same as above, but with a non-__main__ module. with temp_dir() as script_dir: diff --git a/Lib/test/test_importlib/__init__.py b/Lib/test/test_importlib/__init__.py index 4b16ecc31156a5..03256c3c3dd9fe 100644 --- a/Lib/test/test_importlib/__init__.py +++ b/Lib/test/test_importlib/__init__.py @@ -1,5 +1,9 @@ import os +import sys from test.support import load_package_tests +if sys.platform == "wasm": + unittest.skip("zlib unavailable") + def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 06785e275f6b11..61bebf1042b121 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -35,7 +35,7 @@ except ImportError: ThreadPoolExecutor = None -from test.support import cpython_only, import_helper +from test.support import cpython_only, import_helper, requires_zlib from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ from test.support import run_no_yield_async_fn from test.support.import_helper import DirsOnSysPath, ready_to_import @@ -6049,6 +6049,7 @@ def assertInspectEqual(self, path, source): inspected_src.splitlines(True) ) + @requires_zlib def test_getsource_reload(self): # see issue 1218234 with ready_to_import('reload_bug', self.src_before) as (name, path): diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py index b64e684f80599f..14a7c813448ddc 100644 --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -350,36 +350,47 @@ def _do_test(self, info, report=False, debug=0, replace_paths=[], modulefinder_c self.assertEqual(bad, missing) self.assertEqual(maybe, maybe_missing) + @support.requires_zlib() def test_package(self): self._do_test(package_test) + @support.requires_zlib() def test_maybe(self): self._do_test(maybe_test) + @support.requires_zlib() def test_maybe_new(self): self._do_test(maybe_test_new) + @support.requires_zlib() def test_absolute_imports(self): self._do_test(absolute_import_test) + @support.requires_zlib() def test_relative_imports(self): self._do_test(relative_import_test) + @support.requires_zlib() def test_relative_imports_2(self): self._do_test(relative_import_test_2) + @support.requires_zlib() def test_relative_imports_3(self): self._do_test(relative_import_test_3) + @support.requires_zlib() def test_relative_imports_4(self): self._do_test(relative_import_test_4) + @support.requires_zlib() def test_syntax_error(self): self._do_test(syntax_error_test) + @support.requires_zlib() def test_same_name_as_bad(self): self._do_test(same_name_as_bad_test) + @support.requires_zlib() def test_bytecode(self): base_path = os.path.join(self.test_dir, 'a') source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0] @@ -390,6 +401,7 @@ def test_bytecode(self): os.remove(source_path) self._do_test(bytecode_test) + @support.requires_zlib() def test_replace_paths(self): old_path = os.path.join(self.test_dir, 'a', 'module.py') new_path = os.path.join(self.test_dir, 'a', 'spam.py') @@ -400,6 +412,7 @@ def test_replace_paths(self): expected = "co_filename %r changed to %r" % (old_path, new_path) self.assertIn(expected, output) + @support.requires_zlib() def test_extended_opargs(self): extended_opargs_test = [ "a", @@ -413,15 +426,19 @@ def test_extended_opargs(self): """ % list(range(2**16))] # 2**16 constants self._do_test(extended_opargs_test) + @support.requires_zlib() def test_coding_default_utf8(self): self._do_test(coding_default_utf8_test) + @support.requires_zlib() def test_coding_explicit_utf8(self): self._do_test(coding_explicit_utf8_test) + @support.requires_zlib() def test_coding_explicit_cp1252(self): self._do_test(coding_explicit_cp1252_test) + @support.requires_zlib() def test_load_module_api(self): class CheckLoadModuleApi(modulefinder.ModuleFinder): def __init__(self, *args, **kwds): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index fa439c1fe8915c..88216aa8599c71 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -10,7 +10,6 @@ import subprocess import textwrap import linecache -import zipapp from contextlib import ExitStack, redirect_stdout from io import StringIO @@ -20,6 +19,11 @@ from test.support.pty_helper import run_pty, FakeInput from unittest.mock import patch +if sys.platform == "wasm": + unittest.skip("zlib unavailable") + +import zipapp + SKIP_CORO_TESTS = False diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 736b83711def03..2d14578280a900 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -9,13 +9,17 @@ import os import os.path import tempfile -import shutil -import zipfile from test.support.import_helper import DirsOnSysPath from test.support.os_helper import FakePath from test.test_importlib.util import uncache +if sys.platform == "wasm": + unittest.skip("Zlib unavailable") + +import shutil +import zipfile + # Note: pkgutil.walk_packages is currently tested in test_runpy. This is # a hack to get a major issue resolved for 3.3b2. Longer term, it should # be moved back here, perhaps by factoring out the helper code for diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 0abd36c5e076e2..461bb8e3f5c618 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -34,7 +34,7 @@ from test.support import threading_helper from test.support import (reap_children, captured_stdout, captured_stderr, is_emscripten, is_wasi, - requires_docstrings, MISSING_C_DOCSTRINGS) + requires_docstrings, MISSING_C_DOCSTRINGS, requires_zlib) from test.support.os_helper import (TESTFN, rmtree, unlink) from test.test_pydoc import pydoc_mod from test.test_pydoc import pydocfodder @@ -1251,6 +1251,7 @@ def setUp(self): self.addCleanup(rmtree, TESTFN) importlib.invalidate_caches() + @requires_zlib def test_badimport(self): # This tests the fix for issue 5230, where if pydoc found the module # but the module had an internal import error pydoc would report no doc @@ -1272,6 +1273,7 @@ def test_badimport(self): expected = badimport_pattern % (modname, expectedinmsg) self.assertEqual(expected, result) + @requires_zlib def test_apropos_with_bad_package(self): # Issue 7425 - pydoc -k failed when bad package on path pkgdir = os.path.join(TESTFN, "syntaxerr") @@ -1293,6 +1295,7 @@ def test_apropos_with_bad_package(self): self.assertEqual(out.getvalue().strip(), 'syntaxerr') self.assertEqual(err.getvalue(), '') + @requires_zlib def test_apropos_with_unreadable_dir(self): # Issue 7367 - pydoc -k failed when unreadable dir on path self.unreadable_dir = os.path.join(TESTFN, "unreadable") @@ -1325,6 +1328,7 @@ def test_apropos_empty_doc(self): finally: os.chmod(pkgdir, current_mode) + @requires_zlib def test_url_search_package_error(self): # URL handler search should cope with packages that raise exceptions pkgdir = os.path.join(TESTFN, "test_error_package") @@ -1390,6 +1394,7 @@ def test_modules_search_builtin(self): self.assertTrue(result.startswith(expected)) + @requires_zlib def test_importfile(self): try: loaded_pydoc = pydoc.importfile(pydoc.__file__) diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py index ffeb1fba7b80c6..560af94b898e36 100644 --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -11,12 +11,14 @@ import unittest import textwrap -from test.support import verbose +from test.support import verbose, requires_zlib from test.support.os_helper import create_empty_file from reprlib import repr as r # Don't shadow builtin repr from reprlib import Repr from reprlib import recursive_repr +from Lib.test.support import requires_zlib + def nestedTuple(nesting): t = () @@ -681,6 +683,7 @@ def _check_path_limitations(self, module_name): elif os.name == 'nt' and verbose: print("cached_path_len =", cached_path_len) + @requires_zlib def test_module(self): self.maxDiff = None self._check_path_limitations(self.pkgname) @@ -691,6 +694,7 @@ def test_module(self): self.assertEqual(repr(module), "" % (module.__name__, module.__file__)) self.assertEqual(repr(sys), "") + @requires_zlib def test_type(self): self._check_path_limitations('foo') eq = self.assertEqual @@ -709,6 +713,7 @@ def test_object(self): # tp_repr. WIBNI we had ::Inline? :) pass + @requires_zlib def test_class(self): self._check_path_limitations('bar') write_file(os.path.join(self.subpkgname, 'bar.py'), '''\ @@ -720,6 +725,7 @@ class bar: # Module name may be prefixed with "test.", depending on how run. self.assertEqual(repr(bar.bar), "" % bar.__name__) + @requires_zlib def test_instance(self): self._check_path_limitations('baz') write_file(os.path.join(self.subpkgname, 'baz.py'), '''\ @@ -732,6 +738,7 @@ class baz: self.assertTrue(repr(ibaz).startswith( "<%s.baz object at 0x" % baz.__name__)) + @requires_zlib def test_method(self): self._check_path_limitations('qux') eq = self.assertEqual diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index ada78ec8e6b0c7..9a55fb3c0c1869 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -19,6 +19,7 @@ requires_resource, requires_subprocess, verbose, + requires_zlib, ) from test.support.import_helper import forget, make_legacy_pyc, unload from test.support.os_helper import create_empty_file, temp_dir, FakePath @@ -437,16 +438,19 @@ def _check_relative_imports(self, depth, run_name=None): self._del_pkg(pkg_dir) if verbose > 1: print("Module executed successfully") + @requires_zlib def test_run_module(self): for depth in range(4): if verbose > 1: print("Testing package depth:", depth) self._check_module(depth) + @requires_zlib def test_run_module_in_namespace_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) self._check_module(depth, namespace=True, parent_namespaces=True) + @requires_zlib def test_run_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) @@ -505,6 +509,7 @@ def test_package_imported_no_warning(self): with self.assertWarnsRegex(RuntimeWarning, r"found in sys\.modules"): run_module(package) + @requires_zlib def test_run_package_in_namespace_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) @@ -515,26 +520,31 @@ def test_run_namespace_package(self): if verbose > 1: print("Testing package depth:", depth) self._check_package(depth, namespace=True) + @requires_zlib def test_run_namespace_package_in_namespace_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) self._check_package(depth, namespace=True, parent_namespaces=True) + @requires_zlib def test_run_module_alter_sys(self): for depth in range(4): if verbose > 1: print("Testing package depth:", depth) self._check_module(depth, alter_sys=True) + @requires_zlib def test_run_package_alter_sys(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) self._check_package(depth, alter_sys=True) + @requires_zlib def test_explicit_relative_import(self): for depth in range(2, 5): if verbose > 1: print("Testing relative imports at depth:", depth) self._check_relative_imports(depth) + @requires_zlib def test_main_relative_import(self): for depth in range(2, 5): if verbose > 1: print("Testing main relative imports at depth:", depth) @@ -656,6 +666,7 @@ def _check_import_error(self, script_name, msg): msg = re.escape(msg) self.assertRaisesRegex(ImportError, msg, run_path, script_name) + @requires_zlib def test_basic_script(self): with temp_dir() as script_dir: mod_name = 'script' @@ -663,6 +674,7 @@ def test_basic_script(self): self._check_script(script_name, "", script_name, script_name, expect_spec=False) + @requires_zlib def test_basic_script_with_pathlike_object(self): with temp_dir() as script_dir: mod_name = 'script' @@ -672,6 +684,7 @@ def test_basic_script_with_pathlike_object(self): script_name, expect_spec=False) + @requires_zlib def test_basic_script_no_suffix(self): with temp_dir() as script_dir: mod_name = 'script' @@ -689,6 +702,7 @@ def test_script_compiled(self): self._check_script(compiled_name, "", compiled_name, compiled_name, expect_spec=False) + @requires_zlib def test_directory(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -696,6 +710,7 @@ def test_directory(self): self._check_script(script_dir, "", script_name, script_dir, mod_name=mod_name) + @requires_zlib def test_directory_compiled(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -707,6 +722,7 @@ def test_directory_compiled(self): self._check_script(script_dir, "", legacy_pyc, script_dir, mod_name=mod_name) + @requires_zlib def test_directory_error(self): with temp_dir() as script_dir: mod_name = 'not_main' @@ -714,6 +730,7 @@ def test_directory_error(self): msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) + @requires_zlib def test_zipfile(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -722,6 +739,7 @@ def test_zipfile(self): self._check_script(zip_name, "", fname, zip_name, mod_name=mod_name, check_loader=False) + @requires_zlib def test_zipfile_compiled(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -732,6 +750,7 @@ def test_zipfile_compiled(self): self._check_script(zip_name, "", fname, zip_name, mod_name=mod_name, check_loader=False) + @requires_zlib def test_zipfile_error(self): with temp_dir() as script_dir: mod_name = 'not_main' diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 078ddd6c431b37..afff0cb981d3ef 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -2,9 +2,13 @@ import unittest import unittest.mock +import sys + +if sys.platform == "wasm": + unittest.skip("zlib unavailable") + import shutil import tempfile -import sys import stat import os import os.path diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 61b00778f8361c..60873c6fdd9838 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import unittest -from test.support import script_helper, captured_stdout, requires_subprocess, requires_resource +from test.support import script_helper, captured_stdout, requires_subprocess, requires_resource, requires_zlib from test.support.os_helper import TESTFN, unlink, rmtree from test.support.import_helper import unload import importlib @@ -114,6 +114,7 @@ def test_exec_valid_coding(self): exec(b'# coding: cp949\na = "\xaa\xa7"\n', d) self.assertEqual(d['a'], '\u3047') + @requires_zlib def test_file_parse(self): # issue1134: all encodings outside latin-1 and utf-8 fail on # multiline strings and long lines (>512 columns) diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index 5cef612a340be9..4911eb1e9f44a4 100644 --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -6,7 +6,7 @@ import threading import unittest from unittest.mock import patch -from test.support import import_helper, threading_helper +from test.support import import_helper, threading_helper, requires_zlib class A: @@ -342,6 +342,7 @@ def test_super_argtype(self): with self.assertRaisesRegex(TypeError, "argument 1 must be a type"): super(1, int) + @requires_zlib def test_shadowed_global(self): source = textwrap.dedent( """ diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index d900db546ada8d..7938b959c07bf3 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -20,6 +20,7 @@ from test.support import script_helper from test.support import socket_helper from test.support import warnings_helper +from test.support import requires_zlib TESTFN = os_helper.TESTFN @@ -107,6 +108,7 @@ def test_rmtree(self): os_helper.rmtree(dirpath) self.assertFalse(os.path.exists(dirpath)) + @requires_zlib def test_forget(self): mod_filename = TESTFN + '.py' with open(mod_filename, 'w', encoding="utf-8") as f: diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 52d3341975088b..3fa541da899fc2 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -9,7 +9,7 @@ from test import support from test.test_grammar import (VALID_UNDERSCORE_LITERALS, INVALID_UNDERSCORE_LITERALS) -from test.support import os_helper +from test.support import os_helper, requires_zlib from test.support.script_helper import run_test_script, make_script, run_python_until_end # Converts a source string into a list of textual representation @@ -3162,7 +3162,7 @@ def fib(n): self.assertEqual(get_tokens(code), get_tokens(code_no_cont)) - +@requires_zlib() class CTokenizerBufferTests(unittest.TestCase): def test_newline_at_the_end_of_buffer(self): # See issue 99581: Make sure that if we need to add a new line at the diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py index 00a5ed6626ddc5..dad3682dde0e2c 100644 --- a/Lib/test/test_zipapp.py +++ b/Lib/test/test_zipapp.py @@ -6,6 +6,10 @@ import sys import tempfile import unittest + +if sys.platform == "wasm": + unittest.skip("zlib unavailable") + import zipapp import zipfile from test.support import requires_zlib diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 1f288c8b45d589..7a9c76f9849270 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -15,6 +15,9 @@ from test.support import import_helper from test.support import os_helper +if sys.platform == "wasm": + unittest.skip("zlib unavailable") + from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED import zipimport @@ -23,10 +26,8 @@ import inspect import io from traceback import extract_tb, extract_stack, print_tb -try: - import zlib -except ImportError: - zlib = None +import zlib + test_src = """\ def get_name(): diff --git a/Lib/test/test_zoneinfo/__init__.py b/Lib/test/test_zoneinfo/__init__.py index 4b16ecc31156a5..03256c3c3dd9fe 100644 --- a/Lib/test/test_zoneinfo/__init__.py +++ b/Lib/test/test_zoneinfo/__init__.py @@ -1,5 +1,9 @@ import os +import sys from test.support import load_package_tests +if sys.platform == "wasm": + unittest.skip("zlib unavailable") + def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) From e9db27c2222e230356ab6091df4e1dbdd97f6ba8 Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 13:40:28 +0000 Subject: [PATCH 06/14] Petr suggestion --- Lib/tarfile.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 5523ab3598e3bc..738d95cd1d15a7 100644 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2694,10 +2694,13 @@ def next(self): except SubsequentHeaderError as e: raise ReadError(str(e)) from None except Exception as e: - import zlib - if isinstance(e, zlib.error): - raise ReadError(f'zlib error: {e}') from None - else: + try: + import zlib + if isinstance(e, zlib.error): + raise ReadError(f'zlib error: {e}') from None + else: + raise e + except ImportError: raise e break From 97db96ce0bfbe9b1dda3de517ec74453c0cb0f91 Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 13:52:01 +0000 Subject: [PATCH 07/14] Revert "Add skips" This reverts commit be513cba989da280d5610ca21cfab4d1219b3bc8. --- Lib/test/support/__init__.py | 6 ++--- Lib/test/test_bdb.py | 16 ------------- Lib/test/test_cmd_line_script.py | 34 --------------------------- Lib/test/test_ensurepip.py | 2 -- Lib/test/test_eof.py | 2 -- Lib/test/test_gc.py | 3 +-- Lib/test/test_importlib/__init__.py | 4 ---- Lib/test/test_inspect/test_inspect.py | 3 +-- Lib/test/test_modulefinder.py | 17 -------------- Lib/test/test_pdb.py | 6 +---- Lib/test/test_pkgutil.py | 8 ++----- Lib/test/test_pydoc/test_pydoc.py | 7 +----- Lib/test/test_reprlib.py | 9 +------ Lib/test/test_runpy.py | 19 --------------- Lib/test/test_shutil.py | 6 +---- Lib/test/test_source_encoding.py | 3 +-- Lib/test/test_super.py | 3 +-- Lib/test/test_support.py | 2 -- Lib/test/test_tokenize.py | 4 ++-- Lib/test/test_zipapp.py | 4 ---- Lib/test/test_zipimport.py | 9 ++++--- Lib/test/test_zoneinfo/__init__.py | 4 ---- 22 files changed, 18 insertions(+), 153 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 140c8bb00a8a93..f31d98bf731d67 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -497,10 +497,8 @@ def requires_zlib(reason='requires zlib'): try: import zlib except ImportError: - if sys.platform.startswith('wasi'): - zlib = None - return unittest.skipUnless(zlib, reason) - raise + zlib = None + return unittest.skipUnless(zlib, reason) def requires_gzip(reason='requires gzip'): try: diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index 74b69b0a7018f9..f15dae13eb384e 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -60,7 +60,6 @@ from test.support import import_helper from test.support import os_helper from test.support import patch_list -from test.support import requires_zlib class BdbException(Exception): pass @@ -635,7 +634,6 @@ def test_next(self): with TracerRun(self) as tracer: tracer.runcall(tfunc_main) - @requires_zlib def test_next_over_import(self): code = """ def main(): @@ -731,7 +729,6 @@ def test_until_in_caller_frame(self): tracer.runcall(tfunc_main) @patch_list(sys.meta_path) - @requires_zlib def test_skip(self): # Check that tracing is skipped over the import statement in # 'tfunc_import()'. @@ -792,7 +789,6 @@ def test_bp_on_non_existent_module(self): with TracerRun(self) as tracer: self.assertRaises(BdbError, tracer.runcall, tfunc_import) - @requires_zlib def test_bp_after_last_statement(self): code = """ def main(): @@ -806,7 +802,6 @@ def main(): with TracerRun(self) as tracer: self.assertRaises(BdbError, tracer.runcall, tfunc_import) - @requires_zlib def test_temporary_bp(self): code = """ def func(): @@ -858,7 +853,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_bp_condition(self): code = """ def func(a): @@ -879,7 +873,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_bp_exception_on_condition_evaluation(self): code = """ def func(a): @@ -899,7 +892,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_bp_ignore_count(self): code = """ def func(): @@ -921,7 +913,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_ignore_count_on_disabled_bp(self): code = """ def func(): @@ -949,7 +940,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_clear_two_bp_on_same_line(self): code = """ def func(): @@ -1040,7 +1030,6 @@ def test_run_step(self): with TracerRun(self) as tracer: tracer.run(compile(textwrap.dedent(code), '', 'exec')) - @requires_zlib def test_runeval_step(self): # Test bdb 'runeval'. code = """ @@ -1064,7 +1053,6 @@ def main(): class IssuesTestCase(BaseTestCase): """Test fixed bdb issues.""" - @requires_zlib def test_step_at_return_with_no_trace_in_caller(self): # Issue #13183. # Check that the tracer does step into the caller frame when the @@ -1095,7 +1083,6 @@ def func(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_next_until_return_in_generator(self): # Issue #16596. # Check that set_next(), set_until() and set_return() do not treat the @@ -1137,7 +1124,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_next_command_in_generator_for_loop(self): # Issue #16596. code = """ @@ -1169,7 +1155,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_next_command_in_generator_with_subiterator(self): # Issue #16596. code = """ @@ -1201,7 +1186,6 @@ def main(): with TracerRun(self) as tracer: tracer.runcall(tfunc_import) - @requires_zlib def test_return_command_in_generator_with_subiterator(self): # Issue #16596. code = """ diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index 65a6bcd6242677..53dc9b1a7effb5 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -19,8 +19,6 @@ make_pkg, make_script, make_zip_pkg, make_zip_script, assert_python_ok, assert_python_failure, spawn_python, kill_python) -from Lib.test.support import requires_zlib - verbose = support.verbose example_args = ['test1', 'test2', 'test3'] @@ -222,7 +220,6 @@ def test_repl_stderr_flush(self): def test_repl_stderr_flush_separate_stderr(self): self.check_repl_stderr_flush(True) - @requires_zlib def test_basic_script(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') @@ -231,7 +228,6 @@ def test_basic_script(self): importlib.machinery.SourceFileLoader, expected_cwd=script_dir) - @requires_zlib def test_script_abspath(self): # pass the script using the relative path, expect the absolute path # in __file__ @@ -244,7 +240,6 @@ def test_script_abspath(self): script_dir, None, importlib.machinery.SourceFileLoader) - @requires_zlib def test_script_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') @@ -255,7 +250,6 @@ def test_script_compiled(self): pyc_file, script_dir, None, importlib.machinery.SourcelessFileLoader) - @requires_zlib def test_directory(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -263,7 +257,6 @@ def test_directory(self): script_dir, '', importlib.machinery.SourceFileLoader) - @requires_zlib def test_directory_compiled(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -279,7 +272,6 @@ def test_directory_error(self): msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) - @requires_zlib def test_zipfile(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -287,7 +279,6 @@ def test_zipfile(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) - @requires_zlib def test_zipfile_compiled_timestamp(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -298,7 +289,6 @@ def test_zipfile_compiled_timestamp(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) - @requires_zlib def test_zipfile_compiled_checked_hash(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -309,7 +299,6 @@ def test_zipfile_compiled_checked_hash(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) - @requires_zlib def test_zipfile_compiled_unchecked_hash(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -320,7 +309,6 @@ def test_zipfile_compiled_unchecked_hash(self): self._check_script(zip_name, run_name, zip_name, zip_name, '', zipimport.zipimporter) - @requires_zlib def test_zipfile_error(self): with os_helper.temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'not_main') @@ -328,7 +316,6 @@ def test_zipfile_error(self): msg = "can't find '__main__' module in %r" % zip_name self._check_import_error(zip_name, msg) - @requires_zlib def test_module_in_package(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -339,7 +326,6 @@ def test_module_in_package(self): importlib.machinery.SourceFileLoader, cwd=script_dir) - @requires_zlib def test_module_in_package_in_zipfile(self): with os_helper.temp_dir() as script_dir: zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script') @@ -355,7 +341,6 @@ def test_module_in_subpackage_in_zipfile(self): zipimport.zipimporter, PYTHONPATH=zip_name, cwd=script_dir) - @requires_zlib def test_package(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -366,7 +351,6 @@ def test_package(self): importlib.machinery.SourceFileLoader, cwd=script_dir) - @requires_zlib def test_package_compiled(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -380,7 +364,6 @@ def test_package_compiled(self): importlib.machinery.SourcelessFileLoader, cwd=script_dir) - @requires_zlib def test_package_error(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -389,7 +372,6 @@ def test_package_error(self): "be directly executed") self._check_import_error(["-m", "test_pkg"], msg, cwd=script_dir) - @requires_zlib def test_package_recursion(self): with os_helper.temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -401,7 +383,6 @@ def test_package_recursion(self): "be directly executed") self._check_import_error(["-m", "test_pkg"], msg, cwd=script_dir) - @requires_zlib def test_issue8202(self): # Make sure package __init__ modules see "-m" in sys.argv0 while # searching for the module to execute @@ -434,7 +415,6 @@ def test_issue8202_dash_c_file_ignored(self): expected = "sys.path[0]==%r" % '' self.assertIn(expected.encode('utf-8'), out) - @requires_zlib def test_issue8202_dash_m_file_ignored(self): # Make sure a "-m" file in the current directory # does not alter the value of sys.path[0] @@ -481,7 +461,6 @@ def check_dash_m_failure(self, *args): self.assertEqual(rc, 1) return err - @requires_zlib def test_dash_m_error_code_is_one(self): # If a module is invoked with the -m command line flag # and results in an error that the return code to the @@ -536,7 +515,6 @@ def test_hint_when_triying_to_import_a_py_file(self): self.assertIn(b"Try using 'asyncio' instead " b"of 'asyncio.py' as the module name", err) - @requires_zlib def test_dash_m_init_traceback(self): # These were wrapped in an ImportError and tracebacks were # suppressed; see Issue 14285 @@ -561,7 +539,6 @@ def test_dash_m_main_traceback(self): self.assertIn(b'Exception in __main__ module', err) self.assertIn(b'Traceback', err) - @requires_zlib def test_pep_409_verbiage(self): # Make sure PEP 409 syntax properly suppresses # the context of an exception @@ -580,7 +557,6 @@ def test_pep_409_verbiage(self): self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) - @requires_zlib def test_non_ascii(self): # Apple platforms deny the creation of a file with an invalid UTF-8 name. # Windows allows creating a name with an arbitrary bytes name, but @@ -610,7 +586,6 @@ def test_non_ascii(self): 'stdout=%r stderr=%r' % (stdout, stderr)) self.assertEqual(0, rc) - @requires_zlib def test_issue20500_exit_with_exception_value(self): script = textwrap.dedent("""\ import sys @@ -629,7 +604,6 @@ def test_issue20500_exit_with_exception_value(self): text = stderr.decode('ascii') self.assertEqual(text.rstrip(), "some text") - @requires_zlib def test_syntaxerror_unindented_caret_position(self): script = "1 + 1 = 2\n" with os_helper.temp_dir() as script_dir: @@ -639,7 +613,6 @@ def test_syntaxerror_unindented_caret_position(self): # Confirm that the caret is located under the '=' sign self.assertIn("\n ^^^^^\n", text) - @requires_zlib def test_syntaxerror_indented_caret_position(self): script = textwrap.dedent("""\ if True: @@ -663,7 +636,6 @@ def test_syntaxerror_indented_caret_position(self): self.assertNotIn("\f", text) self.assertIn("\n 1 + 1 = 2\n ^^^^^\n", text) - @requires_zlib def test_syntaxerror_multi_line_fstring(self): script = 'foo = f"""{}\nfoo"""\n' with os_helper.temp_dir() as script_dir: @@ -678,7 +650,6 @@ def test_syntaxerror_multi_line_fstring(self): ], ) - @requires_zlib def test_syntaxerror_invalid_escape_sequence_multi_line(self): script = 'foo = """\\q"""\n' with os_helper.temp_dir() as script_dir: @@ -695,7 +666,6 @@ def test_syntaxerror_invalid_escape_sequence_multi_line(self): ], ) - @requires_zlib def test_syntaxerror_null_bytes(self): script = "x = '\0' nothing to see here\n';import os;os.system('echo pwnd')\n" with os_helper.temp_dir() as script_dir: @@ -708,7 +678,6 @@ def test_syntaxerror_null_bytes(self): ], ) - @requires_zlib def test_syntaxerror_null_bytes_in_multiline_string(self): scripts = ["\n'''\nmultilinestring\0\n'''", "\nf'''\nmultilinestring\0\n'''"] # Both normal and f-strings with os_helper.temp_dir() as script_dir: @@ -732,7 +701,6 @@ def test_source_lines_are_shown_when_running_source(self): b'ZeroDivisionError: division by zero'] self.assertEqual(stderr.splitlines(), expected_lines) - @requires_zlib def test_syntaxerror_does_not_crash(self): script = "nonlocal x\n" with os_helper.temp_dir() as script_dir: @@ -744,7 +712,6 @@ def test_syntaxerror_does_not_crash(self): 'SyntaxError: nonlocal declaration not allowed at module level\n', ), text) - @requires_zlib def test_consistent_sys_path_for_direct_execution(self): # This test case ensures that the following all give the same # sys.path configuration: @@ -776,7 +743,6 @@ def test_consistent_sys_path_for_direct_execution(self): out_by_dir_isolated = kill_python(p).decode().splitlines() self.assertEqual(out_by_dir_isolated, out_by_dir, out_by_name) - @requires_zlib def test_consistent_sys_path_for_module_execution(self): # This test case ensures that the following both give the same # sys.path configuration: diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py index 672838a665535a..6d3c91b0b6d9f9 100644 --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -11,8 +11,6 @@ import ensurepip import ensurepip._uninstall -if sys.platform == "wasm": - unittest.skip("zlib unavailable") class TestPackages(unittest.TestCase): def touch(self, directory, filename): diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py index 6cb2a6f991e6bc..582e5b6de6e687 100644 --- a/Lib/test/test_eof.py +++ b/Lib/test/test_eof.py @@ -6,7 +6,6 @@ from test.support import os_helper from test.support import script_helper from test.support import warnings_helper -from test.support import requires_zlib import unittest class EOFTestCase(unittest.TestCase): @@ -46,7 +45,6 @@ def test_EOFS(self): self.assertEqual(cm.exception.offset, 5) @force_not_colorized - @requires_zlib def test_EOFS_with_file(self): expect = ("(, line 1)") with os_helper.temp_dir() as temp_dir: diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 4e676fad615d10..b5140057a69d36 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -8,7 +8,7 @@ from test.support.import_helper import import_module from test.support.os_helper import temp_dir, TESTFN, unlink from test.support.script_helper import assert_python_ok, make_script -from test.support import threading_helper, gc_threshold, requires_zlib +from test.support import threading_helper, gc_threshold import gc import sys @@ -752,7 +752,6 @@ def __del__(self): rc, out, err = assert_python_ok('-c', code) self.assertEqual(out.strip(), b'__del__ called') - @requires_zlib def test_gc_ordinary_module_at_shutdown(self): # Same as above, but with a non-__main__ module. with temp_dir() as script_dir: diff --git a/Lib/test/test_importlib/__init__.py b/Lib/test/test_importlib/__init__.py index 03256c3c3dd9fe..4b16ecc31156a5 100644 --- a/Lib/test/test_importlib/__init__.py +++ b/Lib/test/test_importlib/__init__.py @@ -1,9 +1,5 @@ import os -import sys from test.support import load_package_tests -if sys.platform == "wasm": - unittest.skip("zlib unavailable") - def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 61bebf1042b121..06785e275f6b11 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -35,7 +35,7 @@ except ImportError: ThreadPoolExecutor = None -from test.support import cpython_only, import_helper, requires_zlib +from test.support import cpython_only, import_helper from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ from test.support import run_no_yield_async_fn from test.support.import_helper import DirsOnSysPath, ready_to_import @@ -6049,7 +6049,6 @@ def assertInspectEqual(self, path, source): inspected_src.splitlines(True) ) - @requires_zlib def test_getsource_reload(self): # see issue 1218234 with ready_to_import('reload_bug', self.src_before) as (name, path): diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py index 14a7c813448ddc..b64e684f80599f 100644 --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -350,47 +350,36 @@ def _do_test(self, info, report=False, debug=0, replace_paths=[], modulefinder_c self.assertEqual(bad, missing) self.assertEqual(maybe, maybe_missing) - @support.requires_zlib() def test_package(self): self._do_test(package_test) - @support.requires_zlib() def test_maybe(self): self._do_test(maybe_test) - @support.requires_zlib() def test_maybe_new(self): self._do_test(maybe_test_new) - @support.requires_zlib() def test_absolute_imports(self): self._do_test(absolute_import_test) - @support.requires_zlib() def test_relative_imports(self): self._do_test(relative_import_test) - @support.requires_zlib() def test_relative_imports_2(self): self._do_test(relative_import_test_2) - @support.requires_zlib() def test_relative_imports_3(self): self._do_test(relative_import_test_3) - @support.requires_zlib() def test_relative_imports_4(self): self._do_test(relative_import_test_4) - @support.requires_zlib() def test_syntax_error(self): self._do_test(syntax_error_test) - @support.requires_zlib() def test_same_name_as_bad(self): self._do_test(same_name_as_bad_test) - @support.requires_zlib() def test_bytecode(self): base_path = os.path.join(self.test_dir, 'a') source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0] @@ -401,7 +390,6 @@ def test_bytecode(self): os.remove(source_path) self._do_test(bytecode_test) - @support.requires_zlib() def test_replace_paths(self): old_path = os.path.join(self.test_dir, 'a', 'module.py') new_path = os.path.join(self.test_dir, 'a', 'spam.py') @@ -412,7 +400,6 @@ def test_replace_paths(self): expected = "co_filename %r changed to %r" % (old_path, new_path) self.assertIn(expected, output) - @support.requires_zlib() def test_extended_opargs(self): extended_opargs_test = [ "a", @@ -426,19 +413,15 @@ def test_extended_opargs(self): """ % list(range(2**16))] # 2**16 constants self._do_test(extended_opargs_test) - @support.requires_zlib() def test_coding_default_utf8(self): self._do_test(coding_default_utf8_test) - @support.requires_zlib() def test_coding_explicit_utf8(self): self._do_test(coding_explicit_utf8_test) - @support.requires_zlib() def test_coding_explicit_cp1252(self): self._do_test(coding_explicit_cp1252_test) - @support.requires_zlib() def test_load_module_api(self): class CheckLoadModuleApi(modulefinder.ModuleFinder): def __init__(self, *args, **kwds): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 88216aa8599c71..fa439c1fe8915c 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -10,6 +10,7 @@ import subprocess import textwrap import linecache +import zipapp from contextlib import ExitStack, redirect_stdout from io import StringIO @@ -19,11 +20,6 @@ from test.support.pty_helper import run_pty, FakeInput from unittest.mock import patch -if sys.platform == "wasm": - unittest.skip("zlib unavailable") - -import zipapp - SKIP_CORO_TESTS = False diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 2d14578280a900..736b83711def03 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -9,17 +9,13 @@ import os import os.path import tempfile +import shutil +import zipfile from test.support.import_helper import DirsOnSysPath from test.support.os_helper import FakePath from test.test_importlib.util import uncache -if sys.platform == "wasm": - unittest.skip("Zlib unavailable") - -import shutil -import zipfile - # Note: pkgutil.walk_packages is currently tested in test_runpy. This is # a hack to get a major issue resolved for 3.3b2. Longer term, it should # be moved back here, perhaps by factoring out the helper code for diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 461bb8e3f5c618..0abd36c5e076e2 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -34,7 +34,7 @@ from test.support import threading_helper from test.support import (reap_children, captured_stdout, captured_stderr, is_emscripten, is_wasi, - requires_docstrings, MISSING_C_DOCSTRINGS, requires_zlib) + requires_docstrings, MISSING_C_DOCSTRINGS) from test.support.os_helper import (TESTFN, rmtree, unlink) from test.test_pydoc import pydoc_mod from test.test_pydoc import pydocfodder @@ -1251,7 +1251,6 @@ def setUp(self): self.addCleanup(rmtree, TESTFN) importlib.invalidate_caches() - @requires_zlib def test_badimport(self): # This tests the fix for issue 5230, where if pydoc found the module # but the module had an internal import error pydoc would report no doc @@ -1273,7 +1272,6 @@ def test_badimport(self): expected = badimport_pattern % (modname, expectedinmsg) self.assertEqual(expected, result) - @requires_zlib def test_apropos_with_bad_package(self): # Issue 7425 - pydoc -k failed when bad package on path pkgdir = os.path.join(TESTFN, "syntaxerr") @@ -1295,7 +1293,6 @@ def test_apropos_with_bad_package(self): self.assertEqual(out.getvalue().strip(), 'syntaxerr') self.assertEqual(err.getvalue(), '') - @requires_zlib def test_apropos_with_unreadable_dir(self): # Issue 7367 - pydoc -k failed when unreadable dir on path self.unreadable_dir = os.path.join(TESTFN, "unreadable") @@ -1328,7 +1325,6 @@ def test_apropos_empty_doc(self): finally: os.chmod(pkgdir, current_mode) - @requires_zlib def test_url_search_package_error(self): # URL handler search should cope with packages that raise exceptions pkgdir = os.path.join(TESTFN, "test_error_package") @@ -1394,7 +1390,6 @@ def test_modules_search_builtin(self): self.assertTrue(result.startswith(expected)) - @requires_zlib def test_importfile(self): try: loaded_pydoc = pydoc.importfile(pydoc.__file__) diff --git a/Lib/test/test_reprlib.py b/Lib/test/test_reprlib.py index 560af94b898e36..ffeb1fba7b80c6 100644 --- a/Lib/test/test_reprlib.py +++ b/Lib/test/test_reprlib.py @@ -11,14 +11,12 @@ import unittest import textwrap -from test.support import verbose, requires_zlib +from test.support import verbose from test.support.os_helper import create_empty_file from reprlib import repr as r # Don't shadow builtin repr from reprlib import Repr from reprlib import recursive_repr -from Lib.test.support import requires_zlib - def nestedTuple(nesting): t = () @@ -683,7 +681,6 @@ def _check_path_limitations(self, module_name): elif os.name == 'nt' and verbose: print("cached_path_len =", cached_path_len) - @requires_zlib def test_module(self): self.maxDiff = None self._check_path_limitations(self.pkgname) @@ -694,7 +691,6 @@ def test_module(self): self.assertEqual(repr(module), "" % (module.__name__, module.__file__)) self.assertEqual(repr(sys), "") - @requires_zlib def test_type(self): self._check_path_limitations('foo') eq = self.assertEqual @@ -713,7 +709,6 @@ def test_object(self): # tp_repr. WIBNI we had ::Inline? :) pass - @requires_zlib def test_class(self): self._check_path_limitations('bar') write_file(os.path.join(self.subpkgname, 'bar.py'), '''\ @@ -725,7 +720,6 @@ class bar: # Module name may be prefixed with "test.", depending on how run. self.assertEqual(repr(bar.bar), "" % bar.__name__) - @requires_zlib def test_instance(self): self._check_path_limitations('baz') write_file(os.path.join(self.subpkgname, 'baz.py'), '''\ @@ -738,7 +732,6 @@ class baz: self.assertTrue(repr(ibaz).startswith( "<%s.baz object at 0x" % baz.__name__)) - @requires_zlib def test_method(self): self._check_path_limitations('qux') eq = self.assertEqual diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py index 9a55fb3c0c1869..ada78ec8e6b0c7 100644 --- a/Lib/test/test_runpy.py +++ b/Lib/test/test_runpy.py @@ -19,7 +19,6 @@ requires_resource, requires_subprocess, verbose, - requires_zlib, ) from test.support.import_helper import forget, make_legacy_pyc, unload from test.support.os_helper import create_empty_file, temp_dir, FakePath @@ -438,19 +437,16 @@ def _check_relative_imports(self, depth, run_name=None): self._del_pkg(pkg_dir) if verbose > 1: print("Module executed successfully") - @requires_zlib def test_run_module(self): for depth in range(4): if verbose > 1: print("Testing package depth:", depth) self._check_module(depth) - @requires_zlib def test_run_module_in_namespace_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) self._check_module(depth, namespace=True, parent_namespaces=True) - @requires_zlib def test_run_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) @@ -509,7 +505,6 @@ def test_package_imported_no_warning(self): with self.assertWarnsRegex(RuntimeWarning, r"found in sys\.modules"): run_module(package) - @requires_zlib def test_run_package_in_namespace_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) @@ -520,31 +515,26 @@ def test_run_namespace_package(self): if verbose > 1: print("Testing package depth:", depth) self._check_package(depth, namespace=True) - @requires_zlib def test_run_namespace_package_in_namespace_package(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) self._check_package(depth, namespace=True, parent_namespaces=True) - @requires_zlib def test_run_module_alter_sys(self): for depth in range(4): if verbose > 1: print("Testing package depth:", depth) self._check_module(depth, alter_sys=True) - @requires_zlib def test_run_package_alter_sys(self): for depth in range(1, 4): if verbose > 1: print("Testing package depth:", depth) self._check_package(depth, alter_sys=True) - @requires_zlib def test_explicit_relative_import(self): for depth in range(2, 5): if verbose > 1: print("Testing relative imports at depth:", depth) self._check_relative_imports(depth) - @requires_zlib def test_main_relative_import(self): for depth in range(2, 5): if verbose > 1: print("Testing main relative imports at depth:", depth) @@ -666,7 +656,6 @@ def _check_import_error(self, script_name, msg): msg = re.escape(msg) self.assertRaisesRegex(ImportError, msg, run_path, script_name) - @requires_zlib def test_basic_script(self): with temp_dir() as script_dir: mod_name = 'script' @@ -674,7 +663,6 @@ def test_basic_script(self): self._check_script(script_name, "", script_name, script_name, expect_spec=False) - @requires_zlib def test_basic_script_with_pathlike_object(self): with temp_dir() as script_dir: mod_name = 'script' @@ -684,7 +672,6 @@ def test_basic_script_with_pathlike_object(self): script_name, expect_spec=False) - @requires_zlib def test_basic_script_no_suffix(self): with temp_dir() as script_dir: mod_name = 'script' @@ -702,7 +689,6 @@ def test_script_compiled(self): self._check_script(compiled_name, "", compiled_name, compiled_name, expect_spec=False) - @requires_zlib def test_directory(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -710,7 +696,6 @@ def test_directory(self): self._check_script(script_dir, "", script_name, script_dir, mod_name=mod_name) - @requires_zlib def test_directory_compiled(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -722,7 +707,6 @@ def test_directory_compiled(self): self._check_script(script_dir, "", legacy_pyc, script_dir, mod_name=mod_name) - @requires_zlib def test_directory_error(self): with temp_dir() as script_dir: mod_name = 'not_main' @@ -730,7 +714,6 @@ def test_directory_error(self): msg = "can't find '__main__' module in %r" % script_dir self._check_import_error(script_dir, msg) - @requires_zlib def test_zipfile(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -739,7 +722,6 @@ def test_zipfile(self): self._check_script(zip_name, "", fname, zip_name, mod_name=mod_name, check_loader=False) - @requires_zlib def test_zipfile_compiled(self): with temp_dir() as script_dir: mod_name = '__main__' @@ -750,7 +732,6 @@ def test_zipfile_compiled(self): self._check_script(zip_name, "", fname, zip_name, mod_name=mod_name, check_loader=False) - @requires_zlib def test_zipfile_error(self): with temp_dir() as script_dir: mod_name = 'not_main' diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index afff0cb981d3ef..078ddd6c431b37 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -2,13 +2,9 @@ import unittest import unittest.mock -import sys - -if sys.platform == "wasm": - unittest.skip("zlib unavailable") - import shutil import tempfile +import sys import stat import os import os.path diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 60873c6fdd9838..61b00778f8361c 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- import unittest -from test.support import script_helper, captured_stdout, requires_subprocess, requires_resource, requires_zlib +from test.support import script_helper, captured_stdout, requires_subprocess, requires_resource from test.support.os_helper import TESTFN, unlink, rmtree from test.support.import_helper import unload import importlib @@ -114,7 +114,6 @@ def test_exec_valid_coding(self): exec(b'# coding: cp949\na = "\xaa\xa7"\n', d) self.assertEqual(d['a'], '\u3047') - @requires_zlib def test_file_parse(self): # issue1134: all encodings outside latin-1 and utf-8 fail on # multiline strings and long lines (>512 columns) diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index 4911eb1e9f44a4..5cef612a340be9 100644 --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -6,7 +6,7 @@ import threading import unittest from unittest.mock import patch -from test.support import import_helper, threading_helper, requires_zlib +from test.support import import_helper, threading_helper class A: @@ -342,7 +342,6 @@ def test_super_argtype(self): with self.assertRaisesRegex(TypeError, "argument 1 must be a type"): super(1, int) - @requires_zlib def test_shadowed_global(self): source = textwrap.dedent( """ diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 7938b959c07bf3..d900db546ada8d 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -20,7 +20,6 @@ from test.support import script_helper from test.support import socket_helper from test.support import warnings_helper -from test.support import requires_zlib TESTFN = os_helper.TESTFN @@ -108,7 +107,6 @@ def test_rmtree(self): os_helper.rmtree(dirpath) self.assertFalse(os.path.exists(dirpath)) - @requires_zlib def test_forget(self): mod_filename = TESTFN + '.py' with open(mod_filename, 'w', encoding="utf-8") as f: diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 3fa541da899fc2..52d3341975088b 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -9,7 +9,7 @@ from test import support from test.test_grammar import (VALID_UNDERSCORE_LITERALS, INVALID_UNDERSCORE_LITERALS) -from test.support import os_helper, requires_zlib +from test.support import os_helper from test.support.script_helper import run_test_script, make_script, run_python_until_end # Converts a source string into a list of textual representation @@ -3162,7 +3162,7 @@ def fib(n): self.assertEqual(get_tokens(code), get_tokens(code_no_cont)) -@requires_zlib() + class CTokenizerBufferTests(unittest.TestCase): def test_newline_at_the_end_of_buffer(self): # See issue 99581: Make sure that if we need to add a new line at the diff --git a/Lib/test/test_zipapp.py b/Lib/test/test_zipapp.py index dad3682dde0e2c..00a5ed6626ddc5 100644 --- a/Lib/test/test_zipapp.py +++ b/Lib/test/test_zipapp.py @@ -6,10 +6,6 @@ import sys import tempfile import unittest - -if sys.platform == "wasm": - unittest.skip("zlib unavailable") - import zipapp import zipfile from test.support import requires_zlib diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 7a9c76f9849270..1f288c8b45d589 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -15,9 +15,6 @@ from test.support import import_helper from test.support import os_helper -if sys.platform == "wasm": - unittest.skip("zlib unavailable") - from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED import zipimport @@ -26,8 +23,10 @@ import inspect import io from traceback import extract_tb, extract_stack, print_tb -import zlib - +try: + import zlib +except ImportError: + zlib = None test_src = """\ def get_name(): diff --git a/Lib/test/test_zoneinfo/__init__.py b/Lib/test/test_zoneinfo/__init__.py index 03256c3c3dd9fe..4b16ecc31156a5 100644 --- a/Lib/test/test_zoneinfo/__init__.py +++ b/Lib/test/test_zoneinfo/__init__.py @@ -1,9 +1,5 @@ import os -import sys from test.support import load_package_tests -if sys.platform == "wasm": - unittest.skip("zlib unavailable") - def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) From 6b636892993a21707f2a2fdf70495508982e769f Mon Sep 17 00:00:00 2001 From: stan Date: Wed, 19 Feb 2025 13:54:24 +0000 Subject: [PATCH 08/14] Fix tests --- Lib/zipfile/__init__.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index c8b5bcdc05d179..ac5c4d980d5413 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -14,8 +14,12 @@ import threading import time -import zlib -crc32 = zlib.crc32 +try: + import zlib + crc32 = zlib.crc32 +except ImportError: + zlib = None + crc32 = binascii.crc32 try: import bz2 # We may need its compression method @@ -767,8 +771,12 @@ def decompress(self, data): } def _check_compression(compression): - if compression in (ZIP_STORED, ZIP_DEFLATED): + if compression == ZIP_STORED: pass + elif compression == ZIP_DEFLATED: + if not zlib: + raise RuntimeError( + "Compression requires the (missing) zlib module") elif compression == ZIP_BZIP2: if not bz2: raise RuntimeError( From c62bf24de7aef89f6dc1667d963359fb7b0ead2c Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:08:04 +0000 Subject: [PATCH 09/14] Apply suggestions from Petr Co-authored-by: Petr Viktorin --- Doc/whatsnew/3.14.rst | 2 +- configure.ac | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 4e7ef3293b6ad1..3aee7604072c8b 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1314,7 +1314,7 @@ Build changes It is still technically possible to build CPython without it for special needs, like bootstrapping. Such builds are not supported, but we can accept pull requests to keep them working. As an exception, zlib is not required on WASI. - (Contributed by Stan Ulbrych in :gh:`130297`.) + (Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`91246`.) .. _whatsnew314-pep761: diff --git a/configure.ac b/configure.ac index c803bf9e9f530c..a931e52f52cfc4 100644 --- a/configure.ac +++ b/configure.ac @@ -5350,9 +5350,12 @@ AS_CASE([$ac_sys_system], ], [*], [ if test "$have_zlib" != "yes"; then - AC_MSG_ERROR([m4_normalize([ - zlib.h and libz are required. Install your OS's zlib-devel or - zlib1g-dev equivalent library or get it from https://zlib.net/. + AC_MSG_WARN([m4_normalize([ + zlib (zlib.h and libz) was not found. Building CPython + without zlib is not supported, although it might work + for limited use cases. + Install your OS's zlib-devel or zlib1g-dev equivalent + library or get it from https://zlib.net/. ])]) fi BINASCII_CFLAGS="$ZLIB_CFLAGS" From 4300d9e0b54ff206be0d94ade22b975a91ba480e Mon Sep 17 00:00:00 2001 From: stan Date: Thu, 20 Feb 2025 15:33:39 +0000 Subject: [PATCH 10/14] Update configure --- configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 5dc67de0db5354..6e06be6b029b50 100755 --- a/configure +++ b/configure @@ -21819,7 +21819,8 @@ case $ac_sys_system in #( *) : if test "$have_zlib" != "yes"; then - as_fn_error $? "zlib.h and libz are required. Install your OS's zlib-devel or zlib1g-dev equivalent library or get it from https://zlib.net/." "$LINENO" 5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: zlib (zlib.h and libz) was not found. Building CPython without zlib is not supported, although it might work for limited use cases. Install your OS's zlib-devel or zlib1g-dev equivalent library or get it from https://zlib.net/." >&5 +printf "%s\n" "$as_me: WARNING: zlib (zlib.h and libz) was not found. Building CPython without zlib is not supported, although it might work for limited use cases. Install your OS's zlib-devel or zlib1g-dev equivalent library or get it from https://zlib.net/." >&2;} fi BINASCII_CFLAGS="$ZLIB_CFLAGS" BINASCII_LIBS="$ZLIB_LIBS" From 490349147d08a51ab5442c88b16c8aefb317c69e Mon Sep 17 00:00:00 2001 From: stan Date: Sun, 23 Feb 2025 18:45:58 +0000 Subject: [PATCH 11/14] Adjust docs and @requires_zlib --- Doc/library/shutil.rst | 12 +++++------- Doc/library/test.rst | 7 ++++++- Doc/library/zlib.rst | 7 ++----- Doc/using/configure.rst | 9 ++++++++- Lib/test/support/__init__.py | 8 ++------ 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 1819f708890c09..4c481bc8025d7f 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -601,8 +601,7 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. any format-specific extension. *format* is the archive format: one of - "zip" (if the :mod:`zlib` module is available), "tar", "gztar" (if the - :mod:`zlib` module is available), "bztar" (if the :mod:`bz2` module is + "zip", "tar", "gztar", "bztar" (if the :mod:`bz2` module is available), or "xztar" (if the :mod:`lzma` module is available). *root_dir* is a directory that will be the root directory of the @@ -653,9 +652,9 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. By default :mod:`shutil` provides these formats: - - *zip*: ZIP file (if the :mod:`zlib` module is available). + - *zip*: ZIP file. - *tar*: Uncompressed tar file. Uses POSIX.1-2001 pax format for new archives. - - *gztar*: gzip'ed tar-file (if the :mod:`zlib` module is available). + - *gztar*: gzip'ed tar-file. - *bztar*: bzip2'ed tar-file (if the :mod:`bz2` module is available). - *xztar*: xz'ed tar-file (if the :mod:`lzma` module is available). @@ -768,10 +767,9 @@ provided. They rely on the :mod:`zipfile` and :mod:`tarfile` modules. By default :mod:`shutil` provides these formats: - - *zip*: ZIP file (unpacking compressed files works only if the corresponding - module is available). + - *zip*: ZIP file. - *tar*: uncompressed tar file. - - *gztar*: gzip'ed tar-file (if the :mod:`zlib` module is available). + - *gztar*: gzip'ed tar-file. - *bztar*: bzip2'ed tar-file (if the :mod:`bz2` module is available). - *xztar*: xz'ed tar-file (if the :mod:`lzma` module is available). diff --git a/Doc/library/test.rst b/Doc/library/test.rst index def22f8bb8ab2d..2e89944bff8442 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -748,7 +748,12 @@ The :mod:`test.support` module defines the following functions: .. decorator:: requires_zlib - Decorator for skipping tests if :mod:`zlib` doesn't exist. + Decorator for skipping tests if running on WASI as :mod:`zlib` is + unsupported. + +.. versionchanged:: next + Test is skipped only if it is running on WASI as builds without :mod:`zlib` on + other systems are unsupported. .. decorator:: requires_gzip diff --git a/Doc/library/zlib.rst b/Doc/library/zlib.rst index 965b82a3daffb9..e057ab16854168 100644 --- a/Doc/library/zlib.rst +++ b/Doc/library/zlib.rst @@ -9,14 +9,11 @@ For applications that require data compression, the functions in this module allow compression and decompression, using the zlib library. The zlib library -has its own home page at https://www.zlib.net. There are known -incompatibilities between the Python module and versions of the zlib library -earlier than 1.1.3; 1.1.3 has a `security vulnerability `_, so we recommend using -1.1.4 or later. +has its own `home page `_. zlib's functions have many options and often need to be used in a particular order. This documentation doesn't attempt to cover all of the permutations; -consult the zlib manual at http://www.zlib.net/manual.html for authoritative +consult the `zlib manual `_ for authoritative information. For reading and writing ``.gz`` files see the :mod:`gzip` module. diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 72912cea2f0c28..b2b85ef609dbdf 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -32,6 +32,10 @@ Features and minimum versions required to build CPython: * Autoconf 2.72 and aclocal 1.16.5 are required to regenerate the :file:`configure` script. +* `zlib `_ 1.1.3 is the minium version and 1.1.4 is recommended due to + a ` security vulnerability `_ for the :mod:`zlib` + extension module. + .. versionchanged:: 3.1 Tcl/Tk version 8.3.1 is now required. @@ -61,6 +65,9 @@ Features and minimum versions required to build CPython: .. versionchanged:: 3.14 Autoconf 2.72 is now required. +.. versionchanged:: next + zlib 1.1.3 is now required. + See also :pep:`7` "Style Guide for C Code" and :pep:`11` "CPython platform support". @@ -454,7 +461,7 @@ Options for third-party dependencies .. option:: ZLIB_CFLAGS .. option:: ZLIB_LIBS - C compiler and linker flags for ``libzlib``, used by :mod:`gzip` module, + C compiler and linker flags for ``libzlib``, used by the :mod:`zlib` module, overriding ``pkg-config``. diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index f31d98bf731d67..b57ae5ac74aaaa 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -493,12 +493,8 @@ def dec(*args, **kwargs): float.__getformat__("double").startswith("IEEE"), "test requires IEEE 754 doubles") -def requires_zlib(reason='requires zlib'): - try: - import zlib - except ImportError: - zlib = None - return unittest.skipUnless(zlib, reason) +def requires_zlib(reason): + return unittest.skipIf(sys.platform == "wasi", "zlib is unsupported on WASI") def requires_gzip(reason='requires gzip'): try: From a1b931ff7899adaca100f015e8170166b4bc5c64 Mon Sep 17 00:00:00 2001 From: stan Date: Sun, 23 Feb 2025 19:04:23 +0000 Subject: [PATCH 12/14] Remove extra space --- Doc/using/configure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index b2b85ef609dbdf..c82aa6f5fa050a 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -33,7 +33,7 @@ Features and minimum versions required to build CPython: :file:`configure` script. * `zlib `_ 1.1.3 is the minium version and 1.1.4 is recommended due to - a ` security vulnerability `_ for the :mod:`zlib` + a `security vulnerability `_ for the :mod:`zlib` extension module. .. versionchanged:: 3.1 From 1513e9f865bb2747451c2b1dbd5e6caac4fb631a Mon Sep 17 00:00:00 2001 From: stan Date: Sun, 23 Feb 2025 19:07:09 +0000 Subject: [PATCH 13/14] Fix @requires_zlib --- Lib/test/support/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index b57ae5ac74aaaa..4f7e21afa409ee 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -493,8 +493,8 @@ def dec(*args, **kwargs): float.__getformat__("double").startswith("IEEE"), "test requires IEEE 754 doubles") -def requires_zlib(reason): - return unittest.skipIf(sys.platform == "wasi", "zlib is unsupported on WASI") +def requires_zlib(reason='zlib is unsupported on WASI'): + return unittest.skipIf(sys.platform == "wasi", reason) def requires_gzip(reason='requires gzip'): try: From d735769374d3ded27d0387112cc3a747c34cf0c2 Mon Sep 17 00:00:00 2001 From: stan Date: Mon, 24 Feb 2025 18:03:45 +0000 Subject: [PATCH 14/14] Adam's suggestions --- Doc/whatsnew/3.14.rst | 6 ++---- Lib/shutil.py | 7 +++---- Lib/test/test_zlib.py | 3 +-- .../Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst | 4 ++-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 3aee7604072c8b..883695bd6a3d1a 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1310,10 +1310,8 @@ Build changes * GNU Autoconf 2.72 is now required to generate :file:`configure`. (Contributed by Erlend Aasland in :gh:`115765`.) -* zlib is now officially required to build CPython. - It is still technically possible to build CPython without it for special needs, like bootstrapping. - Such builds are not supported, but we can accept pull requests to keep them working. - As an exception, zlib is not required on WASI. +* zlib is now required to build CPytho on all platforms except WASI. + For more information see :pep:`775`. (Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`91246`.) .. _whatsnew314-pep761: diff --git a/Lib/shutil.py b/Lib/shutil.py index 090325647cc328..4037c75c89fa2a 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1113,12 +1113,11 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, _ARCHIVE_FORMATS = { 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), + 'gztar': (_make_tarball, [('compress', 'gzip')], + "gzip'ed tar-file"), + 'zip': (_make_zipfile, [], "ZIP file") } -_ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')], - "gzip'ed tar-file") -_ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file") - if _BZ2_SUPPORTED: _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file") diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index b8f35c59bedaa4..307438bd45192e 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -1,13 +1,12 @@ import unittest from test import support -from test.support import import_helper import binascii import copy import pickle import random import sys -from test.support import bigmemtest, _1G, _4G, is_s390x import importlib +from test.support import bigmemtest, _1G, _4G, is_s390x # Building CPython without zlib is not supported except WASI. # diff --git a/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst b/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst index c6868c15903aef..a75a823a5d43c7 100644 --- a/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst +++ b/Misc/NEWS.d/next/Build/2025-02-19-00-00-00.gh-issue-91246.ahsgd3.rst @@ -1,2 +1,2 @@ -Make zlib required to build CPython with the exception of WASI. -(Contributed by Stan Ulbrych in :gh:`130297`.) +Make zlib required to build CPython with the exception of WASI implementing :pep:`775`. +(Contributed by Stan Ulbrych and Gregory P. Smith in :gh:`130297`.)