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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:`130297`.)

.. _whatsnew314-pep761:

PEP 761: Discontinuation of PGP signatures
Expand Down
2 changes: 1 addition & 1 deletion Lib/encodings/zlib_codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""

import codecs
import zlib # this codec needs the optional zlib module !
import zlib

### Codec APIs

Expand Down
20 changes: 5 additions & 15 deletions Lib/shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@
import collections
import errno

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

try:
import bz2
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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')],
Expand Down Expand Up @@ -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")
Expand Down
16 changes: 5 additions & 11 deletions Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down Expand Up @@ -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

Expand Down
17 changes: 15 additions & 2 deletions Lib/test/test_zlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,22 @@
import random
import sys
from test.support import bigmemtest, _1G, _4G, is_s390x
import importlib
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep imports sorted

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are all technically "Standard library imports"...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment was about alphabetically sorted, your reply about grouped by type 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry but where in PEP 8 is that specified, I cannot seem to find any mention of it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s a very common practice. But another one is to always import os and sys at the top.
Yet another is to sort by module length to get a nice pyramid drawing 📐



zlib = import_helper.import_module('zlib')
# 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.

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"),
Expand Down
14 changes: 3 additions & 11 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
7 changes: 1 addition & 6 deletions Lib/zipimport.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Make zlib required to build CPython with the exception of WASI.
(Contributed by Stan Ulbrych in :gh:`130297`.)
16 changes: 9 additions & 7 deletions Modules/binascii.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
**********************************************************************|
Expand Down Expand Up @@ -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
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
4 changes: 1 addition & 3 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -457,9 +457,7 @@
<ClCompile Include="..\Modules\_weakref.c" />
<ClCompile Include="..\Modules\arraymodule.c" />
<ClCompile Include="..\Modules\atexitmodule.c" />
<ClCompile Include="..\Modules\binascii.c">
<PreprocessorDefinitions>USE_ZLIB_CRC32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\Modules\binascii.c" />
<ClCompile Include="..\Modules\cmathmodule.c" />
<ClCompile Include="..\Modules\_datetimemodule.c" />
<ClCompile Include="..\Modules\errnomodule.c" />
Expand Down
36 changes: 16 additions & 20 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 18 additions & 11 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5323,14 +5323,10 @@ 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])

dnl detect zlib from Emscripten emport
PY_CHECK_EMSCRIPTEN_PORT([ZLIB], [-sUSE_ZLIB])
AH_TEMPLATE([HAVE_ZLIB_COPY], [Define if the zlib library has inflateCopy; zlib 1.2.0 (2003) added inflateCopy.])

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([
Expand All @@ -5346,12 +5342,23 @@ PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.0], [
])
])
])

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 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])
Expand Down
3 changes: 2 additions & 1 deletion pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 <zlib.h> header file. */
Expand Down
Loading