Skip to content

Commit 9df0778

Browse files
committed
feat: add <requirementsFile> support with direct pip install -r forwarding
1 parent 9d151f5 commit 9df0778

File tree

7 files changed

+242
-209
lines changed

7 files changed

+242
-209
lines changed

graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/AbstractGraalPyMojo.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
package org.graalvm.python.maven.plugin;
4242

43+
import java.util.ArrayList;
4344
import org.apache.maven.artifact.Artifact;
4445
import org.apache.maven.artifact.DefaultArtifact;
4546
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
@@ -110,7 +111,7 @@ public AbstractGraalPyMojo(ProjectBuilder projectBuilder) {
110111
@Parameter
111112
List<String> packages;
112113

113-
@Parameter(property = "requirementsFile", defaultValue = "requirements.txt")
114+
@Parameter(property = "requirementsFile")
114115
String requirementsFile;
115116

116117
@SuppressFBWarnings("UUF_UNUSED_FIELD")
@@ -164,8 +165,7 @@ protected void preExec(boolean enableWarnings) throws MojoExecutionException {
164165
"Cannot use <packages> and <requirementsFile> at the same time. "
165166
+ "New option <requirementsFile> is a replacement for using <packages> with list of inline <package>.");
166167
}
167-
168-
packages = loadRequirementsPackages(reqFilePath);
168+
packages = new ArrayList<>();
169169
} else if (packages != null) {
170170
packages = packages.stream()
171171
.filter(p -> p != null && !p.trim().isEmpty())
@@ -216,7 +216,7 @@ protected void preExec(boolean enableWarnings) throws MojoExecutionException {
216216
}
217217
}
218218

