def _initialize_element(self, resource, results): """ Initialize the element's resource, _data, and Gremlin proxy. This is called explicitly by Element.__init__ and Model.__init__ :param resource: The Resource object for the database. :param results: The results list returned by Rexster. """ self._data = {} self.resource = resource self._set_element_data(results) self._gremlin = Gremlin(self.resource)
def rebuild(self,raw=False): # need class_map b/c the Blueprints need capitalized class names, # but Rexster returns lower-case class names for index_class class_map = dict(vertex='Vertex',edge='Edge') klass = class_map[self.index_class] script = "index = g.getIndex('%s',%s);" % (self.index_name,klass) script = script + "AutomaticIndexHelper.reIndexElements(g, index, g.getVertices())" resp = Gremlin(self.resource).execute(script,raw=True) if raw or not resp.results: return resp return list(resp.results)
def _initialize_element(self,resource,results): """ Initialize the element's resource, _data, and Gremlin proxy. This is called explicitly by Element.__init__ and Model.__init__ :param resource: The Resource object for the database. :param results: The results list returned by Rexster. """ self.resource = resource self._set_element_data(results) self._gremlin = Gremlin(self.resource)
def __init__(self,db_url=config.DATABASE_URL): self.resource = Resource(db_url) self.vertices = VertexProxy(self.resource) self.edges = EdgeProxy(self.resource) self.indices = IndexProxy(self.resource) self.gremlin = Gremlin(self.resource)
class Graph(object): """ The primary interface to graph databases on the Rexster REST server. Instantiates the database :class:`~bulbs.rest.Resource` object using the specified database URL and sets up proxy objects to the database. :keyword db_url: The URL to the specific database on Rexster. :ivar vertices: :class:`~bulbs.element.VertexProxy` object for the Resource. :ivar edges: :class:`~bulbs.element.EdgeProxy` object for the Resource. :ivar indices: :class:`~bulbs.index.IndexProxy` object for the Resource. :ivar gremlin: :class:`~bulbs.gremlin.Gremlin` object for the Resource. Example:: >>> from bulbs.graph import Graph >>> g = Graph() >>> james = g.vertices.create({'name':'James'}) >>> julie = g.vertices.create({'name':'Julie'}) >>> g.edges.create(james,"knows",julie) """ def __init__(self,db_url=config.DATABASE_URL): self.resource = Resource(db_url) self.vertices = VertexProxy(self.resource) self.edges = EdgeProxy(self.resource) self.indices = IndexProxy(self.resource) self.gremlin = Gremlin(self.resource) #def __rshift__(self,b): # return list(self) @property def V(self): """ Returns all the vertices of the graph. Example:: >>> g = Graph() >>> vertices = g.V :rtype: List of :class:`~bulbs.element.Vertex` objects. """ vertices = self.gremlin.query("g.V",Vertex,raw=True) return list(vertices) @property def E(self): """ Returns all the edges of the graph. Example:: >>> g = Graph() >>> edges = g.E :rtype: List of :class:`~bulbs.element.Edge` objects. """ edges = self.gremlin.query("g.E",Edge,raw=True) return list(edges) def idxV(self,**kwds): """ Looks up a key/value pair in the vertex index and returns a generator containing the vertices matching the key and value. :keyword pair: The key/value pair to match on. :keyword raw: Boolean. If True, return the raw Response object. Defaults to False. Example:: >>> g = Graph() >>> vertices = g.idxV(name="James") :rtype: Generator of :class:`~bulbs.element.Vertex` objects. You can turn the generator into a list by doing:: >>> vertices = g.idxV(name="James") >>> vertices = list(vertices) """ return self._idx("vertices",**kwds) #def _initialize_results(self,results,raw): # if raw is True: # return (result for result in results) # else: # return (Vertex(self.resource,result) for result in results) def idxE(self,**kwds): """ Looks up a key/value pair in the edge index and returns a generator containing the edges matching the key and value. :keyword pair: The key/value pair to match on. :keyword raw: Boolean. If True, return the raw Response object. Defaults to False. Example:: >>> g = Graph() >>> edges = g.idxE(label="knows") :rtype: Generator of :class:`~bulbs.element.Edge` objects. You can turn the generator into a list by doing:: >>> edges = g.idxE(label="knows") >>> edges = list(edges) """ return self._idx("edges",**kwds) def _idx(self,index_name,**kwds): """ Returns the Rexster Response object of the index look up. :param index_name: The name of the index. :param pair: The key/value pair to match on. :keyword raw: Boolean. If True, return the raw Response object. Defaults to False. """ raw = kwds.pop("raw",False) key, value = kwds.popitem() target = "%s/indices/%s" % (self.resource.db_name,index_name) params = dict(key=key,value=value) resp = self.resource.get(target,params) if raw: return resp if resp.results: class_map = dict(vertices=Vertex,edges=Edge) element_class = class_map[index_name] return (element_class(self.resource,result) for result in resp.results) def load_graphml(self,url): """ Loads a GraphML file into the database, and returns the Rexster response object. :param url: The URL of the GraphML file to load. """ script = "g.loadGraphML('%s')" % url params = dict(script=script) resp = self.resource.get(self.base_target,params) return resp def save_graphml(self): """ Returns a GraphML file representing the entire database. """ script = """ g.saveGraphML('data/graphml'); new File('data/graphml').getText(); """ params = dict(script=script) resp = self.resource.get(self.base_target,params) return resp.results def clear(self): """ Deletes all the elements in the graph. Example:: >>> g = Graph() >>> g.clear() .. admonition:: WARNING g.clear() will delete all your data! """ target = self.resource.db_name resp = self.resource.delete(target,params=None) return resp
class Element(object): """This is an abstract base class for Vertex and Edge""" def __init__(self, resource, results): """ Initializes an element after it is added, updated, or retrieved from the database. :param resource: The Resource object for the database. :param results: The results list returned by Rexster. """ # NOTE: Put all the init stuff in initialize_element() because # Model() calls it explicitly instead of super().__init__() self._initialize_element(resource, results) def _initialize_element(self, resource, results): """ Initialize the element's resource, _data, and Gremlin proxy. This is called explicitly by Element.__init__ and Model.__init__ :param resource: The Resource object for the database. :param results: The results list returned by Rexster. """ self._data = {} self.resource = resource self._set_element_data(results) self._gremlin = Gremlin(self.resource) def _set_element_data(self, results): """ Set the elements data returned by the DB. :param results: The results list returned by Rexster. """ self._data = results def __getattr__(self, attribute): """ Returns the value stored in the DB if the property hasn't been set explicitly. If you explicitly set/change the values of an element's properties, make sure you call save() to updated the values in the DB. """ try: return self._data[attribute] except: raise AttributeError("%s not found and not in self._data" \ % (attribute)) def __len__(self): """Returns the number of items stored in the DB results""" return len(self._data) def __contains__(self, item): """Returns True if attribute is a key that has been stored in the DB""" return item in self._data def __eq__(self, obj): """Returns True if the elements are equal""" return (hasattr(obj, "_id") and self._id == obj._id and hasattr(obj, "_data") and self._data == obj._data and hasattr(obj, "__class__") and self.__class__ == obj.__class__) def __ne__(self, obj): """Returns True if the elements are not equal.""" return not self.__eq__(obj) def __repr__(self): """Returns the string representation of the attribute.""" return self.__unicode__() def __str__(self): """Returns the string representation of the attribute.""" return self.__unicode__() def __unicode__(self): """Returns the unicode representation of the attribute.""" #return u"<Rexster %s %s: %s>" % \ # (self.resource.db_name, self.__class__.__name__, self._id) return u"<%s: %s>" % (self.__class__.__name__, self._proxy(self.resource)._uri(self._id)) @property def _id(self): """ Returns the element ID. This is the element's "primary key"; however, some DBs (such as neo4j) reuse IDs if they are deleted so be careful with how you use them. If you want to guarantee they are unique across the DB's lifetime either don't physically delete elements and just set a deleted flag, or use some other mechanism, such as an external sequence or a hash. """ #int(self._data['_id']) return utils.coerce_id(self._data['_id']) @property def _type(self): """Returns the _type set by Rexster: either vertex, edge, or index.""" return self._data['_type'] @property def _proxy(self): """Returns the element's proxy to Rexster.""" proxy_map = dict(vertex=VertexProxy, edge=EdgeProxy) return proxy_map[self._type] @property def map(self): """Returns a dict of the element's data that's stored in the DB.""" private_keys = ['_id', '_type', '_outV', '_inV', '_label'] map_ = dict() for key, value in self._data.items(): if key not in private_keys: map_.update({key: value}) return map_ def gremlin(self, script, *classes, **kwds): """ Returns a generator containing the results of the Gremlin script. Remember you can always use the list() function to turn an iterator or a generator into a list. Sometimes it's useful to turn a generator into a list when doing unittests or when you want to check how many items are in the results. :param script: Gremlin script to send to Rexster. Since this begins from the context of an element instead of a graph, the script should begin with the reference to itself (v or e) instead of a reference to the graph (g). Example: .. code-block:: groovy // do this... v.outE('created') // instead of... g.v(1).outE('created') :param classes: Zero or more subclasses of Element to use when initializing the the elements returned by the query. For example, if Person is a subclass of Node (which is defined in model.py and is a subclass of Vertex), and the query returns person elements, pass in the Person class and the method will use the element_type defined in the class to initialize the returned items to a Person object. :keyword return_keys: Optional keyword param. A comma-separated list of keys (DB properties) to return. If set to None, it returns all properties. Defaults to None. :keyword raw: Optional keyword param. If set to True, it won't try to initialize data. Defaults to False. :rtype: Generator of items. The data types of the items returned vary depending on the query. Example:: >>> from bulbs.graph import Graph() >>> g = Graph() >>> james = g.vertices.get(3) >>> script = "v.outE('knows').inV" >>> results = james.gremlin(script) """ # TODO: now that we're using a proxy, should we always include the # calling class in the class_map? return_keys = kwds.pop('return_keys', None) raw = kwds.pop('raw', False) class_map = dict(vertex=Vertex, edge=Edge) kwds = dict(default_class_map=class_map, return_keys=return_keys, raw=raw) return self._gremlin._element_query(self, script, *classes, **kwds)
def __init__(self, db_url=config.DATABASE_URL): self.resource = Resource(db_url) self.vertices = VertexProxy(self.resource) self.edges = EdgeProxy(self.resource) self.indices = IndexProxy(self.resource) self.gremlin = Gremlin(self.resource)
class Graph(object): """ The primary interface to graph databases on the Rexster REST server. Instantiates the database :class:`~bulbs.rest.Resource` object using the specified database URL and sets up proxy objects to the database. :keyword db_url: The URL to the specific database on Rexster. :ivar vertices: :class:`~bulbs.element.VertexProxy` object for the Resource. :ivar edges: :class:`~bulbs.element.EdgeProxy` object for the Resource. :ivar indices: :class:`~bulbs.index.IndexProxy` object for the Resource. :ivar gremlin: :class:`~bulbs.gremlin.Gremlin` object for the Resource. Example:: >>> from bulbs.graph import Graph >>> g = Graph() >>> james = g.vertices.create({'name':'James'}) >>> julie = g.vertices.create({'name':'Julie'}) >>> g.edges.create(james,"knows",julie) """ def __init__(self, db_url=config.DATABASE_URL): self.resource = Resource(db_url) self.vertices = VertexProxy(self.resource) self.edges = EdgeProxy(self.resource) self.indices = IndexProxy(self.resource) self.gremlin = Gremlin(self.resource) #def __rshift__(self,b): # return list(self) @property def V(self): """ Returns all the vertices of the graph. Example:: >>> g = Graph() >>> vertices = g.V :rtype: List of :class:`~bulbs.element.Vertex` objects. """ vertices = self.gremlin.query("g.V", Vertex, raw=True) return list(vertices) @property def E(self): """ Returns all the edges of the graph. Example:: >>> g = Graph() >>> edges = g.E :rtype: List of :class:`~bulbs.element.Edge` objects. """ edges = self.gremlin.query("g.E", Edge, raw=True) return list(edges) def idxV(self, **kwds): """ Looks up a key/value pair in the vertex index and returns a generator containing the vertices matching the key and value. :keyword pair: The key/value pair to match on. :keyword raw: Boolean. If True, return the raw Response object. Defaults to False. Example:: >>> g = Graph() >>> vertices = g.idxV(name="James") :rtype: Generator of :class:`~bulbs.element.Vertex` objects. You can turn the generator into a list by doing:: >>> vertices = g.idxV(name="James") >>> vertices = list(vertices) """ return self._idx("vertices", **kwds) #def _initialize_results(self,results,raw): # if raw is True: # return (result for result in results) # else: # return (Vertex(self.resource,result) for result in results) def idxE(self, **kwds): """ Looks up a key/value pair in the edge index and returns a generator containing the edges matching the key and value. :keyword pair: The key/value pair to match on. :keyword raw: Boolean. If True, return the raw Response object. Defaults to False. Example:: >>> g = Graph() >>> edges = g.idxE(label="knows") :rtype: Generator of :class:`~bulbs.element.Edge` objects. You can turn the generator into a list by doing:: >>> edges = g.idxE(label="knows") >>> edges = list(edges) """ return self._idx("edges", **kwds) def _idx(self, index_name, **kwds): """ Returns the Rexster Response object of the index look up. :param index_name: The name of the index. :param pair: The key/value pair to match on. :keyword raw: Boolean. If True, return the raw Response object. Defaults to False. """ raw = kwds.pop("raw", False) key, value = kwds.popitem() target = "%s/indices/%s" % (self.resource.db_name, index_name) params = dict(key=key, value=value) resp = self.resource.get(target, params) if raw: return resp if resp.results: class_map = dict(vertices=Vertex, edges=Edge) element_class = class_map[index_name] return (element_class(self.resource, result) for result in resp.results) def load_graphml(self, url): """ Loads a GraphML file into the database, and returns the Rexster response object. :param url: The URL of the GraphML file to load. """ script = "g.loadGraphML('%s')" % url resp = self.gremlin.execute(script) return resp def save_graphml(self): """ Returns a GraphML file representing the entire database. """ script = """ g.saveGraphML('data/graphml'); new File('data/graphml').getText(); """ results = self.gremlin.execute(script) return results[0] def clear(self): """ Deletes all the elements in the graph. Example:: >>> g = Graph() >>> g.clear() .. admonition:: WARNING g.clear() will delete all your data! """ target = self.resource.db_name resp = self.resource.delete(target, params=None) return resp
class Element(object): """This is an abstract base class for Vertex and Edge""" def __init__(self,resource,results): """ Initializes an element after it is added, updated, or retrieved from the database. :param resource: The Resource object for the database. :param results: The results list returned by Rexster. """ # NOTE: Put all the init stuff in initialize_element() because # Model() calls it explicitly instead of super().__init__() self._initialize_element(resource,results) def _initialize_element(self,resource,results): """ Initialize the element's resource, _data, and Gremlin proxy. This is called explicitly by Element.__init__ and Model.__init__ :param resource: The Resource object for the database. :param results: The results list returned by Rexster. """ self._data = {} self.resource = resource self._set_element_data(results) self._gremlin = Gremlin(self.resource) def _set_element_data(self,results): """ Set the elements data returned by the DB. :param results: The results list returned by Rexster. """ self._data = results def __getattr__(self,attribute): """ Returns the value stored in the DB if the property hasn't been set explicitly. If you explicitly set/change the values of an element's properties, make sure you call save() to updated the values in the DB. """ try: return self._data[attribute] except: raise AttributeError("%s not found and not in self._data" \ % (attribute)) def __len__(self): """Returns the number of items stored in the DB results""" return len(self._data) def __contains__(self, item): """Returns True if attribute is a key that has been stored in the DB""" return item in self._data def __eq__(self, obj): """Returns True if the elements are equal""" return (hasattr(obj, "_id") and self._id == obj._id and hasattr(obj, "_data") and self._data == obj._data and hasattr(obj, "__class__") and self.__class__ == obj.__class__ ) def __ne__(self, obj): """Returns True if the elements are not equal.""" return not self.__eq__(obj) def __repr__(self): """Returns the string representation of the attribute.""" return self.__unicode__() def __str__(self): """Returns the string representation of the attribute.""" return self.__unicode__() def __unicode__(self): """Returns the unicode representation of the attribute.""" #return u"<Rexster %s %s: %s>" % \ # (self.resource.db_name, self.__class__.__name__, self._id) return u"<%s: %s>" % (self.__class__.__name__, self._proxy(self.resource)._uri(self._id)) @property def _id(self): """ Returns the element ID. This is the element's "primary key"; however, some DBs (such as neo4j) reuse IDs if they are deleted so be careful with how you use them. If you want to guarantee they are unique across the DB's lifetime either don't physically delete elements and just set a deleted flag, or use some other mechanism, such as an external sequence or a hash. """ #int(self._data['_id']) return utils.coerce_id(self._data['_id']) @property def _type(self): """Returns the _type set by Rexster: either vertex, edge, or index.""" return self._data['_type'] @property def _proxy(self): """Returns the element's proxy to Rexster.""" proxy_map = dict(vertex=VertexProxy,edge=EdgeProxy) return proxy_map[self._type] @property def map(self): """Returns a dict of the element's data that's stored in the DB.""" private_keys = ['_id','_type','_outV','_inV','_label'] map_ = dict() for key, value in self._data.items(): if key not in private_keys: map_.update({key:value}) return map_ def gremlin(self,script,*classes,**kwds): """ Returns a generator containing the results of the Gremlin script. Remember you can always use the list() function to turn an iterator or a generator into a list. Sometimes it's useful to turn a generator into a list when doing unittests or when you want to check how many items are in the results. :param script: Gremlin script to send to Rexster. Since this begins from the context of an element instead of a graph, the script should begin with the reference to itself (v or e) instead of a reference to the graph (g). Example: .. code-block:: groovy // do this... v.outE('created') // instead of... g.v(1).outE('created') :param classes: Zero or more subclasses of Element to use when initializing the the elements returned by the query. For example, if Person is a subclass of Node (which is defined in model.py and is a subclass of Vertex), and the query returns person elements, pass in the Person class and the method will use the element_type defined in the class to initialize the returned items to a Person object. :keyword return_keys: Optional keyword param. A comma-separated list of keys (DB properties) to return. If set to None, it returns all properties. Defaults to None. :keyword raw: Optional keyword param. If set to True, it won't try to initialize data. Defaults to False. :rtype: Generator of items. The data types of the items returned vary depending on the query. Example:: >>> from bulbs.graph import Graph() >>> g = Graph() >>> james = g.vertices.get(3) >>> script = "v.outE('knows').inV" >>> results = james.gremlin(script) """ # TODO: now that we're using a proxy, should we always include the # calling class in the class_map? return_keys = kwds.pop('return_keys',None) raw = kwds.pop('raw',False) class_map = dict(vertex=Vertex,edge=Edge) kwds = dict(default_class_map=class_map,return_keys=return_keys,raw=raw) return self._gremlin._element_query(self,script,*classes,**kwds)