Skip to content

Instantly share code, notes, and snippets.

@espeed
Created November 20, 2011 21:18
Show Gist options
  • Save espeed/1380943 to your computer and use it in GitHub Desktop.
Save espeed/1380943 to your computer and use it in GitHub Desktop.
Bulbs 0.3 gremlin.py
# -*- coding: utf-8 -*-
#
# Copyright 2011 James Thornton (http://jamesthornton.com)
# BSD License (see LICENSE for details)
#
"""
An interface for executing Gremlin scripts on the resource.
"""
import os
import yaml
from string import Template
from utils import initialize_element
class Gremlin(object):
"""An interface for executing Gremlin scripts on the resource."""
def __init__(self,resource):
self.resource = resource
# Registering it here isn't a good idea b/c you will
# have a chicken and egg scneario if you try to use
# the sripts inside Resource -- register it at the resource level
#self.register_scripts("gremlin","gremlin.yaml")
def query(self,script,**kwds):
"""
Returns initialized results of an arbitrary Gremlin scripts
run on the resource.
:param script: Gremlin script to send to the resource.
:param kwds: Resource-specific keyword params.
"""
resp = self.resource.gremlin(script,**kwds)
for result in resp.results:
yield initialize_element(self.resource,result)
def execute(self,script,**kwds):
"""
Returns raw results of an arbitrary Gremlin script.
:param script: Gremlin script to send to the resource.
:param kwds: Resource-specific keyword params.
"""
resp = self.resource.gremlin(script,**kwds)
return list(resp.results)
def register_scripts(self,name,file_name):
"""Only load/register the scripts library once to reduce overhead."""
scripts = self.resource.config.get_scripts(name)
if not scripts:
scripts = Scripts(file_name)
self.resource.config.register_scripts(name,scripts)
def get_scripts(self,name="gremlin"):
return self.resource.registry.get_scripts(name)
class Scripts(object):
"""Load Gremlin scripts from a YAML source file."""
def __init__(self,file_name="gremlin.yaml"):
self.file_name = self._get_file_name(file_name)
self.templates = self._load_templates()
def get(self,name,params={}):
"""Return a Gremlin script, generated from the params."""
template = self.templates.get(name)
params = self._quote_params(params)
return template.substitute(params)
def refresh(self):
"""Refresh the stored templates from the YAML source."""
self.templates = self._load_templates()
def _load_templates(self):
return self._parse_yaml(self.file_name)
def _get_file_name(self,file_name):
if file_name == "gremlin.yaml":
dir_name = os.path.dirname(__file__)
file_name = "%s/%s" % (dir_name,file_name)
return file_name
def _parse_yaml(self,file_name):
templates = dict()
f = open(file_name)
yaml_map = yaml.load(f)
for name, template in yaml_map.items():
#template = ';'.join(lines.split('\n'))
templates[name] = Template(template)
return templates
def _quote_params(self,params):
quoted_tuple = map(self._quote,params.items())
params = dict(quoted_tuple)
return params
def _quote(self,pair):
key, value = pair
if type(value) == str:
value = "'%s'" % value
elif value is None:
value = ""
return key, value
class ScriptWriter(object):
"""
ScriptWriter is an experiment that would be akin to a Python-based
Google Web Toolkit (http://code.google.com/webtoolkit/) for
building Gremlin scripts. And while it works well, I think it's simpler
to source Gremlin code from gremlin.yaml. But I'm leaving ScriptWriter
in the codebase for now so others can experiment with it. - James
Example:
def create_indexed_vertex(index_name,data,keys=None):
s = ScriptWriter()
s.start_transaction()
s.add_vertex("v")
s.set_property_data("v",data)
s.get_index("i",index_name,"Vertex")
keys = s.get_keys(data,keys)
for key, value in data.items():
if key in keys:
s.index_put("i",key,value,"v")
s.end_transaction()
s.return_var("v")
return s.get()
data = dict(name="James",age=34)
script = create_indexed_vertex("people",data)
resp = self.resource.gremlin(script)
"""
def __init__(self):
self.lines = []
def __add__(self,line):
self.lines.append(line)
# Elements
def add_vertex(self,varname):
line = "Vertex %s = g.addVertex(null)" % (varname)
self.lines.append(line)
def add_edge(self,varname,outV,label,inV):
line = "Edge %s = g.addEdge(null,%s,%s,%s)" % (varname,outV,inV,label)
self.lines.append(line)
def set_property(self,element,key,value):
line = "%s.setProperty('%s',%s)" % (element,key,self.quote(value))
self.lines.append(line)
def set_property_data(self,element,data):
for key, value in data.items():
self.set_property(element,key,value)
# Indices
def get_index(self,varname,index_name,index_class):
line = "%s = g.getIndex(%s,%s)" % (varname, index_name,index_class)
self.lines.append(line)
def index_put(self,index,key,value,element):
line = "%s.put('%s',%s,%s)" % (index,key,self.quote(value),element)
self.lines.append(line)
def index_get(self,index,key,value):
line = "%s.get('%s',%s,%s)" % (index,key,self.quote(value))
def index_remove(self,index,key,value,element):
line = "%s.remove('%s',%s,%s)" % (index,key,self.quote(value),element)
self.lines.append(line)
# Graph
def return_var(self,varname):
self.lines.append("return %s" % varname)
def start_transaction(self,buffer_size=0):
self.lines.append("g.setMaxBufferSize(%d)" % buffer_size)
self.lines.append("g.startTransaction()")
def end_transaction(self):
self.lines.append("g.stopTransaction(TransactionalGraph.Conclusion.SUCCESS)")
# Script Methods
def append(self,script):
self.lines.append(script)
def get(self):
script = ";".join(self.lines)
return script
def display(self):
script = ";\n".join(self.lines)
print script
def compile(self):
# store pre-compiled tempaltes in config?
pass
# Utils
def quote(value):
# quote it if it's a string, set to null if None, else return the value
if type(value) == str:
value = "'%s'" % value
elif value is None:
value = "null"
return value
def get_keys(data,keys):
if not keys:
keys = data.keys()
return keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment