We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Pants poetry-based lockfiles fail to include hashes.
This was detected in a unit test in the Pants repo, but is a wider problem for all versions of Pants that support generating lockfiles using Poetry.

The proximal cause is this announcement from PyPI:
  https://discuss.python.org/t/backwards-incompatible-change-to-pypi-json-api/17154

And the root cause is this Poetry code:
  https://github.com/python-poetry/poetry/blob/bce13c14f73060b3abbb791dea585d8fde26eaef/poetry/repositories/pypi_repository.py#L272-L283

There was a Poetry fix released and backported to the 1.1. branch here:
  https://github.com/python-poetry/poetry/pull/5973

Users can fix with 2 steps:
1. Update Pants config
```toml
[poetry]
# N.B.: Works around issue described at https://github.com/pantsbuild/pants/issues/16111
# Undo once on a Pants with this version or greater as the default.
version = "poetry==1.1.14"
```
2. Clear Poetry caches with `rm -rf ~/.cache/pypoetry` on Linux and `rm -rf ~/Library/Caches/pypoetry` on Mac.

This issue tracks bumping Pants default to this fixed Poetry version.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/python/pants/backend/python/subsystems/poetry.py`
Content:
```
1 # Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 
4 from __future__ import annotations
5 
6 from collections import defaultdict
7 from dataclasses import dataclass
8 from textwrap import dedent
9 from typing import Any, Iterable, Sequence
10 
11 import toml
12 from pkg_resources import Requirement
13 
14 from pants.backend.python.subsystems.python_tool_base import PythonToolRequirementsBase
15 from pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints
16 from pants.engine.fs import FileContent
17 
18 # ----------------------------------------------------------------------------------------
19 # Subsystem
20 # ----------------------------------------------------------------------------------------
21 
22 
23 class PoetrySubsystem(PythonToolRequirementsBase):
24     options_scope = "poetry"
25     help = "Used to generate lockfiles for third-party Python dependencies."
26 
27     default_version = "poetry==1.1.8"
28 
29     register_interpreter_constraints = True
30     default_interpreter_constraints = ["CPython>=3.7,<4"]
31 
32 
33 # We must monkeypatch Poetry to include `setuptools` and `wheel` in the lockfile. This was fixed
34 # in Poetry 1.2. See https://github.com/python-poetry/poetry/issues/1584.
35 # WONTFIX(#12314): only use this custom launcher if using Poetry 1.1..
36 POETRY_LAUNCHER = FileContent(
37     "__pants_poetry_launcher.py",
38     dedent(
39         """\
40         from poetry.console import main
41         from poetry.puzzle.provider import Provider
42 
43         Provider.UNSAFE_PACKAGES = set()
44         main()
45         """
46     ).encode(),
47 )
48 
49 
50 # ----------------------------------------------------------------------------------------
51 # Parsing
52 # ----------------------------------------------------------------------------------------
53 
54 _HEADER = {
55     "name": "pants-lockfile-generation",
56     "version": "0.1.0",
57     "description": "",
58     "authors": ["pantsbuild"],
59 }
60 
61 
62 def create_pyproject_toml(
63     requirements: Iterable[str], interpreter_constraints: InterpreterConstraints
64 ) -> str:
65     return toml.dumps(create_pyproject_toml_as_dict(requirements, interpreter_constraints))
66 
67 
68 def create_pyproject_toml_as_dict(
69     raw_requirements: Iterable[str], interpreter_constraints: InterpreterConstraints
70 ) -> dict:
71     python_constraint = {"python": interpreter_constraints.to_poetry_constraint()}
72     project_name_to_poetry_deps = defaultdict(list)
73     for raw_req in raw_requirements:
74         # WONTFIX(#12314): add error handling.
75         req = Requirement.parse(raw_req)
76         poetry_dep = PoetryDependency.from_requirement(req)
77         project_name_to_poetry_deps[req.project_name].append(poetry_dep)
78 
79     deps = {
80         project_name: PoetryDependency.to_pyproject_toml_metadata(poetry_deps)
81         for project_name, poetry_deps in project_name_to_poetry_deps.items()
82     }
83     return {"tool": {"poetry": {**_HEADER, "dependencies": {**python_constraint, **deps}}}}
84 
85 
86 @dataclass(frozen=True)
87 class PoetryDependency:
88     name: str
89     version: str | None
90     extras: tuple[str, ...] = ()
91     markers: str | None = None
92 
93     @classmethod
94     def from_requirement(cls, requirement: Requirement) -> PoetryDependency:
95         return PoetryDependency(
96             requirement.project_name,
97             version=str(requirement.specifier) or None,  # type: ignore[attr-defined]
98             extras=tuple(sorted(requirement.extras)),
99             markers=str(requirement.marker) if requirement.marker else None,
100         )
101 
102     @classmethod
103     def to_pyproject_toml_metadata(
104         cls, deps: Sequence[PoetryDependency]
105     ) -> dict[str, Any] | list[dict[str, Any]]:
106         def convert_dep(dep: PoetryDependency) -> dict[str, Any]:
107             metadata: dict[str, Any] = {"version": dep.version or "*"}
108             if dep.extras:
109                 metadata["extras"] = dep.extras
110             if dep.markers:
111                 metadata["markers"] = dep.markers
112             return metadata
113 
114         if not deps:
115             raise AssertionError("Must have at least one element!")
116         if len(deps) == 1:
117             return convert_dep(deps[0])
118 
119         entries = []
120         name = deps[0].name
121         for dep in deps:
122             if dep.name != name:
123                 raise AssertionError(f"All elements must have the same project name. Given: {deps}")
124             entries.append(convert_dep(dep))
125         return entries
126
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/python/pants/backend/python/subsystems/poetry.py b/src/python/pants/backend/python/subsystems/poetry.py
--- a/src/python/pants/backend/python/subsystems/poetry.py
+++ b/src/python/pants/backend/python/subsystems/poetry.py
@@ -24,7 +24,7 @@
     options_scope = "poetry"
     help = "Used to generate lockfiles for third-party Python dependencies."
 
