Skip to content

Commit

Permalink
Merge pull request #41 from itziakos/remove-py2-support
Browse files Browse the repository at this point in the history
Drop python < 3.8 and support 3.12
  • Loading branch information
itziakos authored Sep 28, 2024
2 parents 031853b + a1f5a86 commit 8823f72
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 275 deletions.
6 changes: 6 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
include LICENSE
include CHANGELOG
include *.rst
include *.txt
include *.cfg
recursive-include docs *.bat *.py *.rst
include docs/Makefile
3 changes: 1 addition & 2 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
zipfile2 contains an improved ZipFile class that may be used as a 100 %
zipfile2 contains an improved ZipFile class that may be used as a
backward compatible replacement.

Improvements compared to upstream zipfile stdlib:

* Handling of symlinks (read and write)
* Compatible 2.6 onwards (including 3.x), include context manager
* Raises an exception by default when duplicate members are detected.
* Special class `LeanZipFile` to avoid using too much memory when handling
zip files with a large number of members. Contrary to the stdlib
Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.0.dev
25 changes: 25 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[metadata]
name = zipfile2
version = file: VERSION
url = https://github.com/itziakos/zipfile2
author = Ioannis Tziakos
author_email = itziakos@gmail.com
description = An improved ZipFile class that may be used as a backward compatible replacement.
long_description = file: README.rst, CHANGELOG.txt
license = BSD-3-Clause
license_files = file: LICENSE
classifier =
Programming Language :: Python :: 3
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12

[options]
zip_safe = False
packages = find:
python_requires = >=3.8

[options.packages.find]
exclude = docs*
121 changes: 6 additions & 115 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,118 +1,9 @@
import os
import subprocess

from pathlib import Path
from setuptools import setup

HERE = Path(__file__).parent
version = (HERE / 'VERSION').read_text().strip()
filename = (HERE / 'zipfile2' / '_version.py')
filename.write_text(f"__version__ = '{version}'\n")

MAJOR = 0
MINOR = 0
MICRO = 13

IS_RELEASED = False

VERSION_INFO = (MAJOR, MINOR, MICRO)
VERSION = ".".join(str(i) for i in VERSION_INFO)


# Return the git revision as a string
def git_version():
def _minimal_ext_cmd(cmd):
# construct minimal environment
env = {}
for k in ['SYSTEMROOT', 'PATH']:
v = os.environ.get(k)
if v is not None:
env[k] = v
# LANGUAGE is used on win32
env['LANGUAGE'] = 'C'
env['LANG'] = 'C'
env['LC_ALL'] = 'C'
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env).communicate()[0]
return out

try:
out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
git_revision = out.strip().decode('ascii')
except OSError:
git_revision = "Unknown"

try:
out = _minimal_ext_cmd(['git', 'rev-list', '--count', 'HEAD'])
git_count = out.strip().decode('ascii')
except OSError:
git_count = "0"

return git_revision, git_count


def write_version_py(filename):
template = """\
# THIS FILE IS GENERATED FROM ZIPFILE2 SETUP.PY
version = '{version}'
full_version = '{full_version}'
git_revision = '{git_revision}'
is_released = {is_released}
if not is_released:
version = full_version
"""
version = full_version = VERSION
is_released = IS_RELEASED

git_rev = "Unknown"
git_count = "0"

if os.path.exists('.git'):
git_rev, git_count = git_version()
elif os.path.exists(filename):
# must be a source distribution, use existing version file
try:
from zipfile2._version import git_revision as git_rev
except ImportError:
raise ImportError("Unable to import git_revision. Try removing "
"zipfile2/_version.py and the build directory "
"before building.")

if not is_released:
full_version += '.dev{0}+{1}'.format(git_count, git_rev[:7])

with open(filename, "wt") as fp:
fp.write(template.format(version=version,
full_version=full_version,
git_revision=git_rev,
is_released=is_released))


def main():
write_version_py("zipfile2/_version.py")

from zipfile2 import __version__

setup(
name="zipfile2",
author="David Cournapeau",
author_email="cournape@gmail.com",
description="An improved ZipFile class.",
packages=[
"zipfile2",
"zipfile2.tests",
],
package_data={
"zipfile2.tests": ["data/*.zip", "data/*egg"],
},
version=__version__,
license="PSFL",
classifiers=[
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: Python Software Foundation License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
]
)


if __name__ == "__main__":
main()
setup()
24 changes: 9 additions & 15 deletions zipfile2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
from __future__ import absolute_import

try:
from ._version import (full_version as __version__,
git_revision as __git_revision__,
is_released as __is_released__)
from ._version import __version__
except ImportError:
__version__ = __git_revision__ = "no-built"
__is_released__ = False
__version__ = "no-built"

from .common import TooManyFiles
from ._zipfile import (
PERMS_PRESERVE_NONE, PERMS_PRESERVE_SAFE, PERMS_PRESERVE_ALL, ZipFile
)
PERMS_PRESERVE_NONE, PERMS_PRESERVE_SAFE, PERMS_PRESERVE_ALL, ZipFile)
from ._lean_zipfile import LeanZipFile
from zipfile import (
ZIP64_LIMIT, ZIP_DEFLATED, ZIP_FILECOUNT_LIMIT, ZIP_MAX_COMMENT,
ZIP_STORED,
)
ZIP_STORED)

