def hydrate_(data, inst=None): if isinstance(data, dict): if "self" in data: if "type" in data: return Relationship.hydrate(data["self"], inst=inst, **data) else: return Node.hydrate(data["self"], inst=inst, **data) elif "nodes" in data and "relationships" in data: if "directions" not in data: directions = [] relationships = graph.evaluate( "MATCH ()-[r]->() WHERE id(r) IN {x} RETURN collect(r)", x=[int(uri.rpartition("/")[-1]) for uri in data["relationships"]]) node_uris = data["nodes"] for i, relationship in enumerate(relationships): if remote(relationship.start_node()).uri == node_uris[i]: directions.append("->") else: directions.append("<-") data["directions"] = directions return Path.hydrate(data) else: # from warnings import warn # warn("Map literals returned over the Neo4j REST interface are ambiguous " # "and may be hydrated as graph objects") return data elif is_collection(data): return type(data)(map(hydrate_, data)) else: return data
def hydrate_(obj, inst=None): # TODO: hydrate directly instead of via HTTP hydration if isinstance(obj, Structure): signature, args = obj if signature == b"N": uri = "%snode/%s" % (graph_uri, args[0]) return Node.hydrate(uri, inst=inst, metadata={"labels": list(args[1])}, data=hydrate_(args[2])) elif signature == b"R": uri = "%srelationship/%s" % (graph_uri, args[0]) return Relationship.hydrate( uri, inst=inst, start="%snode/%s" % (graph_uri, args[1]), end="%snode/%s" % (graph_uri, args[2]), type=args[3], data=hydrate_(args[4])) elif signature == b"P": nodes = [hydrate_(node) for node in args[0]] u_rels = [ UnboundRelationship.hydrate(*map(hydrate_, r)) for _, r in args[1] ] sequence = args[2] last_node = nodes[0] steps = [last_node] for i, rel_index in enumerate(sequence[::2]): next_node = nodes[sequence[2 * i + 1]] last_node_uri = "%snode/%s" % (graph_uri, remote(last_node)._id) next_node_uri = "%snode/%s" % (graph_uri, remote(next_node)._id) if rel_index > 0: u_rel = u_rels[rel_index - 1] uri = "%srelationship/%s" % (graph_uri, u_rel.id) rel = Relationship.hydrate(uri, start=last_node_uri, end=next_node_uri, type=u_rel.type, data=u_rel.properties) else: u_rel = u_rels[-rel_index - 1] uri = "%srelationship/%s" % (graph_uri, u_rel.id) rel = Relationship.hydrate(uri, start=next_node_uri, end=last_node_uri, type=u_rel.type, data=u_rel.properties) steps.append(rel) steps.append(next_node) last_node = next_node return Path(*steps) else: # If we don't recognise the structure type, just return it as-is # TODO: add warning for unsupported structure types return obj elif isinstance(obj, list): return list(map(hydrate_, obj)) elif isinstance(obj, dict): return {key: hydrate_(value) for key, value in obj.items()} else: return obj