diff --git a/pipenv/cli.py b/pipenv/cli.py index fb0b2b2dc9..f9adbf7eb4 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -300,6 +300,15 @@ def cli( default=False, help="Install package(s) in [dev-packages].", ) +@option( + "--editable", + "-e", + nargs=1, + default=False, + multiple=True, + help="Install a project in editable mode (i.e. setuptools " + "\"develop mode\") from a local project path.", +) @option( "--three/--two", is_flag=True, @@ -378,6 +387,7 @@ def install( package_name=False, more_packages=False, dev=False, + editable=False, three=False, python=False, pypi_mirror=None, @@ -400,6 +410,7 @@ def install( package_name=package_name, more_packages=more_packages, dev=dev, + editable=editable, three=three, python=python, pypi_mirror=pypi_mirror, diff --git a/pipenv/core.py b/pipenv/core.py index 783677f0f1..a0dd6b413c 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1700,6 +1700,7 @@ def do_install( package_name=False, more_packages=False, dev=False, + editable=False, three=False, python=False, pypi_mirror=None, @@ -1832,12 +1833,14 @@ def do_install( for req in import_from_code(code): click.echo(" Found {0}!".format(crayons.green(req))) project.add_package_to_pipfile(req) - # Capture -e argument and assign it to following package_name. - more_packages = list(more_packages) - if package_name == "-e": - if not more_packages: - raise click.BadArgumentUsage("Please provide path to editable package") - package_name = " ".join([package_name, more_packages.pop(0)]) + # Assign editable (-e) to following package_name. + if editable: + editable = list(editable) + package_name = " ".join(["-e", editable.pop(0)]) + more_packages = ["-e %s" % (p) for p in editable] + if isinstance(more_packages, tuple): + more_packages = list(more_packages) + # capture indexes and extra indexes line = [package_name] + more_packages line = " ".join(str(s) for s in line).strip() diff --git a/tests/integration/test_install_basic.py b/tests/integration/test_install_basic.py index 8b4e03b5a6..276f0c19ff 100644 --- a/tests/integration/test_install_basic.py +++ b/tests/integration/test_install_basic.py @@ -344,7 +344,12 @@ def test_editable_no_args(PipenvInstance): with PipenvInstance() as p: c = p.pipenv("install -e") assert c.return_code != 0 - assert "Please provide path to editable package" in c.err + assert 'Error: -e option requires an argument' in c.err + + with PipenvInstance() as p: + c = p.pipenv('install --editable') + assert c.return_code != 0 + assert 'Error: --editable option requires an argument' in c.err @pytest.mark.install diff --git a/tests/integration/test_install_uri.py b/tests/integration/test_install_uri.py index 24f7996f9c..d7b3c2f9cc 100644 --- a/tests/integration/test_install_uri.py +++ b/tests/integration/test_install_uri.py @@ -120,6 +120,26 @@ def test_install_editable_git_tag(PipenvInstance, pip_src_dir, pypi): assert "ref" in p.lockfile["default"]["six"] +@pytest.mark.install +@pytest.mark.vcs +@pytest.mark.tablib +@pytest.mark.needs_internet +@flaky +def test_install_multiple_editable(PipenvInstance, pip_src_dir, pypi): + with PipenvInstance(pypi=pypi) as p: + c = p.pipenv('install -e git+https://github.com/requests/requests.git#egg=requests ' + '-e git+https://github.com/benjaminp/six.git@1.11.0#egg=six') + assert c.return_code == 0 + assert 'requests' in p.pipfile['packages'] + assert 'six' in p.pipfile['packages'] + assert 'git' in p.pipfile['packages']['requests'] + assert 'git' in p.pipfile['packages']['six'] + assert 'editable' in p.pipfile['packages']['requests'] + assert 'editable' in p.lockfile['default']['requests'] + assert 'editable' in p.pipfile['packages']['six'] + assert 'editable' in p.lockfile['default']['six'] + + @pytest.mark.install @pytest.mark.index @pytest.mark.needs_internet