__all__ = [
"__git_revision__", "__is_released__", "__version__", "LeanZipFile",
"TooManyFiles", "ZipFile", "PERMS_PRESERVE_NONE", "PERMS_PRESERVE_SAFE",
"PERMS_PRESERVE_ALL", "ZIP64_LIMIT", "ZIP_DEFLATED", "ZIP_FILECOUNT_LIMIT",
"ZIP_MAX_COMMENT", "ZIP_STORED",
"__version__",
"LeanZipFile", "TooManyFiles", "ZipFile",
"PERMS_PRESERVE_NONE", "PERMS_PRESERVE_SAFE",
"PERMS_PRESERVE_ALL", "ZIP64_LIMIT", "ZIP_DEFLATED",
"ZIP_FILECOUNT_LIMIT", "ZIP_MAX_COMMENT", "ZIP_STORED",
]
122 changes: 39 additions & 83 deletions zipfile2/_lean_zipfile.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,39 @@
from __future__ import absolute_import

import struct
import sys

from .common import PY2, BytesIO, string_types

if PY2:
MAX_EXTRACT_VERSION = 63
from zipfile import (
BadZipfile as BadZipFile,
ZipExtFile,
ZipInfo,
_CD_COMMENT_LENGTH,
_CD_EXTRA_FIELD_LENGTH,
_CD_FILENAME_LENGTH,
_CD_LOCAL_HEADER_OFFSET,
_CD_SIGNATURE,
_ECD_LOCATION,
_ECD_OFFSET,
_ECD_SIGNATURE,
_ECD_SIZE,
_EndRecData,
_FH_EXTRA_FIELD_LENGTH,
_FH_FILENAME_LENGTH,
_FH_SIGNATURE,
sizeCentralDir,
sizeEndCentDir64,
sizeEndCentDir64Locator,
sizeFileHeader,
stringCentralDir,
stringEndArchive64,
stringFileHeader,
structCentralDir,
structFileHeader,
)
else:
from zipfile import (
BadZipFile,
MAX_EXTRACT_VERSION,
ZipExtFile,
ZipInfo,
_CD_COMMENT_LENGTH,
_CD_EXTRA_FIELD_LENGTH,
_CD_FILENAME_LENGTH,
_CD_LOCAL_HEADER_OFFSET,
_CD_SIGNATURE,
_ECD_LOCATION,
_ECD_OFFSET,
_ECD_SIGNATURE,
_ECD_SIZE,
_EndRecData,
_FH_EXTRA_FIELD_LENGTH,
_FH_FILENAME_LENGTH,
_FH_SIGNATURE,
sizeCentralDir,
sizeEndCentDir64,
sizeEndCentDir64Locator,
sizeFileHeader,
stringCentralDir,
stringEndArchive64,
stringFileHeader,
structCentralDir,
structFileHeader,
)

from .common import TooManyFiles
from io import BytesIO
from zipfile import (
BadZipFile,
MAX_EXTRACT_VERSION,
ZipExtFile,
ZipInfo,
_CD_COMMENT_LENGTH,
_CD_EXTRA_FIELD_LENGTH,
_CD_FILENAME_LENGTH,
_CD_LOCAL_HEADER_OFFSET,
_CD_SIGNATURE,
_ECD_LOCATION,
_ECD_OFFSET,
_ECD_SIGNATURE,
_ECD_SIZE,
_EndRecData,
_FH_EXTRA_FIELD_LENGTH,
_FH_FILENAME_LENGTH,
_FH_SIGNATURE,
sizeCentralDir,
sizeEndCentDir64,
sizeEndCentDir64Locator,
sizeFileHeader,
stringCentralDir,
stringEndArchive64,
stringFileHeader,
structCentralDir,
structFileHeader,
crc32
)

from .common import TooManyFiles, PY312

_UTF8_EXTENSION_FLAG = 0x800

if sys.version_info[:2] < (2, 7):
class _ZipExtFile(ZipExtFile):
def __enter__(self):
return self

def __exit__(self, *a, **kw):
self.close()


class LeanZipFile(object):
""" A limited but memory efficient zipfile reader.
Expand Down Expand Up @@ -164,6 +122,7 @@ def get_zip_infos(self, *filenames):
if centdir[_CD_SIGNATURE] != stringCentralDir:
raise BadZipFile("Bad magic number for central directory")
filename = fp.read(centdir[_CD_FILENAME_LENGTH])
orig_filename_crc = crc32(filename)
flags = centdir[5]
if flags & _UTF8_EXTENSION_FLAG:
# UTF-8 file names extension
Expand All @@ -187,8 +146,10 @@ def get_zip_infos(self, *filenames):
x._raw_time = t
x.date_time = ((d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F,
t >> 11, (t >> 5) & 0x3F, (t & 0x1F) * 2)

x._decodeExtra()
if PY312:
x._decodeExtra(orig_filename_crc)
else:
x._decodeExtra()
x.header_offset = x.header_offset + concat

# update total bytes read from central directory
Expand Down Expand Up @@ -247,12 +208,7 @@ def open(self, zinfo):
'File name in directory %r and header %r differ.'
% (zinfo.orig_filename, fname))

if sys.version_info[:2] < (2, 7):
return _ZipExtFile(zef_file, zinfo)
elif sys.version_info[:2] < (3, 4) and sys.platform == 'win32':
return ZipExtFile(zef_file, 'r', zinfo)
else:
return ZipExtFile(zef_file, 'r', zinfo, None, close_fileobj=False)
return ZipExtFile(zef_file, 'r', zinfo, None, close_fileobj=False)

def read(self, zinfo_or_name):
"""Return file bytes (as a string) for the given ZipInfo object or
Expand All @@ -269,7 +225,7 @@ def read(self, zinfo_or_name):
Will raise an error if more than one member is found with the
given name.
"""
if isinstance(zinfo_or_name, string_types):
if isinstance(zinfo_or_name, str):
candidates = list(self.get_zip_infos(zinfo_or_name))
if len(candidates) < 1:
msg = "There is no item named {0!r} found in the archive"
Expand Down
Loading

0 comments on commit 8823f72

Please sign in to comment.