Skip to content

Commit 1ab3e2e

Browse files
committed
introduce tool.poetry.self.version to define a constraint for the Poetry version the project is compatible with (#9547)
1 parent 7d7179f commit 1ab3e2e

File tree

9 files changed

+84
-2
lines changed

9 files changed

+84
-2
lines changed

docs/pyproject.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,18 @@ If you publish your package on PyPI, they will appear in the `Project Links` sec
487487
## `self`
488488

489489
In this section, you can specify requirements for Poetry itself.
490+
For example, you can specify a constraint for the Poetry version that is required
491+
for this project:
490492

491-
You can also specify that a plugin is required for your project:
492-
You can specify that certain plugins are required for your project:
493+
```toml
494+
[tool.poetry.self]
495+
version = ">=2.0"
496+
```
497+
498+
If you are using a Poetry version that is not allowed by this constraint,
499+
an error will be raised.
500+
501+
Further, you can specify that certain plugins are required for your project:
493502

494503
```toml
495504
[tool.poetry.self.plugins]

src/poetry/factory.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010

1111
from cleo.io.null_io import NullIO
1212
from packaging.utils import canonicalize_name
13+
from poetry.core.constraints.version import Version
14+
from poetry.core.constraints.version import parse_constraint
1315
from poetry.core.factory import Factory as BaseFactory
1416
from poetry.core.packages.dependency_group import MAIN_GROUP
1517

18+
from poetry.__version__ import __version__
1619
from poetry.config.config import Config
1720
from poetry.exceptions import PoetryException
1821
from poetry.json import validate_object
@@ -56,6 +59,17 @@ def create_poetry(
5659

5760
base_poetry = super().create_poetry(cwd=cwd, with_groups=with_groups)
5861

62+
if version_str := base_poetry.pyproject.poetry_config.get("self", {}).get(
63+
"version"
64+
):
65+
version_constraint = parse_constraint(version_str)
66+
version = Version.parse(__version__)
67+
if not version_constraint.allows(version):
68+
raise PoetryException(
69+
f"This project requires Poetry {version_constraint},"
70+
f" but you are using Poetry {version}"
71+
)
72+
5973
poetry_file = base_poetry.pyproject_path
6074
locker = Locker(poetry_file.parent / "poetry.lock", base_poetry.pyproject.data)
6175

src/poetry/json/schemas/poetry.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
"type": "object",
99
"description": "Requirements for Poetry itself.",
1010
"properties": {
11+
"version": {
12+
"type": "string",
13+
"description": "The version constraint for Poetry itself.",
14+
"$ref": "#/definitions/dependency"
15+
},
1116
"plugins": {
1217
"type": "object",
1318
"description": "Poetry plugins that are required for this project.",
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[tool.poetry]
2+
package-mode = false
3+
4+
[tool.poetry.self]
5+
version = "<1.2"
6+
7+
[tool.poetry.dependencies]
8+
python = "^3.8"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[tool.poetry]
2+
package-mode = false
3+
4+
[tool.poetry.self]
5+
version = ">=1.2"
6+
7+
[tool.poetry.dependencies]
8+
python = "^3.8"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[tool.poetry]
2+
name = "foobar"
3+
version = "0.1.0"
4+
description = ""
5+
authors = ["Your Name <[email protected]>"]
6+
7+
[tool.poetry.self]
8+
version = 2

tests/json/fixtures/self_valid.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@ version = "0.1.0"
44
description = ""
55
authors = ["Your Name <[email protected]>"]
66

7+
[tool.poetry.self]
8+
version = ">=2.0"
9+
710
[tool.poetry.self.plugins]
811
foo = ">=1.0"

tests/json/test_schema.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ def test_self_valid() -> None:
6161
assert Factory.validate(content) == {"errors": [], "warnings": []}
6262

6363

64+
def test_self_invalid_version() -> None:
65+
toml: dict[str, Any] = TOMLFile(FIXTURE_DIR / "self_invalid_version.toml").read()
66+
content = toml["tool"]["poetry"]
67+
assert Factory.validate(content) == {
68+
"errors": ["data.self.version must be string"],
69+
"warnings": [],
70+
}
71+
72+
6473
def test_self_invalid_plugin() -> None:
6574
toml: dict[str, Any] = TOMLFile(FIXTURE_DIR / "self_invalid_plugin.toml").read()
6675
content = toml["tool"]["poetry"]

tests/test_factory.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from poetry.core.packages.package import Package
1515
from poetry.core.packages.vcs_dependency import VCSDependency
1616

17+
from poetry.__version__ import __version__
1718
from poetry.exceptions import PoetryException
1819
from poetry.factory import Factory
1920
from poetry.plugins.plugin import Plugin
@@ -230,6 +231,23 @@ def test_create_poetry_non_package_mode(fixture_dir: FixtureDirGetter) -> None:
230231
assert not poetry.is_package_mode
231232

232233

234+
def test_create_poetry_version_ok(fixture_dir: FixtureDirGetter) -> None:
235+
io = BufferedIO()
236+
Factory().create_poetry(fixture_dir("self_version_ok"), io=io)
237+
238+
assert io.fetch_output() == ""
239+
assert io.fetch_error() == ""
240+
241+
242+
def test_create_poetry_version_not_ok(fixture_dir: FixtureDirGetter) -> None:
243+
with pytest.raises(PoetryException) as e:
244+
Factory().create_poetry(fixture_dir("self_version_not_ok"))
245+
assert (
246+
str(e.value)
247+
== f"This project requires Poetry <1.2, but you are using Poetry {__version__}"
248+
)
249+
250+
233251
def test_poetry_with_default_source_legacy(
234252
fixture_dir: FixtureDirGetter, with_simple_keyring: None
235253
) -> None:

0 commit comments

Comments
 (0)