cucumber.runtime.jython.JythonBackend Maven / Gradle / Ivy
package cucumber.runtime.jython;
import cucumber.api.DataTable;
import cucumber.api.Scenario;
import cucumber.runtime.Backend;
import cucumber.runtime.CucumberException;
import cucumber.runtime.Glue;
import cucumber.runtime.UnreportedStepExecutor;
import cucumber.runtime.io.Resource;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.snippets.FunctionNameGenerator;
import cucumber.runtime.snippets.SnippetGenerator;
import gherkin.formatter.model.Step;
import org.python.core.Py;
import org.python.core.PyException;
import org.python.core.PyInstance;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
public class JythonBackend implements Backend {
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new JythonSnippet());
private final ResourceLoader resourceLoader;
private final PythonInterpreter jython;
private PyObject pyWorld;
private Glue glue;
public JythonBackend(ResourceLoader resourceLoader, PythonInterpreter jython) {
this.resourceLoader = resourceLoader;
this.jython = jython;
jython.set("backend", this);
for (Resource resource : resourceLoader.resources("classpath:cucumber/runtime/jython", "dsl.py")) {
runScript(resource);
}
}
public JythonBackend(ResourceLoader resourceLoader) {
this(resourceLoader, new PythonInterpreter());
}
@Override
public void loadGlue(Glue glue, List gluePaths) {
this.glue = glue;
for (String gluePath : gluePaths) {
for (Resource resource : resourceLoader.resources(gluePath, ".py")) {
runScript(resource);
}
}
}
@Override
public void setUnreportedStepExecutor(UnreportedStepExecutor executor) {
//Not used yet
}
@Override
public void buildWorld() {
this.pyWorld = jython.eval("World()");
}
private void runScript(Resource resource) {
try {
jython.execfile(resource.getInputStream(), resource.getAbsolutePath());
} catch (IOException e) {
throw new CucumberException(e);
}
}
@Override
public void disposeWorld() {
}
@Override
public String getSnippet(Step step, FunctionNameGenerator functionNameGenerator) {
return snippetGenerator.getSnippet(step, functionNameGenerator);
}
public void registerStepdef(PyInstance stepdef, int arity) {
glue.addStepDefinition(new JythonStepDefinition(this, stepdef, arity));
}
public void addBeforeHook(PyInstance hookDefinition) {
glue.addBeforeHook(new JythonHookDefinition(this, hookDefinition));
}
public void addAfterHook(PyInstance hookDefinition) {
glue.addAfterHook(new JythonHookDefinition(this, hookDefinition));
}
public void executeHook(PyInstance hookDefinition, Scenario scenario) {
try {
// Try to pass the scenario
hookDefinition.invoke("execute", pyWorld, Py.java2py(scenario));
} catch (PyException e) {
if (getStacktrace(e).contains("takes exactly 1 argument (2 given)")) {
// The stepdef doesn't want the scenario
hookDefinition.invoke("execute", pyWorld);
} else {
// Some other error. Just rethrow.
throw e;
}
}
}
private String getStacktrace(PyException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return sw.getBuffer().toString();
}
private PyObject argToPyObject(Object arg) {
if (arg instanceof DataTable) {
return dataTableToPyArray((DataTable) arg);
}
return new PyString((String) arg);
}
private PyObject dataTableToPyArray(DataTable table) {
PyList pyTable = new PyList();
for (List row : table.raw()) {
PyList pyRow = new PyList();
for (String cell : row) {
pyRow.append(new PyString(cell));
}
pyTable.append(pyRow);
}
return pyTable;
}
public void execute(PyInstance stepdef, Object[] args) throws Throwable {
PyObject[] pyArgs = new PyObject[args.length + 1];
pyArgs[0] = pyWorld;
for (int i = 0; i < args.length; i++) {
pyArgs[i + 1] = argToPyObject(args[i]);
}
try {
stepdef.invoke("execute", pyArgs);
} catch (PyException t) {
Object unwrapped = t.value.__tojava__(Object.class);
if (unwrapped instanceof Throwable) {
throw (Throwable) unwrapped;
} else {
throw t.getCause() == null ? t : t.getCause();
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy