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)
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)