Skip to content

Commit b7513ea

Browse files
Add support for PEP 621 for specifying Python version (#503)
* Add support for PEP 621 for specifying Python version
1 parent 7107430 commit b7513ea

9 files changed

Lines changed: 102 additions & 7 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.DS_Store
22
!integration/testdata
33
.bin
4+
bin
45
build
56
.idea/
67
linux

detect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func Detect(parser PyProjectPythonVersionParser) packit.DetectFunc {
3939
}
4040

4141
if pythonVersion == "" {
42-
return packit.DetectResult{}, packit.Fail.WithMessage("%s must include [tool.poetry.dependencies.python], see https://python-poetry.org/docs/pyproject/#dependencies-and-dev-dependencies", PyProjectTomlFile)
42+
return packit.DetectResult{}, packit.Fail.WithMessage("%s must include [project.requires-python] or [tool.poetry.dependencies.python], see https://python-poetry.org/docs/pyproject/#requires-python", PyProjectTomlFile)
4343
}
4444

4545
requirements := []packit.BuildPlanRequirement{

detect_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func testDetect(t *testing.T, context spec.G, it spec.S) {
141141
_, err := detect(packit.DetectContext{
142142
WorkingDir: workingDir,
143143
})
144-
Expect(err).To(MatchError(packit.Fail.WithMessage("pyproject.toml must include [tool.poetry.dependencies.python], see https://python-poetry.org/docs/pyproject/#dependencies-and-dev-dependencies")))
144+
Expect(err).To(MatchError(packit.Fail.WithMessage("pyproject.toml must include [project.requires-python] or [tool.poetry.dependencies.python], see https://python-poetry.org/docs/pyproject/#requires-python")))
145145
})
146146
})
147147

