diff --git a/pip/req/req_set.py b/pip/req/req_set.py index 58951adba96..91db853c3cb 100644 --- a/pip/req/req_set.py +++ b/pip/req/req_set.py @@ -263,6 +263,8 @@ def add_requirement(self, install_req, parent_req_name=None): # If we're now installing a constraint, mark the existing # object for real installation. existing_req.constraint = False + existing_req.extras = tuple(set(existing_req.extras).union( + set(install_req.extras))) # And now we need to scan this. result = [existing_req] # Canonicalise to the already-added object for the backref diff --git a/tests/data/packages/LocalExtras/setup.py b/tests/data/packages/LocalExtras/setup.py index 7c2839819a8..fea6e16039a 100644 --- a/tests/data/packages/LocalExtras/setup.py +++ b/tests/data/packages/LocalExtras/setup.py @@ -24,6 +24,6 @@ def path_to_url(path): name='LocalExtras', version='0.0.1', packages=find_packages(), - extras_require={ 'bar': ['simple'] }, + extras_require={ 'bar': ['simple'], 'baz': ['singlemodule'] }, dependency_links=[DEP_URL] ) diff --git a/tests/functional/test_install_reqs.py b/tests/functional/test_install_reqs.py index f1ba71b1b71..4f5b36eee93 100644 --- a/tests/functional/test_install_reqs.py +++ b/tests/functional/test_install_reqs.py @@ -313,3 +313,46 @@ def test_constrained_to_url_install_same_url(script, data): 'install', '--no-index', '-f', data.find_links, '-c', script.scratch_path / 'constraints.txt', to_install) assert 'Running setup.py install for singlemodule' in result.stdout + + +def test_install_with_extras_from_constraints(script, data): + to_install = data.packages.join("LocalExtras") + script.scratch_path.join("constraints.txt").write( + "file://%s#egg=LocalExtras[bar]" % to_install + ) + result = script.pip_install_local( + '-c', script.scratch_path / 'constraints.txt', 'LocalExtras') + assert script.site_packages / 'simple' in result.files_created + + +def test_install_with_extras_from_install(script, data): + to_install = data.packages.join("LocalExtras") + script.scratch_path.join("constraints.txt").write( + "file://%s#egg=LocalExtras" % to_install + ) + result = script.pip_install_local( + '-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]') + assert script.site_packages / 'singlemodule.py'in result.files_created + + +def test_install_with_extras_joined(script, data): + to_install = data.packages.join("LocalExtras") + script.scratch_path.join("constraints.txt").write( + "file://%s#egg=LocalExtras[bar]" % to_install + ) + result = script.pip_install_local( + '-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]' + ) + assert script.site_packages / 'simple' in result.files_created + assert script.site_packages / 'singlemodule.py'in result.files_created + + +def test_install_with_extras_editable_joined(script, data): + to_install = data.packages.join("LocalExtras") + script.scratch_path.join("constraints.txt").write( + "-e file://%s#egg=LocalExtras[bar]" % to_install + ) + result = script.pip_install_local( + '-c', script.scratch_path / 'constraints.txt', 'LocalExtras[baz]') + assert script.site_packages / 'simple' in result.files_created + assert script.site_packages / 'singlemodule.py'in result.files_created