diff --git a/pyproject.toml b/pyproject.toml index db9823d..874996b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ test = [ "pytest-ignore-flaky", "jaraco.test", "importlib_resources; python_version < '3.9'", + "pytest-timeout", ] doc = [ diff --git a/tests/test_path.py b/tests/test_path.py index 273ede1..4571c00 100644 --- a/tests/test_path.py +++ b/tests/test_path.py @@ -586,6 +586,7 @@ def test_getinfo_missing(self, alpharep): alpharep.getinfo('does-not-exist') @pytest.mark.xfail(reason="python/cpython#123270") + @pytest.mark.timeout(1) def test_malformed_paths(self): """ Path should handle malformed paths. @@ -604,7 +605,6 @@ def test_malformed_paths(self): ] assert root.joinpath('..').joinpath('parent.txt').read_bytes() == b'content' - @pytest.mark.xfail(reason="python/cpython#123270") def test_unsupported_names(self): """ Path segments with special characters are readable. @@ -624,7 +624,6 @@ def test_unsupported_names(self): assert next(contents).name == 'V: NMS.flac' assert root.joinpath('V: NMS.flac').read_bytes() == b"fLaC..." - @pytest.mark.xfail(reason="python/cpython#123270") def test_backslash_not_separator(self): """ In a zip file, backslashes are not separators. diff --git a/zipp/__init__.py b/zipp/__init__.py index 10e9540..051bfc9 100644 --- a/zipp/__init__.py +++ b/zipp/__init__.py @@ -95,69 +95,7 @@ def __setstate__(self, state): super().__init__(*args, **kwargs) -class SanitizedNames: - """ - ZipFile mix-in to ensure names are sanitized. - """ - - def namelist(self): - return list(map(self._sanitize, super().namelist())) - - @staticmethod - def _sanitize(name): - r""" - Ensure a relative path with posix separators and no dot names. - - Modeled after - https://github.com/python/cpython/blob/bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c/Lib/zipfile/__init__.py#L1799-L1813 - but provides consistent cross-platform behavior. - - >>> san = SanitizedNames._sanitize - >>> san('/foo/bar') - 'foo/bar' - >>> san('//foo.txt') - 'foo.txt' - >>> san('foo/.././bar.txt') - 'foo/bar.txt' - >>> san('foo../.bar.txt') - 'foo../.bar.txt' - >>> san('\\foo\\bar.txt') - 'foo/bar.txt' - >>> san('D:\\foo.txt') - 'D/foo.txt' - >>> san('\\\\server\\share\\file.txt') - 'server/share/file.txt' - >>> san('\\\\?\\GLOBALROOT\\Volume3') - '?/GLOBALROOT/Volume3' - >>> san('\\\\.\\PhysicalDrive1\\root') - 'PhysicalDrive1/root' - - Retain any trailing slash. - >>> san('abc/') - 'abc/' - - Raises a ValueError if the result is empty. - >>> san('../..') - Traceback (most recent call last): - ... - ValueError: Empty filename - """ - - def allowed(part): - return part and part not in {'..', '.'} - - # Remove the drive letter. - # Don't use ntpath.splitdrive, because that also strips UNC paths - bare = re.sub('^([A-Z]):', r'\1', name, flags=re.IGNORECASE) - clean = bare.replace('\\', '/') - parts = clean.split('/') - joined = '/'.join(filter(allowed, parts)) - if not joined: - raise ValueError("Empty filename") - return joined + '/' * name.endswith('/') - - -class CompleteDirs(InitializedState, SanitizedNames, zipfile.ZipFile): +class CompleteDirs(InitializedState, zipfile.ZipFile): """ A ZipFile subclass that ensures that implied directories are always included in the namelist.