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 1.8.0 does not tolerate new sources in pyproject.toml #9042

Closed
aabmets opened this issue Feb 27, 2024 · 11 comments · Fixed by #9051
Closed

Poetry 1.8.0 does not tolerate new sources in pyproject.toml #9042

aabmets opened this issue Feb 27, 2024 · 11 comments · Fixed by #9051
Labels
kind/bug Something isn't working as expected

Comments

@aabmets
Copy link

aabmets commented Feb 27, 2024

EDIT: Was this fixed with Poetry 1.8.1?

Description

I'm using Poetry in a Jenkins pipeline to install packages from a private repository for the pytest stage:

withDockerContainer(image:'*********.com/python:3.12.1-slim-bookworm', args:'-u root') {
    sh "pip install poetry==${env.POETRY_VERSION} " +
        "--trusted-host ${env.TRUSTED_PIP_HOST} " +
        "--index-url ${env.PIP_REGISTRY} " +
        "--root-user-action ignore " +
        "--no-cache-dir"
    sh "poetry config virtualenvs.create false"
    sh "poetry source add --priority=primary privsrc ${env.PIP_REGISTRY}"
    sh "poetry install --with dev"
    sh "pytest"
}

The pipeline broke, because I hadn't pinned poetry version to 1.7.1 and it automatically used the latest version 1.8.0, which poetry had released on 25th of February. The pipeline works as expected with Poetry version 1.7.1.

The line poetry install --with dev causes poetry to throw the following error:

pyproject.toml changed significantly since poetry.lock was last generated.  
Run `poetry lock [--no-update]` to fix the lock file.

Inserting the suggested command poetry lock --no-update after the poetry source add command will produce the following error instead:

17:08:37  poetry lock --no-update
17:08:37  Skipping virtualenv creation, as specified in config file.
17:08:37  Updating dependencies
17:08:37  Resolving dependencies...
17:08:47  
17:08:47  'content-range'

Workarounds

Option A:

Downgrade to 1.7.1

Option B:

poetry config solver.lazy-wheel false
poetry source add --priority=primary <your private source>
poetry lock --no-update
poetry install [--with dev]

Poetry Installation Method

pip

Operating System

Linux

Poetry Version

1.8.0

Poetry Configuration

10:20:34  poetry config --list
10:20:35  cache-dir = "/root/.cache/pypoetry"
10:20:35  experimental.system-git-client = false
10:20:35  installer.max-workers = null
10:20:35  installer.modern-installation = true
10:20:35  installer.no-binary = null
10:20:35  installer.parallel = true
10:20:35  keyring.enabled = true
10:20:35  repositories.privsrc.url = "https://********.com/repository/pypi.org/simple"
10:20:35  solver.lazy-wheel = true
10:20:35  virtualenvs.create = false
10:20:35  virtualenvs.in-project = null
10:20:35  virtualenvs.options.always-copy = false
10:20:35  virtualenvs.options.no-pip = false
10:20:35  virtualenvs.options.no-setuptools = false
10:20:35  virtualenvs.options.system-site-packages = false
10:20:35  virtualenvs.path = "{cache-dir}/virtualenvs"  # /root/.cache/pypoetry/virtualenvs
10:20:35  virtualenvs.prefer-active-python = false
10:20:35  virtualenvs.prompt = "{project_name}-py{python_version}"
10:20:35  warnings.export = true

Python Sysconfig

No response

Example pyproject.toml

[tool.poetry]
name = "project"
version = "0.0.0"
description = "description"
authors = ["Author <author@project.com>"]
license = "MIT"
readme = "README.md"
packages = [
    {include = "*", from = "src"}
]

[tool.poetry.dependencies]
python = "^3.12.1"
dapr = "^1.12.1"
dotmap = "^1.3.30"
orjson = "^3.9.15"
aiodns = "^3.1.1"
fastapi = "^0.110.0"
uvicorn = "^0.27.1"
pydantic = "^2.6.2"
pydantic-settings = "^2.2.1"
piccolo = {extras = ["all"], version = "^1.3.1"}
aiohttp = {extras = ["speedups"], version = "^3.9.3"}
uvloop = {version = "^0.19.0", platform = "linux"}
dapr-ext-fastapi = "^1.12.0"
piccolo-admin = "^1.2.2"

[tool.poetry.group.dev]
optional = true