219-
private Path resolveReqFile() {
219+
protected Path resolveReqFile() {
220220
if (requirementsFile == null || requirementsFile.isBlank()) {
221221
return null;
222222
}
@@ -237,15 +237,6 @@ private Path resolveReqFile() {
237237

238238
return null;
239239
}
240-
private List<String> loadRequirementsPackages(Path path) throws MojoExecutionException {
241-
try {
242-
return VFSUtils.requirementsPackages(path);
243-
} catch (IOException e) {
244-
throw new MojoExecutionException(
245-
"Failed to read Python requirements from file: " + requirementsFile
246-
+ ". Please verify that the file exists and is readable.", e);
247-
}
248-
}
249240

250241
protected void postExec() throws MojoExecutionException {
251242
for (Resource r : project.getBuild().getResources()) {

graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/InstallPackagesMojo.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.apache.maven.plugins.annotations.ResolutionScope;
4747
import org.apache.maven.project.ProjectBuilder;
4848
import org.graalvm.python.embedding.tools.vfs.VFSUtils;
49+
import org.graalvm.python.embedding.tools.vfs.VFSUtils.Launcher;
4950
import org.graalvm.python.embedding.tools.vfs.VFSUtils.PackagesChangedException;
5051

5152
import javax.inject.Inject;
@@ -98,9 +99,10 @@ private void manageVenv() throws MojoExecutionException {
9899
Path venvDirectory = getVenvDirectory();
99100
MavenDelegateLog log = new MavenDelegateLog(getLog());
100101
Path lockFile = getLockFile();
102+
Path reqFile = resolveReqFile();
101103
try {
102104
VFSUtils.createVenv(venvDirectory, packages, lockFile, MISSING_LOCK_FILE_WARNING, createLauncher(),
103-
getGraalPyVersion(project), log);
105+
getGraalPyVersion(project), log, reqFile);
104106
} catch (PackagesChangedException pce) {
105107
String pluginPkgsString = pce.getPluginPackages().isEmpty()
106108
? "None"

graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/LockPackagesMojo.java

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,46 @@ public class LockPackagesMojo extends AbstractGraalPyMojo {
6464
This file contains a list of all required Python packages with their specific versions,
6565
based on the packages defined in the plugin configuration and their dependencies.
6666
""";
67-
68-
@Inject
67+
public static final String MISSING_DEPENDENCY_CONFIGURATION_ERROR = """
68+
In order to run the lock-packages goal you must declare Python dependencies in the graalpy-maven-plugin configuration.
69+
70+
You must configure Python dependencies in one of the following ways:
71+
72+
Option 1: Use <packages> with inline versioned package entries:
73+
74+
<plugin>
75+
<groupId>org.graalvm.python</groupId>
76+
<artifactId>graalpy-maven-plugin</artifactId>
77+
<configuration>
78+
<packages>
79+
<package>{package_name}=={package_version}</package>
80+
</packages>
81+
...
82+
</configuration>
83+
</plugin>
84+
85+
Option 2: Use a pip-compatible requirements file:
86+
87+
<plugin>
88+
<groupId>org.graalvm.python</groupId>
89+
<artifactId>graalpy-maven-plugin</artifactId>
90+
<configuration>
91+
<requirementsFile>requirements.txt</requirementsFile>
92+
...
93+
</configuration>
94+
</plugin>
95+
96+
NOTE:
97+
• The <configuration> section must be declared on the graalpy-maven-plugin itself,
98+
not inside the process-graalpy-resources execution goal.
99+
• Do not define both <packages> and <requirementsFile> at the same time.
100+
101+
For more information, please refer to:
102+
https://github.com/oracle/graalpython/blob/master/docs/user/Embedding-Build-Tools.md
103+
""";
104+
105+
106+
@Inject
69107
public LockPackagesMojo(ProjectBuilder projectBuilder) {
70108
super(projectBuilder);
71109
}
@@ -93,33 +131,15 @@ protected void manageVenv() throws MojoExecutionException {
93131
}
94132
}
95133

96-
private void checkEmptyPackages() throws MojoExecutionException {
97-
if ((packages == null || packages.isEmpty())) {
98-
getLog().error("");
99-
getLog().error(
100-
"In order to run the lock-packages goal there have to be python packages declared in the graalpy-maven-plugin configuration.");
101-
getLog().error("");
102-
getLog().error(
103-
"NOTE that the <configuration> section has to be declared for the whole graalpy-maven-plugin");
104-
getLog().error("and not specifically for the process-graalpy-resources execution goal.");
105-
getLog().error("");
106-
getLog().error("Please add the <packages> section to your configuration as follows:");
107-
getLog().error("<plugin>");
108-
getLog().error(" <groupId>org.graalvm.python</groupId>");
109-
getLog().error(" <artifactId>graalpy-maven-plugin</artifactId>");
110-
getLog().error(" <configuration>");
111-
getLog().error(" <packages>");
112-
getLog().error(" <package>{package_name}=={package_version}</package>");
113-
getLog().error(" </packages>");
114-
getLog().error(" ...");
115-
getLog().error(" </configuration>");
116-
getLog().error("");
117-
118-
getLog().error(
119-
"For more information, please refer to https://github.com/oracle/graalpython/blob/master/docs/user/Embedding-Build-Tools.md");
120-
getLog().error("");
121-
122-
throw new MojoExecutionException("missing python packages in plugin configuration");
123-
}
124-
}
134+
private void checkEmptyPackages() throws MojoExecutionException {
135+
Path reqFilePath = resolveReqFile();
136+
boolean emptyPackages = packages == null || packages.isEmpty();
137+
boolean requirementsExists = reqFilePath != null;
138+
if (emptyPackages && !requirementsExists) {
139+
getLog().error("");
140+
getLog().error(MISSING_DEPENDENCY_CONFIGURATION_ERROR);
141+
getLog().error("");
142+
throw new MojoExecutionException("Missing Python dependency configuration.");
143+
}
144+
}
125145
}

integration-tests/test_maven_plugin.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -857,28 +857,9 @@ def test_requirements_txt_packages(self):
857857
util.check_ouput("BUILD SUCCESS", out)
858858
assert return_code == 0
859859

860-
cmd = mvnw_cmd + ["org.graalvm.python:graalpy-maven-plugin:lock-packages"]
861-
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
862-
863-
util.check_ouput("BUILD SUCCESS", out)
864-
assert return_code == 0
865-
866-
util.check_ouput(
867-
"In order to run the lock-packages goal there have to be python packages declared in the graalpy-maven-plugin configuration",
868-
out,
869-
contains=False,
870-
)
871-
872-
# lock-файл створився
873860
lock_file = os.path.join(target_dir, "graalpy.lock")
874-
assert os.path.exists(lock_file)
875-
876-
# 3) перевіряємо, що в lock-файлі є хоча б один пакет з requirements.txt
877-
with open(lock_file, encoding="utf-8") as f:
878-
lock_content = f.read()
861+
assert not os.path.exists(lock_file)
879862

880-
# підстав назву пакета з requirements.txt
881-
assert "pyfiglet==" in lock_content
882863

883864
if __name__ == "__main__":
884865
run_path = os.path.join(os.path.abspath(__file__), 'run.py')

0 commit comments

Comments
 (0)