Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poetry cannot resolve git URLs with '+' in the path. #9727

Closed
uhryniuk opened this issue Oct 1, 2024 · 1 comment · Fixed by python-poetry/poetry-core#765
Closed

Poetry cannot resolve git URLs with '+' in the path. #9727

uhryniuk opened this issue Oct 1, 2024 · 1 comment · Fixed by python-poetry/poetry-core#765
Labels
kind/bug Something isn't working as expected status/triage This issue needs to be triaged

Comments

@uhryniuk
Copy link

uhryniuk commented Oct 1, 2024

Description

What

poetry add is unable to parse repositories that contain '+' in their path. Below is an example of the usage.

$ poetry add  git+ssh://git.launchpad.net/~uhryniuk/+git/example-repo

When this is run, an exception is thrown for Invalid git url "git+ssh://git.launchpad.net/~uhryniuk/+git/example-repo".

This error occurs because of the regex rules for PATH in core/vcs/git.py, which does not support '+'.

Why

The practice of having a '+' in the path for repos may seem odd, especially on github but this pattern occurs more frequently on Launchpad. Users on Launchpad have the option of using different VCS systems and the +git is a distinction of which VCS (in this case git) is being used.

The URL, git+ssh://git.launchpad.net/~uhryniuk/+git/example-repo, is an actual repo created on Launchpad and will cause the error when trying to resolve it with poetry.

Workarounds

No current work arounds, adding this manually to the poetry dependencies results in the same error.

Poetry Installation Method

system package manager (eg: dnf, apt etc.)

Operating System

Ubuntu 22.04

Poetry Version

1.8.3

Poetry Configuration

cache-dir = "/home/dylan/.cache/pypoetry"
experimental.system-git-client = false
installer.max-workers = null
installer.modern-installation = true
installer.no-binary = null
installer.parallel = true
keyring.enabled = true
solver.lazy-wheel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.no-setuptools = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/<name>/.cache/pypoetry/virtualenvs
virtualenvs.prefer-active-python = false
virtualenvs.prompt = "{project_name}-py{python_version}"
warnings.export = true

Python Sysconfig

No response

Example pyproject.toml

No response

Poetry Runtime Logs

Loading configuration file /home/dylan/.config/pypoetry/config.toml
Using virtualenv: /home/dylan/.venv

  Stack trace:

  21  ~/.local/share/pypoetry/venv/lib/python3.10/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

  20  ~/.local/share/pypoetry/venv/lib/python3.10/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│ 

  19  ~/.local/share/pypoetry/venv/lib/python3.10/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│ 

  18  ~/.local/share/pypoetry/venv/lib/python3.10/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

  17  ~/.local/share/pypoetry/venv/lib/python3.10/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

  16  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/cleo/commands/base_command.py:117 in run
       115│         io.input.validate()
       116│ 
     → 117│         return self.execute(io) or 0
       118│ 
       119│     def merge_application_definition(self, merge_args: bool = True) -> None:

  15  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/cleo/commands/command.py:61 in execute
        59│ 
        60│         try:
     →  61│             return self.handle()
        62│         except KeyboardInterrupt:
        63│             return 1

  14  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/add.py:164 in handle
       162│             return 0
       163│ 
     → 164│         requirements = self._determine_requirements(
       165│             packages,
       166│             allow_prereleases=self.option("allow-prereleases"),

  13  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/init.py:375 in _determine_requirements
       373│ 
       374│         result = []
     → 375│         for requirement in self._parse_requirements(requires):
       376│             if "git" in requirement or "url" in requirement or "path" in requirement:
       377│                 result.append(requirement)

  12  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/init.py:441 in _parse_requirements
       439│             cwd=cwd,
       440│         )
     → 441│         return [parser.parse(requirement) for requirement in requirements]
       442│ 
       443│     def _format_requirements(self, requirements: list[dict[str, str]]) -> Requirements:

  11  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/init.py:441 in <listcomp>
       439│             cwd=cwd,
       440│         )
     → 441│         return [parser.parse(requirement) for requirement in requirements]
       442│ 
       443│     def _format_requirements(self, requirements: list[dict[str, str]]) -> Requirements:

  10  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/dependency_specification.py:89 in parse
        87│ 
        88│         specification = (
     →  89│             self._parse_url(requirement)
        90│             or self._parse_path(requirement)
        91│             or self._parse_simple(requirement)

   9  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/dependency_specification.py:149 in _parse_url
       147│ 
       148│         if url_parsed.scheme in GIT_URL_SCHEMES:
     → 149│             return self._parse_git_url(requirement)
       150│ 
       151│         if url_parsed.scheme in ["http", "https"]:

   8  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/utils/dependency_specification.py:133 in _parse_git_url
       131│ 
       132│         source_root = self._env.path.joinpath("src") if self._env else None
     → 133│         package = self._direct_origin.get_package_from_vcs(
       134│             "git",
       135│             url=url.url,

   7  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/packages/direct_origin.py:106 in get_package_from_vcs
       104│             raise ValueError(f"Unsupported VCS dependency {vcs}")
       105│ 
     → 106│         return _get_package_from_git(
       107│             url=url,
       108│             branch=branch,

   6  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/packages/direct_origin.py:32 in _get_package_from_git
        30│     source_root: Path | None = None,
        31│ ) -> Package:
     →  32│     source = Git.clone(
        33│         url=url,
        34│         source_root=source_root,

   5  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/vcs/git/backend.py:455 in clone
       453│         try:
       454│             if not cls.is_using_legacy_client():
     → 455│                 local = cls._clone(url=url, refspec=refspec, target=target)
       456│                 cls._clone_submodules(repo=local)
       457│                 return local

   4  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/vcs/git/backend.py:263 in _clone
       261│             local = Repo(str(target))
       262│ 
     → 263│         remote_refs = cls._fetch_remote_refs(url=url, local=local)
       264│ 
       265│         logger.debug(

   3  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/poetry/vcs/git/backend.py:208 in _fetch_remote_refs
       206│ 
       207│         with local:
     → 208│             result: FetchPackResult = client.fetch(
       209│                 path,
       210│                 local,

   2  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/dulwich/client.py:839 in fetch
        837│             f, commit, abort = target.object_store.add_pack()
        838│         try:
     →  839│             result = self.fetch_pack(
        840│                 path,
        841│                 determine_wants,

   1  ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/dulwich/client.py:1152 in fetch_pack
       1150│         with proto:
       1151│             try:
     → 1152│                 refs, server_capabilities = read_pkt_refs(proto.read_pkt_seq())
       1153│             except HangupException as exc:
       1154│                 raise _remote_error_from_stderr(stderr) from exc

  GitProtocolError

  Repository '~uhryniuk/git/example-repo' not found.

  at ~/.local/share/pypoetry/venv/lib/python3.10/site-packages/dulwich/client.py:247 in read_pkt_refs
       243│     # Receive refs from server
       244│     for pkt in pkt_seq:
       245│         (sha, ref) = pkt.rstrip(b"\n").split(None, 1)
       246│         if sha == b"ERR":
    →  247│             raise GitProtocolError(ref.decode("utf-8", "replace"))
       248│         if server_capabilities is None:
       249│             (ref, server_capabilities) = extract_capabilities(ref)
       250│         refs[ref] = sha
       251│
@uhryniuk uhryniuk added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Oct 1, 2024
Copy link

github-actions bot commented Nov 2, 2024

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/bug Something isn't working as expected status/triage This issue needs to be triaged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant