Skip to content

Commit

Permalink
Fix excluding directories extracted from wheels
Browse files Browse the repository at this point in the history
Closes gh-168
  • Loading branch information
takluyver committed Oct 29, 2018
1 parent 0156bca commit b7e3f53
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
18 changes: 16 additions & 2 deletions nsist/tests/test_local_wheels.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
from pathlib import Path
import platform
import subprocess
from zipfile import ZipFile

import pytest
from testpath import assert_isfile, assert_isdir
from testpath import assert_isfile, assert_isdir, assert_not_path_exists

from nsist.wheels import WheelGetter
from nsist.wheels import WheelGetter, extract_wheel

# To exclude tests requiring network on an unplugged machine, use: pytest -m "not network"

Expand Down Expand Up @@ -85,3 +86,16 @@ def test_useless_wheel_glob_path_raise(tmpdir):

with pytest.raises(ValueError, match='does not match any files'):
wg.get_globs()

def test_extract_exclude_folder(tmpdir):
whl_file = str(tmpdir / 'foo.whl')
pkgs = tmpdir.mkdir('pkgs')

with ZipFile(whl_file, 'w') as zf:
zf.writestr('foo/bar.txt', b'blah')
zf.writestr('foo/bar/abc.txt', b'blah')

extract_wheel(whl_file, str(pkgs), exclude=['pkgs/foo/bar'])

assert_isfile(str(pkgs / 'foo' / 'bar.txt'))
assert_not_path_exists(str(pkgs / 'foo' / 'bar'))
28 changes: 22 additions & 6 deletions nsist/wheels.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,9 @@ def extract_wheel(whl_file, target_dir, exclude=None):
td = Path(mkdtemp())
with zipfile.ZipFile(str(whl_file), mode='r') as zf:
if exclude:
basename = Path(Path(target_dir).name)
exclude_regexen = make_exclude_regexen(exclude)
for zpath in zf.namelist():
path = basename / zpath
if is_excluded(path, exclude):
if is_excluded('pkgs/' + zpath, exclude_regexen):
continue # Skip excluded paths
zf.extract(zpath, path=str(td))
else:
Expand Down Expand Up @@ -324,10 +323,27 @@ def validate_wheel(self, whl_path):
self.got_distributions[distribution] = whl_path


def is_excluded(path, exclude):
def make_exclude_regexen(exclude_patterns):
"""Translate exclude glob patterns to regex pattern objects.
Handles matching files under a named directory.
"""
re_pats = set()
for pattern in exclude_patterns:
re_pats.add(fnmatch.translate(pattern))
if not pattern.endswith('*'):
# Also use the pattern as a directory name and match anything
# under that directory.
suffix = '*' if pattern.endswith('/') else '/*'
re_pats.add(fnmatch.translate(pattern + suffix))

return [re.compile(p) for p in sorted(re_pats)]


def is_excluded(path, exclude_regexen):
"""Return True if path matches an exclude pattern"""
path = normalize_path(path)
for pattern in (exclude or ()):
if fnmatch.fnmatch(path, pattern):
for re_pattern in exclude_regexen:
if re_pattern.match(path):
return True
return False

0 comments on commit b7e3f53

Please sign in to comment.