diff --git a/docs/docs/cli.md b/docs/docs/cli.md index 1a2615a9d9d..0581a6048e1 100644 --- a/docs/docs/cli.md +++ b/docs/docs/cli.md @@ -174,6 +174,7 @@ update the constraint, for example `^2.3`. You can do this using the `add` comma * `--dry-run` : Outputs the operations but will not execute anything (implicitly enables --verbose). * `--no-dev` : Do not install dev dependencies. * `--lock` : Do not perform install (only update the lockfile). +* `--editable`: "Add as dependency in editable mode. Only permissible for non path or VCS dependencies!" ## add @@ -230,7 +231,13 @@ 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 pass the `--editable` flag or specify it in the `pyproject.toml` file. It means that changes in the local directory will be reflected directly in environment. + +```bash +poetry add --editable ../my/path +``` + +or ```toml [tool.poetry.dependencies] @@ -242,6 +249,14 @@ my-package = {path = "../my/path", develop = true} Before poetry 1.1 path dependencies were installed in editable mode by default. You should always set the `develop` attribute explicit, to make sure the behavior is the same for all poetry versions. +!!!note + + We are working on resolving the inconsistency in the naming of the `--editable` flag and the `develop` attribute. In future the `develop` attribute will be deprecated! + +!!!note + + Currently passing the `--editable` flag with a non path or VCS dependency will result in a nonintuitive runtime error. We are currently working on providing a better error message. + If the package(s) you want to install provide extras, you can specify them when adding the package: diff --git a/poetry/console/commands/add.py b/poetry/console/commands/add.py index 29cf07d2a26..c17cf9aaef6 100644 --- a/poetry/console/commands/add.py +++ b/poetry/console/commands/add.py @@ -50,6 +50,11 @@ class AddCommand(InstallerCommand, InitCommand): "Output the operations but do not execute anything (implicitly enables --verbose).", ), option("lock", None, "Do not perform operations (only update the lockfile)."), + option( + "editable", + None, + "Add as dependency in editable mode. Will cause command to fail for non path or VCS dependencies!", + ), ] help = ( "The add command adds required packages to your pyproject.toml and installs them.\n\n" @@ -146,6 +151,9 @@ def handle(self): if self.option("source"): constraint["source"] = self.option("source") + if self.option("editable"): + constraint["develop"] = True + if len(constraint) == 1 and "version" in constraint: constraint = constraint["version"] diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 19998592ac3..cff3d3d67f3 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -811,6 +811,61 @@ def test_add_with_lock(app, repo, tester): assert content_hash != app.poetry.locker.lock_data["metadata"]["content-hash"] +def test_add_with_editable_fails_for_schema_without_develop(app, repo, tester): + repo.add_package(get_package("cachy", "0.2.0")) + + with pytest.raises(RuntimeError) as e: + tester.execute("cachy --editable") + # TODO: Provide better error message. + # `Develop` attribute is only supported by directory + # https://github.com/python-poetry/poetry-core/blob/master/poetry/core/packages/directory_dependency.py + # and vcs https://github.com/python-poetry/poetry-core/blob/master/poetry/core/packages/directory_dependency.py + # dependencies. There should be an explicit error message raised, stating that `develop` is + # inappropriate for other source types. + assert """\ +The Poetry configuration is invalid: + - [dependencies.cachy] {'version': '^0.2.0', 'develop': True} is not valid under any of the given schemas +""" in str( + e.value + ) + + +def test_add_with_editable(app, repo, tester, mocker): + p = mocker.patch("poetry.utils._compat.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("{} --editable".format(path)) + + expected = """\ + +Updating dependencies +Resolving dependencies... + +Writing lock file + +Package operations: 2 installs, 0 updates, 0 removals + + • Installing pendulum (1.4.4) + • Installing demo (0.1.2 {}) +""".format( + app.poetry.file.parent.joinpath(path).resolve().as_posix() + ) + + assert expected == tester.io.fetch_output() + + content = app.poetry.file.read()["tool"]["poetry"] + + assert "demo" in content["dependencies"] + assert content["dependencies"]["demo"] == { + "path": "../git/github.com/demo/demo", + "develop": True, + } + + def test_add_no_constraint_old_installer(app, repo, installer, old_tester): repo.add_package(get_package("cachy", "0.1.0")) repo.add_package(get_package("cachy", "0.2.0")) @@ -1653,3 +1708,39 @@ def test_dry_run_restore_original_content(app, repo, installer, tester): tester.execute("cachy --dry-run") assert original_content == app.poetry.file.read() + + +def test_add_with_editable_old_installer(app, repo, old_tester, mocker): + p = mocker.patch("poetry.utils._compat.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" + old_tester.execute("{} --editable".format(path)) + + expected = """\ + +Updating dependencies +Resolving dependencies... + +Writing lock file + +Package operations: 2 installs, 0 updates, 0 removals + + - Installing pendulum (1.4.4) + - Installing demo (0.1.2 {}) +""".format( + app.poetry.file.parent.joinpath(path).resolve().as_posix() + ) + + assert expected == old_tester.io.fetch_output() + + content = app.poetry.file.read()["tool"]["poetry"] + + assert "demo" in content["dependencies"] + assert content["dependencies"]["demo"] == { + "path": "../git/github.com/demo/demo", + "develop": True, + }