def __call__(self, *args, **kwargs): parameters = self._parse_parameters(args, kwargs) response, content = Request().post(self.url, data=parameters) if response.status == 200: results_list = json.loads(content) # The returns param is a temporary solution while # a proper way to get the data type of returned values by # the extensions is implemented in Neo4j returns = kwargs.pop("returns", None) # Another option is to inspect the results if not returns and isinstance(results_list, (tuple, list)): returns = results_list[0].get("self", None) if results_list and returns: if NODE in returns: return [Node(r["self"]) for r in results_list] elif RELATIONSHIP in returns: return [Relationship(r["self"]) for r in results_list] elif PATH in returns: return [Path(r) for r in results_list] elif POSITION in returns: return [Position(r) for r in results_list] else: return [] elif response.status == 404: raise NotFoundError(response.status, "Extension not found") else: raise StatusException(response.status, "Invalid data sent")
def __setitem__(self, value, item): # Neo4j hardly crush if you try to index a relationship in a # node index and viceversa. is_node_index = self._index_for == NODE and isinstance(item, Node) is_relationship_index = (self._index_for == RELATIONSHIP and isinstance(item, Relationship)) if not (is_node_index or is_relationship_index): raise TypeError("%s is a %s and the index is for %ss" % (item, self._index_for.capitalize(), self._index_for)) value = urllib.quote(value) if isinstance(item, Base): url_ref = item.url else: url_ref = item request_url = "%s/%s" % (self.url, value) response, content = Request().post(request_url, data=url_ref) if response.status == 201: # Returns object that was indexed entity = json.loads(content) if self._index_for == NODE: return Node(entity['self'], data=entity['data']) else: return Relationship(entity['self'], data=entity['data']) else: raise StatusException(response.status, "Error requesting index with POST %s " \ ", data %s" % (request_url, url_ref))
def __delitem__(self, key): property_url = self._dic["property"].replace("{key}", key) response, content = Request().delete(property_url) if response.status == 204: del self._dic["data"][key] elif response.status == 404: raise NotFoundError(response.status, "Node or property not found") else: raise StatusException(response.status, "Node or propery not found")
def __setitem__(self, key, value): property_url = self._dic["property"].replace("{key}", key) response, content = Request().put(property_url, data=value) if response.status == 204: self._dic["data"].update({key: value}) elif response.status == 404: raise NotFoundError(response.status, "Node or property not found") else: raise StatusException(response.status, "Invalid data sent")
def _set_properties(self, props={}): if not props: return None properties_url = self._dic["properties"] response, content = Request().put(properties_url, data=props) if response.status == 204: self._dic["data"] = props.copy() return props elif response.status == 400: raise StatusException(response.status, "Invalid data sent") else: raise NotFoundError(response.status, "Properties not found")
def delete(self, key=None): if key: self.__delitem__(key) return response, content = Request().delete(self.url) if response.status == 204: del self elif response.status == 404: raise NotFoundError(response.status, "Node or property not found") else: raise StatusException(response.status, "Node could not be "\ "deleted (still has " \ "relationships?)")
def request(self, return_type): try: return self._cache[return_type] except KeyError: url = self._endpoint.replace("{returnType}", return_type) response, content = Request(**self._auth).post(url, data=self._data) if response.status == 200: results_list = json.loads(content) self._cache[return_type] = results_list return results_list elif response.status == 404: raise NotFoundError(response.status, "Node or relationship " \ "not found") raise StatusException(response.status, "Invalid data sent")
def traverse(self, types=None, order=None, stop=None, returnable=None, uniqueness=None, is_stop_node=None, is_returnable=None, returns=None): data = {} if order in (BREADTH_FIRST, DEPTH_FIRST): data.update({"order": order}) if isinstance(stop, (int, float)) or stop is STOP_AT_END_OF_GRAPH: data.update({"max depth": stop}) if returnable in (BREADTH_FIRST, DEPTH_FIRST): data.update({"return filter": { "language": "builtin", "name": returnable, }}) if uniqueness in (NODE_GLOBAL, NODE_PATH, NODE_RECENT, NODE, RELATIONSHIP_GLOBAL, RELATIONSHIP_PATH, RELATIONSHIP_RECENT): data.update({"uniqueness": uniqueness}) if types: if not isinstance(types, (list, tuple)): types = [types] relationships = [] for relationship in types: if relationship.direction == "both": relationships.append({"type": relationship.type}) else: relationships.append({"type": relationship.type, "direction": relationship.direction}) if relationships: data.update({"relationships": relationships}) if returns not in (NODE, RELATIONSHIP, PATH, POSITION): returns = NODE traverse_url = self._dic["traverse"].replace("{returnType}", returns) response, content = Request().post(traverse_url, data=data) if response.status == 200: results_list = json.loads(content) if returns is NODE: return [Node(r["self"]) for r in results_list] elif returns is RELATIONSHIP: return [Relationship(r["self"]) for r in results_list] elif returns is PATH: return [Path(r) for r in results_list] elif returns is POSITION: return [Position(r) for r in results_list] elif response.status == 404: raise NotFoundError(response.status, "Node or relationship not " \ "found") else: raise StatusException(response.status, "Invalid data sent")
def _get_results(self, url): response, content = Request().get(url) if response.status == 200: data_list = json.loads(content) if self._index_for == NODE: return [Node(n['self'], data=n['data']) for n in data_list] else: return [Relationship(r['self'], data=r['data']) for r in data_list] elif response.status == 404: raise NotFoundError(response.status, "Node or relationship not found") else: raise StatusException(response.status, "Error requesting index with GET %s" \ % url)
def get_response(self): # Preparing slicing and ordering q = self.q params = self.params if self._order_by: orders = [] for o, order in enumerate(self._order_by): order_key = "_order_by_%s" % o if order_key not in params: nullable = "" if len(order) == 3: if order[2] is True: nullable = "!" elif order[2] is False: nullable = "?" orders.append(u"n.`{%s}`%s %s" % (order_key, nullable, order[1])) params[order_key] = order[0] if orders: q = u"%s order by %s" % (q, ", ".join(orders)) # Lazy slicing if isinstance(self._skip, int) and "_skip" not in params: q = u"%s skip {_skip} " % q params["_skip"] = self._skip if isinstance(self._limit, int) and "_limit" not in params: q = u"%s limit {_limit} " % q params["_limit"] = self._limit # Making the real resquest data = { "query": q, "params": params, } response, content = Request(**self._auth).post(self._cypher, data=data) if response.status == 200: response_json = json.loads(content) return response_json elif response.status == 400: err_msg = u"Cypher query exception" try: err_msg = "%s: %s" % (err_msg, json.loads(content)["message"]) except: err_msg = "%s: %s" % (err_msg, content) raise CypherException(err_msg) else: raise StatusException(response.status, "Invalid data sent")
def relationship(to, *args, **kwargs): create_relationship_url = self._dic["create_relationship"] data = { "to": to.url, "type": relationship_name, } if kwargs: data.update({"data": kwargs}) response, content = Request().post(create_relationship_url, data=data) if response.status == 201: return Relationship(response.get("location")) elif response.status == 404: raise NotFoundError(response.status, "Node specified by the " \ "URI not of \"to\" node" \ "not found") else: raise StatusException(response.status, "Invalid data sent")
def create(self, name, **kwargs): data = { 'name': name, 'config': { 'type': kwargs.get("type", INDEX_FULLTEXT), 'provider': kwargs.get("provider", "lucene"), } } if name not in self._dict: response, content = Request().post(self.url, data=data) if response.status == 201: loaded_dict = json.loads(content) result_dict = {} for key, val in loaded_dict.items(): result_dict[str(key)] = val self._dict[name] = Index(self._index_for, name, **result_dict) else: raise StatusException(response.status, "Invalid data sent") return self._dict[name]
def _get_dict(self): indexes_dict = {} response, content = Request().get(self.url) if response.status == 200: indexes_dict = json.loads(content) for index_name, index_properties in indexes_dict.items(): index_props = {} for key, val in index_properties.items(): index_props[str(key)] = val indexes_dict[index_name] = Index(self._index_for, index_name, **index_props) return indexes_dict elif response.status == 404: raise NotFoundError(response.status, "Indexes not found") elif response.status == 204: return indexes_dict else: raise StatusException(response.status, "Error requesting indexes with GET %s" \ % self.url)
def get_relationships(types=None, *args, **kwargs): if relationship_type in ["all", "incoming", "outgoing"]: if types and isinstance(types, (tuple, list)): key = "%s_typed_relationships" % relationship_type url_string = self._node._dic[key] url = url_string.replace(self._pattern, "&".join(types)) else: key = "%s_relationships" % relationship_type url = self._node._dic[key] response, content = Request().get(url) if response.status == 200: relationship_list = json.loads(content) relationships = [Relationship(r["self"]) for r in relationship_list] return relationships elif response.status == 404: raise NotFoundError(response.status, "Node or relationship not found") else: raise StatusException(response.status, "Node not found") raise NameError("name %s is not defined" % relationship_type)
def delete(self, key, value, item): if not isinstance(item, Base): raise TypeError("%s has no url attribute" % item) if key and value: key = urllib.quote(key) value = urllib.quote(value) url = self.template.replace("{key}", key).replace("{value}", value) url = "%s/%s" % (url, item.id) elif key and not value: key = urllib.quote(key) url = "%s/%s" % (self.template.replace("{key}", key), item.id) elif not key and not value: url = self.template.replace("{key}/{value}", item.id) else: raise TypeError("remove() take at least 2 arguments, the key " \ "of the index and the %s to remove" % self._index_for) response, content = Request().delete(url) if response.status == 404: raise NotFoundError(response.status, "%s not found" % self._index_for.capitalize()) elif response.status != 204: raise StatusException(response.status)