Skip to content

Commit

Permalink
Python Plugin: Allow to use python for scripts, closes elastic#418.
Browse files Browse the repository at this point in the history
  • Loading branch information
kimchy committed Oct 9, 2010
1 parent 05e413a commit a754eba
Show file tree
Hide file tree
Showing 11 changed files with 930 additions and 0 deletions.
1 change: 1 addition & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions .idea/modules/plugin-lang-python.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

145 changes: 145 additions & 0 deletions plugins/lang/python/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
dependsOn(':elasticsearch')

apply plugin: 'java'
apply plugin: 'maven'

archivesBaseName = "elasticsearch-lang-python"

explodedDistDir = new File(distsDir, 'exploded')

configurations.compile.transitive = true
configurations.testCompile.transitive = true

// no need to use the resource dir
sourceSets.main.resources.srcDirs 'src/main/java'
sourceSets.test.resources.srcDirs 'src/test/java'

// add the source files to the dist jar
//jar {
// from sourceSets.main.allSource
//}

configurations {
dists
distLib {
visible = false
transitive = false
}
}

dependencies {
compile project(':elasticsearch')

compile('org.python:jython:2.5.2b2') { transitive = false }
distLib('org.python:jython:2.5.2b2') { transitive = false }

testCompile project(':test-testng')
testCompile('org.testng:testng:5.10:jdk15') { transitive = false }
testCompile 'org.hamcrest:hamcrest-all:1.1'
}

test {
useTestNG()
jmvArgs = ["-ea", "-Xmx1024m"]
suiteName = project.name
listeners = ["org.elasticsearch.util.testng.Listeners"]
systemProperties["es.test.log.conf"] = System.getProperty("es.test.log.conf", "log4j-gradle.properties")
}

task explodedDist(dependsOn: [jar], description: 'Builds the plugin zip file') << {
[explodedDistDir]*.mkdirs()

copy {
from configurations.distLib
into explodedDistDir
}

// remove elasticsearch files (compile above adds the elasticsearch one)
ant.delete { fileset(dir: explodedDistDir, includes: "elasticsearch-*.jar") }

copy {
from libsDir
into explodedDistDir
}

ant.delete { fileset(dir: explodedDistDir, includes: "elasticsearch-*-javadoc.jar") }
ant.delete { fileset(dir: explodedDistDir, includes: "elasticsearch-*-sources.jar") }
}

task zip(type: Zip, dependsOn: ['explodedDist']) {
from(explodedDistDir) {
}
}

task release(dependsOn: [zip]) << {
ant.delete(dir: explodedDistDir)
copy {
from distsDir
into(new File(rootProject.distsDir, "plugins"))
}
}

configurations {
deployerJars
}

dependencies {
deployerJars "org.apache.maven.wagon:wagon-http:1.0-beta-2"
}

task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

jar {
// from sourceSets.main.allJava
manifest {
attributes("Implementation-Title": "ElasticSearch", "Implementation-Version": rootProject.version, "Implementation-Date": buildTimeStr)
}
}


artifacts {
archives sourcesJar
archives javadocJar
}

uploadArchives {
repositories.mavenDeployer {
configuration = configurations.deployerJars
repository(url: rootProject.mavenRepoUrl) {
authentication(userName: rootProject.mavenRepoUser, password: rootProject.mavenRepoPass)
}
snapshotRepository(url: rootProject.mavenSnapshotRepoUrl) {
authentication(userName: rootProject.mavenRepoUser, password: rootProject.mavenRepoPass)
}

pom.project {
inceptionYear '2009'
name 'elasticsearch-plugins-lang-python'
description 'Python Plugin for ElasticSearch'
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http:https://www.apache.org/licenses/LICENSE-2.0.txt'
distribution 'repo'
}
}
scm {
connection 'git:https://github.com/elasticsearch/elasticsearch.git'
developerConnection '[email protected]:elasticsearch/elasticsearch.git'
url 'http:https://github.com/elasticsearch/elasticsearch'
}
}

pom.whenConfigured {pom ->
pom.dependencies = pom.dependencies.findAll {dep -> dep.scope != 'test' } // removes the test scoped ones
}
}
}
1 change: 1 addition & 0 deletions plugins/lang/python/src/main/java/es-plugin.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
plugin=org.elasticsearch.plugin.python.PythonPlugin
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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:https://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.
*/

package org.elasticsearch.plugin.python;

import org.elasticsearch.common.inject.Module;
import org.elasticsearch.plugins.AbstractPlugin;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.python.PythonScriptEngineService;

/**
* @author kimchy (shay.banon)
*/
public class PythonPlugin extends AbstractPlugin {

@Override public String name() {
return "lang-python";
}

@Override public String description() {
return "Python plugin allowing to add javascript scripting support";
}

@Override public void processModule(Module module) {
if (module instanceof ScriptModule) {
((ScriptModule) module).addScriptEngine(PythonScriptEngineService.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you 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:https://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.
*/

package org.elasticsearch.script.python;

import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.ScriptEngineService;
import org.python.core.Py;
import org.python.core.PyCode;
import org.python.core.PyObject;
import org.python.core.PyStringMap;
import org.python.util.PythonInterpreter;

import java.util.Map;

/**
* @author kimchy (shay.banon)
*/
//TODO we can optimize the case for Map<String, Object> similar to PyStringMap
public class PythonScriptEngineService extends AbstractComponent implements ScriptEngineService {

private final PythonInterpreter interp;

@Inject public PythonScriptEngineService(Settings settings) {
super(settings);

this.interp = PythonInterpreter.threadLocalStateInterpreter(null);
}

@Override public String[] types() {
return new String[]{"python"};
}

@Override public Object compile(String script) {
return interp.compile(script);
}

@Override public ExecutableScript executable(Object compiledScript, Map<String, Object> vars) {
return new PythonExecutableScript((PyCode) compiledScript, vars);
}

@Override public Object execute(Object compiledScript, Map<String, Object> vars) {
PyObject pyVars = Py.java2py(vars);
interp.setLocals(pyVars);
PyObject ret = interp.eval((PyCode) compiledScript);
if (ret == null) {
return null;
}
return ret.__tojava__(Object.class);
}

@Override public void close() {
interp.cleanup();
}

public class PythonExecutableScript implements ExecutableScript {

private final PyCode code;

private final PyStringMap pyVars;

public PythonExecutableScript(PyCode code, Map<String, Object> vars) {
this.code = code;
this.pyVars = new PyStringMap();
for (Map.Entry<String, Object> entry : vars.entrySet()) {
pyVars.__setitem__(entry.getKey(), Py.java2py(entry.getValue()));
}
}

@Override public Object run() {
interp.setLocals(pyVars);
PyObject ret = interp.eval(code);
if (ret == null) {
return null;
}
return ret.__tojava__(Object.class);
}

@Override public Object run(Map<String, Object> vars) {
for (Map.Entry<String, Object> entry : vars.entrySet()) {
pyVars.__setitem__(entry.getKey(), Py.java2py(entry.getValue()));
}
interp.setLocals(pyVars);
PyObject ret = interp.eval(code);
if (ret == null) {
return null;
}
return ret.__tojava__(Object.class);
}
}
}
Loading

0 comments on commit a754eba

Please sign in to comment.