Skip to content

Commit

Permalink
[fix] zipfile does return unseekable file objects with Python 3.6
Browse files Browse the repository at this point in the history
  • Loading branch information
mxmlnkn committed Sep 26, 2021
1 parent b44073b commit 738a2ec
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 30 deletions.
61 changes: 34 additions & 27 deletions ratarmount.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import tempfile
import time
import traceback
import zipfile
from abc import ABC, abstractmethod
from timeit import default_timer as timer
import typing
Expand Down Expand Up @@ -56,6 +55,13 @@
pass


# The file object returned by ZipFile.open is not seekable in Python 3.6 for some reason.
# Therefore disable ZIP support there!
# I don't see it documented, instead I tested different Python versions with Docker.
if sys.version_info[2] > 6:
import zipfile


__version__ = '0.9.1'


Expand Down Expand Up @@ -2595,32 +2601,33 @@ def openMountSource(fileOrPath: Union[str, IO[bytes]], **options) -> MountSource
if hasattr(fileOrPath, 'seek'):
fileOrPath.seek(0) # type: ignore

try:
# is_zipfile is much too lax when testing for ZIPs because it's only testing for the central directory
# at the end of the file not the magic bits at the beginning. Meaning, if another non-ZIP archive has
# zip contents at the end, then it might get misclassified! Thefore, manually check for PK at start.
# https://bugs.python.org/issue16735
# https://bugs.python.org/issue28494
# https://bugs.python.org/issue42096
# https://bugs.python.org/issue45287
# TODO This will not recognize self-extracting ZIP archives, so for now, those are simply not supported!
if isinstance(fileOrPath, str):
with open(fileOrPath, 'rb') as file:
if supportedCompressions['zip'].checkHeader(file) and zipfile.is_zipfile(fileOrPath):
if 'zipfile' in sys.modules:
try:
# is_zipfile is much too lax when testing for ZIPs because it's only testing for the central directory
# at the end of the file not the magic bits at the beginning. Meaning, if another non-ZIP archive has
# zip contents at the end, then it might get misclassified! Thefore, manually check for PK at start.
# https://bugs.python.org/issue16735
# https://bugs.python.org/issue28494
# https://bugs.python.org/issue42096
# https://bugs.python.org/issue45287
# TODO This will not recognize self-extracting ZIP archives, so for now, those are simply not supported!
if isinstance(fileOrPath, str):
with open(fileOrPath, 'rb') as file:
if supportedCompressions['zip'].checkHeader(file) and zipfile.is_zipfile(fileOrPath):
return ZipMountSource(fileOrPath, **options)
else:
# TODO One problem here is when trying to read and then seek back but there also is no peek method.
# https://github.com/markokr/rarfile/issues/73
if fileOrPath.read(2) == b'PK' and zipfile.is_zipfile(fileOrPath):
return ZipMountSource(fileOrPath, **options)
else:
# TODO One problem here is when trying to read and then seek back but there also is no peek method.
# https://github.com/markokr/rarfile/issues/73
if fileOrPath.read(2) == b'PK' and zipfile.is_zipfile(fileOrPath):
return ZipMountSource(fileOrPath, **options)
except Exception as exception:
if printDebug >= 1:
print("[Info] Checking for ZIP file raised an exception:", exception)
if printDebug >= 3:
traceback.print_exc()
finally:
if hasattr(fileOrPath, 'seek'):
fileOrPath.seek(0) # type: ignore
except Exception as exception:
if printDebug >= 1:
print("[Info] Checking for ZIP file raised an exception:", exception)
if printDebug >= 3:
traceback.print_exc()
finally:
if hasattr(fileOrPath, 'seek'):
fileOrPath.seek(0) # type: ignore

raise CompressionError("Archive to open has unrecognized format!")

Expand Down Expand Up @@ -3471,7 +3478,7 @@ def _parseArgs(rawArgs: Optional[List[str]] = None):

# Manually check that all specified TARs and folders exist
def checkMountSource(path):
if os.path.isdir(path) or zipfile.is_zipfile(path):
if os.path.isdir(path) or ('zipfile' in sys.modules and zipfile.is_zipfile(path)):
return os.path.realpath(path)
return TarFileType(encoding=args.encoding)(path)[0]

Expand Down
16 changes: 13 additions & 3 deletions tests/runtests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1166,17 +1166,24 @@ tests=()
# TODO Some bug with rarfile throwing: Failed the read enough data: req=304 got=51 and then seek(0) not working?
if ! uname | 'grep' -q -i darwin; then
tests+=(
2709a3348eb2c52302a7606ecf5860bc tests/zip.rar natsu.zip/ufo
10d6977ec2ab378e60339323c24f9308 tests/zip.rar natsu.zip/foo
2709a3348eb2c52302a7606ecf5860bc tests/nested-with-symlink.rar foo/fighter/ufo
2709a3348eb2c52302a7606ecf5860bc tests/nested-with-symlink.rar foo/fighter/saucer
2b87e29fca6ee7f1df6c1a76cb58e101 tests/nested-with-symlink.rar foo/lighter.tar/fighter/bar
)
fi

# zipfile returns unseekable file object with python 3.6. Therefore I disabled it completely there.
python3MinorVersion=$( python3 --version | sed -n -E 's|.* 3[.]([0-9]+)[.][0-9]+|\1|p' )
if [[ -n "$python3MinorVersion" && "$python3MinorVersion" -gt 6 ]]; then
if ! uname | 'grep' -q -i darwin; then
tests+=(
2709a3348eb2c52302a7606ecf5860bc tests/zip.rar natsu.zip/ufo
10d6977ec2ab378e60339323c24f9308 tests/zip.rar natsu.zip/foo
49b996b16f59ab6c87dea31e227f8798 tests/rar-misrecognized-as-zip.rar bag.zip/README.md
49b996b16f59ab6c87dea31e227f8798 tests/rar-misrecognized-as-zip.rar bag.zip/CHANGELOG.md
49b996b16f59ab6c87dea31e227f8798 tests/rar-misrecognized-as-zip.rar bag1.zip/CHANGELOG.md
)
fi

tests+=(
2709a3348eb2c52302a7606ecf5860bc tests/file-in-non-existing-folder.zip foo2/ufo
2709a3348eb2c52302a7606ecf5860bc tests/rar.zip natsu.rar/ufo
Expand All @@ -1186,7 +1193,10 @@ tests+=(
2b87e29fca6ee7f1df6c1a76cb58e101 tests/nested-with-symlink.zip foo/lighter.tar/fighter/bar
2709a3348eb2c52302a7606ecf5860bc tests/folder-symlink.zip foo/fighter/ufo
2709a3348eb2c52302a7606ecf5860bc tests/folder-symlink.zip foo/jet/ufo
)
fi

tests+=(
2709a3348eb2c52302a7606ecf5860bc tests/file-in-non-existing-folder.rar foo2/ufo
2709a3348eb2c52302a7606ecf5860bc tests/folder-symlink.rar foo/fighter/ufo
2709a3348eb2c52302a7606ecf5860bc tests/folder-symlink.rar foo/jet/ufo
Expand Down

0 comments on commit 738a2ec

Please sign in to comment.