Skip to content

Commit bd51e94

Browse files
committed
[GR-50391] Create template for JBang
1 parent e0db1b4 commit bd51e94

File tree

6 files changed

+305
-0
lines changed

6 files changed

+305
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ GRAALPYTHON.dist
2222
GRAALPYTHON_UNIT_TESTS.dist
2323
mx.graalpython/eclipse-launches
2424
*.json
25+
!jbang-catalog.json
2526
!**/resources/*.json
2627
!**/META-INF/**/*.json
2728
!graalpython/lib-graalpython/modules/standalone/native-image-resources.json

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ language runtime. The main focus is on user-observable behavior of the engine.
1515
* Raise `KeyboardInterrupt` exception when the process is interrupted. Enabled only when using the launcher.
1616
* Add option `python.InitialLocale` to change the default locale. If not set, then Java Locale#getDefault is used.
1717
* `multiprocessing` module now uses the `spawn` method (creates new processes) by default. The formerly default method that uses threads and multiple Truffle contexts can be selected using `multiprocessing.set_start_method('graalpy')`.
18+
*Adding integration with jBang (https://www.jbang.dev/)
19+
** running example via `jbang hello@oracle/graalpython` or `jbang hello@oracle/graalpython "print(1*4)"`
20+
** creating new script via: `jbang init --template=graalpy@oracle/graalpython myscript.java`
21+
** creating new srcript with local maven repo for testing: `jbag init --temlate=graalpy@oracle/graalpython -Dpath_to_local_repo=/absolute/path/to/local/maven/repository myscript.java'
1822

1923
## Version 23.1.0
2024
* Oracle GraalPy distributions (previously known as GraalPy Enterprise) are now available under the [GFTC license](https://www.oracle.com/downloads/licenses/graal-free-license.html). The community builds published on Github have been renamed to `graalpy-community-<version>-<os>-<arch>.tar.gz`.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
///usr/bin/env jbang "$0" "$@" ; exit $?
2+
3+
//DEPS org.graalvm.python:python-language:24.0.0-dev
4+
//DEPS org.graalvm.python:python-resources:24.0.0-dev
5+
//DEPS org.graalvm.python:python-launcher:24.0.0-dev
6+
//DEPS org.graalvm.python:python-embedding:24.0.0-dev
7+
//PIP termcolor
8+
9+
import org.graalvm.polyglot.Context;
10+
import org.graalvm.polyglot.PolyglotAccess;
11+
import org.graalvm.polyglot.PolyglotException;
12+
import org.graalvm.polyglot.io.IOAccess;
13+
import org.graalvm.python.embedding.utils.VirtualFileSystem;
14+
15+
public class hello {
16+
public static void main(String[] args) {
17+
System.out.println("Running main method from Java.");
18+
try (Context context = VirtualGraalPyContext.getContext()) {
19+
switch (args.length) {
20+
case 0:
21+
context.eval("python", "print('Hello from Python')");
22+
break;
23+
case 1:
24+
context.eval("python", args[0]);
25+
break;
26+
default:
27+
throw new IllegalArgumentException("The main() helper only takes 0-1 arguments.");
28+
}
29+
} catch (PolyglotException e) {
30+
if (e.isExit()) {
31+
System.exit(e.getExitStatus());
32+
} else {
33+
throw e;
34+
}
35+
}
36+
}
37+
}
38+
39+
final class VirtualGraalPyContext {
40+
private static final String VENV_PREFIX = "/vfs/venv";
41+
private static final String HOME_PREFIX = "/vfs/home";
42+
43+
public static Context getContext() {
44+
VirtualFileSystem vfs = VirtualFileSystem.create();
45+
var builder = Context.newBuilder()
46+
// set true to allow experimental options
47+
.allowExperimentalOptions(false)
48+
// deny all privileges unless configured below
49+
.allowAllAccess(false)
50+
// allow access to the virtual and the host filesystem, as well as sockets
51+
.allowIO(IOAccess.newBuilder()
52+
.allowHostSocketAccess(true)
53+
.fileSystem(vfs)
54+
.build())
55+
// allow creating python threads
56+
.allowCreateThread(true)
57+
// allow running Python native extensions
58+
.allowNativeAccess(true)
59+
// allow exporting Python values to polyglot bindings and accessing Java from Python
60+
.allowPolyglotAccess(PolyglotAccess.ALL)
61+
// choose the backend for the POSIX module
62+
.option("python.PosixModuleBackend", "java")
63+
// equivalent to the Python -B flag
64+
.option("python.DontWriteBytecodeFlag", "true")
65+
// equivalent to the Python -v flag
66+
.option("python.VerboseFlag", System.getenv("PYTHONVERBOSE") != null ? "true" : "false")
67+
// log level
68+
.option("log.python.level", System.getenv("PYTHONVERBOSE") != null ? "FINE" : "SEVERE")
69+
// equivalent to setting the PYTHONWARNINGS environment variable
70+
.option("python.WarnOptions", System.getenv("PYTHONWARNINGS") == null ? "" : System.getenv("PYTHONWARNINGS"))
71+
// print Python exceptions directly
72+
.option("python.AlwaysRunExcepthook", "true")
73+
// Force to automatically import site.py module, to make Python packages available
74+
.option("python.ForceImportSite", "true")
75+
// The sys.executable path, a virtual path that is used by the interpreter to discover packages
76+
.option("python.Executable", vfs.resourcePathToPlatformPath(VENV_PREFIX) + (VirtualFileSystem.isWindows() ? "\\Scripts\\python.exe" : "/bin/python"))
77+
// Do not warn if running without JIT. This can be desirable for short running scripts
78+
// to reduce memory footprint.
79+
.option("engine.WarnInterpreterOnly", "false");
80+
if (System.getProperty("org.graalvm.nativeimage.imagecode") != null) {
81+
// Set the python home to be read from the embedded resources
82+
builder.option("python.PythonHome", vfs.resourcePathToPlatformPath(HOME_PREFIX));
83+
}
84+
return builder.build();
85+
}
86+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
///usr/bin/env jbang "$0" "$@" ; exit $?
2+
{#for dep in dependencies.orEmpty}
3+
//DEPS {dep}
4+
{/for}
5+
{#if dependencies.isEmpty()}// //DEPS <dependency1> <dependency2>{/if}
6+
7+
//DEPS org.graalvm.python:python-language:24.0.0-dev
8+
//DEPS org.graalvm.python:python-resources:24.0.0-dev
9+
//DEPS org.graalvm.python:python-launcher:24.0.0-dev
10+
//DEPS org.graalvm.python:python-embedding:24.0.0-dev
11+
//PIP termcolor
12+
13+
import org.graalvm.polyglot.Context;
14+
import org.graalvm.polyglot.PolyglotAccess;
15+
import org.graalvm.polyglot.PolyglotException;
16+
import org.graalvm.polyglot.io.IOAccess;
17+
import org.graalvm.python.embedding.utils.VirtualFileSystem;
18+
19+
public class {baseName} {
20+
public static void main(String[] args) {
21+
System.out.println("Running2");
22+
try (Context context = VirtualGraalPyContext.getContext()) {
23+
switch (args.length) {
24+
case 0:
25+
context.eval("python", "import site; site._script()");
26+
break;
27+
case 1:
28+
context.eval("python", args[0]);
29+
break;
30+
default:
31+
throw new IllegalArgumentException("The main() helper only takes 0-1 arguments.");
32+
}
33+
} catch (PolyglotException e) {
34+
if (e.isExit()) {
35+
System.exit(e.getExitStatus());
36+
} else {
37+
throw e;
38+
}
39+
}
40+
}
41+
}
42+
43+
final class VirtualGraalPyContext {
44+
private static final String VENV_PREFIX = "/vfs/venv";
45+
private static final String HOME_PREFIX = "/vfs/home";
46+
47+
public static Context getContext() {
48+
VirtualFileSystem vfs = VirtualFileSystem.create();
49+
var builder = Context.newBuilder()
50+
// set true to allow experimental options
51+
.allowExperimentalOptions(false)
52+
// deny all privileges unless configured below
53+
.allowAllAccess(false)
54+
// allow access to the virtual and the host filesystem, as well as sockets
55+
.allowIO(IOAccess.newBuilder()
56+
.allowHostSocketAccess(true)
57+
.fileSystem(vfs)
58+
.build())
59+
// allow creating python threads
60+
.allowCreateThread(true)
61+
// allow running Python native extensions
62+
.allowNativeAccess(true)
63+
// allow exporting Python values to polyglot bindings and accessing Java from Python
64+
.allowPolyglotAccess(PolyglotAccess.ALL)
65+
// choose the backend for the POSIX module
66+
.option("python.PosixModuleBackend", "java")
67+
// equivalent to the Python -B flag
68+
.option("python.DontWriteBytecodeFlag", "true")
69+
// equivalent to the Python -v flag
70+
.option("python.VerboseFlag", System.getenv("PYTHONVERBOSE") != null ? "true" : "false")
71+
// log level
72+
.option("log.python.level", System.getenv("PYTHONVERBOSE") != null ? "FINE" : "SEVERE")
73+
// equivalent to setting the PYTHONWARNINGS environment variable
74+
.option("python.WarnOptions", System.getenv("PYTHONWARNINGS") == null ? "" : System.getenv("PYTHONWARNINGS"))
75+
// print Python exceptions directly
76+
.option("python.AlwaysRunExcepthook", "true")
77+
// Force to automatically import site.py module, to make Python packages available
78+
.option("python.ForceImportSite", "true")
79+
// The sys.executable path, a virtual path that is used by the interpreter to discover packages
80+
.option("python.Executable", vfs.resourcePathToPlatformPath(VENV_PREFIX) + (VirtualFileSystem.isWindows() ? "\\Scripts\\python.exe" : "/bin/python"))
81+
// Do not warn if running without JIT. This can be desirable for short running scripts
82+
// to reduce memory footprint.
83+
.option("engine.WarnInterpreterOnly", "false");
84+
if (System.getProperty("org.graalvm.nativeimage.imagecode") != null) {
85+
// Set the python home to be read from the embedded resources
86+
builder.option("python.PythonHome", vfs.resourcePathToPlatformPath(HOME_PREFIX));
87+
}
88+
return builder.build();
89+
}
90+
}
91+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
///usr/bin/env jbang "$0" "$@" ; exit $?
2+
{#for dep in dependencies.orEmpty}
3+
//DEPS {dep}
4+
{/for}
5+
{#if dependencies.isEmpty()}// //DEPS <dependency1> <dependency2>{/if}
6+
7+
//REPOS mc=https://repo1.maven.org/maven2/
8+
//REPOS local=file://{path_to_local_repo}
9+
//DEPS org.graalvm.python:python-language:24.0.0-dev
10+
//DEPS org.graalvm.python:python-resources:24.0.0-dev
11+
//DEPS org.graalvm.python:python-launcher:24.0.0-dev
12+
//DEPS org.graalvm.python:python-embedding:24.0.0-dev
13+
//PIP termcolor
14+
15+
import org.graalvm.polyglot.Context;
16+
import org.graalvm.polyglot.PolyglotAccess;
17+
import org.graalvm.polyglot.PolyglotException;
18+
import org.graalvm.polyglot.io.IOAccess;
19+
import org.graalvm.python.embedding.utils.VirtualFileSystem;
20+
21+
public class {baseName} {
22+
public static void main(String[] args) {
23+
System.out.println("Running2");
24+
try (Context context = VirtualGraalPyContext.getContext()) {
25+
switch (args.length) {
26+
case 0:
27+
context.eval("python", "import site; site._script()");
28+
break;
29+
case 1:
30+
context.eval("python", args[0]);
31+
break;
32+
default:
33+
throw new IllegalArgumentException("The main() helper only takes 0-1 arguments.");
34+
}
35+
} catch (PolyglotException e) {
36+
if (e.isExit()) {
37+
System.exit(e.getExitStatus());
38+
} else {
39+
throw e;
40+
}
41+
}
42+
}
43+
}
44+
45+
final class VirtualGraalPyContext {
46+
private static final String VENV_PREFIX = "/vfs/venv";
47+
private static final String HOME_PREFIX = "/vfs/home";
48+
49+
public static Context getContext() {
50+
VirtualFileSystem vfs = VirtualFileSystem.create();
51+
var builder = Context.newBuilder()
52+
// set true to allow experimental options
53+
.allowExperimentalOptions(false)
54+
// deny all privileges unless configured below
55+
.allowAllAccess(false)
56+
// allow access to the virtual and the host filesystem, as well as sockets
57+
.allowIO(IOAccess.newBuilder()
58+
.allowHostSocketAccess(true)
59+
.fileSystem(vfs)
60+
.build())
61+
// allow creating python threads
62+
.allowCreateThread(true)
63+
// allow running Python native extensions
64+
.allowNativeAccess(true)
65+
// allow exporting Python values to polyglot bindings and accessing Java from Python
66+
.allowPolyglotAccess(PolyglotAccess.ALL)
67+
// choose the backend for the POSIX module
68+
.option("python.PosixModuleBackend", "java")
69+
// equivalent to the Python -B flag
70+
.option("python.DontWriteBytecodeFlag", "true")
71+
// equivalent to the Python -v flag
72+
.option("python.VerboseFlag", System.getenv("PYTHONVERBOSE") != null ? "true" : "false")
73+
// log level
74+
.option("log.python.level", System.getenv("PYTHONVERBOSE") != null ? "FINE" : "SEVERE")
75+
// equivalent to setting the PYTHONWARNINGS environment variable
76+
.option("python.WarnOptions", System.getenv("PYTHONWARNINGS") == null ? "" : System.getenv("PYTHONWARNINGS"))
77+
// print Python exceptions directly
78+
.option("python.AlwaysRunExcepthook", "true")
79+
// Force to automatically import site.py module, to make Python packages available
80+
.option("python.ForceImportSite", "true")
81+
// The sys.executable path, a virtual path that is used by the interpreter to discover packages
82+
.option("python.Executable", vfs.resourcePathToPlatformPath(VENV_PREFIX) + (VirtualFileSystem.isWindows() ? "\\Scripts\\python.exe" : "/bin/python"))
83+
// Do not warn if running without JIT. This can be desirable for short running scripts
84+
// to reduce memory footprint.
85+
.option("engine.WarnInterpreterOnly", "false");
86+
if (System.getProperty("org.graalvm.nativeimage.imagecode") != null) {
87+
// Set the python home to be read from the embedded resources
88+
builder.option("python.PythonHome", vfs.resourcePathToPlatformPath(HOME_PREFIX));
89+
}
90+
return builder.build();
91+
}
92+
}
93+

jbang-catalog.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"catalogs": {},
3+
"aliases": {
4+
"hello": {
5+
"script-ref": "./graalpython/graalpy-jbang/examples/hello.java",
6+
"description": "Script that says hello from Python started from Java or execute Python expression as parameter."
7+
}
8+
},
9+
"templates": {
10+
"graalpy": {
11+
"file-refs": {
12+
"{basename}.java": "./graalpython/graalpy-jbang/templates/graalpy-template.java.qute"
13+
},
14+
"properties": {},
15+
"description": "Basic template for Graal Python java file."
16+
},
17+
"graalpy_local_repo": {
18+
"file-refs": {
19+
"{basename}.java": "./graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute"
20+
},
21+
"properties": {
22+
"path_to_local_repo": {
23+
"default": "/path/to/local/maven/repository",
24+
"description": "Path to your local maven repository"
25+
}
26+
},
27+
"description": "Basic template for Graal Python java file. Mainly for testing."
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)