integration/default_test.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,75 @@ func testDefault(t *testing.T, context spec.G, it spec.S) {
9393
Expect(logs).To(ContainLines(
9494
" Resolving CPython version",
9595
" Candidate version sources (in priority order):",
96-
` pyproject.toml -> "3.9.*"`,
96+
` pyproject.toml -> "3.13.*"`,
9797
` -> ""`,
9898
` <unknown> -> ""`,
9999
))
100100
Expect(logs).To(ContainLines(
101-
MatchRegexp(`\s*Python version \(using pyproject.toml\): 3\.9\.\d+`),
101+
MatchRegexp(`\s*Python version \(using pyproject.toml\): 3\.13\.\d+`),
102+
))
103+
104+
container, err = docker.Container.Run.
105+
WithCommand("poetry --version").
106+
Execute(image.ID)
107+
Expect(err).ToNot(HaveOccurred())
108+
109+
Eventually(func() string {
110+
cLogs, err := docker.Container.Logs.Execute(container.ID)
111+
Expect(err).NotTo(HaveOccurred())
112+
return cLogs.String()
113+
}).Should(MatchRegexp(`Poetry.*version \d+\.\d+\.\d+`))
114+
})
115+
116+
it("builds with the poetry v1 pyproject.toml", func() {
117+
var err error
118+
var logs fmt.Stringer
119+
120+
source, err = occam.Source(filepath.Join("testdata", "poetry_v1"))
121+
Expect(err).NotTo(HaveOccurred())
122+
123+
image, logs, err = pack.WithNoColor().Build.
124+
WithPullPolicy("never").
125+
WithBuildpacks(
126+
settings.Buildpacks.CPython.Online,
127+
settings.Buildpacks.Pip.Online,
128+
settings.Buildpacks.Poetry.Online,
129+
settings.Buildpacks.BuildPlan.Online,
130+
).
131+
Execute(name, source)
132+
Expect(err).ToNot(HaveOccurred(), logs.String)
133+
134+
Expect(logs).To(ContainLines(
135+
MatchRegexp(fmt.Sprintf(`%s \d+\.\d+\.\d+`, buildpackInfo.Buildpack.Name)),
136+
" Resolving Poetry version",
137+
" Candidate version sources (in priority order):",
138+
` <unknown> -> ""`,
139+
))
140+
Expect(logs).To(ContainLines(
141+
MatchRegexp(` Selected Poetry version \(using <unknown>\): \d+\.\d+\.\d+`),
142+
))
143+
Expect(logs).To(ContainLines(
144+
" Executing build process",
145+
MatchRegexp(` Installing Poetry \d+\.\d+\.\d+`),
146+
MatchRegexp(` Completed in \d+\.\d+`),
147+
))
148+
Expect(logs).To(ContainLines(
149+
" Configuring build environment",
150+
MatchRegexp(fmt.Sprintf(` PYTHONPATH -> "\/layers\/%s\/poetry\/lib\/python\d+\.\d+\/site-packages:\$PYTHONPATH"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))),
151+
"",
152+
" Configuring launch environment",
153+
MatchRegexp(fmt.Sprintf(` PYTHONPATH -> "\/layers\/%s\/poetry\/lib\/python\d+\.\d+\/site-packages:\$PYTHONPATH"`, strings.ReplaceAll(buildpackInfo.Buildpack.ID, "/", "_"))),
154+
))
155+
156+
Expect(logs).To(ContainLines(
157+
" Resolving CPython version",
158+
" Candidate version sources (in priority order):",
159+
` pyproject.toml -> "3.12.*"`,
160+
` -> ""`,
161+
` <unknown> -> ""`,
162+
))
163+
Expect(logs).To(ContainLines(
164+
MatchRegexp(`\s*Python version \(using pyproject.toml\): 3\.12\.\d+`),
102165
))
103166

104167
container, err = docker.Container.Run.
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
[tool.poetry.dependencies]
2-
python = "3.9.*"
1+
[project]
2+
name = "integration-test"
3+
version = "0.0.0"
4+
requires-python = "3.13.*"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[[requires]]
2+
name = "poetry"
3+
4+
[requires.metadata]
5+
launch = true
6+
7+
[[requires]]
8+
name = "cpython"
9+
10+
[requires.metadata]
11+
launch = true
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[tool.poetry.dependencies]
2+
python = "3.12.*"

pyproject_parser.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ type PyProjectToml struct {
1212
}
1313
}
1414
}
15+
Project struct {
16+
RequiresPython string `toml:"requires-python"`
17+
}
1518
}
1619

1720
type PyProjectParser struct {
@@ -29,5 +32,8 @@ func (p PyProjectParser) ParsePythonVersion(pyProjectToml string) (string, error
2932
return "", err
3033
}
3134

35+
if pyProject.Project.RequiresPython != "" {
36+
return pyProject.Project.RequiresPython, nil
37+
}
3238
return pyProject.Tool.Poetry.Dependencies.Python, nil
3339
}

pyproject_parser_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ func testPyProjectParser(t *testing.T, context spec.G, it spec.S) {
2323
const (
2424
version = `[tool.poetry.dependencies]
2525
python = "===1.2.3"`
26+
version_pep621 = `[project]
27+
requires-python = ">=1.2.3"`
2628
)
2729

2830
it.Before(func() {
@@ -48,7 +50,15 @@ python = "===1.2.3"`
4850
Expect(version).To(Equal("===1.2.3"))
4951
})
5052

51-
it("returns empty string if file does not contain 'tool.poetry.dependencies.python'", func() {
53+
it("parses version PEP621", func() {
54+
Expect(os.WriteFile(pyProjectToml, []byte(version_pep621), 0644)).To(Succeed())
55+
56+
version, err := parser.ParsePythonVersion(pyProjectToml)
57+
Expect(err).NotTo(HaveOccurred())
58+
Expect(version).To(Equal(">=1.2.3"))
59+
})
60+
61+
it("returns empty string if file does not contain 'tool.poetry.dependencies.python' or project.requires-python", func() {
5262
Expect(os.WriteFile(pyProjectToml, []byte(""), 0644)).To(Succeed())
5363

5464
version, err := parser.ParsePythonVersion(pyProjectToml)

0 commit comments

Comments
 (0)