Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ mvn -pl org.graalvm.python.gradle.plugin -am clean
tl;dr:

```
mvn install exec:java@integration-tests -Dintegration.test.args="test_maven_plugin.py" -Dgradle.java.home=...
mvn install exec:java@integration-tests # to view the help
mvn install exec:java@integration-tests -Dintegration.tests.args="test_maven_plugin.py" -Dgradle.java.home=...
```

The integration tests are driven by Python and implemented using unittest framework, which is
Expand All @@ -78,7 +79,7 @@ published in Mavencentral or some snapshot repository configured in Maven settin

The whole execution of the tests is wrapped in Maven goal `exec:java@integration-tests`, which passes
some necessary arguments to the test driver Python script. One can pass additional arguments for the
unittest framework using system property `integration.test.args`, for example, tests to execute or
unittest framework using system property `integration.tests.args`, for example, tests to execute or
verbosity level.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,16 +293,25 @@ protected static String getGraalPyVersion(MavenProject project) throws IOExcepti

private static Artifact getGraalPyArtifact(MavenProject project) throws IOException {
var projectArtifacts = resolveProjectDependencies(project);
Artifact graalPyArtifact = projectArtifacts.stream().filter(a -> isPythonArtifact(a)).findFirst().orElse(null);
Artifact graalPyArtifact = projectArtifacts.stream().filter(AbstractGraalPyMojo::isPythonArtifact)
.findFirst()
.orElse(null);
return Optional.ofNullable(graalPyArtifact).orElseThrow(() -> new IOException(
"Missing GraalPy dependency. Please add to your pom either %s:%s or %s:%s".formatted(POLYGLOT_GROUP_ID,
PYTHON_COMMUNITY_ARTIFACT_ID, POLYGLOT_GROUP_ID, PYTHON_ARTIFACT_ID)));
PYTHON_ARTIFACT_ID, GRAALPY_GROUP_ID, PYTHON_ARTIFACT_ID)));
}

private static boolean isPythonArtifact(Artifact a) {
return (POLYGLOT_GROUP_ID.equals(a.getGroupId()) || GRAALPY_GROUP_ID.equals(a.getGroupId()))
&& (PYTHON_COMMUNITY_ARTIFACT_ID.equals(a.getArtifactId())
|| PYTHON_ARTIFACT_ID.equals(a.getArtifactId()));
return isPythonOrPolyglotGroup(a) && (PYTHON_COMMUNITY_ARTIFACT_ID.equals(a.getArtifactId())
|| PYTHON_ARTIFACT_ID.equals(a.getArtifactId()));
}

private static boolean isPythonCommunityArtifact(Artifact a) {
return isPythonOrPolyglotGroup(a) && (PYTHON_COMMUNITY_ARTIFACT_ID.equals(a.getArtifactId()));
}

private static boolean isPythonOrPolyglotGroup(Artifact a) {
return POLYGLOT_GROUP_ID.equals(a.getGroupId()) || GRAALPY_GROUP_ID.equals(a.getGroupId());
}

