diff --git a/pipenv/project.py b/pipenv/project.py index cd047875..21a02995 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -56,23 +56,35 @@ class Project(object): def _build_package_list(self, package_section): """Returns a list of packages for pip-tools to consume.""" ps = {} + # TODO: Separate the logic for showing packages from the filters for supplying pip-tools for k, v in self.parsed_pipfile.get(package_section, {}).items(): # Skip editable VCS deps. if hasattr(v, 'keys'): - # When a vcs url is given without editable it only appears as a key - if is_vcs(v) or is_vcs(k): + # When a vcs url is gven without editable it only appears as a key + # Eliminate any vcs, path, or url entries which are not editable + # Since pip-tools can't do deep resolution on them + # Exempt setuptools-installable directories + if (is_vcs(v) or is_vcs(k) or (is_installable_file(k) and os.path.isfile(k)) or + any((prefix in v and + (os.path.isfile(v[prefix]) or is_valid_url(v[prefix]))) + for prefix in ['path', 'file'])): # Non-editable VCS entries can't be resolved by piptools if 'editable' not in v: continue else: ps.update({k: v}) else: - if not (is_installable_file(k) or is_installable_file(v) or - any(file_prefix in v for file_prefix in ['path', 'file'])): - ps.update({k: v}) + ps.update({k: v}) else: + # Since these entries have no attributes we know they are not editable + # So we can safely exclude things that need to be editable in order to be resolved + # First exclude anything that is a vcs entry either in the key or value if not (any(is_vcs(i) for i in [k, v]) or - any(is_installable_file(i) for i in [k, v]) or + # Then exclude any installable files that are not directories + # Because pip-tools can resolve setup.py for example + any((is_installable_file(i) and os.path.isfile(i)) for i in [k, v]) or + # Then exclude any URLs because they need to be editable also + # Things that are excluded can only be 'shallow resolved' any(is_valid_url(i) for i in [k, v])): ps.update({k: v}) return ps diff --git a/tests/test_pipenv.py b/tests/test_pipenv.py index e0dd731f..8e332e74 100644 --- a/tests/test_pipenv.py +++ b/tests/test_pipenv.py @@ -879,6 +879,29 @@ requests = "==2.14.0" assert 'file' in dep + @pytest.mark.install + @pytest.mark.files + @pytest.mark.resolver + def test_local_package(self): + """This test ensures that local packages (directories with a setup.py) + installed in editable mode have their dependencies resolved as well""" + file_name = 'tablib-0.12.1.tar.gz' + package = 'tablib-0.12.1' + # Not sure where travis/appveyor run tests from + test_dir = os.path.dirname(os.path.abspath(__file__)) + source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name)) + with PipenvInstance() as p: + # This tests for a bug when installing a zipfile in the current dir + copy_to = os.path.join(p.path, file_name) + shutil.copy(source_path, copy_to) + import tarfile + with tarfile.open(copy_to, 'r:gz') as tgz: + tgz.extractall(path=p.path) + c = p.pipenv('install -e {0}'.format(package)) + assert c.return_code == 0 + assert all(pkg in p.lockfile['default'] for pkg in ['xlrd', 'xlwt', 'pyyaml', 'odfpy']) + + @pytest.mark.install @pytest.mark.files def test_local_zipfiles(self):