Skip to content

Commit 321b99b

Browse files
committed
merged code of polyglot_java_python_app with native_executable and java_bindings commands in standalone module
1 parent 54a40f3 commit 321b99b

File tree

23 files changed

+1110
-2027
lines changed

23 files changed

+1110
-2027
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ mx.graalpython/eclipse-launches
2424
asv
2525
*.json
2626
!**/resources/*.json
27-
!graalpython/lib-graalpython/modules/standalone/app/native-image-resources.json
27+
!graalpython/lib-graalpython/modules/standalone/shared/native-image-resources.json
28+
!graalpython/lib-graalpython/modules/standalone/shared/native-image-proxy-configuration.json
2829
language
2930
*.bc
3031
*.iml

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "overlay": "32dabcc2b777b4bbd934f634b3a07ad5ce4e8725" }
1+
{ "overlay": "fdf83c219692bf4a4d0637e68b7ae9399a546297" }
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
import os
41+
import subprocess
42+
import tempfile
43+
import unittest
44+
45+
is_enabled = 'ENABLE_STANDALONE_UNITTESTS' in os.environ and os.environ['ENABLE_STANDALONE_UNITTESTS'] == "true"
46+
47+
def get_executable(file):
48+
if os.path.isfile(file):
49+
return file
50+
exe = f"{file}.exe"
51+
if os.path.isfile(exe):
52+
return exe
53+
exe = f"{file}.cmd"
54+
if os.path.isfile(exe):
55+
return exe
56+
return None
57+
58+
def get_gp():
59+
java_home = os.path.join(__graalpython__.home, "..", "..")
60+
61+
ni = get_executable(os.path.join(java_home, "bin", "native-image"))
62+
jc = get_executable(os.path.join(java_home, "bin", "javac"))
63+
graalpy = get_executable(os.path.join(java_home, "bin", "graalpy"))
64+
java = get_executable(os.path.join(java_home, "bin", "java"))
65+
66+
if not os.path.isfile(graalpy) or not os.path.isfile(java) or not os.path.isfile(jc) or not os.path.isfile(ni):
67+
print(
68+
"Standalone module tests require a GraalVM installation including graalpy, java, javac and native-image",
69+
"Please point the JAVA_HOME environment variable to such a GraalVM root.",
70+
"__graalpython__.home : " + java_home,
71+
"native-image exists: " + str(os.path.exists(ni)),
72+
"javac exists: " + str(os.path.exists(jc)),
73+
"graalpy exits: " + str(os.path.exists(graalpy)),
74+
"java exists: " + str(os.path.exists(java)),
75+
sep="\n",
76+
)
77+
assert False
78+
return java_home, graalpy, java
79+
80+
def get_env(java_home):
81+
env = os.environ.copy()
82+
env.update({"JAVA_HOME" : java_home})
83+
84+
to_be_removed = []
85+
for k in env:
86+
# subprocess complaining about key names with "=" in them
87+
if "=" in k:
88+
to_be_removed.append(k)
89+
for k in to_be_removed:
90+
del env[k]
91+
if len(to_be_removed) > 0:
92+
print("\ntest_standalone: removed keys from subprocess environment :", to_be_removed)
93+
94+
return env
95+
96+
@unittest.skipUnless(is_enabled)
97+
def test_polyglot_app():
98+
99+
java_home, graalpy, java = get_gp()
100+
env = get_env(java_home)
101+
102+
with tempfile.TemporaryDirectory() as tmpdir:
103+
104+
target_dir = os.path.join(tmpdir, "polyglot_jp_app")
105+
106+
cmd = [graalpy, "-m", "standalone", "--verbose", "polyglot_app", "-o", target_dir]
107+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
108+
out = p.stdout.decode()
109+
print(p.stdout.decode())
110+
print(p.stderr.decode())
111+
assert "Creating polyglot java python application in directory " + target_dir in out
112+
113+
cmd = ["mvn", "package", "-Pnative"]
114+
p = subprocess.run(cmd, cwd=target_dir, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
115+
out = p.stdout.decode()
116+
print(out)
117+
print(p.stderr.decode())
118+
assert "BUILD SUCCESS" in out
119+
120+
cmd = [os.path.join(target_dir, "target", "java_python_app")]
121+
p = subprocess.run(cmd, cwd=target_dir, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
122+
out = p.stdout.decode()
123+
print(out)
124+
print(p.stderr.decode())
125+
assert out.endswith("hello java\n")
126+
127+
cmd = ["mvn", "package", "-Pjar"]
128+
p = subprocess.run(cmd, cwd=target_dir, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
129+
out = p.stdout.decode()
130+
print(out)
131+
print(p.stderr.decode())
132+
assert "BUILD SUCCESS" in out
133+
134+
cmd = [java, "-jar", os.path.join(target_dir, "target", "java_python_app-1.0-SNAPSHOT.jar")]
135+
p = subprocess.run(cmd, cwd=target_dir, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
136+
out = p.stdout.decode()
137+
print(out)
138+
print(p.stderr.decode())
139+
assert out.endswith("hello java\n")
140+
141+
@unittest.skipUnless(is_enabled)
142+
def test_native_executable_one_file():
143+
java_home, graalpy, java = get_gp()
144+
if graalpy is None or java is None:
145+
return
146+
147+
env = get_env(java_home)
148+
149+
with tempfile.TemporaryDirectory() as tmpdir:
150+
151+
source_file = os.path.join(tmpdir, "hello.py")
152+
with open(source_file, 'w') as f:
153+
f.write("print('hello world')")
154+
155+
target_file = os.path.join(tmpdir, "hello")
156+
cmd = [graalpy, "-m", "standalone", "--verbose", "native", "-m", source_file, "-o", target_file]
157+
158+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
159+
out = p.stdout.decode()
160+
print(out)
161+
print(p.stderr.decode())
162+
assert "Bundling Python resources into" in out
163+
164+
cmd = [target_file]
165+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
166+
out = p.stdout.decode()
167+
print(out)
168+
print(p.stderr.decode())
169+
assert "hello world" in out
170+
171+
@unittest.skipUnless(is_enabled)
172+
def test_native_executable_one_file_venv():
173+
java_home, graalpy, java = get_gp()
174+
if graalpy is None or java is None:
175+
return
176+
177+
env = get_env(java_home)
178+
179+
with tempfile.TemporaryDirectory() as target_dir:
180+
source_file = os.path.join(target_dir, "hello.py")
181+
with open(source_file, 'w') as f:
182+
f.write("from termcolor import colored, cprint\n")
183+
f.write("colored_text = colored('hello standalone world', 'red', attrs=['reverse', 'blink'])\n")
184+
f.write("print(colored_text)\n")
185+
186+
venv_dir = os.path.join(target_dir, "venv")
187+
cmd = [graalpy, "-m", "venv", venv_dir]
188+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
189+
out = p.stdout.decode()
190+
print(out)
191+
print(p.stderr.decode())
192+
193+
pip = os.path.join(venv_dir, "bin", "pip")
194+
cmd = [pip, "install", "termcolor"]
195+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
196+
out = p.stdout.decode()
197+
print(out)
198+
print(p.stderr.decode())
199+
200+
target_file = os.path.join(target_dir, "hello")
201+
cmd = [graalpy, "-m", "standalone", "--verbose", "native", "-Os", "-m", source_file, "--venv", venv_dir, "-o", target_file]
202+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
203+
out = p.stdout.decode()
204+
print(out)
205+
print(p.stderr.decode())
206+
assert "Bundling Python resources into" in out
207+
208+
cmd = [target_file]
209+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
210+
out = p.stdout.decode()
211+
print(out)
212+
print(p.stderr.decode())
213+
214+
assert "hello standalone world" in out
215+
216+
@unittest.skipUnless(is_enabled)
217+
def test_native_executable_module():
218+
java_home, graalpy, java = get_gp()
219+
if graalpy is None or java is None:
220+
return
221+
222+
env = get_env(java_home)
223+
224+
with tempfile.TemporaryDirectory() as tmp_dir:
225+
226+
module_dir = os.path.join(tmp_dir, "hello_app")
227+
os.makedirs(module_dir, exist_ok=True)
228+
229+
source_file = os.path.join(module_dir, "hello.py")
230+
with open(source_file, 'w') as f:
231+
f.write("def print_hello():\n")
232+
f.write(" print('hello standalone world')\n")
233+
234+
source_file = os.path.join(module_dir, "__main__.py")
235+
with open(source_file, 'w') as f:
236+
f.write("import hello\n")
237+
f.write("hello.print_hello()\n")
238+
239+
target_file = os.path.join(tmp_dir, "hello")
240+
cmd = [graalpy, "-m", "standalone", "--verbose", "native", "-Os", "-m", module_dir, "-o", target_file]
241+
242+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
243+
out = p.stdout.decode()
244+
print(out)
245+
print(p.stderr.decode())
246+
assert "Bundling Python resources into" in out
247+
248+
cmd = [target_file]
249+
p = subprocess.run(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
250+
out = p.stdout.decode()
251+
print(out)
252+
print(p.stderr.decode())
253+
assert "hello standalone world" in out

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GraalPythonModuleBuiltins.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import java.nio.file.Paths;
7575
import java.util.ArrayList;
7676
import java.util.Arrays;
77+
import java.util.Collection;
7778
import java.util.List;
7879
import java.util.logging.Level;
7980

@@ -255,6 +256,9 @@ public void postInitialize(Python3Core core) {
255256
mod.setAttribute(tsLiteral("dump_heap"), PNone.NO_VALUE);
256257
mod.setAttribute(tsLiteral("is_native_object"), PNone.NO_VALUE);
257258
}
259+
if (!context.getOption(PythonOptions.RunViaLauncher)) {
260+
mod.setAttribute(tsLiteral("list_files"), PNone.NO_VALUE);
261+
}
258262
}
259263

260264
@TruffleBoundary
@@ -957,15 +961,15 @@ abstract static class ListFiles extends PythonBinaryBuiltinNode {
957961
Object list(TruffleString dirPath, TruffleString filesListPath) {
958962
print(getContext().getStandardOut(), String.format("listing files from '%s' to '%s'\n", dirPath, filesListPath));
959963

960-
File dir = new File(dirPath.toJavaStringUncached());
964+
TruffleFile dir = getContext().getPublicTruffleFileRelaxed(dirPath);
961965
if (!dir.exists() || !dir.isDirectory()) {
962966
print(getContext().getStandardErr(), String.format("'%s' has to exist and be a directory.\n", dirPath));
963967
}
964-
new File(filesListPath.toJavaStringUncached()).getParentFile().mkdirs();
965968

966969
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filesListPath.toJavaStringUncached())))) {
970+
getContext().getPublicTruffleFileRelaxed(filesListPath).getParent().createDirectories();
967971
List<String> ret = list(dir);
968-
String parentPathString = dir.getParentFile().getAbsolutePath();
972+
String parentPathString = dir.getParent().getAbsoluteFile().getPath();
969973
for (String f : ret) {
970974
bw.write(f.substring(parentPathString.length()));
971975
bw.write("\n");
@@ -977,18 +981,18 @@ Object list(TruffleString dirPath, TruffleString filesListPath) {
977981
return PNone.NONE;
978982
}
979983

980-
private static List<String> list(File dir) {
984+
private static List<String> list(TruffleFile dir) throws IOException {
981985
List<String> ret = new ArrayList<>();
982-
File[] files = dir.listFiles();
983-
String dirPath = dir.getAbsolutePath();
986+
Collection<TruffleFile> files = dir.list();
987+
String dirPath = dir.getAbsoluteFile().getPath();
984988
if (!dirPath.endsWith("/")) {
985989
dirPath = dirPath + "/";
986990
}
987991
ret.add(dirPath);
988992
if (files != null) {
989-
for (File f : files) {
990-
if (f.isFile()) {
991-
ret.add(f.getAbsolutePath());
993+
for (TruffleFile f : files) {
994+
if (f.isRegularFile()) {
995+
ret.add(f.getAbsoluteFile().getPath());
992996
} else {
993997
ret.addAll(list(f));
994998
}

0 commit comments

Comments
 (0)