Skip to content

Commit

Permalink
command/add: introduce --editable option
Browse files Browse the repository at this point in the history
This change allows for vcs/path dependencies to be installed with
`develop=true` configured.
  • Loading branch information
abn authored and kasteph committed Apr 21, 2021
1 parent 9a2e157 commit 494dec2
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
10 changes: 9 additions & 1 deletion docs/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

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
[tool.poetry.dependencies]
Expand All @@ -296,6 +303,7 @@ poetry add "git+https://github.com/pallets/flask.git@1.1.1[dotenv,dev]"
### Options

* `--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)
* `--optional`: Add as an optional dependency.
* `--python`: Python version for which the dependency must be installed.
Expand Down
14 changes: 14 additions & 0 deletions poetry/console/commands/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class AddCommand(InstallerCommand, InitCommand):
arguments = [argument("name", "The packages to add.", multiple=True)]
options = [
option("dev", "D", "Add as a development dependency."),
option("editable", "e", "Add vcs/path dependencies as editable."),
option(
"extras",
"E",
Expand Down Expand Up @@ -139,6 +140,19 @@ def handle(self) -> int:

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"):
constraint["python"] = self.option("python")

Expand Down
43 changes: 37 additions & 6 deletions tests/console/commands/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ def test_add_no_constraint(app, repo, tester):
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):
repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(get_package("cachy", "0.2.0"))
Expand Down Expand Up @@ -243,13 +261,15 @@ def test_add_git_constraint_with_extras(app, repo, tester, tmp_venv):
}


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)

repo.add_package(get_package("pendulum", "1.4.4"))
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 = """\
Expand All @@ -270,21 +290,27 @@ def test_add_git_ssh_constraint(app, repo, tester, tmp_venv):
content = app.poetry.file.read()["tool"]["poetry"]

assert "demo" in content["dependencies"]
assert content["dependencies"]["demo"] == {

expected = {
"git": "ssh://git@github.com/demo/demo.git",
"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.return_value = Path(__file__).parent

repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5"))

path = "../git/github.com/demo/demo"
tester.execute("{}".format(path))
tester.execute(f"{path}" if not editable else f"-e {path}")

expected = """\
Expand All @@ -307,7 +333,12 @@ def test_add_directory_constraint(app, repo, tester, mocker):
content = app.poetry.file.read()["tool"]["poetry"]

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):
Expand Down

0 comments on commit 494dec2

Please sign in to comment.