Commit 494dec27 by Arun Babu Neelicattu Committed by Steph Samson

command/add: introduce --editable option

This change allows for vcs/path dependencies to be installed with
`develop=true` configured.
parent 9a2e1577
...@@ -272,7 +272,14 @@ poetry add ../my-package/dist/my-package-0.1.0.tar.gz ...@@ -272,7 +272,14 @@ poetry add ../my-package/dist/my-package-0.1.0.tar.gz
poetry add ../my-package/dist/my_package-0.1.0.whl poetry add ../my-package/dist/my_package-0.1.0.whl
``` ```
If you want the dependency to be installed in editable mode you can specify it in the `pyproject.toml` file. It means that changes in the local directory will be reflected directly in environment. If you want the dependency to be installed in editable mode you can use the `--editable` option.
```bash
poetry add --editable ./my-package/
poetry add --editable git+ssh://github.com/sdispater/pendulum.git#develop
```
Alternatively, you can specify it in the `pyproject.toml` file. It means that changes in the local directory will be reflected directly in environment.
```toml ```toml
[tool.poetry.dependencies] [tool.poetry.dependencies]
...@@ -296,6 +303,7 @@ poetry add "git+https://github.com/pallets/flask.git@1.1.1[dotenv,dev]" ...@@ -296,6 +303,7 @@ poetry add "git+https://github.com/pallets/flask.git@1.1.1[dotenv,dev]"
### Options ### Options
* `--dev (-D)`: Add package as development dependency. * `--dev (-D)`: Add package as development dependency.
* `--editable (-e)`: Add vcs/path dependencies as editable.
* `--extras (-E)`: Extras to activate for the dependency. (multiple values allowed) * `--extras (-E)`: Extras to activate for the dependency. (multiple values allowed)
* `--optional`: Add as an optional dependency. * `--optional`: Add as an optional dependency.
* `--python`: Python version for which the dependency must be installed. * `--python`: Python version for which the dependency must be installed.
......
...@@ -17,6 +17,7 @@ class AddCommand(InstallerCommand, InitCommand): ...@@ -17,6 +17,7 @@ class AddCommand(InstallerCommand, InitCommand):
arguments = [argument("name", "The packages to add.", multiple=True)] arguments = [argument("name", "The packages to add.", multiple=True)]
options = [ options = [
option("dev", "D", "Add as a development dependency."), option("dev", "D", "Add as a development dependency."),
option("editable", "e", "Add vcs/path dependencies as editable."),
option( option(
"extras", "extras",
"E", "E",
...@@ -139,6 +140,19 @@ class AddCommand(InstallerCommand, InitCommand): ...@@ -139,6 +140,19 @@ class AddCommand(InstallerCommand, InitCommand):
constraint["extras"] = self.option("extras") constraint["extras"] = self.option("extras")
if self.option("editable"):
if "git" in _constraint or "path" in _constraint:
constraint["develop"] = True
else:
self.line_error(
"\n"
"<error>Failed to add packages. "
"Only vcs/path dependencies support editable installs. "
f"<c1>{_constraint['name']}</c1> is neither."
)
self.line_error("\nNo changes were applied.")
return 1
if self.option("python"): if self.option("python"):
constraint["python"] = self.option("python") constraint["python"] = self.option("python")
......
...@@ -50,6 +50,24 @@ Package operations: 1 install, 0 updates, 0 removals ...@@ -50,6 +50,24 @@ Package operations: 1 install, 0 updates, 0 removals
assert content["dependencies"]["cachy"] == "^0.2.0" assert content["dependencies"]["cachy"] == "^0.2.0"
def test_add_no_constraint_editable_error(app, repo, tester):
content = app.poetry.file.read()["tool"]["poetry"]
repo.add_package(get_package("cachy", "0.2.0"))
tester.execute("-e cachy")
expected = """
Failed to add packages. Only vcs/path dependencies support editable installs. cachy is neither.
No changes were applied.
"""
assert 1 == tester.status_code
assert expected == tester.io.fetch_error()
assert 0 == tester.command.installer.executor.installations_count
assert content == app.poetry.file.read()["tool"]["poetry"]
def test_add_equal_constraint(app, repo, tester): def test_add_equal_constraint(app, repo, tester):
repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(get_package("cachy", "0.2.0")) repo.add_package(get_package("cachy", "0.2.0"))
...@@ -243,13 +261,15 @@ Package operations: 4 installs, 0 updates, 0 removals ...@@ -243,13 +261,15 @@ Package operations: 4 installs, 0 updates, 0 removals
} }
def test_add_git_ssh_constraint(app, repo, tester, tmp_venv): @pytest.mark.parametrize("editable", [False, True])
def test_add_git_ssh_constraint(editable, app, repo, tester, tmp_venv):
tester.command.set_env(tmp_venv) tester.command.set_env(tmp_venv)
repo.add_package(get_package("pendulum", "1.4.4")) repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5")) repo.add_package(get_package("cleo", "0.6.5"))
tester.execute("git+ssh://git@github.com/demo/demo.git@develop") url = "git+ssh://git@github.com/demo/demo.git@develop"
tester.execute(f"{url}" if not editable else f"-e {url}")
expected = """\ expected = """\
...@@ -270,13 +290,19 @@ Package operations: 2 installs, 0 updates, 0 removals ...@@ -270,13 +290,19 @@ Package operations: 2 installs, 0 updates, 0 removals
content = app.poetry.file.read()["tool"]["poetry"] content = app.poetry.file.read()["tool"]["poetry"]
assert "demo" in content["dependencies"] assert "demo" in content["dependencies"]
assert content["dependencies"]["demo"] == {
expected = {
"git": "ssh://git@github.com/demo/demo.git", "git": "ssh://git@github.com/demo/demo.git",
"rev": "develop", "rev": "develop",
} }
if editable:
expected["develop"] = True
assert content["dependencies"]["demo"] == expected
def test_add_directory_constraint(app, repo, tester, mocker): @pytest.mark.parametrize("editable", [False, True])
def test_add_directory_constraint(editable, app, repo, tester, mocker):
p = mocker.patch("pathlib.Path.cwd") p = mocker.patch("pathlib.Path.cwd")
p.return_value = Path(__file__).parent p.return_value = Path(__file__).parent
...@@ -284,7 +310,7 @@ def test_add_directory_constraint(app, repo, tester, mocker): ...@@ -284,7 +310,7 @@ def test_add_directory_constraint(app, repo, tester, mocker):
repo.add_package(get_package("cleo", "0.6.5")) repo.add_package(get_package("cleo", "0.6.5"))
path = "../git/github.com/demo/demo" path = "../git/github.com/demo/demo"
tester.execute("{}".format(path)) tester.execute(f"{path}" if not editable else f"-e {path}")
expected = """\ expected = """\
...@@ -307,7 +333,12 @@ Package operations: 2 installs, 0 updates, 0 removals ...@@ -307,7 +333,12 @@ Package operations: 2 installs, 0 updates, 0 removals
content = app.poetry.file.read()["tool"]["poetry"] content = app.poetry.file.read()["tool"]["poetry"]
assert "demo" in content["dependencies"] assert "demo" in content["dependencies"]
assert content["dependencies"]["demo"] == {"path": "../git/github.com/demo/demo"}
expected = {"path": "../git/github.com/demo/demo"}
if editable:
expected["develop"] = True
assert content["dependencies"]["demo"] == expected
def test_add_directory_with_poetry(app, repo, tester, mocker): def test_add_directory_with_poetry(app, repo, tester, mocker):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment