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

[email protected] installed using python3.11 is unable to install dependencies using file: urls. #10094

Open
lucamuscat opened this issue Jan 22, 2025 · 2 comments
Labels
kind/bug Something isn't working as expected status/triage This issue needs to be triaged

Comments

@lucamuscat
Copy link

Description

Hey 👋

When using a version of [email protected] installed using python3.11, projects depending on local projects
by declaring dependencies using the file url (whilst also using the PEP508 specification) fails to
install said project with the following error: The requirement is invalid: invalid URL "file:../dummy".

Note that this error does not occur when poetry is installed using python3.12.

Reproduction

I've created a repository containing a dockerfile which reproduces this bug, and validates that this error does not occur when installing poetry using python3.12, which you may find here.

Workarounds

Install poetry using python3.12

Poetry Installation Method

pip

Operating System

Ubuntu 20.04.1

Poetry Version

Poetry (version 2.0.1)

Poetry Configuration

cache-dir = "/home/lmuscat/.cache/pypoetry"
installer.max-workers = null
installer.no-binary = null
installer.only-binary = null
installer.parallel = true
installer.re-resolve = true
keyring.enabled = true
requests.max-retries = 0
solver.lazy-wheel = true
system-git-client = false
virtualenvs.create = true
virtualenvs.in-project = true
virtualenvs.options.always-copy = false
virtualenvs.options.no-pip = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/lmuscat/.cache/pypoetry/virtualenvs
virtualenvs.prompt = "{project_name}-py{python_version}"
virtualenvs.use-poetry-python = false

Python Sysconfig

sysconfig.log
Paste the output of 'python -m sysconfig', over this line.

Example pyproject.toml

[project]
name = "repro"
version = "0.1.0"
description = ""
authors = [
    {name = "Luca Muscat"}
]
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
    "dummy @ file:../dummy"
]


[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

Poetry Runtime Logs

Stack trace:

15 /usr/local/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 /usr/local/lib/python3.11/site-packages/poetry/console/application.py:236 in _run
234│
235│ with directory(self._working_directory):
→ 236│ exit_code: int = super()._run(io)
237│
238│ return exit_code

13 /usr/local/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 /usr/local/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 /usr/local/lib/python3.11/site-packages/cleo/application.py:454 in _run_command
452│
453│ try:
→ 454│ self._event_dispatcher.dispatch(command_event, COMMAND)
455│
456│ if command_event.command_should_run():

10 /usr/local/lib/python3.11/site-packages/cleo/events/event_dispatcher.py:26 in dispatch
24│
25│ if listeners:
→ 26│ self._do_dispatch(listeners, event_name, event)
27│
28│ return event

9 /usr/local/lib/python3.11/site-packages/cleo/events/event_dispatcher.py:85 in _do_dispatch
83│ break
84│
→ 85│ listener(event, event_name, self)
86│
87│ def _sort_listeners(self, event_name: str) -> None:

8 /usr/local/lib/python3.11/site-packages/poetry/console/application.py:343 in configure_env
341│
342│ io = event.io
→ 343│ poetry = command.poetry
344│
345│ env_manager = EnvManager(poetry, io=io)

7 /usr/local/lib/python3.11/site-packages/poetry/console/commands/command.py:24 in poetry
22│ def poetry(self) -> Poetry:
23│ if self._poetry is None:
→ 24│ return self.get_application().poetry
25│
26│ return self._poetry

6 /usr/local/lib/python3.11/site-packages/poetry/console/application.py:181 in poetry
179│ return self._poetry
180│
→ 181│ self._poetry = Factory().create_poetry(
182│ cwd=self._project_directory,
183│ io=self._io,

5 /usr/local/lib/python3.11/site-packages/poetry/factory.py:60 in create_poetry
58│ io = NullIO()
59│
→ 60│ base_poetry = super().create_poetry(cwd=cwd, with_groups=with_groups)
61│
62│ if version_str := base_poetry.local_config.get("requires-poetry"):

4 /usr/local/lib/python3.11/site-packages/poetry/core/factory.py:76 in create_poetry
74│ assert isinstance(version, str)
75│ package = self.get_package(name, version)
→ 76│ self.configure_package(
77│ package, pyproject, poetry_file.parent, with_groups=with_groups
78│ )

3 /usr/local/lib/python3.11/site-packages/poetry/core/factory.py:141 in configure_package
139│ cls._configure_package_metadata(package, project, tool_poetry, root)
140│ cls._configure_entry_points(package, project, tool_poetry)
→ 141│ cls._configure_package_dependencies(
142│ package, project, tool_poetry, with_groups=with_groups
143│ )

2 /usr/local/lib/python3.11/site-packages/poetry/core/factory.py:307 in _configure_package_dependencies
305│ for constraint in dependencies:
306│ group.add_dependency(
→ 307│ Dependency.create_from_pep_508(
308│ constraint, relative_to=package.root_dir
309│ )

1 /usr/local/lib/python3.11/site-packages/poetry/core/packages/dependency.py:360 in create_from_pep_508
358│ name += " ;" + rest.split(" ;", 1)[1]
359│
→ 360│ req = Requirement(name)
361│
362│ name = req.name

InvalidRequirementError

The requirement is invalid: invalid URL "file:../dummy"

at /usr/local/lib/python3.11/site-packages/poetry/core/version/requirements.py:51 in init
47│ url = url.value
48│ parsed_url = urlparse.urlparse(url)
49│ if parsed_url.scheme == "file":
50│ if urlparse.urlunparse(parsed_url) != url:
→ 51│ raise InvalidRequirementError(
52│ f'The requirement is invalid: invalid URL "{url}"'
53│ )
54│ elif (
55│ not (parsed_url.scheme and parsed_url.netloc)

@lucamuscat lucamuscat added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Jan 22, 2025
@abn
Copy link
Member

abn commented Jan 22, 2025

https://python-poetry.org/docs/dependency-specification/#path-dependencies

In the project section, you can only use absolute paths

Use the rich syntax instead https://python-poetry.org/docs/dependency-specification/#path-poetry.

@dimbleby
Copy link
Contributor

this is not a path dependency (though perhaps it should have been)

looks like there has been a change in behaviour of urllib.parse.urlunparse() in python 3.13.

from urllib.parse import urlparse, urlunparse
parsed = urlparse("file:../dummy")
unparsed = urlunparse(parsed)
print(unparsed)

gives either file:../dummy or file:///../dummy depending on version

You'd probably need to go spelunking through cpython commits - or ask over there - to figure out whether this is intended or correct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working as expected status/triage This issue needs to be triaged
Projects
None yet
Development

No branches or pull requests

3 participants