private static Collection<Artifact> resolveProjectDependencies(MavenProject project) {
Expand Down Expand Up @@ -330,6 +339,15 @@ private Set<String> calculateLauncherClasspath(MavenProject project) throws IOEx
// and transitively all its dependencies
launcherClassPath.addAll(resolveDependencies(graalPyLauncherArtifact));

// check for deprecated python-community
var projectArtifacts = resolveProjectDependencies(project);
Optional<Artifact> community = projectArtifacts.stream().filter(AbstractGraalPyMojo::isPythonCommunityArtifact).findFirst();
if (community.isPresent()) {
getLog().warn("Deprecated artifact detected on classpath: " + community.get().getGroupId() + ":"
+ community.get().getArtifactId() + ". Please use '" + POLYGLOT_GROUP_ID + ":"
+ PYTHON_ARTIFACT_ID + "' instead.");
}

// 2.) graalpy dependencies
Artifact graalPyArtifact = getGraalPyArtifact(project);
assert graalPyArtifact != null;
Expand Down
19 changes: 19 additions & 0 deletions integration-tests/test_gradle_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
MISSING_FILE_WARNING = "The list of installed Python packages does not match the packages specified in the graalpy-maven-plugin configuration"
PACKAGES_CHANGED_ERROR = "packages and their version constraints in graalpy-gradle-plugin configuration are different then previously used to generate the lock file"
VENV_UPTODATE = "Virtual environment is up to date with lock file, skipping install"
DEPRECATION_MSG = "python-community' is deprecated"

def append(file, txt):
with open(file, "a") as f:
Expand Down Expand Up @@ -156,6 +157,7 @@ def check_gradle_generated_app(self):
util.check_ouput("BUILD SUCCESS", out, logger=log)
util.check_ouput("Virtual filesystem is deployed to default resources directory", out, logger=log)
util.check_ouput("This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem", out, logger=log)
util.check_ouput(DEPRECATION_MSG, out, contains=False, logger=log)
self.check_filelist(target_dir, log)

gradlew_cmd = util.get_gradle_wrapper(target_dir, self.env)
Expand Down Expand Up @@ -224,6 +226,7 @@ def check_lock_packages(self):
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir, logger=log)
util.check_ouput("pip install", out, logger=log)
util.check_ouput("BUILD SUCCESS", out, logger=log)
util.check_ouput(DEPRECATION_MSG, out, contains=False, logger=log)
util.check_ouput(MISSING_FILE_WARNING, out, contains=True, logger=log)
assert not os.path.exists(os.path.join(target_dir, "test-graalpy.lock")), log

Expand Down Expand Up @@ -641,6 +644,22 @@ def test_gradle_python_resources_dir_and_external_dir_error(self):
def test_proxy_settings(self):
self.check_proxy_settings()

def test_gradle_community_deprecation(self):
with TemporaryTestDirectory() as tmpdir:
target_dir = os.path.join(str(tmpdir), "community_deprecation_gradle" + self.target_dir_name_sufix())
self.generate_app(target_dir)
build_file = os.path.join(target_dir, self.build_file_name)
append(build_file, textwrap.dedent("""
graalPy {
community = true
packages = ["termcolor"]
}
"""))
gradlew_cmd = util.get_gradle_wrapper(target_dir, self.env)
cmd = gradlew_cmd + ["graalPyInstallPackages"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
util.check_ouput(DEPRECATION_MSG, out, contains=True)

def target_dir_name_sufix(self):
return "_groovy"

Expand Down
26 changes: 23 additions & 3 deletions integration-tests/test_maven_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
MISSING_FILE_WARNING = "The list of installed Python packages does not match the packages specified in the graalpy-maven-plugin configuration."
PACKAGES_CHANGED_ERROR = "but packages and their version constraints in graalpy-maven-plugin configuration are different then previously used to generate the lock file"
VENV_UPTODATE = "Virtual environment is up to date with lock file, skipping install"
DEPRECATION_MSG = "Deprecated artifact detected on classpath"

class MavenPluginTest(util.BuildToolTestBase):
@classmethod
Expand Down Expand Up @@ -134,8 +135,9 @@ def setUpClass(cls):
if util.extra_maven_repos and not found and not cls.extraRemoteRepo:
print("WARNING: extra Maven repos passed, but could not find GraalPy Maven archetype "
"in any of the local repos and there is no extra remote repo. This is OK only if "
"GraalPy Maven archetype of the required version is available at Mavencentral, "
"otherwise the tests will fail to generate the example application.")
"GraalPy Maven archetype of the required version is available at Mavencentral or "
"it is installed in local repo, otherwise the tests will fail to generate the "
"example application.")

def generate_app(self, tmpdir, target_dir, target_name, pom_template=None, group_id="archetype.it", package="it.pkg", log=Logger()):
extra_repo = []
Expand Down Expand Up @@ -204,6 +206,7 @@ def check_generated_app(self, use_default_vfs_path):
util.check_ouput("BUILD SUCCESS", out, logger=log)
util.check_ouput("Virtual filesystem is deployed to default resources directory", out, contains=use_default_vfs_path, logger=log)
util.check_ouput("This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem.", out, contains=use_default_vfs_path, logger=log)
util.check_ouput(DEPRECATION_MSG, out, contains=False, logger=log)