[tool.poetry.group.dev.dependencies]
httpx = "^0.27.0"
pytest = "^8.0.2"
pytest-cov = "^4.1.0"
pytest-asyncio = "^0.23.5"
devtools-cli = "^0.13.1"
coverage = "^7.4.3"
aerich = "^0.7.2"
pyarrow = "^15.0.0"
pandas = {extras = ["excel"], version = "^2.2.1"}

# added by poetry source add command
# [[tool.poetry.source]]
# name = "privsrc"
# url = "https://********.com/repository/pypi.org/simple"
# priority = "primary"

[tool.pytest.ini_options]
asyncio_mode = "auto"
console_output_style = "count"
filterwarnings = ["ignore::DeprecationWarning"]
testpaths = ["tests"]
addopts = [
    "--cov=src",
    "--cov-report=html",
    "--no-cov-on-fail",
    "--import-mode=append"
]
pythonpath = [
    ".",
    "./src"
]

[tool.coverage.run]
branch = true
source = ["src/*"]

[tool.coverage.report]
skip_empty = true
ignore_errors = true
exclude_lines = [
    "pragma: no cover",
    "def __repr__",
    "raise AssertionError",
    "raise NotImplementedError",
    "if __name__ == .__main__.:",
    "@abstractmethod"
]

[tool.coverage.html]
directory = ".htmlcov"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Poetry Runtime Logs

Error log without poetry lock --no-update:

10:24:02  poetry -vvv install --with dev
10:24:02  Loading configuration file /root/.config/pypoetry/config.toml
10:24:02  Adding repository privsrc (https://*********.com/repository/pypi.org/simple) and setting it as primary
10:24:02  Deactivating the PyPI repository
10:24:02  Skipping virtualenv creation, as specified in config file.
10:24:03  Installing dependencies from lock file
10:24:03  
10:24:03    Stack trace:
10:24:03  
10:24:03    9  /usr/local/lib/python3.12/site-packages/cleo/application.py:327 in run
10:24:03        325│ 
10:24:03        326│             try:
10:24:03      → 327│                 exit_code = self._run(io)
10:24:03        328│             except BrokenPipeError:
10:24:03        329│                 # If we are piped to another process, it may close early and send a
10:24:03  
10:24:03    8  /usr/local/lib/python3.12/site-packages/poetry/console/application.py:190 in _run
10:24:03        188│         self._load_plugins(io)
10:24:03        189│ 
10:24:03      → 190│         exit_code: int = super()._run(io)
10:24:03        191│         return exit_code
10:24:03        192│ 
10:24:03  
10:24:03    7  /usr/local/lib/python3.12/site-packages/cleo/application.py:431 in _run
10:24:03        429│             io.input.interactive(interactive)
10:24:03        430│ 
10:24:03      → 431│         exit_code = self._run_command(command, io)
10:24:03        432│         self._running_command = None
10:24:03        433│ 
10:24:03  
10:24:03    6  /usr/local/lib/python3.12/site-packages/cleo/application.py:473 in _run_command
10:24:03        471│ 
10:24:03        472│         if error is not None:
10:24:03      → 473│             raise error
10:24:03        474│ 
10:24:03        475│         return terminate_event.exit_code
10:24:03  
10:24:03    5  /usr/local/lib/python3.12/site-packages/cleo/application.py:457 in _run_command
10:24:03        455│ 
10:24:03        456│             if command_event.command_should_run():
10:24:03      → 457│                 exit_code = command.run(io)
10:24:03        458│             else:
10:24:03        459│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED
10:24:03  
10:24:03    4  /usr/local/lib/python3.12/site-packages/cleo/commands/base_command.py:117 in run
10:24:03        115│         io.input.validate()
10:24:03        116│ 
10:24:03      → 117│         return self.execute(io) or 0
10:24:03        118│ 
10:24:03        119│     def merge_application_definition(self, merge_args: bool = True) -> None:
10:24:03  
10:24:03    3  /usr/local/lib/python3.12/site-packages/cleo/commands/command.py:61 in execute
10:24:03         59│ 
10:24:03         60│         try:
10:24:03      →  61│             return self.handle()
10:24:03         62│         except KeyboardInterrupt:
10:24:03         63│             return 1
10:24:03  
10:24:03    2  /usr/local/lib/python3.12/site-packages/poetry/console/commands/install.py:153 in handle
10:24:03        151│         self.installer.verbose(self.io.is_verbose())
10:24:03        152│ 
10:24:03      → 153│         return_code = self.installer.run()
10:24:03        154│ 
10:24:03        155│         if return_code != 0:
10:24:03  
10:24:03    1  /usr/local/lib/python3.12/site-packages/poetry/installation/installer.py:104 in run
10:24:03        102│             self.verbose(True)
10:24:03        103│ 
10:24:03      → 104│         return self._do_install()
10:24:03        105│ 
10:24:03        106│     def dry_run(self, dry_run: bool = True) -> Installer:
10:24:03  
10:24:03    ValueError
10:24:03  
10:24:03    pyproject.toml changed significantly since poetry.lock was last generated. Run `poetry lock [--no-update]` to fix the lock file.
10:24:03  
10:24:03    at /usr/local/lib/python3.12/site-packages/poetry/installation/installer.py:248 in _do_install
10:24:03        244│ 
10:24:03        245│             locked_repository = self._locker.locked_repository()
10:24:03        246│ 
10:24:03        247│             if not self._locker.is_fresh():
10:24:03      → 248│                 raise ValueError(
10:24:03        249│                     "pyproject.toml changed significantly since poetry.lock was last generated. "
10:24:03        250│                     "Run `poetry lock [--no-update]` to fix the lock file."
10:24:03        251│                 )
10:24:03        252│ 

Error log with poetry lock --no-update, thrown by the same command:

<omitted a lot of dependnecies which succeeded>

10:33:54  [urllib3:urllib3.connectionpool] https://*********.com:443 "GET /repository/pypi.org/packages/aiodns/3.1.1/aiodns-3.1.1-py3-none-any.whl HTTP/1.1" 416 1594
10:33:54     1: Version solving took 4.362 seconds.
10:33:54     1: Tried 1 solutions.
10:33:54  
10:33:54    ValueError
10:33:54  
10:33:54    Package('aiodns', '3.1.1') is not in list
10:33:54  
10:33:54    at /usr/local/lib/python3.12/site-packages/poetry/repositories/legacy_repository.py:66 in package
10:33:54         62│         Note that this will be cached so the subsequent operations
10:33:54         63│         should be much faster.
10:33:54         64│         """
10:33:54         65│         try:
10:33:54      →  66│             index = self._packages.index(Package(name, version))
10:33:54         67│ 
10:33:54         68│             return self._packages[index]
10:33:54         69│         except ValueError:
10:33:54         70│             package = super().package(name, version, extras)
10:33:54  
10:33:54  The following error occurred when trying to handle this error:
10:33:54  
10:33:54  
10:33:54    Stack trace:
10:33:54  
10:33:54    4  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:609 in _extract_content_length
10:33:54        607│         try:
10:33:54        608│             # Initial range request for just the end of the file.
10:33:54      → 609│             file_length, tail = self._try_initial_chunk_request(initial_chunk_size)
10:33:54        610│         except HTTPError as e:
10:33:54        611│             resp = e.response
10:33:54  
10:33:54    3  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:572 in _try_initial_chunk_request
10:33:54        570│ 
10:33:54        571│         self._request_count += 1
10:33:54      → 572│         tail = self._session.get(self._url, headers=headers, stream=True)
10:33:54        573│         tail.raise_for_status()
10:33:54        574│ 
10:33:54  
10:33:54    2  /usr/local/lib/python3.12/site-packages/poetry/utils/authenticator.py:267 in get
10:33:54        265│ 
10:33:54        266│     def get(self, url: str, **kwargs: Any) -> requests.Response:
10:33:54      → 267│         return self.request("get", url, **kwargs)
10:33:54        268│ 
10:33:54        269│     def head(self, url: str, **kwargs: Any) -> requests.Response:
10:33:54  
10:33:54    1  /usr/local/lib/python3.12/site-packages/poetry/utils/authenticator.py:245 in request
10:33:54        243│                 if resp.status_code not in STATUS_FORCELIST or is_last_attempt:
10:33:54        244│                     if raise_for_status:
10:33:54      → 245│                         resp.raise_for_status()
10:33:54        246│                     return resp
10:33:54        247│ 
10:33:54  
10:33:54    HTTPError
10:33:54  
10:33:54    416 Client Error: Range Not Satisfiable for url: https://*********.com/repository/pypi.org/packages/aiodns/3.1.1/aiodns-3.1.1-py3-none-any.whl#sha256=a387b63da4ced6aad35b1dda2d09620ad608a1c7c0fb71efa07ebb4cd511928d
10:33:54  
10:33:54    at /usr/local/lib/python3.12/site-packages/requests/models.py:1021 in raise_for_status
10:33:54        1017│                 f"{self.status_code} Server Error: {reason} for url: {self.url}"
10:33:54        1018│             )
10:33:54        1019│ 
10:33:54        1020│         if http_error_msg:
10:33:54      → 1021│             raise HTTPError(http_error_msg, response=self)
10:33:54        1022│ 
10:33:54        1023│     def close(self):
10:33:54        1024│         """Releases the connection back to the pool. Once this method has been
10:33:54        1025│         called the underlying ``raw`` object must not be accessed again.
10:33:54  
10:33:54  The following error occurred when trying to handle this error:
10:33:54  
10:33:54  
10:33:54    Stack trace:
10:33:54  
10:33:54    31  /usr/local/lib/python3.12/site-packages/cleo/application.py:327 in run
10:33:55         325│ 
10:33:55         326│             try:
10:33:55       → 327│                 exit_code = self._run(io)
10:33:55         328│             except BrokenPipeError:
10:33:55         329│                 # If we are piped to another process, it may close early and send a
10:33:55  
10:33:55    30  /usr/local/lib/python3.12/site-packages/poetry/console/application.py:190 in _run
10:33:55         188│         self._load_plugins(io)
10:33:55         189│ 
10:33:55       → 190│         exit_code: int = super()._run(io)
10:33:55         191│         return exit_code
10:33:55         192│ 
10:33:55  
10:33:55    29  /usr/local/lib/python3.12/site-packages/cleo/application.py:431 in _run
10:33:55         429│             io.input.interactive(interactive)
10:33:55         430│ 
10:33:55       → 431│         exit_code = self._run_command(command, io)
10:33:55         432│         self._running_command = None
10:33:55         433│ 
10:33:55  
10:33:55    28  /usr/local/lib/python3.12/site-packages/cleo/application.py:473 in _run_command
10:33:55         471│ 
10:33:55         472│         if error is not None:
10:33:55       → 473│             raise error
10:33:55         474│ 
10:33:55         475│         return terminate_event.exit_code
10:33:55  
10:33:55    27  /usr/local/lib/python3.12/site-packages/cleo/application.py:457 in _run_command
10:33:55         455│ 
10:33:55         456│             if command_event.command_should_run():
10:33:55       → 457│                 exit_code = command.run(io)
10:33:55         458│             else:
10:33:55         459│                 exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED
10:33:55  
10:33:55    26  /usr/local/lib/python3.12/site-packages/cleo/commands/base_command.py:117 in run
10:33:55         115│         io.input.validate()
10:33:55         116│ 
10:33:55       → 117│         return self.execute(io) or 0
10:33:55         118│ 
10:33:55         119│     def merge_application_definition(self, merge_args: bool = True) -> None:
10:33:55  
10:33:55    25  /usr/local/lib/python3.12/site-packages/cleo/commands/command.py:61 in execute
10:33:55          59│ 
10:33:55          60│         try:
10:33:55       →  61│             return self.handle()
10:33:55          62│         except KeyboardInterrupt:
10:33:55          63│             return 1
10:33:55  
10:33:55    24  /usr/local/lib/python3.12/site-packages/poetry/console/commands/lock.py:55 in handle
10:33:55          53│         self.installer.lock(update=not self.option("no-update"))
10:33:55          54│ 
10:33:55       →  55│         return self.installer.run()
10:33:55          56│ 
10:33:55  
10:33:55    23  /usr/local/lib/python3.12/site-packages/poetry/installation/installer.py:95 in run
10:33:55          93│         # Check if refresh
10:33:55          94│         if not self._update and self._lock and self._locker.is_locked():
10:33:55       →  95│             return self._do_refresh()
10:33:55          96│ 
10:33:55          97│         # Force update if there is no lock file present
10:33:55  
10:33:55    22  /usr/local/lib/python3.12/site-packages/poetry/installation/installer.py:201 in _do_refresh
10:33:55         199│             source_root=self._env.path.joinpath("src")
10:33:55         200│         ):
10:33:55       → 201│             ops = solver.solve(use_latest=use_latest).calculate_operations()
10:33:55         202│ 
10:33:55         203│         lockfile_repo = LockfileRepository()
10:33:55  
10:33:55    21  /usr/local/lib/python3.12/site-packages/poetry/puzzle/solver.py:71 in solve
10:33:55          69│         with self._progress(), self._provider.use_latest_for(use_latest or []):
10:33:55          70│             start = time.time()
10:33:55       →  71│             packages, depths = self._solve()
10:33:55          72│             end = time.time()
10:33:55          73│ 
10:33:55  
10:33:55    20  /usr/local/lib/python3.12/site-packages/poetry/puzzle/solver.py:154 in _solve
10:33:55         152│ 
10:33:55         153│         try:
10:33:55       → 154│             result = resolve_version(self._package, self._provider)
10:33:55         155│ 
10:33:55         156│             packages = result.packages
10:33:55  
10:33:55    19  /usr/local/lib/python3.12/site-packages/poetry/mixology/__init__.py:18 in resolve_version
10:33:55          16│     solver = VersionSolver(root, provider)
10:33:55          17│ 
10:33:55       →  18│     return solver.solve()
10:33:55          19│ 
10:33:55  
10:33:55    18  /usr/local/lib/python3.12/site-packages/poetry/mixology/version_solver.py:175 in solve
10:33:55         173│             while next is not None:
10:33:55         174│                 self._propagate(next)
10:33:55       → 175│                 next = self._choose_package_version()
10:33:55         176│ 
10:33:55         177│             return self._result()
10:33:55  
10:33:55    17  /usr/local/lib/python3.12/site-packages/poetry/mixology/version_solver.py:514 in _choose_package_version
10:33:55         512│             package = locked
10:33:55         513│ 
10:33:55       → 514│         package = self._provider.complete_package(package)
10:33:55         515│ 
10:33:55         516│         conflict = False
10:33:55  
10:33:55    16  /usr/local/lib/python3.12/site-packages/poetry/puzzle/provider.py:489 in complete_package
10:33:55         487│                 dependency_package = DependencyPackage(
10:33:55         488│                     dependency,
10:33:55       → 489│                     self._pool.package(
10:33:55         490│                         package.pretty_name,
10:33:55         491│                         package.version,
10:33:55  
10:33:55    15  /usr/local/lib/python3.12/site-packages/poetry/repositories/repository_pool.py:204 in package
10:33:55         202│         for repo in self.repositories:
10:33:55         203│             try:
10:33:55       → 204│                 return repo.package(name, version, extras=extras)
10:33:55         205│             except PackageNotFound:
10:33:55         206│                 continue
10:33:55  
10:33:55    14  /usr/local/lib/python3.12/site-packages/poetry/repositories/legacy_repository.py:70 in package
10:33:55          68│             return self._packages[index]
10:33:55          69│         except ValueError:
10:33:55       →  70│             package = super().package(name, version, extras)
10:33:55          71│             package._source_type = "legacy"
10:33:55          72│             package._source_url = self._url
10:33:55  
10:33:55    13  /usr/local/lib/python3.12/site-packages/poetry/repositories/cached_repository.py:75 in package
10:33:55          73│         extras: list[str] | None = None,
10:33:55          74│     ) -> Package:
10:33:55       →  75│         return self.get_release_info(canonicalize_name(name), version).to_package(
10:33:55          76│             name=name, extras=extras
10:33:55          77│         )
10:33:55  
10:33:55    12  /usr/local/lib/python3.12/site-packages/poetry/repositories/cached_repository.py:52 in get_release_info
10:33:55          50│             return PackageInfo.load(self._get_release_info(name, version))
10:33:55          51│ 
10:33:55       →  52│         cached = self._release_cache.remember(
10:33:55          53│             f"{name}:{version}", lambda: self._get_release_info(name, version)
10:33:55          54│         )
10:33:55  
10:33:55    11  /usr/local/lib/python3.12/site-packages/poetry/utils/cache.py:147 in remember
10:33:55         145│         value = self.get(key)
10:33:55         146│         if value is None:
10:33:55       → 147│             value = callback() if callable(callback) else callback
10:33:55         148│             self.put(key, value, minutes)
10:33:55         149│         return value
10:33:55  
10:33:55    10  /usr/local/lib/python3.12/site-packages/poetry/repositories/cached_repository.py:53 in <lambda>
10:33:55          51│ 
10:33:55          52│         cached = self._release_cache.remember(
10:33:55       →  53│             f"{name}:{version}", lambda: self._get_release_info(name, version)
10:33:55          54│         )
10:33:55          55│ 
10:33:55  
10:33:55     9  /usr/local/lib/python3.12/site-packages/poetry/repositories/legacy_repository.py:123 in _get_release_info
10:33:55         121│         yanked = page.yanked(name, version)
10:33:55         122│ 
10:33:55       → 123│         return self._links_to_data(
10:33:55         124│             links,
10:33:55         125│             PackageInfo(
10:33:55  
10:33:55     8  /usr/local/lib/python3.12/site-packages/poetry/repositories/http_repository.py:360 in _links_to_data
10:33:55         358│ 
10:33:55         359│         # drop yanked files unless the entire release is yanked
10:33:55       → 360│         info = self._get_info_from_links(links, ignore_yanked=not data.yanked)
10:33:55         361│ 
10:33:55         362│         data.summary = info.summary
10:33:55  
10:33:55     7  /usr/local/lib/python3.12/site-packages/poetry/repositories/http_repository.py:310 in _get_info_from_links
10:33:55         308│                 return self._get_info_from_metadata(
10:33:55         309│                     universal_python3_wheel
10:33:55       → 310│                 ) or self._get_info_from_wheel(universal_python3_wheel)
10:33:55         311│ 
10:33:55         312│             if universal_python2_wheel:
10:33:55  
10:33:55     6  /usr/local/lib/python3.12/site-packages/poetry/repositories/http_repository.py:123 in _get_info_from_wheel
10:33:55         121│             try:
10:33:55         122│                 package_info = PackageInfo.from_metadata(
10:33:55       → 123│                     metadata_from_wheel_url(link.filename, link.url, self.session)
10:33:55         124│                 )
10:33:55         125│             except HTTPRangeRequestUnsupported:
10:33:55  
10:33:55     5  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:77 in metadata_from_wheel_url
10:33:55          75│         # After context manager exit, wheel.name will point to a deleted file path.
10:33:55          76│         # Add `delete_backing_file=False` to disable this for debugging.
10:33:55       →  77│         with LazyWheelOverHTTP(url, session) as lazy_file:
10:33:55          78│             metadata_bytes = lazy_file.read_metadata(name)
10:33:55          79│ 
10:33:55  
10:33:55     4  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:289 in __enter__
10:33:55         287│     def __enter__(self: U) -> U:
10:33:55         288│         super().__enter__()
10:33:55       → 289│         self._setup_content()
10:33:55         290│         return self
10:33:55         291│ 
10:33:55  
10:33:55     3  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:357 in _setup_content
10:33:55         355│         if self._length is None:
10:33:55         356│             logger.debug("begin fetching content length")
10:33:55       → 357│             self._length = self._fetch_content_length()
10:33:55         358│             logger.debug("done fetching content length (is: %d)", self._length)
10:33:55         359│             # Enable us to seek and write anywhere in the backing file up to this
10:33:55  
10:33:55     2  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:508 in _fetch_content_length
10:33:55         506│         """
10:33:55         507│         initial_chunk_size = self._initial_chunk_length()
10:33:55       → 508│         ret_length, tail = self._extract_content_length(initial_chunk_size)
10:33:55         509│ 
10:33:55         510│         # Need to explicitly truncate here in order to perform the write and seek
10:33:55  
10:33:55     1  /usr/local/lib/python3.12/site-packages/poetry/inspection/lazy_wheel.py:634 in _extract_content_length
10:33:55         632│                 assert resp is not None
10:33:55         633│                 file_length = self._parse_full_length_from_content_range(
10:33:55       → 634│                     resp.headers["Content-Range"]
10:33:55         635│                 )
10:33:55         636│                 return (file_length, None)
10:33:55  
10:33:55    KeyError
10:33:55  
10:33:55    'content-range'
10:33:55  
10:33:55    at /usr/local/lib/python3.12/site-packages/requests/structures.py:52 in __getitem__
10:33:55         48│         # key alongside the value.
10:33:55         49│         self._store[key.lower()] = (key, value)
10:33:55         50│ 
10:33:55         51│     def __getitem__(self, key):
10:33:55      →  52│         return self._store[key.lower()][1]
10:33:55         53│ 
10:33:55         54│     def __delitem__(self, key):
10:33:55         55│         del self._store[key.lower()]
10:33:55         56│
@aabmets aabmets added kind/bug Something isn't working as expected status/triage This issue needs to be triaged labels Feb 27, 2024
@rcala1

This comment was marked as duplicate.

@abn
Copy link
Member

abn commented Feb 27, 2024

Can you verify the issue still exists with 1.8.1?

And an interim workaround, if the issue is not fixed in 1.8.1, for the poetry lock --no-uodate error, try disabling https://python-poetry.org/docs/configuration#solverlazy-wheel.

@kiran94
Copy link

kiran94 commented Feb 27, 2024

Making a note that we experienced this where we had:

  • An internal source added to our pyproject.yaml
  • The same pyproject.toml changed significantly since poetry.lock was last generated error reported
  • Failure at the poetry install --with dev step of our CI pipeline
  • Upgrading to 1.8.1 did not help
  • Issue was observed in GitHub Actions rather then Jenkins Pipelines
  • The suggested action of poetry lock --no-update does not help

The internal source we have looks like this:

[[tool.poetry.source]]
name = "SOURCE"
url = "INTERNAL_PYPI_URL"
priority = "default"

For now we have pinned back to 1.7.1 to avoid any disruption to our development team.

@aabmets
Copy link
Author

aabmets commented Feb 27, 2024

@abn

This modification makes 1.8.1 work correctly, but it's a workaround and the original issue should still get fixed:

withDockerContainer(image:'*********.com/python:3.12.1-slim-bookworm', args:'-u root') {
    sh "pip install poetry==1.8.1 " +
        "--trusted-host ${env.TRUSTED_PIP_HOST} " +
        "--index-url ${env.PIP_REGISTRY} " +
        "--root-user-action ignore " +
        "--no-cache-dir"
    sh "poetry config virtualenvs.create false"
    sh "poetry config solver.lazy-wheel false"  // <--- ADDED
    sh "poetry source add --priority=primary privsrc ${env.PIP_REGISTRY}"
    sh "poetry lock --no-update"  // <--- ADDED
    sh "poetry install --with dev"
    sh "pytest"
}

@radoering
Copy link
Member

This issue contains two different issues:

  1. poetry install fails if you change significant parts of pyproject.toml without locking again
  2. poetry lock fails if the server handles range requests in a way we did not expect

Regarding 2: please try 1.8.1 and open a new issue if poetry lock still fails.

Regarding 1: That's mentioned in the blog post. See #8737 for more details why this error makes sense.

@aabmets @kiran94 What I don't understand in your example: Why do you add a source (poetry source add) before running poetry install? That should be a NOP without locking because the source will not be used.

@dimbleby
Copy link
Contributor

        resp.headers["Content-Range"] ...

presumably there's every reason to think that this will continue to fail in 1.8.1, if the server has not sent that header

@aabmets

This comment was marked as off-topic.

@radoering
Copy link
Member

A server that generates a 416 response to a byte-range request SHOULD generate a Content-Range header field specifying the current length of the selected representation (Section 14.4).

I suppose SHOULD is not MUST. 😩

@aabmets May I ask what type of custom package index you are using?

Actually, the source is used. How do I know? If the private repo source would not be there, the Jenkins build would fail, because Jenkins runs in a limited network environment and it cannot directly connect to PyPI. The source must be only added in the Jenkins pipeline, because our dev machines can connect with PyPI.

In other words, the source is used even though the packages are locked for another source? That sound like a bug. I have to check if I can reproduce that later. Or do you use any Poetry plugins that alter the behavior?

@aabmets

This comment was marked as off-topic.

@abn
Copy link
Member

abn commented Feb 28, 2024

I have moved the off-topic (in the context of this issue) concern regarding build time package source urls to #9057.

@abn abn removed the status/triage This issue needs to be triaged label Feb 28, 2024
@abn abn closed this as completed in #9051 Feb 28, 2024
Copy link

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 Mar 31, 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
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants