def sync(self, host, graph_name, username=None, password=None): """ Sync the current internal spec using the given graph on the given host. :param host: The host in <hostname>:<port> or <hostname> format :type host: str :param graph_name: The name of the graph as defined in rexster.xml :type graph_name: str :param username: The username for the rexster server :type username: str :param password: The password for the rexster server :type password: str """ from thunderdome.connection import setup, execute_query setup(hosts=[host], graph_name=graph_name, username=username, password=password, index_all_fields=False) first_undefined = self._get_first_undefined(self._results) if first_undefined is None: return first_undefined = first_undefined[0] q = "" # Assign any already defined types to variables and search for the # first undefined type to be used as the starting point for executing # the remaining statements. results = [] for i,x in enumerate(self._results): if isinstance(x, Property): if x.name == first_undefined: results = self._results[i:] break else: q += "{} = g.getType('{}')\n".format(x.name, x.name) elif isinstance(x, Edge): if x.label == first_undefined: results = self._results[i:] break else: q += "{} = g.getType('{}')\n".format(x.label, x.label) elif isinstance(x, KeyIndex): if x.name == first_undefined: results = self._results[i:] break for stmt in results: q += "{}\n".format(stmt.gremlin) q += "g.stopTransaction(SUCCESS)" print q execute_query(q)
def test_db_field_io(self): v1 = DBFieldVertex.create(text='vertex1') v2 = DBFieldVertex.create(text='vertex2') e1 = DBFieldEdge.create(v1, v2, text='edge1') v1_raw = connection.execute_query('g.v(eid)', params={'eid': v1.eid}) assert v1.text == v1_raw[0]['vertex_text'] v2_raw = connection.execute_query('g.v(eid)', params={'eid': v2.eid}) assert v2.text == v2_raw[0]['vertex_text'] e1_raw = connection.execute_query('g.e(eid)', params={'eid': e1.eid}) assert e1.text == e1_raw[0]['edge_text']
def test_db_field_io(self): v1 = DBFieldVertex.create(text='vertex1') v2 = DBFieldVertex.create(text='vertex2') e1 = DBFieldEdge.create(v1, v2, text='edge1') v1_raw = connection.execute_query('g.v(eid)', params={'eid':v1.eid}) assert v1.text == v1_raw[0]['vertex_text'] v2_raw = connection.execute_query('g.v(eid)', params={'eid':v2.eid}) assert v2.text == v2_raw[0]['vertex_text'] e1_raw = connection.execute_query('g.e(eid)', params={'eid':e1.eid}) assert e1.text == e1_raw[0]['edge_text']
def sync(self, host, graph_name, username=None, password=None, dry_run=False): """ Sync the current internal spec using the given graph on the given host. :param host: The host in <hostname>:<port> or <hostname> format :type host: str :param graph_name: The name of the graph as defined in rexster.xml :type graph_name: str :param username: The username for the rexster server :type username: str :param password: The password for the rexster server :type password: str :param dry_run: If true then the generated Gremlin will just be printed :type dry_run: boolean """ def _get_name(x): """ Return the name for the given object. :param x: The object :type x: Property, Edge, KeyIndex :rtype: str """ if isinstance(x, Property) or isinstance(x, KeyIndex): return x.name elif isinstance(x, Edge): return x.label raise RuntimeError("Invalid object type {}".format(type(x))) if not dry_run: from thunderdome.connection import setup, execute_query setup(hosts=[host], graph_name=graph_name, username=username, password=password, index_all_fields=False) q = "def t = null" for x in self._results: name = _get_name(x) q += "t = g.getType('{}')\n".format(name) q += "if (t == null) {\n" q += " {}\n".format(x.gremlin) q += "} else {\n" q += " {} = g.getType('{}')\n".format(name, name) q += "}\n" q += "null" print q from thunderdome.connection import execute_query if not dry_run: return execute_query(q)
def __call__(self, instance, *args, **kwargs): args = list(args) if not self.classmethod: args = [instance.eid] + args params = self.defaults.copy() if len(args + kwargs.values()) > len(self.arg_list): raise TypeError('{}() takes {} args, {} given'.format(self.attr_name, len(self.arg_list), len(args))) #check for and calculate callable defaults for k,v in params.items(): if callable(v): params[k] = v() arglist = self.arg_list[:] for arg in args: params[arglist.pop(0)] = arg for k,v in kwargs.items(): if k not in arglist: an = self.attr_name if k in params: raise TypeError( "{}() got multiple values for keyword argument '{}'".format(an, k)) else: raise TypeError( "{}() got an unexpected keyword argument '{}'".format(an, k)) arglist.pop(arglist.index(k)) params[k] = v params = self.transform_params_to_database(params) tmp = execute_query(self.function_body, params, transaction=self.transaction) return tmp
def _reload_values(self): """ Re-read the values for this edge from the graph database. """ results = execute_query('g.e(eid)', {'eid': self.eid})[0] del results['_id'] del results['_type'] return results
def _reload_values(self): """ Re-read the values for this edge from the graph database. """ results = execute_query('g.e(eid)', {'eid':self.eid})[0] del results['_id'] del results['_type'] return results
def _execute(self, func, deserialize=True): tmp = "{}.{}()".format(self._get_partial(), func) self._vars.update({"eid": self._vertex.eid, "limit": self._limit}) results = execute_query(tmp, self._vars) if deserialize: return [Element.deserialize(r) for r in results] else: return results
def _execute(self, func, deserialize=True): tmp = "{}.{}()".format(self._get_partial(), func) self._vars.update({"eid":self._vertex.eid, "limit":self._limit}) results = execute_query(tmp, self._vars) if deserialize: return [Element.deserialize(r) for r in results] else: return results
def _reload_values(self): """ Method for reloading the current vertex by reading its current values from the database. """ results = execute_query('g.v(eid)', {'eid':self.eid})[0] del results['_id'] del results['_type'] return results
def _reload_values(self): """ Method for reloading the current vertex by reading its current values from the database. """ results = execute_query('g.v(eid)', {'eid': self.eid})[0] del results['_id'] del results['_type'] return results
def _simple_traversal(self, operation): """ Perform a simple traversal starting from the current edge returning a list of results. :param operation: The operation to be performed :type operation: str :rtype: list """ results = execute_query('g.e(eid).%s()' % operation, {'eid': self.eid}) return [Element.deserialize(r) for r in results]
def _simple_traversal(self, operation): """ Perform a simple traversal starting from the current edge returning a list of results. :param operation: The operation to be performed :type operation: str :rtype: list """ results = execute_query('g.e(eid).%s()'%operation, {'eid':self.eid}) return [Element.deserialize(r) for r in results]
def delete(self): """ Delete the current vertex from the graph. """ if self.__abstract__: raise ThunderdomeException('cant delete abstract elements') if self.eid is None: return self query = """ g.removeVertex(g.v(eid)) g.stopTransaction(SUCCESS) """ results = execute_query(query, {'eid': self.eid})
def get_by_eid(cls, eid): """ Return the edge with the given Titan-specific eid. Raises a DoesNotExist exception if no edge is found. :param eid: The Titan-specific edge id (eid) :type eid: int """ results = execute_query('g.e(eid)', {'eid': eid}) if not results: raise cls.DoesNotExist return Element.deserialize(results[0])
def get_by_eid(cls, eid): """ Return the edge with the given Titan-specific eid. Raises a DoesNotExist exception if no edge is found. :param eid: The Titan-specific edge id (eid) :type eid: int """ results = execute_query('g.e(eid)', {'eid':eid}) if not results: raise cls.DoesNotExist return Element.deserialize(results[0])
def get_by_eid(cls, eid): """ Look update a vertex by its Titan-specific id (eid). Raises a DoesNotExist exception if a vertex with the given eid was not found. :param eid: The numeric Titan-specific id :type eid: int :rtype: thunderdome.models.Vertex """ results = execute_query('g.v(eid)', {'eid':eid}) if not results: raise cls.DoesNotExist return Element.deserialize(results[0])
def get_by_eid(cls, eid): """ Look update a vertex by its Titan-specific id (eid). Raises a DoesNotExist exception if a vertex with the given eid was not found. :param eid: The numeric Titan-specific id :type eid: int :rtype: thunderdome.models.Vertex """ results = execute_query('g.v(eid)', {'eid': eid}) if not results: raise cls.DoesNotExist return Element.deserialize(results[0])
def delete(self): """ Delete the current edge from the graph. """ if self.__abstract__: raise ThunderdomeException('cant delete abstract elements') if self.eid is None: return self query = """ e = g.e(eid) if (e != null) { g.removeEdge(e) g.stopTransaction(SUCCESS) } """ results = execute_query(query, {'eid':self.eid})
def delete(self): """ Delete the current edge from the graph. """ if self.__abstract__: raise ThunderdomeException('cant delete abstract elements') if self.eid is None: return self query = """ e = g.e(eid) if (e != null) { g.removeEdge(e) g.stopTransaction(SUCCESS) } """ results = execute_query(query, {'eid': self.eid})
def all(cls, vids, as_dict=False): """ Load all vertices with the given vids from the graph. By default this will return a list of vertices but if as_dict is True then it will return a dictionary containing vids as keys and vertices found as values. :param vids: A list of thunderdome UUIDS (vids) :type vids: list :param as_dict: Toggle whether to return a dictionary or list :type as_dict: boolean :rtype: dict or list """ if not isinstance(vids, (list, tuple)): raise ThunderdomeQueryError("vids must be of type list or tuple") strvids = [str(v) for v in vids] qs = ['vids.collect{g.V("vid", it).toList()[0]}'] results = execute_query('\n'.join(qs), {'vids': strvids}) results = filter(None, results) if len(results) != len(vids): raise ThunderdomeQueryError( "the number of results don't match the number of vids requested" ) objects = [] for r in results: try: objects += [Element.deserialize(r)] except KeyError: raise ThunderdomeQueryError( 'Vertex type "{}" is unknown'.format( r.get('element_type', ''))) if as_dict: return {v.vid: v for v in objects} return objects
def all(cls, vids, as_dict=False): """ Load all vertices with the given vids from the graph. By default this will return a list of vertices but if as_dict is True then it will return a dictionary containing vids as keys and vertices found as values. :param vids: A list of thunderdome UUIDS (vids) :type vids: list :param as_dict: Toggle whether to return a dictionary or list :type as_dict: boolean :rtype: dict or list """ if not isinstance(vids, (list, tuple)): raise ThunderdomeQueryError("vids must be of type list or tuple") strvids = [str(v) for v in vids] qs = ['vids.collect{g.V("vid", it).toList()[0]}'] results = execute_query('\n'.join(qs), {'vids':strvids}) results = filter(None, results) if len(results) != len(vids): raise ThunderdomeQueryError("the number of results don't match the number of vids requested") objects = [] for r in results: try: objects += [Element.deserialize(r)] except KeyError: raise ThunderdomeQueryError('Vertex type "{}" is unknown'.format( r.get('element_type', '') )) if as_dict: return {v.vid:v for v in objects} return objects
def _get_first_undefined(self, types): """ Returns the name of the first undefined type in the graph. :param types: All types defined in the current spec :type types: list :rtype: str """ def _get_name(x): """ Return the name for the given object. :param x: The object :type x: Property, Edge, KeyIndex :rtype: str """ if isinstance(x, Property) or isinstance(x, KeyIndex): return x.name elif isinstance(x, Edge): return x.label raise RuntimeError("Invalid object type {}".format(type(x))) q = "results = [:]\n" q += "for (x in names) {\n" q += " t = g.getType(x)\n" q += " if (t == null) {\n" q += " return x\n" q += " }\n" q += "}\n" q += "null" names = [_get_name(x) for x in types] from thunderdome.connection import execute_query return execute_query(q, {'names': names})
def __call__(self, instance, *args, **kwargs): """ Intercept attempts to call the GremlinMethod attribute and perform a gremlin query returning the results. :param instance: The class instance the method was called on :type instance: object """ self._setup() args = list(args) if not self.classmethod: args = [instance.eid] + args params = self.defaults.copy() if len(args + kwargs.values()) > len(self.arg_list): raise TypeError('{}() takes {} args, {} given'.format(self.attr_name, len(self.arg_list), len(args))) #check for and calculate callable defaults for k,v in params.items(): if callable(v): params[k] = v() arglist = self.arg_list[:] for arg in args: params[arglist.pop(0)] = arg for k,v in kwargs.items(): if k not in arglist: an = self.attr_name if k in params: raise TypeError( "{}() got multiple values for keyword argument '{}'".format(an, k)) else: raise TypeError( "{}() got an unexpected keyword argument '{}'".format(an, k)) arglist.pop(arglist.index(k)) params[k] = v params = self.transform_params_to_database(params) try: from thunderdome import Vertex from thunderdome import Edge if hasattr(instance, 'get_element_type'): context = "vertices.{}".format(instance.get_element_type()) elif hasattr(instance, 'get_label'): context = "edges.{}".format(instance.get_label()) else: context = "other" context = "{}.{}".format(context, self.method_name) tmp = execute_query(self.function_body, params, transaction=self.transaction, context=context) except ThunderdomeQueryError as tqe: import pprint msg = "Error while executing Gremlin method\n\n" msg += "[Method]\n{}\n\n".format(self.method_name) msg += "[Params]\n{}\n\n".format(pprint.pformat(params)) msg += "[Function Body]\n{}\n".format(self.function_body) msg += "\n[Error]\n{}\n".format(tqe) msg += "\n[Raw Response]\n{}\n".format(tqe.raw_response) raise ThunderdomeGremlinException(msg) return tmp
def __call__(self, instance, *args, **kwargs): """ Intercept attempts to call the GremlinMethod attribute and perform a gremlin query returning the results. :param instance: The class instance the method was called on :type instance: object """ self._setup() args = list(args) if not self.classmethod: args = [instance.eid] + args params = self.defaults.copy() if len(args + kwargs.values()) > len(self.arg_list): raise TypeError('{}() takes {} args, {} given'.format( self.attr_name, len(self.arg_list), len(args))) #check for and calculate callable defaults for k, v in params.items(): if callable(v): params[k] = v() arglist = self.arg_list[:] for arg in args: params[arglist.pop(0)] = arg for k, v in kwargs.items(): if k not in arglist: an = self.attr_name if k in params: raise TypeError( "{}() got multiple values for keyword argument '{}'". format(an, k)) else: raise TypeError( "{}() got an unexpected keyword argument '{}'".format( an, k)) arglist.pop(arglist.index(k)) params[k] = v params = self.transform_params_to_database(params) try: from thunderdome import Vertex from thunderdome import Edge if hasattr(instance, 'get_element_type'): context = "vertices.{}".format(instance.get_element_type()) elif hasattr(instance, 'get_label'): context = "edges.{}".format(instance.get_label()) else: context = "other" context = "{}.{}".format(context, self.method_name) tmp = execute_query(self.function_body, params, transaction=self.transaction, context=context) except ThunderdomeQueryError as tqe: import pprint msg = "Error while executing Gremlin method\n\n" msg += "[Method]\n{}\n\n".format(self.method_name) msg += "[Params]\n{}\n\n".format(pprint.pformat(params)) msg += "[Function Body]\n{}\n".format(self.function_body) msg += "\n[Error]\n{}\n".format(tqe) msg += "\n[Raw Response]\n{}\n".format(tqe.raw_response) raise ThunderdomeGremlinException(msg) return tmp