# check fileslist.txt
fl_path = os.path.join(target_dir, "target", "classes", vfs_prefix, "fileslist.txt")
Expand Down Expand Up @@ -310,6 +313,7 @@ def test_lock_file(self):
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
util.check_ouput("pip install", out)
util.check_ouput("BUILD SUCCESS", out)
util.check_ouput(DEPRECATION_MSG, out, contains=False)
util.check_ouput(MISSING_FILE_WARNING, out, contains=True)
assert not os.path.exists(os.path.join(target_dir, "test-graalpy.lock"))

Expand Down Expand Up @@ -411,6 +415,7 @@ def test_generated_app_external_resources(self):
cmd = mvnw_cmd + ["package"] + native_image_arg + ["-DmainClass=it.pkg.GraalPy"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
util.check_ouput("BUILD SUCCESS", out)
util.check_ouput(DEPRECATION_MSG, out, contains=False)

# execute and check JVM mode
cmd = mvnw_cmd + ["exec:java", "-Dexec.mainClass=it.pkg.GraalPy"]
Expand Down Expand Up @@ -448,7 +453,7 @@ def test_fail_without_graalpy_dep(self):

cmd = mvnw_cmd + ["process-resources"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
util.check_ouput("Missing GraalPy dependency. Please add to your pom either org.graalvm.polyglot:python-community or org.graalvm.polyglot:python", out)
util.check_ouput("Missing GraalPy dependency. Please add to your pom org.graalvm.polyglot:python", out)


def test_check_home_warning(self):
Expand Down Expand Up @@ -835,6 +840,21 @@ def test_multiple_namespaced_vfs(self):
assert return_code == 0, log


def test_community_dep_deprecation_message(self):
with util.TemporaryTestDirectory() as tmpdir:
target_name = "community_dep_deprecation_test"
target_dir = os.path.join(str(tmpdir), target_name)
self.generate_app(tmpdir, target_dir, target_name)

mvnw_cmd = util.get_mvn_wrapper(target_dir, self.env)
pom_path = os.path.join(target_dir, "pom.xml")

util.replace_in_file(pom_path, "<artifactId>python</artifactId>", "<artifactId>python-community</artifactId>")

cmd = mvnw_cmd + ["process-resources"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
util.check_ouput(DEPRECATION_MSG, out, contains=True)

if __name__ == "__main__":
run_path = os.path.join(os.path.abspath(__file__), 'run.py')
print(f"Run this file using the run.py driver ({run_path})")
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ public void apply(Project project) {
"WARNING: Property 'polyglotVersion' is experimental and should be used only for testing pre-release versions.");
}

if (extension.getCommunity().convention(false).get()) {
proj.getLogger().warn(
"WARNING: 'python-community' is deprecated. The plugin defaults to 'python'. Support for 'python-community' may be removed in a future release.");
}

if (extension.getPythonResourcesDirectory().isPresent() && extension.getExternalDirectory().isPresent()) {
throw new GradleException(
"Cannot set both 'externalDirectory' and 'resourceDirectory' at the same time. "
Expand Down Expand Up @@ -332,10 +337,13 @@ private static void makeSureBothEditionsAreNotOnClasspathSimultaneously(Configur
}
if (hasCommunityEdition && hasOracleEdition) {
throw new GradleException(
"You have both 'org.graalvm.python:python' and 'org.graalvm.python:python-community' on the classpath. "
+ "This is likely due to an explicit dependency added, or duplicate dependencies. You may configure "
+ "the GraalPy plugin to inject the 'python-community' artifact by using the graalPy { community = true } "
"You have both 'org.graalvm.python:python' (or 'org.graalvm.polyglot:python') and 'org.graalvm.python:python-community' (or 'org.graalvm.polyglot:python-community') on the classpath. "
+ "The 'python-community' artifact is deprecated. Ensure only one edition is present. You may configure "
+ "the GraalPy plugin to inject the deprecated 'python-community' artifact by using the graalPy { community = true } "
+ "configuration block instead.");
} else if (hasCommunityEdition && !hasOracleEdition) {
org.gradle.api.logging.Logging.getLogger(GraalPyGradlePlugin.class).warn(
"WARNING: 'python-community' is deprecated. Please depend on 'org.graalvm.python:python' or 'org.graalvm.polyglot:python' instead.");
}
});
}
Expand Down
Loading