Package: graph-runner
Graph Runner (ALPHA)Overviewgraph-runnerprovides a way to add actual Python code to Graph DB nodes, which can be used to create real-time dynamically property values. Rather than only storing fixed values, you have the option to create rich property values that can be calculated on-the-fly with other vertex property values.IMPORTANT:This codebase currently uses theexec()method to execute Python code. This was
used for sake of time since this was built for a specific trusted project. Ideally, a more secure
method should be used, but just be aware that arbitrary code can be executed.Quick StartTo installgraph-runner:pip install graph-runnerWhile there's no full documentation yet, here's a code sample that walks you through the majority of the current features. Make sure that you export a CONN_STR environment variable that matches your connections string.The only code this does not show is thehttps://github.com/troylar/graph-runner/blob/master/entities/init.py. Each custom entity maps to a node type. You simply have to define theexec_propertiesin the class definition, which define which properties that contain executable code.fromgremlin_pythonimportstaticsfromgremlin_python.structure.graphimportGraphfromgremlin_python.process.graph_traversalimport__fromgremlin_python.process.strategiesimport*fromgremlin_python.driver.driver_remote_connectionimportDriverRemoteConnectionfromgraph_entityimportGraphEntityfromentitiesimportEventEntity,PersonEntityimportosgraph=Graph()g=graph.traversal().withRemote(DriverRemoteConnection(os.environ.get('CONN_STR'),'g'))# We're going to add an entity to the graphfirst_event=EventEntity(Traversal=g)print('Adding node')# add_node() returns a traversal, so we have to next()first_event.add_node().next()# Now we're going to add a dynamic property called 'ignore_if' with a simple boolean piece of code# NOTE: exec_val is always required as the return valuefirst_event.ignore_if='exec_val=1==1'# print the idprint('Node id ={}'.format(first_event.id))# print the node type, which maps to the EventEntity class and is saved as a property in the graphprint('Node type:{}'.format(first_event.full_self()))# this is where it gets cool . . . the ignore_if property method was dynamically added to the python object# and when you access the property, it executes the code and returns the valueprint('ignore_if property:{}'.format(first_event.ignore_if()))# now let's create a GraphEntity object and from scratch, load the node we just createdge=GraphEntity(Traversal=g)print('Getting node')node=ge.from_node(first_event.id)print('Node id ={}'.format(node.id))print('Node type:{}'.format(node.full_self()))print('ignore_if property:{}'.format(node.ignore_if()))# let's create a person entity with an 'is_present' propertype=PersonEntity(Traversal=g)print('Adding person')pe.add_node().next()pe.is_present='True'# let's create a second eventsecond_event=EventEntity(Traversal=g)print('Adding another event')second_event.add_node().next()# let's add some more complex logic to a property# this property is saying that if the person is present, move to the next eventnext_node_code="""from graph_entity import GraphEntityge = GraphEntity(Traversal=g)if ge.from_node('{}').is_present()=='True':exec_val = g.V('{}')else:exec_val = "N/A"""".format(pe.id,second_event.id)# because is_present is true, we get our next nodefirst_event.next_node=next_node_codeprint(first_event.next_node())# change is_present to false, and the next_node is N/Ape.is_present='False'print(first_event.next_node())# we can also use jinja2 templating, which allows us to pass in dynamic values at run-time# in this case, it's the same code, but we we're alloing the ids to be passed in at run-timenext_node_template="""from graph_entity import GraphEntityge = GraphEntity(Traversal=g)if ge.from_node('{{ person_node_id }}').is_present()=='True':exec_val = g.V('{{ next_node_id }}')else:exec_val = "N/A""""# run the same code, but pass ids at run-timefirst_event.next_node=next_node_templatepe.is_present='True'print(first_event.next_node(Data={'person_node_id':pe.id,'next_node_id':second_event.id}))pe.is_present='False'print(first_event.next_node(Data={'person_node_id':pe.id,'next_node_id':second_event.id}))