-    default_version = "poetry==1.1.8"
+    default_version = "poetry==1.1.14"
 
     register_interpreter_constraints = True
     default_interpreter_constraints = ["CPython>=3.7,<4"]

{"golden_diff": "diff --git a/src/python/pants/backend/python/subsystems/poetry.py b/src/python/pants/backend/python/subsystems/poetry.py\n--- a/src/python/pants/backend/python/subsystems/poetry.py\n+++ b/src/python/pants/backend/python/subsystems/poetry.py\n@@ -24,7 +24,7 @@\n     options_scope = \"poetry\"\n     help = \"Used to generate lockfiles for third-party Python dependencies.\"\n \n-    default_version = \"poetry==1.1.8\"\n+    default_version = \"poetry==1.1.14\"\n \n     register_interpreter_constraints = True\n     default_interpreter_constraints = [\"CPython>=3.7,<4\"]\n", "issue": "Pants poetry-based lockfiles fail to include hashes.\nThis was detected in a unit test in the Pants repo, but is a wider problem for all versions of Pants that support generating lockfiles using Poetry.\r\n\r\nThe proximal cause is this announcement from PyPI:\r\n  https://discuss.python.org/t/backwards-incompatible-change-to-pypi-json-api/17154\r\n\r\nAnd the root cause is this Poetry code:\r\n  https://github.com/python-poetry/poetry/blob/bce13c14f73060b3abbb791dea585d8fde26eaef/poetry/repositories/pypi_repository.py#L272-L283\r\n\r\nThere was a Poetry fix released and backported to the 1.1. branch here:\r\n  https://github.com/python-poetry/poetry/pull/5973\r\n\r\nUsers can fix with 2 steps:\r\n1. Update Pants config\r\n```toml\r\n[poetry]\r\n# N.B.: Works around issue described at https://github.com/pantsbuild/pants/issues/16111\r\n# Undo once on a Pants with this version or greater as the default.\r\nversion = \"poetry==1.1.14\"\r\n```\r\n2. Clear Poetry caches with `rm -rf ~/.cache/pypoetry` on Linux and `rm -rf ~/Library/Caches/pypoetry` on Mac.\r\n\r\nThis issue tracks bumping Pants default to this fixed Poetry version.\r\n\n", "before_files": [{"content": "# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nfrom collections import defaultdict\nfrom dataclasses import dataclass\nfrom textwrap import dedent\nfrom typing import Any, Iterable, Sequence\n\nimport toml\nfrom pkg_resources import Requirement\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolRequirementsBase\nfrom pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints\nfrom pants.engine.fs import FileContent\n\n# ----------------------------------------------------------------------------------------\n# Subsystem\n# ----------------------------------------------------------------------------------------\n\n\nclass PoetrySubsystem(PythonToolRequirementsBase):\n    options_scope = \"poetry\"\n    help = \"Used to generate lockfiles for third-party Python dependencies.\"\n\n    default_version = \"poetry==1.1.8\"\n\n    register_interpreter_constraints = True\n    default_interpreter_constraints = [\"CPython>=3.7,<4\"]\n\n\n# We must monkeypatch Poetry to include `setuptools` and `wheel` in the lockfile. This was fixed\n# in Poetry 1.2. See https://github.com/python-poetry/poetry/issues/1584.\n# WONTFIX(#12314): only use this custom launcher if using Poetry 1.1..\nPOETRY_LAUNCHER = FileContent(\n    \"__pants_poetry_launcher.py\",\n    dedent(\n        \"\"\"\\\n        from poetry.console import main\n        from poetry.puzzle.provider import Provider\n\n        Provider.UNSAFE_PACKAGES = set()\n        main()\n        \"\"\"\n    ).encode(),\n)\n\n\n# ----------------------------------------------------------------------------------------\n# Parsing\n# ----------------------------------------------------------------------------------------\n\n_HEADER = {\n    \"name\": \"pants-lockfile-generation\",\n    \"version\": \"0.1.0\",\n    \"description\": \"\",\n    \"authors\": [\"pantsbuild\"],\n}\n\n\ndef create_pyproject_toml(\n    requirements: Iterable[str], interpreter_constraints: InterpreterConstraints\n) -> str:\n    return toml.dumps(create_pyproject_toml_as_dict(requirements, interpreter_constraints))\n\n\ndef create_pyproject_toml_as_dict(\n    raw_requirements: Iterable[str], interpreter_constraints: InterpreterConstraints\n) -> dict:\n    python_constraint = {\"python\": interpreter_constraints.to_poetry_constraint()}\n    project_name_to_poetry_deps = defaultdict(list)\n    for raw_req in raw_requirements:\n        # WONTFIX(#12314): add error handling.\n        req = Requirement.parse(raw_req)\n        poetry_dep = PoetryDependency.from_requirement(req)\n        project_name_to_poetry_deps[req.project_name].append(poetry_dep)\n\n    deps = {\n        project_name: PoetryDependency.to_pyproject_toml_metadata(poetry_deps)\n        for project_name, poetry_deps in project_name_to_poetry_deps.items()\n    }\n    return {\"tool\": {\"poetry\": {**_HEADER, \"dependencies\": {**python_constraint, **deps}}}}\n\n\n@dataclass(frozen=True)\nclass PoetryDependency:\n    name: str\n    version: str | None\n    extras: tuple[str, ...] = ()\n    markers: str | None = None\n\n    @classmethod\n    def from_requirement(cls, requirement: Requirement) -> PoetryDependency:\n        return PoetryDependency(\n            requirement.project_name,\n            version=str(requirement.specifier) or None,  # type: ignore[attr-defined]\n            extras=tuple(sorted(requirement.extras)),\n            markers=str(requirement.marker) if requirement.marker else None,\n        )\n\n    @classmethod\n    def to_pyproject_toml_metadata(\n        cls, deps: Sequence[PoetryDependency]\n    ) -> dict[str, Any] | list[dict[str, Any]]:\n        def convert_dep(dep: PoetryDependency) -> dict[str, Any]:\n            metadata: dict[str, Any] = {\"version\": dep.version or \"*\"}\n            if dep.extras:\n                metadata[\"extras\"] = dep.extras\n            if dep.markers:\n                metadata[\"markers\"] = dep.markers\n            return metadata\n\n        if not deps:\n            raise AssertionError(\"Must have at least one element!\")\n        if len(deps) == 1:\n            return convert_dep(deps[0])\n\n        entries = []\n        name = deps[0].name\n        for dep in deps:\n            if dep.name != name:\n                raise AssertionError(f\"All elements must have the same project name. Given: {deps}\")\n            entries.append(convert_dep(dep))\n        return entries\n", "path": "src/python/pants/backend/python/subsystems/poetry.py"}], "after_files": [{"content": "# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nfrom collections import defaultdict\nfrom dataclasses import dataclass\nfrom textwrap import dedent\nfrom typing import Any, Iterable, Sequence\n\nimport toml\nfrom pkg_resources import Requirement\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolRequirementsBase\nfrom pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints\nfrom pants.engine.fs import FileContent\n\n# ----------------------------------------------------------------------------------------\n# Subsystem\n# ----------------------------------------------------------------------------------------\n\n\nclass PoetrySubsystem(PythonToolRequirementsBase):\n    options_scope = \"poetry\"\n    help = \"Used to generate lockfiles for third-party Python dependencies.\"\n\n    default_version = \"poetry==1.1.14\"\n\n    register_interpreter_constraints = True\n    default_interpreter_constraints = [\"CPython>=3.7,<4\"]\n\n\n# We must monkeypatch Poetry to include `setuptools` and `wheel` in the lockfile. This was fixed\n# in Poetry 1.2. See https://github.com/python-poetry/poetry/issues/1584.\n# WONTFIX(#12314): only use this custom launcher if using Poetry 1.1..\nPOETRY_LAUNCHER = FileContent(\n    \"__pants_poetry_launcher.py\",\n    dedent(\n        \"\"\"\\\n        from poetry.console import main\n        from poetry.puzzle.provider import Provider\n\n        Provider.UNSAFE_PACKAGES = set()\n        main()\n        \"\"\"\n    ).encode(),\n)\n\n\n# ----------------------------------------------------------------------------------------\n# Parsing\n# ----------------------------------------------------------------------------------------\n\n_HEADER = {\n    \"name\": \"pants-lockfile-generation\",\n    \"version\": \"0.1.0\",\n    \"description\": \"\",\n    \"authors\": [\"pantsbuild\"],\n}\n\n\ndef create_pyproject_toml(\n    requirements: Iterable[str], interpreter_constraints: InterpreterConstraints\n) -> str:\n    return toml.dumps(create_pyproject_toml_as_dict(requirements, interpreter_constraints))\n\n\ndef create_pyproject_toml_as_dict(\n    raw_requirements: Iterable[str], interpreter_constraints: InterpreterConstraints\n) -> dict:\n    python_constraint = {\"python\": interpreter_constraints.to_poetry_constraint()}\n    project_name_to_poetry_deps = defaultdict(list)\n    for raw_req in raw_requirements:\n        # WONTFIX(#12314): add error handling.\n        req = Requirement.parse(raw_req)\n        poetry_dep = PoetryDependency.from_requirement(req)\n        project_name_to_poetry_deps[req.project_name].append(poetry_dep)\n\n    deps = {\n        project_name: PoetryDependency.to_pyproject_toml_metadata(poetry_deps)\n        for project_name, poetry_deps in project_name_to_poetry_deps.items()\n    }\n    return {\"tool\": {\"poetry\": {**_HEADER, \"dependencies\": {**python_constraint, **deps}}}}\n\n\n@dataclass(frozen=True)\nclass PoetryDependency:\n    name: str\n    version: str | None\n    extras: tuple[str, ...] = ()\n    markers: str | None = None\n\n    @classmethod\n    def from_requirement(cls, requirement: Requirement) -> PoetryDependency:\n        return PoetryDependency(\n            requirement.project_name,\n            version=str(requirement.specifier) or None,  # type: ignore[attr-defined]\n            extras=tuple(sorted(requirement.extras)),\n            markers=str(requirement.marker) if requirement.marker else None,\n        )\n\n    @classmethod\n    def to_pyproject_toml_metadata(\n        cls, deps: Sequence[PoetryDependency]\n    ) -> dict[str, Any] | list[dict[str, Any]]:\n        def convert_dep(dep: PoetryDependency) -> dict[str, Any]:\n            metadata: dict[str, Any] = {\"version\": dep.version or \"*\"}\n            if dep.extras:\n                metadata[\"extras\"] = dep.extras\n            if dep.markers:\n                metadata[\"markers\"] = dep.markers\n            return metadata\n\n        if not deps:\n            raise AssertionError(\"Must have at least one element!\")\n        if len(deps) == 1:\n            return convert_dep(deps[0])\n\n        entries = []\n        name = deps[0].name\n        for dep in deps:\n            if dep.name != name:\n                raise AssertionError(f\"All elements must have the same project name. Given: {deps}\")\n            entries.append(convert_dep(dep))\n        return entries\n", "path": "src/python/pants/backend/python/subsystems/poetry.py"}]}