python-poetry / python-poetry/poetry

`poetry add` doesn't work with `git+file:///` URLs (error: `Could not parse version constraint: ...`)

Open
#7,276 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

kind/feature status/triage
Dominant language
Python
Stars
34.3k
Forks
2.5k
Avg merge
2d 19h
Merged PRs (30d)
30

Description

  • Poetry version: 1.3.1
  • Python version: 3.11.1
  • OS version and name: Debian bookworm (12)
  • pyproject.toml: NA
  • I am on the latest stable Poetry version, installed using a recommended method (pipx).
  • I have searched the issues of this repo and believe that this is not a duplicate.
  • I have consulted the FAQ and blog for any relevant entries or release notes.
  • If an exception occurs when executing a command, I executed it again in debug mode (-vvv option) and have included the output below.

Issue

poetry add with git+file:/// URL of local git repository results in error: Could not parse version constraint: ///tmp/tmp.AcoK44cpew/prj1@main.

Reproduce with:

_tmp="$(mktemp -d)"
pushd "${_tmp}"
poetry new prj1
poetry new prj2
_branch='main'
git -C prj1 init --initial-branch "${_branch}"
git -C prj1 add --all
git -C prj1 commit -m 'initial commit'
cd prj2

# poetry fails to add the project from file:/// URL
poetry add "git+file://${_tmp}/prj1@${_branch}"
# => error: Could not parse version constraint: ///tmp/tmp.AcoK44cpew/prj1@main

# pip install works just fine
poetry shell
_branch='main'
pip install "git+file://${_tmp}/prj1@${_branch}"
# => ...
# => Successfully installed prj1-0.1.0

The documentation doesn't claim that git+file:/// URLs are supported. So maybe this is a feature request. But since pip/setuptools has no issue with it, poetry should probably support it, too.

Output of poetry -vvv add "git+file:///tmp/tmp.AcoK44cpew/prj1@main" ```log Loading configuration file /home/kai/.config/pypoetry/config.toml Trying to detect current active python executable as specified in the config. Found: /home/kai/.pyenv/versions/3.11.1/bin/python Using virtualenv: /home/kai/.cache/pypoetry/virtualenvs/prj2-Dc-OYFc9-py3.11

Stack trace:

15 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/cleo/application.py:327 in run
325│
326│ try:
→ 327│ exit_code = self._run(io)
328│ except BrokenPipeError:
329│ # If we are piped to another process, it may close early and send a

14 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/console/application.py:190 in _run
188│ self._load_plugins(io)
189│
→ 190│ exit_code: int = super()._run(io)
191│ return exit_code
192│

13 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/cleo/application.py:431 in _run
429│ io.input.interactive(interactive)
430│
→ 431│ exit_code = self._run_command(command, io)
432│ self._running_command = None
433│

12 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/cleo/application.py:473 in _run_command
471│
472│ if error is not None:
→ 473│ raise error
474│
475│ return terminate_event.exit_code

11 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/cleo/application.py:457 in _run_command
455│
456│ if command_event.command_should_run():
→ 457│ exit_code = command.run(io)
458│ else:
459│ exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED

10 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/cleo/commands/base_command.py:119 in run
117│ io.input.validate()
118│
→ 119│ status_code = self.execute(io)
120│
121│ if status_code is None:

9 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/cleo/commands/command.py:62 in execute
60│
61│ try:
→ 62│ return self.handle()
63│ except KeyboardInterrupt:
64│ return 1

8 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/console/commands/add.py:158 in handle
156│ return 0
157│
→ 158│ requirements = self._determine_requirements(
159│ packages,
160│ allow_prereleases=self.option("allow-prereleases"),

7 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/console/commands/init.py:385 in _determine_requirements
383│ # check that the specified version/constraint exists
384│ # before we proceed
→ 385│ name, _ = self._find_best_version_for_package(
386│ requirement["name"],
387│ requirement["version"],

6 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/console/commands/init.py:408 in _find_best_version_for_package
406│
407│ selector = VersionSelector(self._get_pool())
→ 408│ package = selector.find_best_candidate(
409│ name, required_version, allow_prereleases=allow_prereleases, source=source
410│ )

5 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/version/version_selector.py:31 in find_best_candidate
29│ from poetry.factory import Factory
30│
→ 31│ dependency = Factory.create_dependency(
32│ package_name,
33│ {

4 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/core/factory.py:338 in create_dependency
336│ version = constraint["version"]
337│
→ 338│ dependency = Dependency(
339│ name,
340│ version,

3 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/core/packages/dependency.py:66 in init
64│ self._constraint: VersionConstraint
65│ self._pretty_constraint: str
→ 66│ self.constraint = constraint # type: ignore[assignment]
67│
68│ self._optional = optional

2 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/core/packages/dependency.py:110 in constraint
108│ def constraint(self, constraint: str | VersionConstraint) -> None:
109│ if isinstance(constraint, str):
→ 110│ self._constraint = parse_constraint(constraint)
111│ else:
112│ self._constraint = constraint

1 ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/core/constraints/version/parser.py:36 in parse_constraint
34│ constraint_objects.append(parse_single_constraint(constraint))
35│ else:
→ 36│ constraint_objects.append(parse_single_constraint(and_constraints[0]))
37│
38│ if len(constraint_objects) == 1:

ParseConstraintError

Could not parse version constraint: ///tmp/tmp.AcoK44cpew/prj1@main

at ~/.local/pipx/venvs/poetry/lib/python3.11/site-packages/poetry/core/constraints/version/parser.py:167 in parse_single_constraint
163│ if op == "!=":
164│ return VersionUnion(VersionRange(max=version), VersionRange(min=version))
165│ return version
166│
→ 167│ raise ParseConstraintError(f"Could not parse version constraint: {constraint}")
168│

</details>

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the command, then trace the entry points mentioned in poetry/console/commands/add.py and init.py into poetry/core/factory.py, dependency.py, and constraints/version/parser.py. Done means a local git+file:/// dependency can be added without the version-constraint error and the existing reproduction succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.