Skip to content

Commit

Permalink
feat(script-engine): add Python script engine
Browse files Browse the repository at this point in the history
  • Loading branch information
ashleycaselli committed Jan 4, 2024
1 parent 9ccecc9 commit adb77e2
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 0 deletions.
9 changes: 9 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<ver.log4j1>1.2.17</ver.log4j1>
<ver.graalvm>23.1.1</ver.graalvm>
<ver.graalvm-js>23.1.1</ver.graalvm-js>
<ver.graalvm-py>23.1.1</ver.graalvm-py>
</properties>

<dependencies>
Expand All @@ -92,6 +93,14 @@
<type>pom</type>
</dependency>

<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>python</artifactId>
<version>${ver.graalvm-py}</version>
<scope>runtime</scope>
<type>pom</type>
</dependency>

<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>jena-arq</artifactId>
Expand Down
71 changes: 71 additions & 0 deletions src/main/java/org/topbraid/shacl/py/GraalPyScriptEngine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.topbraid.shacl.py;

import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Resource;
import org.graalvm.polyglot.Context;

import javax.script.ScriptException;

/**
* @author Ashley Caselli
*/
public class GraalPyScriptEngine extends PyScriptEngineImpl {

private Context context;

public GraalPyScriptEngine() {
initEngine();
// TODO implement
}

@Override
public void initEngine() {
this.context = Context.newBuilder()
.option("engine.WarnInterpreterOnly", "false")
.build();
if (this.context == null) {
throw new RuntimeException("GraalVM not found in the current context");
}
}

@Override
public Object eval(String expr) throws ScriptException {
return context.eval("python", expr);
}

@Override
public void executeLibraries(Resource exec) throws Exception {
// TODO implement
}

@Override
public void executeScriptFromURL(String url) throws Exception {
// TODO implement
}

@Override
public Object get(String varName) {
return context.getBindings("python").getMember(varName);
}

@Override
public Object invokeFunction(String functionName, QuerySolution bindings) throws ScriptException, NoSuchMethodException {
return null;
// TODO implement
}

public final Context getContext() {
return context;
}

@Override
public Object invokeFunctionOrdered(String functionName, Object[] args) throws ScriptException, NoSuchMethodException {
return context.getBindings("python").getMember(functionName).execute(args);
}

@Override
public void put(String varName, Object value) {
context.getBindings("python").putMember(varName, value);
}

}
46 changes: 46 additions & 0 deletions src/main/java/org/topbraid/shacl/py/PyScriptEngine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*/
package org.topbraid.shacl.py;

import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Resource;

import javax.script.ScriptException;

/**
* Abstraction layer between TopBraid and the Python API.
*
* @author Ashley Caselli
*/
public interface PyScriptEngine {

void initEngine();

Object eval(String expr) throws ScriptException;

void executeLibraries(Resource exec) throws Exception;

void executeScriptFromURL(String url) throws Exception;

Object get(String varName);

Object invokeFunction(String functionName, QuerySolution bindings) throws ScriptException, NoSuchMethodException;

Object invokeFunctionOrdered(String functionName, Object[] args) throws ScriptException, NoSuchMethodException;

void put(String varName, Object value);
}
22 changes: 22 additions & 0 deletions src/main/java/org/topbraid/shacl/py/PyScriptEngineFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.topbraid.shacl.py;

public class PyScriptEngineFactory {

private static PyScriptEngineFactory singleton = new PyScriptEngineFactory();

public static PyScriptEngineFactory get() {
return singleton;
}

public static void set(PyScriptEngineFactory value) {
PyScriptEngineFactory.singleton = value;
}

public PyScriptEngine createScriptEngine(final String engineName) {
if (engineName.equals("Graal")) {
return new GraalPyScriptEngine();
}
return null;
}

}
39 changes: 39 additions & 0 deletions src/main/java/org/topbraid/shacl/py/PyScriptEngineImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.topbraid.shacl.py;

import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Resource;

import javax.script.ScriptException;

public abstract class PyScriptEngineImpl implements PyScriptEngine {
@Override
public abstract void initEngine();

@Override
public abstract Object eval(String expr) throws ScriptException;

@Override
public void executeLibraries(Resource exec) throws Exception {
// TODO implement
}

@Override
public void executeScriptFromURL(String url) throws Exception {
// TODO implement
}

@Override
public abstract Object get(String varName);

@Override
public Object invokeFunction(String functionName, QuerySolution bindings) throws ScriptException, NoSuchMethodException {
return null;
// TODO implement
}

@Override
public abstract Object invokeFunctionOrdered(String functionName, Object[] args) throws ScriptException, NoSuchMethodException;

@Override
public abstract void put(String varName, Object value);
}
22 changes: 22 additions & 0 deletions src/test/java/org/topbraid/shacl/TestGraalPyScriptEngine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.topbraid.shacl;

import org.graalvm.polyglot.Value;
import org.junit.Test;
import org.topbraid.shacl.py.PyScriptEngine;
import org.topbraid.shacl.py.PyScriptEngineFactory;

import javax.script.ScriptException;
import java.util.Objects;

public class TestGraalPyScriptEngine {

@Test
public void testEngine() throws ScriptException {
PyScriptEngine engine = PyScriptEngineFactory.get().createScriptEngine("Graal");
Value value = (Value) engine.eval("[1,2,42,4]");
int element = value.getArrayElement(2).asInt();
assert Objects.equals(element, 42);
// TODO add test with TermFactory
}

}

0 comments on commit adb77e2

Please sign in to comment.