Skip to content

Commit

Permalink
Improve the add and init commands (#1221)
Browse files Browse the repository at this point in the history
* Add the ability to specify path and git dependencies directly in add

* Add the ability to add git and path dependencies via the init command

* Automatically select latest prereleases if only prereleases are available

* Update documentation for the add command

* Add the ability to add complete dependencies in one go
  • Loading branch information
sdispater authored Jul 13, 2019
1 parent 6f4aa21 commit c6a2d6e
Show file tree
Hide file tree
Showing 8 changed files with 891 additions and 144 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
- Added the ability to specify packages on a per-format basis.
- Added support for custom urls in metadata.
- Full environment markers are now supported for dependencies via the `markers` property.
- Added the ability to specify git dependencies directly in `add`, it no longer requires the `--git` option.
- Added the ability to specify path dependencies directly in `add`, it no longer requires the `--path` option.
- Added the ability to add git and path dependencies via the `init` command.

### Changed

Expand All @@ -24,6 +27,9 @@
- The `debug:resolve` command has been renamed to `debug resolve`.
- The `self:update` command has been renamed to `self update`.
- Changed the way virtualenvs are stored (names now depend on the project's path).
- The `--git` option of the `add` command has been removed.
- The `--path` option of the `add` command has been removed.
- The `add` command will now automatically select the latest prerelease if only prereleases are available.

### Fixed

Expand Down
45 changes: 38 additions & 7 deletions docs/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,36 +182,67 @@ poetry will choose a suitable one based on the available package versions.
poetry add requests pendulum
```

You also can specify a constraint when adding a package, like so:

```bash
poetry add pendulum@^2.0.5
poetry add "pendulum>=2.0.5"
```

If you try to add a package that is already present, you will get an error.
However, if you specify a constraint, like above, the dependency will be updated
by using the specified constraint. If you want to get the latest version of an already
present dependency you can use the special `latest` constraint:

```bash
poetry add pendulum@latest
```

You can also add `git` dependencies:

```bash
poetry add pendulum --git https://github.com/sdispater/pendulum.git
poetry add git+https://github.com/sdispater/pendulum.git
```

If you need to checkout a specific branch, tag or revision,
you can specify it when using `add`:

```bash
poetry add git+https://github.com/sdispater/pendulum.git@develop
poetry add git+https://github.com/sdispater/pendulum.git@2.0.5
```

or make them point to a local directory or file:

```bash
poetry add my-package --path ../my-package/
poetry add my-package --path ../my-package/dist/my-package-0.1.0.tar.gz
poetry add my-package --path ../my-package/dist/my_package-0.1.0.whl
poetry add ./my-package/
poetry add ../my-package/dist/my-package-0.1.0.tar.gz
poetry add ../my-package/dist/my_package-0.1.0.whl
```

Path dependencies pointing to a local directory will be installed in editable mode (i.e. setuptools "develop mode").
It means that changes in the local directory will be reflected directly in environment.

If you don't want the dependency to be installed in editable mode you can specify it in the `pyproject.toml` file:

```
```toml
[tool.poetry.dependencies]
my-package = {path = "../my/path", develop = false}
```

If the package(s) you want to install provide extras, you can specify them
when adding the package:

```bash
poetry add requests[security,socks]
poetry add "requests[security,socks]~=2.22.0"
poetry add "git+https://github.com/pallets/flask.git@1.1.1[dotenv,dev]"
```

### Options

* `--dev (-D)`: Add package as development dependency.
* `--git`: The url of the Git repository.
* `--path`: The path to a dependency.
* `--extras (-E)`: Extras to activate for the dependency.
* `--optional` : Add as an optional dependency.
* `--dry-run` : Outputs the operations but will not execute anything (implicitly enables --verbose).

Expand Down
51 changes: 19 additions & 32 deletions poetry/console/commands/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ class AddCommand(EnvCommand, InitCommand):
arguments = [argument("name", "Packages to add.", multiple=True)]
options = [
option("dev", "D", "Add package as development dependency."),
option("git", None, "The url of the Git repository.", flag=False),
option("path", None, "The path to a dependency.", flag=False),
option(
"extras",
"E",
Expand Down Expand Up @@ -58,17 +56,11 @@ def handle(self):
packages = self.argument("name")
is_dev = self.option("dev")

if (self.option("git") or self.option("path") or self.option("extras")) and len(
packages
) > 1:
if self.option("extras") and len(packages) > 1:
raise ValueError(
"You can only specify one package "
"when using the --git or --path options"
"You can only specify one package " "when using the --extras option"
)

if self.option("git") and self.option("path"):
raise RuntimeError("--git and --path cannot be used at the same time")

section = "dependencies"
if is_dev:
section = "dev-dependencies"
Expand All @@ -83,32 +75,27 @@ def handle(self):
for name in packages:
for key in poetry_content[section]:
if key.lower() == name.lower():
pair = self._parse_requirements([name])[0]
if "git" in pair or pair.get("version") == "latest":
continue

raise ValueError("Package {} is already present".format(name))

if self.option("git") or self.option("path"):
requirements = {packages[0]: ""}
else:
requirements = self._determine_requirements(
packages, allow_prereleases=self.option("allow-prereleases")
)
requirements = self._format_requirements(requirements)
requirements = self._determine_requirements(
packages, allow_prereleases=self.option("allow-prereleases")
)

# validate requirements format
for constraint in requirements.values():
parse_constraint(constraint)
for _constraint in requirements:
if "version" in _constraint:
# Validate version constraint
parse_constraint(_constraint["version"])

for name, _constraint in requirements.items():
constraint = inline_table()
constraint["version"] = _constraint

if self.option("git"):
del constraint["version"]

constraint["git"] = self.option("git")
elif self.option("path"):
del constraint["version"]
for name, value in _constraint.items():
if name == "name":
continue

constraint["path"] = self.option("path")
constraint[name] = value

if self.option("optional"):
constraint["optional"] = True
Expand All @@ -135,7 +122,7 @@ def handle(self):
if len(constraint) == 1 and "version" in constraint:
constraint = constraint["version"]

poetry_content[section][name] = constraint
poetry_content[section][_constraint["name"]] = constraint

# Write new content
self.poetry.file.write(content)
Expand All @@ -152,7 +139,7 @@ def handle(self):

installer.dry_run(self.option("dry-run"))
installer.update(True)
installer.whitelist(requirements)
installer.whitelist([r["name"] for r in requirements])

try:
status = installer.run()
Expand Down
Loading

0 comments on commit c6a2d6e

Please sign in to comment.