python-poetry / python-poetry/poetry
`poetry add` doesn't work with `git+file:///` URLs (error: `Could not parse version constraint: ...`)
Nobody has claimed this yet.
- 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 (
-vvvoption) 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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