def test_can_add_named_node(self): p = Pypher() p.node('name') exp = '(name)' self.assertEqual(str(p), exp)
def test_can_create_pypher(self): p = Pypher() self.assertIsInstance(p, Pypher)
def test_can_add_empty_node_with_one_label(self): p = Pypher() p.node(labels='Test') exp = '(:`Test`)' self.assertEqual(str(p), exp)
def test_can_add_empty_undirected_relationship_with_fixed_length(self): p = Pypher() p.relationship(min_hops=3, max_hops=3) exp = '-[*3]-' self.assertEqual(str(p), exp)
def test_can_add_empty_node(self): p = Pypher() p.node() exp = '()' self.assertEqual(str(p), exp)
def test_can_add_empty_out_relationship(self): p = Pypher() p.relationship(direction='out') exp = '-->' self.assertEqual(str(p), exp)
def test_can_add_named_in_relationship(self): p = Pypher() p.rel('name', direction='<') exp = '<-[name]-' self.assertEqual(str(p), exp)
def test_can_nest_map(self): p = Pypher() p.collect(__.map('one', 'two', 'three')) q = str(p) exp = 'collect({one, two, three})' self.assertEqual(exp, q)
def save_relationship(self, entity, ensure_unique=False): """this method handles creating and saving relationships. It will hanle quite a few situations. Given the structure: (start)-[rel]->[end] We can have: * A new start node * An existing start node * A new rel * An existing rel * A new end node * An existing end node Each start, rel, and end could have uniqueness assigned to it * start/end could have unique properties * rel could have unique relationships A Chyper query should be generated that looks something like this, depending on the settings for each of the nodes: MERGE (n_0:Node {`key`: val}) ON CREATE SET n_0.key = val, n_0.key2 = val2 ON MATCH SET n_0.key = val, n_0.key2 = val2 CREATE (n_0)-[r_0:RelLabel, {`key`: someVal}]->(n_1:Node {`key`: val}) RETURN n_0, n_1, r_0 """ start = entity.start start_properties = {} end = entity.end end_properties = {} props = self._properties(entity) if start is None or end is None: raise Exception('The relationship must have a start and end node') if not isinstance(start, Node): start = Node(id=start) if not isinstance(end, Node): end = Node(id=end) VM.set_query_var(start) VM.set_query_var(end) VM.set_query_var(entity) rel = Pypher() if start not in self.matched_entities: if start.id is not None: self._update_properties(start) self.matches.append(self._node_by_id(start)) else: start_properties = self._properties(start) self.matched_entities.append(start) self.returns.append(start.query_variable) if end not in self.matched_entities: if end.id is not None: self._update_properties(end) self.matches.append(self._node_by_id(end)) else: end_properties = self._properties(end) self.matched_entities.append(end) self.returns.append(end.query_variable) if entity.id is None: if start.id is not None: rel = rel.node(start.query_variable) else: start_query = Query(start, self.params) start_query.build_save_pypher() if len(start_query.creates): rel.append(*start_query.creates) elif len(start_query.merges): has_matches = len(self.matches) > 0 start_merge = Pypher() start_merge.MERGE(*start_query.merges) if start_query.on_create_sets: start_merge.OnCreateSet(*start_query.on_create_sets) if start_query.on_match_sets: start_merge.OnMatchSet(*start_query.on_match_sets) self.before_matches.append(start_merge) rel.node(start.query_variable) rel.rel(entity.query_variable, labels=entity.labels, direction='out', **props) if end.id is not None: rel.node(end.query_variable) else: end_query = Query(end, self.params) end_query.build_save_pypher() if len(end_query.creates): rel.append(*end_query.creates) elif len(end_query.merges): end_merge = Pypher().MERGE(*end_query.merges) if end_query.on_create_sets: end_merge.OnCreateSet(*end_query.on_create_sets) if end_query.on_match_sets: end_merge.OnMatchSet(*end_query.on_match_sets) self.before_matches.append(end_merge) rel.node(end.query_variable) if ensure_unique: self.merges.append(rel) else: self.creates.append(rel) else: _id = VM.get_next(entity, 'id') _id = Param(_id, entity.id) if start.id is not None: rel = rel.node(start.query_variable) else: start_query = Query(start, self.params) start_query.build_save_pypher() if len(start_query.creates): rel.append(*start_query.creates) elif len(start_query.merges): start_merge = Pypher().MERGE(*start_query.merges) if start_query.on_create_sets: start_merge.OnCreateSet(*start_query.on_create_sets) if start_query.on_match_sets: start_merge.OnMatchSet(*start_query.on_match_sets) if len(self.matches): self.matches[-1].append(start_merge) else: self.matches.append(start_merge) rel.node(start.query_variable) rel.rel(entity.query_variable, labels=entity.labels, direction='out') if end.id is not None: rel.node(end.query_variable) else: end_query = Query(end, self.params) end_query.build_save_pypher() if len(end_query.creates): rel.append(*end_query.creates) elif len(end_query.merges): end_merge = Pypher().MERGE(*end_query.merges) if end_query.on_create_sets: end_merge.OnCreateSet(*end_query.on_create_sets) if end_query.on_match_sets: end_merge.OnMatchSet(*end_query.on_match_sets) if len(self.matches): self.matches[-1].append(end_merge) else: self.matches.append(end_merge) rel.node(end.query_variable) rel.WHERE(__.ID(entity.query_variable) == _id) self._update_properties(entity) self.matches.append(rel) self.returns.append(entity.query_variable) return self
def test_can_assign_variable(self): p = Pypher() p.MATCH.p.assign(__.node('n').rel_out().node('m')) exp = 'MATCH p = (n)-->(m)' self.assertEqual(str(p), exp)
def test_can_reuse_params_object_across_pypher_isntances(self): params = Params('xxx') p = Pypher(params=params) p2 = Pypher(params=params) self.assertEqual(id(p.params), id(p2.params))
def test_can_add_multiple_labels(self): p = Pypher() p.n.label(['one', 'two', 'three', 'four']) exp = 'n:`one`:`two`:`three`:`four`' self.assertEqual(str(p), exp)
def test_can_add_named_undirected_relationship_with_labels(self): p = Pypher() p.relationship(variable='test', labels=['one', 'two', 'three']) exp = '-[test:`one`|`two`|`three`]-' self.assertEqual(str(p), exp)
def test_using_hops_and_max_hops_raises_error(self): p = Pypher() with self.assertRaises(ValueError): p.relationship(hops=2, max_hops=3)
def test_can_add_named_node_with_multiple_labels(self): p = Pypher() p.node('name', labels=['Test', 'one', 'two']) exp = '(name:`Test`:`one`:`two`)' self.assertEqual(str(p), exp)
def test_can_add_alias_using_alias(self): p = Pypher() p.mark.alias('MARK') exp = 'mark AS MARK' self.assertEqual(exp, str(p))
def test_can_add_empty_undirected_relationship(self): p = Pypher() p.relationship() exp = '--' self.assertEqual(str(p), exp)
def test_will_get_param_object_from_binding_param(self): v = 'v' p = Pypher() param = p.bind_param(v) self.assertIsInstance(param, Param)
def test_can_add_empty_in_relationship(self): p = Pypher() p.relationship(direction='in') exp = '<--' self.assertEqual(str(p), exp)
def test_can_add_statement_and_property(self): p = Pypher() p.RETURN.property('money') exp = 'RETURN.`money`' self.assertEqual(str(p), exp)
def test_can_add_empty_undirected_relationship_with_types(self): p = Pypher() p.relationship(types=['one', 'two', 'three']) exp = '-[:`one`|`two`|`three`]-' self.assertEqual(str(p), exp)
def test_can_add_empty_undirected_relationship_with_min_max_hop(self): p = Pypher() p.relationship(min_hops=1, max_hops=3) exp = '-[*1..3]-' self.assertEqual(str(p), exp)