From df45e2938b3e6a463ca3de404741d164abb79b0e Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Sun, 3 Mar 2019 22:10:11 +0100 Subject: [PATCH 01/34] New models and methods --- norduniclient/models.py | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index 01d1d5d..8246273 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -277,6 +277,25 @@ def get_ports(self): """ return core.query_to_list(self.manager, q, handle_id=self.handle_id) + def add_property(self, property, value): + q = """ + MATCH (n:Node {{handle_id: {{handle_id}}}}) + SET n.{property} = '{value}' + RETURN n + """.format(property=property, value=value) + with self.manager.session as s: + node = s.run(q, {'handle_id': self.handle_id}).single()['n'] + return self.reload(node=node) + + def remove_property(self, property): + q = """ + MATCH (n:Node {{handle_id: {{handle_id}}}}) + REMOVE n.{property} + RETURN n + """.format(label=property) + with self.manager.session as s: + node = s.run(q, {'handle_id': self.handle_id}).single()['n'] + return self.reload(node=node) class LogicalModel(CommonQueries): @@ -511,6 +530,14 @@ def get_responsible_for(self): """ return self._basic_read_query_to_dict(q) + def set_parent(self, org_handle_id): + q = """ + MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) + MERGE (n)-[r:parent_of]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) + class EquipmentModel(PhysicalModel): @@ -893,3 +920,33 @@ class CustomerModel(RelationModel): class ProviderModel(RelationModel): pass + + +class ContactModel(RelationModel): + def add_role(self, role_handle_id): + q = """ + MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Role {handle_id: {role_handle_id}}) + MERGE (n)-[r:is]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, role_handle_id=role_handle_id) + + def add_organization(self, org_handle_id): + q = """ + MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) + MERGE (n)-[r:part_of]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) + + +class GroupModel(LogicalModel): + pass + + +class RoleModel(LogicalModel): + pass + + +class ProcedureModel(LogicalModel): + pass From 4b8db779646cf341bbc29c89215bc8e66ee82b45 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Mon, 4 Mar 2019 11:14:47 +0100 Subject: [PATCH 02/34] New relations cased according to the rest of the project. --- norduniclient/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 8246273..5e7329f 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -533,7 +533,7 @@ def get_responsible_for(self): def set_parent(self, org_handle_id): q = """ MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) - MERGE (n)-[r:parent_of]->(m) + MERGE (n)-[r:Parent_of]->(m) RETURN m as created, r, n as node """ return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) @@ -926,7 +926,7 @@ class ContactModel(RelationModel): def add_role(self, role_handle_id): q = """ MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Role {handle_id: {role_handle_id}}) - MERGE (n)-[r:is]->(m) + MERGE (n)-[r:Is]->(m) RETURN m as created, r, n as node """ return self._basic_write_query_to_dict(q, role_handle_id=role_handle_id) @@ -934,7 +934,7 @@ def add_role(self, role_handle_id): def add_organization(self, org_handle_id): q = """ MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) - MERGE (n)-[r:part_of]->(m) + MERGE (n)-[r:Part_of]->(m) RETURN m as created, r, n as node """ return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) From b063698efe25c531e22d82b49cdee5ade41b50f9 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Mon, 4 Mar 2019 18:06:02 +0100 Subject: [PATCH 03/34] Name change for relations between contact and organization and small bugfix --- norduniclient/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 5e7329f..583e880 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -216,7 +216,7 @@ def get_child_form_data(self, node_type): def get_relations(self): q = """ - MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for]-(node) + MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Has|Parent_of|Member_of|Is]-(node) RETURN r, node """ return self._basic_read_query_to_dict(q) @@ -292,7 +292,7 @@ def remove_property(self, property): MATCH (n:Node {{handle_id: {{handle_id}}}}) REMOVE n.{property} RETURN n - """.format(label=property) + """.format(property=property) with self.manager.session as s: node = s.run(q, {'handle_id': self.handle_id}).single()['n'] return self.reload(node=node) @@ -934,7 +934,7 @@ def add_role(self, role_handle_id): def add_organization(self, org_handle_id): q = """ MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) - MERGE (n)-[r:Part_of]->(m) + MERGE (n)-[r:Works_for]->(m) RETURN m as created, r, n as node """ return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) From 501bf695fcccfbb489d250474c4f9e11e63f543e Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Mon, 4 Mar 2019 18:06:35 +0100 Subject: [PATCH 04/34] New methods, nodes and relationships added to the test suite. --- norduniclient/tests/test_models.py | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 84b8984..f7c64b2 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -141,6 +141,22 @@ def setUp(self): (physical2)<-[:Connected_to]-(physical4)-[:Connected_to]->(physical3) """ + q3 = """ + // Create organization and contact nodes + CREATE (organization1:Node:Relation:Organization{name:'Organization1', handle_id:'113'}), + (organization2:Node:Relation:Organization{name:'Organization2', handle_id:'114'}), + (contact1:Node:Relation:Contact{name:'Contact1', handle_id:'115'}), + (contact2:Node:Relation:Contact{name:'Contact2', handle_id:'116'}), + (role1:Node:Logical:Role{name:'Role1', handle_id:'117'}), + (role2:Node:Logical:Role{name:'Role2', handle_id:'118'}), + + // Create relationships + (contact1)-[:Is]->(role1), + (contact2)-[:Is]->(role2), + (contact1)-[:Works_for]->(organization1), + (contact2)-[:Works_for]->(organization2) + """ + # Insert mocked network with self.neo4jdb.session as s: s.run(q1) @@ -149,6 +165,10 @@ def setUp(self): with self.neo4jdb.session as s: s.run(q2) + # Insert organizations and contacts + with self.neo4jdb.session as s: + s.run(q3) + def test_base_node_model(self): node_model_1 = core.get_node_model(self.neo4jdb, handle_id='101') node_model_2 = core.get_node_model(self.neo4jdb, handle_id='102') @@ -188,6 +208,21 @@ def test_remove_label(self): new_labels = node_model_1.labels self.assertEqual(sorted(new_labels), sorted(initial_labels)) + def test_add_remove_property(self): + node_model_1 = core.get_node_model(self.neo4jdb, handle_id='115') + initial_data = node_model_1.data + first_name = 'Smith' + node_model_1 = node_model_1.add_property('first_name', first_name) + new_data = node_model_1.data + new_property = {'first_name': first_name} + expected_data = dict(initial_data.items() + new_property.items() + + [(k, initial_data[k] + new_property[k]) \ + for k in set(new_property) & set(initial_data)]) # dict merge + self.assertEqual(sorted(new_data), sorted(expected_data)) + node_model_1 = node_model_1.remove_property('first_name') + new_data = node_model_1.data + self.assertEqual(sorted(new_data), sorted(initial_data)) + def test_change_meta_type(self): node_model_1 = core.get_node_model(self.neo4jdb, handle_id='101') self.assertEqual(node_model_1.meta_type, 'Physical') @@ -287,6 +322,14 @@ def test_get_relations(self): relations = location2.get_relations() self.assertIsInstance(relations['Responsible_for'][0]['node'], models.RelationModel) + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + relations = organization1.get_relations() + self.assertIsInstance(relations['Works_for'][0]['node'], models.RelationModel) + + role1 = core.get_node_model(self.neo4jdb, handle_id='117') + relations = role1.get_relations() + self.assertIsInstance(relations['Is'][0]['node'], models.RelationModel) + def test_get_dependencies(self): logical3 = core.get_node_model(self.neo4jdb, handle_id='107') dependencies = logical3.get_dependencies() @@ -527,6 +570,13 @@ def test_set_responsible_for_location_model(self): relations = rack_4.get_relations() self.assertEqual(len(relations['Responsible_for']), 1) + def test_set_parent(self): + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + organization2 = core.get_node_model(self.neo4jdb, handle_id='114') + organization2.set_parent(organization1.handle_id) + relations = organization1.get_relations() + self.assertIsInstance(relations['Parent_of'][0]['node'], models.RelationModel) + # TODO: EquipmentModel get_ports should probably work as CommonQueries get_ports def test_get_ports_equipment_model(self): odf1 = core.get_node_model(self.neo4jdb, handle_id='23') From 1b636292f707acc5106407defe5dac16030aeb12 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 6 Mar 2019 11:05:26 +0100 Subject: [PATCH 05/34] Parent relationship bugfix --- norduniclient/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 583e880..83b1bd2 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -533,7 +533,7 @@ def get_responsible_for(self): def set_parent(self, org_handle_id): q = """ MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) - MERGE (n)-[r:Parent_of]->(m) + MERGE (m)-[r:Parent_of]->(n) RETURN m as created, r, n as node """ return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) From 5228e9b733b76a293da264098ad00e13425a7545 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 6 Mar 2019 17:41:26 +0100 Subject: [PATCH 06/34] Defects detected on PR fixed --- norduniclient/models.py | 72 ++++++++++++++++++------------ norduniclient/tests/test_models.py | 4 +- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 83b1bd2..4a17433 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -9,6 +9,8 @@ # Python 3 from norduniclient import core +import six + __author__ = 'lundberg' @@ -189,6 +191,29 @@ def delete(self): def reload(self, node=None): return core.get_node_model(self.manager, self.handle_id, node=node) + def add_property(self, property, value): + if isinstance(value, six.string_types): + value = "'{}'".format(value) + + q = """ + MATCH (n:Node {{handle_id: {{handle_id}}}}) + SET n.{property} = {value} + RETURN n + """.format(property=property, value=value) + with self.manager.session as s: + node = s.run(q, {'handle_id': self.handle_id}).single()['n'] + return self.reload(node=node) + + def remove_property(self, property): + q = """ + MATCH (n:Node {{handle_id: {{handle_id}}}}) + REMOVE n.{property} + RETURN n + """.format(property=property) + with self.manager.session as s: + node = s.run(q, {'handle_id': self.handle_id}).single()['n'] + return self.reload(node=node) + class CommonQueries(BaseNodeModel): @@ -216,7 +241,7 @@ def get_child_form_data(self, node_type): def get_relations(self): q = """ - MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Has|Parent_of|Member_of|Is]-(node) + MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Has|Parent_of|Member_of|Is|Uses_a]-(node) RETURN r, node """ return self._basic_read_query_to_dict(q) @@ -277,26 +302,6 @@ def get_ports(self): """ return core.query_to_list(self.manager, q, handle_id=self.handle_id) - def add_property(self, property, value): - q = """ - MATCH (n:Node {{handle_id: {{handle_id}}}}) - SET n.{property} = '{value}' - RETURN n - """.format(property=property, value=value) - with self.manager.session as s: - node = s.run(q, {'handle_id': self.handle_id}).single()['n'] - return self.reload(node=node) - - def remove_property(self, property): - q = """ - MATCH (n:Node {{handle_id: {{handle_id}}}}) - REMOVE n.{property} - RETURN n - """.format(property=property) - with self.manager.session as s: - node = s.run(q, {'handle_id': self.handle_id}).single()['n'] - return self.reload(node=node) - class LogicalModel(CommonQueries): def get_part_of(self): @@ -530,14 +535,6 @@ def get_responsible_for(self): """ return self._basic_read_query_to_dict(q) - def set_parent(self, org_handle_id): - q = """ - MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) - MERGE (m)-[r:Parent_of]->(n) - RETURN m as created, r, n as node - """ - return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) - class EquipmentModel(PhysicalModel): @@ -917,6 +914,23 @@ class FPCModel(SubEquipmentModel): class CustomerModel(RelationModel): pass +class OrganizationModel(RelationModel): + def set_parent(self, org_handle_id): + q = """ + MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) + MERGE (m)-[r:Parent_of]->(n) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) + + def add_procedure(self, proc_handle_id): + q = """ + MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Procedure {handle_id: {proc_handle_id}}) + MERGE (n)-[r:Uses_a]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, proc_handle_id=proc_handle_id) + class ProviderModel(RelationModel): pass diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index f7c64b2..0b26c98 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -574,8 +574,8 @@ def test_set_parent(self): organization1 = core.get_node_model(self.neo4jdb, handle_id='113') organization2 = core.get_node_model(self.neo4jdb, handle_id='114') organization2.set_parent(organization1.handle_id) - relations = organization1.get_relations() - self.assertIsInstance(relations['Parent_of'][0]['node'], models.RelationModel) + relations = organization2.get_relations() + self.assertIsInstance(relations['Parent_of'][0]['node'], models.OrganizationModel) # TODO: EquipmentModel get_ports should probably work as CommonQueries get_ports def test_get_ports_equipment_model(self): From a38610a0a5ec5dd9344d1b9e81401b4316b900a8 Mon Sep 17 00:00:00 2001 From: Johan Lundberg Date: Thu, 7 Mar 2019 14:39:57 +0100 Subject: [PATCH 07/34] Updated .travis.yml and added jenkins.yaml --- .jenkins.yaml | 18 ++++++++++++++++++ .travis.yml | 14 ++------------ 2 files changed, 20 insertions(+), 12 deletions(-) create mode 100644 .jenkins.yaml diff --git a/.jenkins.yaml b/.jenkins.yaml new file mode 100644 index 0000000..2bae8af --- /dev/null +++ b/.jenkins.yaml @@ -0,0 +1,18 @@ +builders: + - script +triggers: + cron: "@weekly" +environment_variables: + NEO4J_VERSION: "latest" +pre_build_script: + - "docker pull neo4j:${NEO4J_VERSION}" +script: + - "python3.7 -m venv venv" + - ". venv/bin/activate" + - "python setup.py testing" + - "pip freeze" + - "python setup.py test" + - "python setup.py sdist bdist_wheel --universal" +publish_over_ssh: + - pypi.sunet.se +clean_workspace: true diff --git a/.travis.yml b/.travis.yml index a19a5ff..06527b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ sudo: required +dist: xenial services: - docker @@ -7,7 +8,7 @@ language: python python: - '2.7' - - '3.5' + - '3.7' env: - NEO4J_VERSION=3.3.2 @@ -20,14 +21,3 @@ install: python setup.py testing script: python setup.py test -deploy: - provider: pypi - distributions: sdist bdist_wheel - user: Lundberg - password: - secure: pDqWOp0OZE9/uzRBcuWr/FgsKl7y1cpDW4GdBPRPstVMdJ42G1Vf8n5F+kJrpd8aSmG4G0+tw7iUN+SSn29Zpw3eTNJqClu4eKEILXKXO50Jr+w1c4hgpGrzbwi+q9IEMy0VJ/gTPFFAgJhY82R+Cp+6YZ0FJ6JkmwxpTkVVaTbiCXlDNhzLH7l1O1iWK6UpVORiYgJvuGkNvV7THU+z6KEwfCnXxV38bXhxYJKbBkXlgT5Te712OqEyBxMYAMZB+Pkoju94Dvd3dqBQpOyNUTe451PzVyWY2KZOiXE18/+CqB/es9xfXTH+hThwAGcms60/zmoQIFA0/1MKeze0jaO6Zlp00Djo91KIxQEkNAn93dt3xDhEStSgfqVgKN2tHqTO2gWASc7U3Om1O5CAyHOfOHNLYf1G7PFZDKVPA19pLgidIu7YNcr71jSuGyp2Cbw/o4BdiXiKPhQMYoHpjvxBbCURa1j8XwpxK9lWQymzXEaJrTeW2iHyyKwIOM8xH4oWBoCdAcjdySKx8vkrFnBJZIWd8NIKIp3xPSm0chzU7ohDEJiC1ucN+KUlHOwUW/aLRyQhhiETCdP42Tdw5yyfenhRwA9eVEepmh6V0CZT4JrKjO3lOiM+wdL/xzK8xEV9jwvueE5HFNh7VMF3UGCdEbQTIb3yrE7TelQfzWo= - on: - tags: true - repo: NORDUnet/python-norduniclient - condition: "$NEO4J_VERSION = 3.3.2" - python: '2.7' From 6cf9ab32d64c86149c77a54172e87751fa3d5681 Mon Sep 17 00:00:00 2001 From: Johan Lundberg Date: Thu, 7 Mar 2019 14:45:55 +0100 Subject: [PATCH 08/34] Install wheel --- .jenkins.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.jenkins.yaml b/.jenkins.yaml index 2bae8af..e3f8010 100644 --- a/.jenkins.yaml +++ b/.jenkins.yaml @@ -9,6 +9,7 @@ pre_build_script: script: - "python3.7 -m venv venv" - ". venv/bin/activate" + - "pip install -U setuptools wheel mypy" - "python setup.py testing" - "pip freeze" - "python setup.py test" From 87e61dd83ebc1d9071eb19a29fb24c1d4a3712b7 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 8 Mar 2019 08:47:23 +0100 Subject: [PATCH 09/34] New ContactModel method --- norduniclient/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index 4a17433..1955616 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -953,6 +953,14 @@ def add_organization(self, org_handle_id): """ return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) + def add_group(self, group_handle_id): + q = """ + MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Group {handle_id: {group_handle_id}}) + MERGE (n)-[r:Member_of]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, group_handle_id=group_handle_id) + class GroupModel(LogicalModel): pass From 99ad93c18a311e3e71de201d6e70d7e771629ab6 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 8 Mar 2019 14:22:23 +0100 Subject: [PATCH 10/34] 'Has' relationship removed from query --- norduniclient/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 1955616..50bbb65 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -241,7 +241,7 @@ def get_child_form_data(self, node_type): def get_relations(self): q = """ - MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Has|Parent_of|Member_of|Is|Uses_a]-(node) + MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Parent_of|Member_of|Is|Uses_a]-(node) RETURN r, node """ return self._basic_read_query_to_dict(q) From ed8d0a7e8425ed03dc070b0929b4062167214485 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 8 Mar 2019 14:41:05 +0100 Subject: [PATCH 11/34] Dict merge simplified. --- norduniclient/tests/test_models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 0b26c98..9d14fef 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -215,9 +215,8 @@ def test_add_remove_property(self): node_model_1 = node_model_1.add_property('first_name', first_name) new_data = node_model_1.data new_property = {'first_name': first_name} - expected_data = dict(initial_data.items() + new_property.items() + - [(k, initial_data[k] + new_property[k]) \ - for k in set(new_property) & set(initial_data)]) # dict merge + expected_data = initial_data.copy() + expected_data.update(new_property) self.assertEqual(sorted(new_data), sorted(expected_data)) node_model_1 = node_model_1.remove_property('first_name') new_data = node_model_1.data From d94620ab4c1e408baf94744237f7fe89623fa0ef Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 13 Mar 2019 13:05:47 +0100 Subject: [PATCH 12/34] New method: add child organization --- norduniclient/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index 50bbb65..c88b241 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -923,6 +923,14 @@ def set_parent(self, org_handle_id): """ return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) + def set_child(self, org_handle_id): + q = """ + MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) + MERGE (n)-[r:Parent_of]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) + def add_procedure(self, proc_handle_id): q = """ MATCH (n:Node:Organization {handle_id: {handle_id}}), (m:Node:Procedure {handle_id: {proc_handle_id}}) From 03253003836c76f675bee20dbdb6d362292c2a41 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Thu, 14 Mar 2019 11:49:38 +0100 Subject: [PATCH 13/34] New method to get all the outgoing relations for Contacts --- norduniclient/models.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index c88b241..53df7b2 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -969,6 +969,12 @@ def add_group(self, group_handle_id): """ return self._basic_write_query_to_dict(q, group_handle_id=group_handle_id) + def get_outgoing_relations(self): + q = """ + MATCH (n:Node:Contact {handle_id: {handle_id}})-[r:Works_for|Member_of|Is]->(node) + RETURN r, node + """ + return self._basic_read_query_to_dict(q) class GroupModel(LogicalModel): pass From ee384cc3f17dbec18a0e189c1547daa4137e8ba9 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 15 Mar 2019 12:36:28 +0100 Subject: [PATCH 14/34] Added tests for some of the new methods. --- norduniclient/tests/test_models.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 9d14fef..b9aef1a 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -149,12 +149,16 @@ def setUp(self): (contact2:Node:Relation:Contact{name:'Contact2', handle_id:'116'}), (role1:Node:Logical:Role{name:'Role1', handle_id:'117'}), (role2:Node:Logical:Role{name:'Role2', handle_id:'118'}), + (procedure1:Node:Logical:Procedure{name:'Procedure1', handle_id:'119'}), + (procedure2:Node:Logical:Procedure{name:'Procedure2', handle_id:'120'}), + // Create relationships (contact1)-[:Is]->(role1), (contact2)-[:Is]->(role2), (contact1)-[:Works_for]->(organization1), - (contact2)-[:Works_for]->(organization2) + (contact2)-[:Works_for]->(organization2), + (organization1)-[:Uses_a]->(procedure1) """ # Insert mocked network @@ -576,6 +580,26 @@ def test_set_parent(self): relations = organization2.get_relations() self.assertIsInstance(relations['Parent_of'][0]['node'], models.OrganizationModel) + def test_get_outgoing_relations(self): + contact1 = core.get_node_model(self.neo4jdb, handle_id='115') + relations = contact1.get_outgoing_relations() + + self.assertIsInstance(relations['Works_for'][0]['node'], models.OrganizationModel) + self.assertIsInstance(relations['Is'][0]['node'], models.RoleModel) + + def test_uses_a_procedure(self): + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + organization2 = core.get_node_model(self.neo4jdb, handle_id='114') + procedure1 = core.get_node_model(self.neo4jdb, handle_id='119') + procedure2 = core.get_node_model(self.neo4jdb, handle_id='120') + + relations1 = procedure1.get_relations() + self.assertIsInstance(relations1['Uses_a'][0]['node'], models.OrganizationModel) + + organization2.add_procedure(procedure2.handle_id) + relations2 = procedure2.get_relations() + self.assertIsInstance(relations2['Uses_a'][0]['node'], models.OrganizationModel) + # TODO: EquipmentModel get_ports should probably work as CommonQueries get_ports def test_get_ports_equipment_model(self): odf1 = core.get_node_model(self.neo4jdb, handle_id='23') From 6eff922f0152e7e4405dcdc94837599b3f50f0e7 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 20 Mar 2019 09:33:08 +0100 Subject: [PATCH 15/34] New methods: one for group and one for organization --- norduniclient/models.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 53df7b2..554a454 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -939,6 +939,13 @@ def add_procedure(self, proc_handle_id): """ return self._basic_write_query_to_dict(q, proc_handle_id=proc_handle_id) + def get_outgoing_relations(self): + q = """ + MATCH (n:Node:Organization {handle_id: {handle_id}})-[r:Parent|Uses_a]->(node) + RETURN r, node + """ + return self._basic_read_query_to_dict(q) + class ProviderModel(RelationModel): pass @@ -977,7 +984,13 @@ def get_outgoing_relations(self): return self._basic_read_query_to_dict(q) class GroupModel(LogicalModel): - pass + def add_member(self, contact_handle_id): + q = """ + MATCH (n:Node:Contact {handle_id: {contact_handle_id}}), (m:Node:Group {handle_id: {handle_id}}) + MERGE (n)-[r:Member_of]->(m) + RETURN m as created, r, n as node + """ + return self._basic_write_query_to_dict(q, contact_handle_id=contact_handle_id) class RoleModel(LogicalModel): From abb0297669df82a14fd5cad5d1a748180389bd2c Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 20 Mar 2019 15:20:55 +0100 Subject: [PATCH 16/34] New tests for the new methods --- norduniclient/tests/test_models.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index b9aef1a..7095b3a 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -151,6 +151,7 @@ def setUp(self): (role2:Node:Logical:Role{name:'Role2', handle_id:'118'}), (procedure1:Node:Logical:Procedure{name:'Procedure1', handle_id:'119'}), (procedure2:Node:Logical:Procedure{name:'Procedure2', handle_id:'120'}), + (group1:Node:Logical:Group{name:'Group1', handle_id:'121'}), // Create relationships @@ -600,6 +601,18 @@ def test_uses_a_procedure(self): relations2 = procedure2.get_relations() self.assertIsInstance(relations2['Uses_a'][0]['node'], models.OrganizationModel) + def test_organization_outgoingrel(self): + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + relations1 = organization1.get_outgoing_relations() + self.assertIsInstance(relations1['Uses_a'][0]['node'], models.ProcedureModel) + + def test_groups(self): + group1 = core.get_node_model(self.neo4jdb, handle_id='121') + contact1 = core.get_node_model(self.neo4jdb, handle_id='115') + group1.add_member(contact1.handle_id) + relations = contact1.get_outgoing_relations() + self.assertIsInstance(relations['Member_of'][0]['node'], models.GroupModel) + # TODO: EquipmentModel get_ports should probably work as CommonQueries get_ports def test_get_ports_equipment_model(self): odf1 = core.get_node_model(self.neo4jdb, handle_id='23') From 18bcc7cb44998bea38e34b2747948e61466d2239 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Mon, 8 Apr 2019 08:04:41 +0200 Subject: [PATCH 17/34] New organization methods --- norduniclient/models.py | 22 ++++++++++++++++++++++ norduniclient/tests/test_models.py | 19 +++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 554a454..bd57ffa 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -946,6 +946,28 @@ def get_outgoing_relations(self): """ return self._basic_read_query_to_dict(q) + def get_contacts(self): + q = """ + MATCH (c:Node:Contact)-[:Works_for]->(o:Node:Organization) + WHERE o.handle_id = {handle_id} + RETURN c.handle_id as handle_id, c.name as name + """ + return core.query_to_list(self.manager, q, handle_id=self.handle_id) + + def remove_role_from_contacts(self, rolename): + handle_id = self.handle_id + if isinstance(self.handle_id, six.string_types): + handle_id = "'{}'".format(handle_id) + + q = """ + MATCH (role:Node:Role)<-[r:Is]-(cont:Node:Contact)-[:Works_for]->(org:Node:Organization) + WHERE org.handle_id = {handle_id} AND role.name = '{rolename}' + DELETE r + RETURN cont + """.format(handle_id=handle_id, rolename=rolename) + + return core.query_to_dict(self.manager, q) + class ProviderModel(RelationModel): pass diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 7095b3a..a6522ae 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -155,8 +155,8 @@ def setUp(self): // Create relationships - (contact1)-[:Is]->(role1), - (contact2)-[:Is]->(role2), + (role1)<-[:Is]-(contact1), + (role2)<-[:Is]-(contact2), (contact1)-[:Works_for]->(organization1), (contact2)-[:Works_for]->(organization2), (organization1)-[:Uses_a]->(procedure1) @@ -606,6 +606,21 @@ def test_organization_outgoingrel(self): relations1 = organization1.get_outgoing_relations() self.assertIsInstance(relations1['Uses_a'][0]['node'], models.ProcedureModel) + def test_organization_contacts(self): + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + contacts = organization1.get_contacts() + contact1 = core.get_node_model(self.neo4jdb, handle_id='115') + self.assertEqual(contact1.handle_id, contacts[0]['handle_id']) + self.assertEqual(contact1.data['name'], contacts[0]['name']) + + def test_detach_contact(self): + role1 = core.get_node_model(self.neo4jdb, handle_id='117') + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + organization1.remove_role_from_contacts(role1.data['name']) + contact1 = core.get_node_model(self.neo4jdb, handle_id='115') + relations = contact1.get_outgoing_relations() + self.assertTrue('Is' not in relations) + def test_groups(self): group1 = core.get_node_model(self.neo4jdb, handle_id='121') contact1 = core.get_node_model(self.neo4jdb, handle_id='115') From 12903d87aa401027421b58d5e2633556157634f2 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Mon, 3 Jun 2019 13:49:55 +0200 Subject: [PATCH 18/34] Implementing methods RoleRelationship --- norduniclient/models.py | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index bd57ffa..9c1290e 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1019,5 +1019,64 @@ class RoleModel(LogicalModel): pass +class RoleRelationship(BaseRelationshipModel): + ROLE_TYPE = 'Works_for' + + def __init__(self, manager): + super(RoleRelationship, self).__init__(manager) + self.type = RoleRelationship.ROLE_TYPE + self.name = None + + def load(self, relationship_bundle): + super(RoleRelationship, self).load(relationship_bundle) + self.type = RoleRelationship.ROLE_TYPE + self.name = self.data.get('name', None) + + return self + + @classmethod + def link_contact_organization(cls, contact_id, organization_id, rolename): + # create relation + manager = core.GraphDB.get_instance().manager + relation_id = core._create_relationship(manager, organization_id, contact_id, cls.ROLE_TYPE) + + # add name + data = { "name": rolename } + core.set_relationship_properties(manager, relation_id, data) + + # load and return + relation = cls.get_relationship_model(manager, relationship_id=relation_id) + + return relation + + @classmethod + def get_relationship_model(cls, manager, relationship_id): + """ + :param manager: Context manager to handle transactions + :type manager: Neo4jDBSessionManager + :param relationship_id: Internal Neo4j relationship id + :type relationship_id: int + :return: Relationship model + :rtype: models.BaseRelationshipModel + """ + manager = core.GraphDB.get_instance().manager + bundle = core.get_relationship_bundle(manager, relationship_id) + return cls(manager).load(bundle) + + @classmethod + def get_all_roles(cls): + manager = core.GraphDB.get_instance().manager + q = """MATCH (n:Contact)-[r:Works_for]->(m:Organization) + WHERE r.name IS NOT NULL + RETURN r.name as role_name""" + + result = core.query_to_list(manager, q) + endresult = [] + for r in result: + if r['role_name'] not in endresult: + endresult.append(r['role_name']) + + return endresult + class ProcedureModel(LogicalModel): pass From 3f882a6cba1969f99de6c0a0d1863e30a9932b98 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Tue, 4 Jun 2019 10:37:12 +0200 Subject: [PATCH 19/34] Removed old methods and tests changed accordingly --- norduniclient/models.py | 80 ++++++++++++++---------------- norduniclient/tests/test_models.py | 37 +++++++------- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 9c1290e..4c70ba2 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -241,7 +241,7 @@ def get_child_form_data(self, node_type): def get_relations(self): q = """ - MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Parent_of|Member_of|Is|Uses_a]-(node) + MATCH (n:Node {handle_id: {handle_id}})<-[r:Owns|Uses|Provides|Responsible_for|Works_for|Parent_of|Member_of|Uses_a]-(node) RETURN r, node """ return self._basic_read_query_to_dict(q) @@ -954,42 +954,12 @@ def get_contacts(self): """ return core.query_to_list(self.manager, q, handle_id=self.handle_id) - def remove_role_from_contacts(self, rolename): - handle_id = self.handle_id - if isinstance(self.handle_id, six.string_types): - handle_id = "'{}'".format(handle_id) - - q = """ - MATCH (role:Node:Role)<-[r:Is]-(cont:Node:Contact)-[:Works_for]->(org:Node:Organization) - WHERE org.handle_id = {handle_id} AND role.name = '{rolename}' - DELETE r - RETURN cont - """.format(handle_id=handle_id, rolename=rolename) - - return core.query_to_dict(self.manager, q) - class ProviderModel(RelationModel): pass class ContactModel(RelationModel): - def add_role(self, role_handle_id): - q = """ - MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Role {handle_id: {role_handle_id}}) - MERGE (n)-[r:Is]->(m) - RETURN m as created, r, n as node - """ - return self._basic_write_query_to_dict(q, role_handle_id=role_handle_id) - - def add_organization(self, org_handle_id): - q = """ - MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Organization {handle_id: {org_handle_id}}) - MERGE (n)-[r:Works_for]->(m) - RETURN m as created, r, n as node - """ - return self._basic_write_query_to_dict(q, org_handle_id=org_handle_id) - def add_group(self, group_handle_id): q = """ MATCH (n:Node:Contact {handle_id: {handle_id}}), (m:Node:Group {handle_id: {group_handle_id}}) @@ -1000,7 +970,7 @@ def add_group(self, group_handle_id): def get_outgoing_relations(self): q = """ - MATCH (n:Node:Contact {handle_id: {handle_id}})-[r:Works_for|Member_of|Is]->(node) + MATCH (n:Node:Contact {handle_id: {handle_id}})-[r:Works_for|Member_of]->(node) RETURN r, node """ return self._basic_read_query_to_dict(q) @@ -1015,10 +985,6 @@ def add_member(self, contact_handle_id): return self._basic_write_query_to_dict(q, contact_handle_id=contact_handle_id) -class RoleModel(LogicalModel): - pass - - class RoleRelationship(BaseRelationshipModel): ROLE_TYPE = 'Works_for' @@ -1036,18 +1002,48 @@ def load(self, relationship_bundle): @classmethod def link_contact_organization(cls, contact_id, organization_id, rolename): + if isinstance(contact_id, six.string_types): + contact_id = "'{}'".format(contact_id) + + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + if not rolename: + rolename = "" + # create relation manager = core.GraphDB.get_instance().manager - relation_id = core._create_relationship(manager, organization_id, contact_id, cls.ROLE_TYPE) - # add name - data = { "name": rolename } - core.set_relationship_properties(manager, relation_id, data) + q = """ + MATCH (c:Contact), (o:Organization) + WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} + MERGE (c)-[r:Works_for {{ name: '{rolename}'}}]->(o) + RETURN ID(r) as relation_id + """.format(contact_id=contact_id, organization_id=organization_id, rolename=rolename) + ret = core.query_to_dict(manager, q) # load and return - relation = cls.get_relationship_model(manager, relationship_id=relation_id) + if ret: + relation_id = ret['relation_id'] + relation = cls.get_relationship_model(manager, relationship_id=relation_id) + + return relation - return relation + @classmethod + def unlink_contact_organization(cls, contact_id, organization_id): + if isinstance(contact_id, six.string_types): + contact_id = "'{}'".format(contact_id) + + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + manager = core.GraphDB.get_instance().manager + q = """ + MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) + WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} + DELETE r RETURN c + """ + core.query_to_dict(manager, q, contact_id=contact_id, organization_id=organization_id) @classmethod def get_relationship_model(cls, manager, relationship_id): diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index a6522ae..eacebbd 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -147,18 +147,14 @@ def setUp(self): (organization2:Node:Relation:Organization{name:'Organization2', handle_id:'114'}), (contact1:Node:Relation:Contact{name:'Contact1', handle_id:'115'}), (contact2:Node:Relation:Contact{name:'Contact2', handle_id:'116'}), - (role1:Node:Logical:Role{name:'Role1', handle_id:'117'}), - (role2:Node:Logical:Role{name:'Role2', handle_id:'118'}), (procedure1:Node:Logical:Procedure{name:'Procedure1', handle_id:'119'}), (procedure2:Node:Logical:Procedure{name:'Procedure2', handle_id:'120'}), (group1:Node:Logical:Group{name:'Group1', handle_id:'121'}), // Create relationships - (role1)<-[:Is]-(contact1), - (role2)<-[:Is]-(contact2), - (contact1)-[:Works_for]->(organization1), - (contact2)-[:Works_for]->(organization2), + (contact1)-[:Works_for {name: 'IT-Manager'}]->(organization1), + (contact2)-[:Works_for {name: 'Abuse Management'}]->(organization2), (organization1)-[:Uses_a]->(procedure1) """ @@ -330,10 +326,6 @@ def test_get_relations(self): relations = organization1.get_relations() self.assertIsInstance(relations['Works_for'][0]['node'], models.RelationModel) - role1 = core.get_node_model(self.neo4jdb, handle_id='117') - relations = role1.get_relations() - self.assertIsInstance(relations['Is'][0]['node'], models.RelationModel) - def test_get_dependencies(self): logical3 = core.get_node_model(self.neo4jdb, handle_id='107') dependencies = logical3.get_dependencies() @@ -584,9 +576,22 @@ def test_set_parent(self): def test_get_outgoing_relations(self): contact1 = core.get_node_model(self.neo4jdb, handle_id='115') relations = contact1.get_outgoing_relations() - self.assertIsInstance(relations['Works_for'][0]['node'], models.OrganizationModel) - self.assertIsInstance(relations['Is'][0]['node'], models.RoleModel) + self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': 'IT-Manager'}) + + def test_contact_role_org(self): + contact1 = core.get_node_model(self.neo4jdb, handle_id='115') + organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + + # unlink + models.RoleRelationship.unlink_contact_organization(contact1.handle_id, organization1.handle_id) + relations = contact1.get_outgoing_relations() + self.assertIsNotNone(relations) + + # relink + models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, 'IT-Manager') + relations = contact1.get_outgoing_relations() + self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': 'IT-Manager'}) def test_uses_a_procedure(self): organization1 = core.get_node_model(self.neo4jdb, handle_id='113') @@ -613,14 +618,6 @@ def test_organization_contacts(self): self.assertEqual(contact1.handle_id, contacts[0]['handle_id']) self.assertEqual(contact1.data['name'], contacts[0]['name']) - def test_detach_contact(self): - role1 = core.get_node_model(self.neo4jdb, handle_id='117') - organization1 = core.get_node_model(self.neo4jdb, handle_id='113') - organization1.remove_role_from_contacts(role1.data['name']) - contact1 = core.get_node_model(self.neo4jdb, handle_id='115') - relations = contact1.get_outgoing_relations() - self.assertTrue('Is' not in relations) - def test_groups(self): group1 = core.get_node_model(self.neo4jdb, handle_id='121') contact1 = core.get_node_model(self.neo4jdb, handle_id='115') From a5c4889ceae090f173ad40855de31a45741b2cb8 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Tue, 4 Jun 2019 12:05:29 +0200 Subject: [PATCH 20/34] Added load_from_nodes --- norduniclient/models.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index 4c70ba2..f002b06 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1045,6 +1045,24 @@ def unlink_contact_organization(cls, contact_id, organization_id): """ core.query_to_dict(manager, q, contact_id=contact_id, organization_id=organization_id) + def load_from_nodes(self, contact_id, organization_id): + if isinstance(contact_id, six.string_types): + contact_id = "'{}'".format(contact_id) + + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + q = """ + MATCH (c:Contact)-[r:Works_for]->(o:Organization) + WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} + RETURN ID(r) as relation_id + """.format(contact_id=contact_id, organization_id=organization_id) + + ret = core.query_to_dict(self.manager, q) + + bundle = core.get_relationship_bundle(self.manager, ret['relation_id']) + self.load(bundle) + @classmethod def get_relationship_model(cls, manager, relationship_id): """ From ebb990fbfbab90f3175e47ffe9086a44bfb0b6da Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 5 Jun 2019 07:38:07 +0200 Subject: [PATCH 21/34] Return distinct nodes --- norduniclient/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index f002b06..b0c9674 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -950,7 +950,7 @@ def get_contacts(self): q = """ MATCH (c:Node:Contact)-[:Works_for]->(o:Node:Organization) WHERE o.handle_id = {handle_id} - RETURN c.handle_id as handle_id, c.name as name + RETURN DISTINCT c.handle_id as handle_id, c.name as name """ return core.query_to_list(self.manager, q, handle_id=self.handle_id) @@ -1059,7 +1059,7 @@ def load_from_nodes(self, contact_id, organization_id): """.format(contact_id=contact_id, organization_id=organization_id) ret = core.query_to_dict(self.manager, q) - + bundle = core.get_relationship_bundle(self.manager, ret['relation_id']) self.load(bundle) From 8eb22255c6018344e26a19629f80985ba6d313a3 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Thu, 6 Jun 2019 13:06:51 +0200 Subject: [PATCH 22/34] db manager as param in static methods and list roles testing --- norduniclient/models.py | 26 ++++++++++++++++---------- norduniclient/tests/test_models.py | 8 ++++++-- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index b0c9674..b0ae5f4 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1001,7 +1001,7 @@ def load(self, relationship_bundle): return self @classmethod - def link_contact_organization(cls, contact_id, organization_id, rolename): + def link_contact_organization(cls, contact_id, organization_id, rolename, manager=None): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) @@ -1012,7 +1012,8 @@ def link_contact_organization(cls, contact_id, organization_id, rolename): rolename = "" # create relation - manager = core.GraphDB.get_instance().manager + if not manager: + manager = core.GraphDB.get_instance().manager q = """ MATCH (c:Contact), (o:Organization) @@ -1030,14 +1031,16 @@ def link_contact_organization(cls, contact_id, organization_id, rolename): return relation @classmethod - def unlink_contact_organization(cls, contact_id, organization_id): + def unlink_contact_organization(cls, contact_id, organization_id, manager=None): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - manager = core.GraphDB.get_instance().manager + if not manager: + manager = core.GraphDB.get_instance().manager + q = """ MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} @@ -1073,22 +1076,25 @@ def get_relationship_model(cls, manager, relationship_id): :return: Relationship model :rtype: models.BaseRelationshipModel """ - manager = core.GraphDB.get_instance().manager + if not manager: + manager = core.GraphDB.get_instance().manager + bundle = core.get_relationship_bundle(manager, relationship_id) return cls(manager).load(bundle) @classmethod - def get_all_roles(cls): - manager = core.GraphDB.get_instance().manager + def get_all_roles(cls, manager=None): + if not manager: + manager = core.GraphDB.get_instance().manager + q = """MATCH (n:Contact)-[r:Works_for]->(m:Organization) WHERE r.name IS NOT NULL - RETURN r.name as role_name""" + RETURN DISTINCT r.name as role_name""" result = core.query_to_list(manager, q) endresult = [] for r in result: - if r['role_name'] not in endresult: - endresult.append(r['role_name']) + endresult.append(r['role_name']) return endresult diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index eacebbd..89f6d36 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -584,15 +584,19 @@ def test_contact_role_org(self): organization1 = core.get_node_model(self.neo4jdb, handle_id='113') # unlink - models.RoleRelationship.unlink_contact_organization(contact1.handle_id, organization1.handle_id) + models.RoleRelationship.unlink_contact_organization(contact1.handle_id, organization1.handle_id, self.neo4jdb) relations = contact1.get_outgoing_relations() self.assertIsNotNone(relations) # relink - models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, 'IT-Manager') + models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, 'IT-Manager', self.neo4jdb) relations = contact1.get_outgoing_relations() self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': 'IT-Manager'}) + # check role list + role_list = models.RoleRelationship.get_all_roles(self.neo4jdb) + self.assertEquals(role_list, [u'IT-Manager', u'Abuse Management']) + def test_uses_a_procedure(self): organization1 = core.get_node_model(self.neo4jdb, handle_id='113') organization2 = core.get_node_model(self.neo4jdb, handle_id='114') From f0f729c2f90de9288ddfa3d1e76fc5ad15b9f7cb Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 12 Jun 2019 08:06:10 +0200 Subject: [PATCH 23/34] New methods for roles, organizations and contacts --- norduniclient/models.py | 24 ++++++++++++++++++++++++ norduniclient/tests/test_models.py | 9 +++++++++ 2 files changed, 33 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index b0ae5f4..054f261 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1048,6 +1048,30 @@ def unlink_contact_organization(cls, contact_id, organization_id, manager=None): """ core.query_to_dict(manager, q, contact_id=contact_id, organization_id=organization_id) + @classmethod + def get_contact_with_role(cls, organization_id, role_name, manager=None): + if not manager: + manager = core.GraphDB.get_instance().manager + + q = """ + MATCH (o:Organization {handle_id: {organization_id}})<-[:Works_for {name: {role_name}}]-(c:Contact) + RETURN c.handle_id AS handle_id + """ + + return core.query_to_dict(manager, q, organization_id=organization_id, role_name=role_name) + + @classmethod + def remove_role_in_organization(cls, organization_id, role_name, manager=None): + if not manager: + manager = core.GraphDB.get_instance().manager + + q = """ + MATCH (o:Organization {handle_id: {organization_id}})<-[r:Works_for {name: {role_name}}]-(c:Contact) + DELETE r RETURN o + """ + + return core.query_to_dict(manager, q, organization_id=organization_id, role_name=role_name) + def load_from_nodes(self, contact_id, organization_id): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 89f6d36..063592c 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -597,6 +597,15 @@ def test_contact_role_org(self): role_list = models.RoleRelationship.get_all_roles(self.neo4jdb) self.assertEquals(role_list, [u'IT-Manager', u'Abuse Management']) + # get contact with role + contact_list = models.RoleRelationship.get_contact_with_role(organization1.handle_id, 'IT-Manager', self.neo4jdb) + self.assertEquals(contact_list, {'handle_id': '115'}) + + # remove free role in organization + models.RoleRelationship.remove_role_in_organization(organization1.handle_id, 'IT-Manager', self.neo4jdb) + relations = organization1.get_relations() + self.assertEquals(relations, {}) + def test_uses_a_procedure(self): organization1 = core.get_node_model(self.neo4jdb, handle_id='113') organization2 = core.get_node_model(self.neo4jdb, handle_id='114') From 5848a98b7da52f09e31004db476b8d1866849a3e Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 14 Jun 2019 14:32:50 +0200 Subject: [PATCH 24/34] Method to get all the persons with a determined rolename --- norduniclient/models.py | 47 ++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 054f261..4a22153 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1000,6 +1000,13 @@ def load(self, relationship_bundle): return self + @classmethod + def get_manager(cls, manager): + if not manager: + manager = core.GraphDB.get_instance().manager + + return manager + @classmethod def link_contact_organization(cls, contact_id, organization_id, rolename, manager=None): if isinstance(contact_id, six.string_types): @@ -1012,8 +1019,7 @@ def link_contact_organization(cls, contact_id, organization_id, rolename, manage rolename = "" # create relation - if not manager: - manager = core.GraphDB.get_instance().manager + manager = cls.get_manager(manager) q = """ MATCH (c:Contact), (o:Organization) @@ -1038,8 +1044,7 @@ def unlink_contact_organization(cls, contact_id, organization_id, manager=None): if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - if not manager: - manager = core.GraphDB.get_instance().manager + manager = cls.get_manager(manager) q = """ MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) @@ -1050,8 +1055,7 @@ def unlink_contact_organization(cls, contact_id, organization_id, manager=None): @classmethod def get_contact_with_role(cls, organization_id, role_name, manager=None): - if not manager: - manager = core.GraphDB.get_instance().manager + manager = cls.get_manager(manager) q = """ MATCH (o:Organization {handle_id: {organization_id}})<-[:Works_for {name: {role_name}}]-(c:Contact) @@ -1062,8 +1066,7 @@ def get_contact_with_role(cls, organization_id, role_name, manager=None): @classmethod def remove_role_in_organization(cls, organization_id, role_name, manager=None): - if not manager: - manager = core.GraphDB.get_instance().manager + manager = cls.get_manager(manager) q = """ MATCH (o:Organization {handle_id: {organization_id}})<-[r:Works_for {name: {role_name}}]-(c:Contact) @@ -1100,16 +1103,14 @@ def get_relationship_model(cls, manager, relationship_id): :return: Relationship model :rtype: models.BaseRelationshipModel """ - if not manager: - manager = core.GraphDB.get_instance().manager + manager = cls.get_manager(manager) bundle = core.get_relationship_bundle(manager, relationship_id) return cls(manager).load(bundle) @classmethod def get_all_roles(cls, manager=None): - if not manager: - manager = core.GraphDB.get_instance().manager + manager = cls.get_manager(manager) q = """MATCH (n:Contact)-[r:Works_for]->(m:Organization) WHERE r.name IS NOT NULL @@ -1122,5 +1123,27 @@ def get_all_roles(cls, manager=None): return endresult + @classmethod + def get_contacts_with_role(cls, role_name, manager=None): + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Contact)-[r:Works_for]->(o:Organization) + WHERE r.name = {role_name} + RETURN c + """ + + result = core.query_to_list(manager, q, role_name=role_name) + contact_list = [] + + for node in result: + contact = ContactModel(manager) + contact.data = {} + contact.data['handle_id'] = node['c'].properties['handle_id'] + contact.reload(node['c']) + contact_list.append(contact) + + return contact_list + class ProcedureModel(LogicalModel): pass From 6619be3290b071afb053bb2101108fa0d7ba9adc Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 28 Jun 2019 14:58:22 +0200 Subject: [PATCH 25/34] Just a simple name change --- norduniclient/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 4a22153..1ca0416 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -986,16 +986,16 @@ def add_member(self, contact_handle_id): class RoleRelationship(BaseRelationshipModel): - ROLE_TYPE = 'Works_for' + RELATION_NAME = 'Works_for' def __init__(self, manager): super(RoleRelationship, self).__init__(manager) - self.type = RoleRelationship.ROLE_TYPE + self.type = RoleRelationship.RELATION_NAME self.name = None def load(self, relationship_bundle): super(RoleRelationship, self).load(relationship_bundle) - self.type = RoleRelationship.ROLE_TYPE + self.type = RoleRelationship.RELATION_NAME self.name = self.data.get('name', None) return self From 68f50cbde50ac426b877daaa347915894393a175 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Tue, 16 Jul 2019 10:06:47 +0200 Subject: [PATCH 26/34] Added organization to the result set --- norduniclient/models.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 1ca0416..71ea729 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1130,7 +1130,7 @@ def get_contacts_with_role(cls, role_name, manager=None): q = """ MATCH (c:Contact)-[r:Works_for]->(o:Organization) WHERE r.name = {role_name} - RETURN c + RETURN c, o """ result = core.query_to_list(manager, q, role_name=role_name) @@ -1141,7 +1141,13 @@ def get_contacts_with_role(cls, role_name, manager=None): contact.data = {} contact.data['handle_id'] = node['c'].properties['handle_id'] contact.reload(node['c']) - contact_list.append(contact) + + organization = OrganizationModel(manager) + organization.data = {} + organization.data['handle_id'] = node['o'].properties['handle_id'] + organization.reload(node['o']) + + contact_list.append((contact, organization)) return contact_list From aa479968737f6446b4ef1a3797582a852ea86dcc Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Thu, 18 Jul 2019 13:56:54 +0200 Subject: [PATCH 27/34] Change in link method, now the handle_id is required --- norduniclient/models.py | 36 ++++++++++++++++++++++++++---- norduniclient/tests/test_models.py | 10 +++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 71ea729..6523745 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1008,7 +1008,7 @@ def get_manager(cls, manager): return manager @classmethod - def link_contact_organization(cls, contact_id, organization_id, rolename, manager=None): + def link_contact_organization(cls, contact_id, organization_id, role_handle_id, rolename, manager=None): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) @@ -1024,9 +1024,9 @@ def link_contact_organization(cls, contact_id, organization_id, rolename, manage q = """ MATCH (c:Contact), (o:Organization) WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} - MERGE (c)-[r:Works_for {{ name: '{rolename}'}}]->(o) + MERGE (c)-[r:Works_for {{ name: '{rolename}', handle_id: {role_handle_id}}}]->(o) RETURN ID(r) as relation_id - """.format(contact_id=contact_id, organization_id=organization_id, rolename=rolename) + """.format(contact_id=contact_id, organization_id=organization_id, rolename=rolename, role_handle_id=role_handle_id) ret = core.query_to_dict(manager, q) # load and return @@ -1124,7 +1124,7 @@ def get_all_roles(cls, manager=None): return endresult @classmethod - def get_contacts_with_role(cls, role_name, manager=None): + def get_contacts_with_role_name(cls, role_name, manager=None): manager = cls.get_manager(manager) q = """ @@ -1151,5 +1151,33 @@ def get_contacts_with_role(cls, role_name, manager=None): return contact_list + @classmethod + def get_contacts_with_role_id(cls, handle_id, manager=None): + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Contact)-[r:Works_for]->(o:Organization) + WHERE r.handle_id = {handle_id} + RETURN c, o + """ + + result = core.query_to_list(manager, q, handle_id=handle_id) + contact_list = [] + + for node in result: + contact = ContactModel(manager) + contact.data = {} + contact.data['handle_id'] = node['c'].properties['handle_id'] + contact.reload(node['c']) + + organization = OrganizationModel(manager) + organization.data = {} + organization.data['handle_id'] = node['o'].properties['handle_id'] + organization.reload(node['o']) + + contact_list.append((contact, organization)) + + return contact_list + class ProcedureModel(LogicalModel): pass diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 063592c..ffbf21f 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -582,6 +582,8 @@ def test_get_outgoing_relations(self): def test_contact_role_org(self): contact1 = core.get_node_model(self.neo4jdb, handle_id='115') organization1 = core.get_node_model(self.neo4jdb, handle_id='113') + role_name = 'IT-Manager' + role = Role.objects.get_or_create(name = role_name)[0] # unlink models.RoleRelationship.unlink_contact_organization(contact1.handle_id, organization1.handle_id, self.neo4jdb) @@ -589,20 +591,20 @@ def test_contact_role_org(self): self.assertIsNotNone(relations) # relink - models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, 'IT-Manager', self.neo4jdb) + models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, role.name, role.handle_id, self.neo4jdb) relations = contact1.get_outgoing_relations() - self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': 'IT-Manager'}) + self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': role.name}) # check role list role_list = models.RoleRelationship.get_all_roles(self.neo4jdb) self.assertEquals(role_list, [u'IT-Manager', u'Abuse Management']) # get contact with role - contact_list = models.RoleRelationship.get_contact_with_role(organization1.handle_id, 'IT-Manager', self.neo4jdb) + contact_list = models.RoleRelationship.get_contact_with_role(organization1.handle_id, role.name, self.neo4jdb) self.assertEquals(contact_list, {'handle_id': '115'}) # remove free role in organization - models.RoleRelationship.remove_role_in_organization(organization1.handle_id, 'IT-Manager', self.neo4jdb) + models.RoleRelationship.remove_role_in_organization(organization1.handle_id, role.name, self.neo4jdb) relations = organization1.get_relations() self.assertEquals(relations, {}) From 75890dcfb55c7a9b1211157bca04972a1f62243d Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 19 Jul 2019 12:05:08 +0200 Subject: [PATCH 28/34] New helper function --- norduniclient/models.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index 6523745..457261e 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1053,6 +1053,19 @@ def unlink_contact_organization(cls, contact_id, organization_id, manager=None): """ core.query_to_dict(manager, q, contact_id=contact_id, organization_id=organization_id) + @classmethod + def update_roles_withid(cls, role_handle_id, new_name, manager=None): + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Contact)-[r:Works_for]->(o:Organization) + WHERE r.handle_id = {role_handle_id} + SET r.name = "{new_name}" + RETURN r + """.format(role_handle_id=role_handle_id, new_name=new_name) + + core.query_to_dict(manager, q) + @classmethod def get_contact_with_role(cls, organization_id, role_name, manager=None): manager = cls.get_manager(manager) From 4aa8b136a08e9cd58ac3226cc58284972c3658a1 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Tue, 23 Jul 2019 11:13:49 +0200 Subject: [PATCH 29/34] RoleRelation: handle_id init, two methods for contact or role and delete --- norduniclient/models.py | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index 457261e..d32841c 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -992,11 +992,13 @@ def __init__(self, manager): super(RoleRelationship, self).__init__(manager) self.type = RoleRelationship.RELATION_NAME self.name = None + self.handle_id = None def load(self, relationship_bundle): super(RoleRelationship, self).load(relationship_bundle) self.type = RoleRelationship.RELATION_NAME self.name = self.data.get('name', None) + self.handle_id = self.data.get('handle_id', None) return self @@ -1036,6 +1038,49 @@ def link_contact_organization(cls, contact_id, organization_id, role_handle_id, return relation + @classmethod + def get_role_relation_from_organization(cls, organization_id, role_handle_id, manager=None): + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + if isinstance(role_handle_id, six.string_types): + role_handle_id = "'{}'".format(role_handle_id) + + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) + WHERE r.handle_id = {role_handle_id} AND o.handle_id = {organization_id} + RETURN ID(r) as relation_id + """ + ret = core.query_to_dict(manager, q, role_handle_id=role_handle_id, organization_id=organization_id) + + if ret: + relation_id = ret['relation_id'] + relation = cls.get_relationship_model(manager, relationship_id=relation_id) + + return relation + + @classmethod + def get_contact_with_role_in_organization(cls, organization_id, role_handle_id, manager=None): + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + if isinstance(role_handle_id, six.string_types): + role_handle_id = "'{}'".format(role_handle_id) + + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) + WHERE r.handle_id = {role_handle_id} AND o.handle_id = {organization_id} + RETURN c.handle_id as contact_handle_id + """ + ret = core.query_to_dict(manager, q, role_handle_id=role_handle_id, organization_id=organization_id) + + if ret: + return ret['contact_handle_id'] + @classmethod def unlink_contact_organization(cls, contact_id, organization_id, manager=None): if isinstance(contact_id, six.string_types): @@ -1066,6 +1111,18 @@ def update_roles_withid(cls, role_handle_id, new_name, manager=None): core.query_to_dict(manager, q) + @classmethod + def delete_roles_withid(cls, role_handle_id, manager=None): + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Contact)-[r:Works_for]->(o:Organization) + WHERE r.handle_id = {role_handle_id} + DELETE r + """.format(role_handle_id=role_handle_id) + + core.query_to_dict(manager, q) + @classmethod def get_contact_with_role(cls, organization_id, role_name, manager=None): manager = cls.get_manager(manager) From 23ed9a206a2a0b880b426a531e35004a1085ae2f Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Tue, 23 Jul 2019 12:28:26 +0200 Subject: [PATCH 30/34] Role: Added specific method to get a contact with a role --- norduniclient/models.py | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/norduniclient/models.py b/norduniclient/models.py index d32841c..a5fd09e 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1081,6 +1081,35 @@ def get_contact_with_role_in_organization(cls, organization_id, role_handle_id, if ret: return ret['contact_handle_id'] + @classmethod + def get_role_relation_from_contact_organization(cls, organization_id, role_handle_id, contact_id, manager=None): + if isinstance(contact_id, six.string_types): + contact_id = "'{}'".format(contact_id) + + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + if isinstance(role_handle_id, six.string_types): + role_handle_id = "'{}'".format(role_handle_id) + + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Node:Contact {handle_id: {contact_id}})\ + -[r:Works_for {handle_id: {role_handle_id}}]->\ + (o:Node:Organization {handle_id: {organization_id}}) + RETURN ID(r) as relation_id + """ + ret = core.query_to_dict(manager, q, contact_id=contact_id, \ + role_handle_id=role_handle_id, \ + organization_id=organization_id) + + if ret: + relation_id = ret['relation_id'] + relation = cls.get_relationship_model(manager, relationship_id=relation_id) + + return relation + @classmethod def unlink_contact_organization(cls, contact_id, organization_id, manager=None): if isinstance(contact_id, six.string_types): @@ -1098,6 +1127,29 @@ def unlink_contact_organization(cls, contact_id, organization_id, manager=None): """ core.query_to_dict(manager, q, contact_id=contact_id, organization_id=organization_id) + @classmethod + def unlink_contact_with_role_organization(cls, contact_id, organization_id, role_handle_id, manager=None): + if isinstance(contact_id, six.string_types): + contact_id = "'{}'".format(contact_id) + + if isinstance(organization_id, six.string_types): + organization_id = "'{}'".format(organization_id) + + if isinstance(role_handle_id, six.string_types): + role_handle_id = "'{}'".format(role_handle_id) + + manager = cls.get_manager(manager) + + q = """ + MATCH (c:Node:Contact {handle_id: {contact_id}})\ + -[r:Works_for {handle_id: {role_handle_id}}]->\ + (o:Node:Organization {handle_id: {organization_id}}) + DELETE r RETURN c + """ + core.query_to_dict(manager, q, contact_id=contact_id, \ + role_handle_id=role_handle_id, \ + organization_id=organization_id) + @classmethod def update_roles_withid(cls, role_handle_id, new_name, manager=None): manager = cls.get_manager(manager) From d90adb2e09074c793bdb873eee2626295c5dc9a1 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Wed, 24 Jul 2019 09:55:03 +0200 Subject: [PATCH 31/34] Deleted outdated methods, some renamed, the new ones added to the tests --- norduniclient/models.py | 107 ++++++----------------------- norduniclient/tests/test_models.py | 66 +++++++++++++----- 2 files changed, 67 insertions(+), 106 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index a5fd09e..7b80015 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -1052,8 +1052,8 @@ def get_role_relation_from_organization(cls, organization_id, role_handle_id, ma MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) WHERE r.handle_id = {role_handle_id} AND o.handle_id = {organization_id} RETURN ID(r) as relation_id - """ - ret = core.query_to_dict(manager, q, role_handle_id=role_handle_id, organization_id=organization_id) + """.format(role_handle_id=role_handle_id, organization_id=organization_id) + ret = core.query_to_dict(manager, q) if ret: relation_id = ret['relation_id'] @@ -1075,8 +1075,8 @@ def get_contact_with_role_in_organization(cls, organization_id, role_handle_id, MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) WHERE r.handle_id = {role_handle_id} AND o.handle_id = {organization_id} RETURN c.handle_id as contact_handle_id - """ - ret = core.query_to_dict(manager, q, role_handle_id=role_handle_id, organization_id=organization_id) + """.format(role_handle_id=role_handle_id, organization_id=organization_id) + ret = core.query_to_dict(manager, q) if ret: return ret['contact_handle_id'] @@ -1095,38 +1095,21 @@ def get_role_relation_from_contact_organization(cls, organization_id, role_handl manager = cls.get_manager(manager) q = """ - MATCH (c:Node:Contact {handle_id: {contact_id}})\ - -[r:Works_for {handle_id: {role_handle_id}}]->\ - (o:Node:Organization {handle_id: {organization_id}}) + MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) + WHERE c.handle_id = {contact_id} + AND r.handle_id = {role_handle_id} + AND o.handle_id = {organization_id} RETURN ID(r) as relation_id - """ - ret = core.query_to_dict(manager, q, contact_id=contact_id, \ - role_handle_id=role_handle_id, \ + """.format(contact_id=contact_id,role_handle_id=role_handle_id, organization_id=organization_id) - + ret = core.query_to_dict(manager, q) + if ret: relation_id = ret['relation_id'] relation = cls.get_relationship_model(manager, relationship_id=relation_id) return relation - @classmethod - def unlink_contact_organization(cls, contact_id, organization_id, manager=None): - if isinstance(contact_id, six.string_types): - contact_id = "'{}'".format(contact_id) - - if isinstance(organization_id, six.string_types): - organization_id = "'{}'".format(organization_id) - - manager = cls.get_manager(manager) - - q = """ - MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) - WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} - DELETE r RETURN c - """ - core.query_to_dict(manager, q, contact_id=contact_id, organization_id=organization_id) - @classmethod def unlink_contact_with_role_organization(cls, contact_id, organization_id, role_handle_id, manager=None): if isinstance(contact_id, six.string_types): @@ -1140,15 +1123,15 @@ def unlink_contact_with_role_organization(cls, contact_id, organization_id, role manager = cls.get_manager(manager) - q = """ - MATCH (c:Node:Contact {handle_id: {contact_id}})\ - -[r:Works_for {handle_id: {role_handle_id}}]->\ - (o:Node:Organization {handle_id: {organization_id}}) + q = ''' + MATCH (c:Contact)-[r:Works_for]->(o:Organization) + WHERE c.handle_id = {contact_id} + AND r.handle_id = {role_handle_id} + AND o.handle_id = {organization_id} DELETE r RETURN c - """ - core.query_to_dict(manager, q, contact_id=contact_id, \ - role_handle_id=role_handle_id, \ - organization_id=organization_id) + '''.format(contact_id=contact_id, role_handle_id=role_handle_id, \ + organization_id=organization_id) + ret = core.query_to_dict(manager, q) @classmethod def update_roles_withid(cls, role_handle_id, new_name, manager=None): @@ -1175,28 +1158,6 @@ def delete_roles_withid(cls, role_handle_id, manager=None): core.query_to_dict(manager, q) - @classmethod - def get_contact_with_role(cls, organization_id, role_name, manager=None): - manager = cls.get_manager(manager) - - q = """ - MATCH (o:Organization {handle_id: {organization_id}})<-[:Works_for {name: {role_name}}]-(c:Contact) - RETURN c.handle_id AS handle_id - """ - - return core.query_to_dict(manager, q, organization_id=organization_id, role_name=role_name) - - @classmethod - def remove_role_in_organization(cls, organization_id, role_name, manager=None): - manager = cls.get_manager(manager) - - q = """ - MATCH (o:Organization {handle_id: {organization_id}})<-[r:Works_for {name: {role_name}}]-(c:Contact) - DELETE r RETURN o - """ - - return core.query_to_dict(manager, q, organization_id=organization_id, role_name=role_name) - def load_from_nodes(self, contact_id, organization_id): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) @@ -1231,7 +1192,7 @@ def get_relationship_model(cls, manager, relationship_id): return cls(manager).load(bundle) @classmethod - def get_all_roles(cls, manager=None): + def get_all_role_names(cls, manager=None): manager = cls.get_manager(manager) q = """MATCH (n:Contact)-[r:Works_for]->(m:Organization) @@ -1245,34 +1206,6 @@ def get_all_roles(cls, manager=None): return endresult - @classmethod - def get_contacts_with_role_name(cls, role_name, manager=None): - manager = cls.get_manager(manager) - - q = """ - MATCH (c:Contact)-[r:Works_for]->(o:Organization) - WHERE r.name = {role_name} - RETURN c, o - """ - - result = core.query_to_list(manager, q, role_name=role_name) - contact_list = [] - - for node in result: - contact = ContactModel(manager) - contact.data = {} - contact.data['handle_id'] = node['c'].properties['handle_id'] - contact.reload(node['c']) - - organization = OrganizationModel(manager) - organization.data = {} - organization.data['handle_id'] = node['o'].properties['handle_id'] - organization.reload(node['o']) - - contact_list.append((contact, organization)) - - return contact_list - @classmethod def get_contacts_with_role_id(cls, handle_id, manager=None): manager = cls.get_manager(manager) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index ffbf21f..8785f51 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -141,6 +141,11 @@ def setUp(self): (physical2)<-[:Connected_to]-(physical4)-[:Connected_to]->(physical3) """ + self.role_name_1 = u'IT-Manager' + self.role_name_2 = u'Abuse Management' + self.role_handle_id_1 = 122 + self.role_handle_id_2 = 123 + q3 = """ // Create organization and contact nodes CREATE (organization1:Node:Relation:Organization{name:'Organization1', handle_id:'113'}), @@ -153,8 +158,8 @@ def setUp(self): // Create relationships - (contact1)-[:Works_for {name: 'IT-Manager'}]->(organization1), - (contact2)-[:Works_for {name: 'Abuse Management'}]->(organization2), + (contact1)-[:Works_for {name: 'IT-Manager', handle_id: 122 }]->(organization1), + (contact2)-[:Works_for {name: 'Abuse Management', handle_id: 123 }]->(organization2), (organization1)-[:Uses_a]->(procedure1) """ @@ -577,36 +582,59 @@ def test_get_outgoing_relations(self): contact1 = core.get_node_model(self.neo4jdb, handle_id='115') relations = contact1.get_outgoing_relations() self.assertIsInstance(relations['Works_for'][0]['node'], models.OrganizationModel) - self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': 'IT-Manager'}) + + expected_value = { 'name': self.role_name_1, 'handle_id': self.role_handle_id_1} + self.assertEquals(relations['Works_for'][0]['relationship'], expected_value) def test_contact_role_org(self): contact1 = core.get_node_model(self.neo4jdb, handle_id='115') organization1 = core.get_node_model(self.neo4jdb, handle_id='113') - role_name = 'IT-Manager' - role = Role.objects.get_or_create(name = role_name)[0] # unlink - models.RoleRelationship.unlink_contact_organization(contact1.handle_id, organization1.handle_id, self.neo4jdb) + models.RoleRelationship.unlink_contact_with_role_organization(contact1.handle_id, + organization1.handle_id, self.role_handle_id_1, self.neo4jdb) + relations = contact1.get_outgoing_relations() - self.assertIsNotNone(relations) + self.assertEquals(relations, {}) # relink - models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, role.name, role.handle_id, self.neo4jdb) + models.RoleRelationship.link_contact_organization(contact1.handle_id, + organization1.handle_id, self.role_handle_id_1, self.role_name_1, self.neo4jdb) relations = contact1.get_outgoing_relations() - self.assertEquals(relations['Works_for'][0]['relationship'], { 'name': role.name}) + expected_value = { 'name': self.role_name_1, 'handle_id': self.role_handle_id_1} + self.assertEquals(relations['Works_for'][0]['relationship'], expected_value) - # check role list - role_list = models.RoleRelationship.get_all_roles(self.neo4jdb) - self.assertEquals(role_list, [u'IT-Manager', u'Abuse Management']) + # get contact which holds this role in this organization + contact_handle_id = models.RoleRelationship.get_contact_with_role_in_organization( + organization1.handle_id, self.role_handle_id_1, self.neo4jdb) + self.assertEqual(contact_handle_id, contact1.handle_id) - # get contact with role - contact_list = models.RoleRelationship.get_contact_with_role(organization1.handle_id, role.name, self.neo4jdb) - self.assertEquals(contact_list, {'handle_id': '115'}) + # get the relation of a organization with a specific role + relation = models.RoleRelationship.get_role_relation_from_organization( + organization1.handle_id, self.role_handle_id_1, self.neo4jdb) + self.assertEqual(relations['Works_for'][0]['relationship_id'], relation.id) - # remove free role in organization - models.RoleRelationship.remove_role_in_organization(organization1.handle_id, role.name, self.neo4jdb) - relations = organization1.get_relations() - self.assertEquals(relations, {}) + # get the relation between contact and organization with a specific role + relation = models.RoleRelationship.get_role_relation_from_contact_organization( + organization1.handle_id, self.role_handle_id_1, contact1.handle_id, self.neo4jdb) + self.assertEqual(relations['Works_for'][0]['relationship_id'], relation.id) + + # check role list + role_list = models.RoleRelationship.get_all_role_names(self.neo4jdb) + self.assertEquals(role_list, [self.role_name_1, self.role_name_2]) + + # role name change + new_role_name = u"Abuse Manager" + models.RoleRelationship.update_roles_withid(self.role_handle_id_2, + new_role_name, self.neo4jdb) + role_list = models.RoleRelationship.get_all_role_names(self.neo4jdb) + self.assertEquals(role_list, [self.role_name_1, new_role_name]) + + # delete role + models.RoleRelationship.delete_roles_withid(self.role_handle_id_2, + self.neo4jdb) + role_list = models.RoleRelationship.get_all_role_names(self.neo4jdb) + self.assertEquals(role_list, [self.role_name_1]) def test_uses_a_procedure(self): organization1 = core.get_node_model(self.neo4jdb, handle_id='113') From b17ebf85b5bb8d1f7524b342fd9587f08b6c1d36 Mon Sep 17 00:00:00 2001 From: Francisco Fuentes Date: Fri, 26 Jul 2019 12:48:43 +0200 Subject: [PATCH 32/34] The role id lookup has been reverted to a name lookup in all methods --- norduniclient/models.py | 67 +++++++++++++----------------- norduniclient/tests/test_models.py | 24 +++++------ 2 files changed, 39 insertions(+), 52 deletions(-) diff --git a/norduniclient/models.py b/norduniclient/models.py index 7b80015..ad06b04 100644 --- a/norduniclient/models.py +++ b/norduniclient/models.py @@ -987,6 +987,7 @@ def add_member(self, contact_handle_id): class RoleRelationship(BaseRelationshipModel): RELATION_NAME = 'Works_for' + DEFAULT_ROLE_NAME = 'Employee' def __init__(self, manager): super(RoleRelationship, self).__init__(manager) @@ -1010,15 +1011,15 @@ def get_manager(cls, manager): return manager @classmethod - def link_contact_organization(cls, contact_id, organization_id, role_handle_id, rolename, manager=None): + def link_contact_organization(cls, contact_id, organization_id, role_name, manager=None): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - if not rolename: - rolename = "" + if not role_name: + role_name = cls.DEFAULT_ROLE_NAME # create relation manager = cls.get_manager(manager) @@ -1026,9 +1027,9 @@ def link_contact_organization(cls, contact_id, organization_id, role_handle_id, q = """ MATCH (c:Contact), (o:Organization) WHERE c.handle_id = {contact_id} AND o.handle_id = {organization_id} - MERGE (c)-[r:Works_for {{ name: '{rolename}', handle_id: {role_handle_id}}}]->(o) + MERGE (c)-[r:Works_for {{ name: '{role_name}'}}]->(o) RETURN ID(r) as relation_id - """.format(contact_id=contact_id, organization_id=organization_id, rolename=rolename, role_handle_id=role_handle_id) + """.format(contact_id=contact_id, organization_id=organization_id, role_name=role_name) ret = core.query_to_dict(manager, q) # load and return @@ -1039,20 +1040,17 @@ def link_contact_organization(cls, contact_id, organization_id, role_handle_id, return relation @classmethod - def get_role_relation_from_organization(cls, organization_id, role_handle_id, manager=None): + def get_role_relation_from_organization(cls, organization_id, role_name, manager=None): if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - if isinstance(role_handle_id, six.string_types): - role_handle_id = "'{}'".format(role_handle_id) - manager = cls.get_manager(manager) q = """ MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) - WHERE r.handle_id = {role_handle_id} AND o.handle_id = {organization_id} + WHERE r.name = "{role_name}" AND o.handle_id = {organization_id} RETURN ID(r) as relation_id - """.format(role_handle_id=role_handle_id, organization_id=organization_id) + """.format(role_name=role_name, organization_id=organization_id) ret = core.query_to_dict(manager, q) if ret: @@ -1062,45 +1060,39 @@ def get_role_relation_from_organization(cls, organization_id, role_handle_id, ma return relation @classmethod - def get_contact_with_role_in_organization(cls, organization_id, role_handle_id, manager=None): + def get_contact_with_role_in_organization(cls, organization_id, role_name, manager=None): if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - if isinstance(role_handle_id, six.string_types): - role_handle_id = "'{}'".format(role_handle_id) - manager = cls.get_manager(manager) q = """ MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) - WHERE r.handle_id = {role_handle_id} AND o.handle_id = {organization_id} + WHERE r.name = "{role_name}" AND o.handle_id = {organization_id} RETURN c.handle_id as contact_handle_id - """.format(role_handle_id=role_handle_id, organization_id=organization_id) + """.format(role_name=role_name, organization_id=organization_id) ret = core.query_to_dict(manager, q) if ret: return ret['contact_handle_id'] @classmethod - def get_role_relation_from_contact_organization(cls, organization_id, role_handle_id, contact_id, manager=None): + def get_role_relation_from_contact_organization(cls, organization_id, role_name, contact_id, manager=None): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - if isinstance(role_handle_id, six.string_types): - role_handle_id = "'{}'".format(role_handle_id) - manager = cls.get_manager(manager) q = """ MATCH (c:Node:Contact)-[r:Works_for]->(o:Node:Organization) WHERE c.handle_id = {contact_id} - AND r.handle_id = {role_handle_id} + AND r.name = "{role_name}" AND o.handle_id = {organization_id} RETURN ID(r) as relation_id - """.format(contact_id=contact_id,role_handle_id=role_handle_id, + """.format(contact_id=contact_id, role_name=role_name, organization_id=organization_id) ret = core.query_to_dict(manager, q) @@ -1111,50 +1103,47 @@ def get_role_relation_from_contact_organization(cls, organization_id, role_handl return relation @classmethod - def unlink_contact_with_role_organization(cls, contact_id, organization_id, role_handle_id, manager=None): + def unlink_contact_with_role_organization(cls, contact_id, organization_id, role_name, manager=None): if isinstance(contact_id, six.string_types): contact_id = "'{}'".format(contact_id) if isinstance(organization_id, six.string_types): organization_id = "'{}'".format(organization_id) - if isinstance(role_handle_id, six.string_types): - role_handle_id = "'{}'".format(role_handle_id) - manager = cls.get_manager(manager) q = ''' MATCH (c:Contact)-[r:Works_for]->(o:Organization) WHERE c.handle_id = {contact_id} - AND r.handle_id = {role_handle_id} + AND r.name = "{role_name}" AND o.handle_id = {organization_id} DELETE r RETURN c - '''.format(contact_id=contact_id, role_handle_id=role_handle_id, \ + '''.format(contact_id=contact_id, role_name=role_name, \ organization_id=organization_id) ret = core.query_to_dict(manager, q) @classmethod - def update_roles_withid(cls, role_handle_id, new_name, manager=None): + def update_roles_withname(cls, role_name, new_name, manager=None): manager = cls.get_manager(manager) q = """ MATCH (c:Contact)-[r:Works_for]->(o:Organization) - WHERE r.handle_id = {role_handle_id} + WHERE r.name = "{role_name}" SET r.name = "{new_name}" RETURN r - """.format(role_handle_id=role_handle_id, new_name=new_name) + """.format(role_name=role_name, new_name=new_name) core.query_to_dict(manager, q) @classmethod - def delete_roles_withid(cls, role_handle_id, manager=None): + def delete_roles_withname(cls, role_name, manager=None): manager = cls.get_manager(manager) q = """ MATCH (c:Contact)-[r:Works_for]->(o:Organization) - WHERE r.handle_id = {role_handle_id} + WHERE r.name = "{role_name}" DELETE r - """.format(role_handle_id=role_handle_id) + """.format(role_name=role_name) core.query_to_dict(manager, q) @@ -1207,16 +1196,16 @@ def get_all_role_names(cls, manager=None): return endresult @classmethod - def get_contacts_with_role_id(cls, handle_id, manager=None): + def get_contacts_with_role_name(cls, role_name, manager=None): manager = cls.get_manager(manager) q = """ MATCH (c:Contact)-[r:Works_for]->(o:Organization) - WHERE r.handle_id = {handle_id} + WHERE r.name = "{role_name}" RETURN c, o - """ + """.format(role_name=role_name) - result = core.query_to_list(manager, q, handle_id=handle_id) + result = core.query_to_list(manager, q) contact_list = [] for node in result: diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index 8785f51..f443e58 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -143,8 +143,6 @@ def setUp(self): self.role_name_1 = u'IT-Manager' self.role_name_2 = u'Abuse Management' - self.role_handle_id_1 = 122 - self.role_handle_id_2 = 123 q3 = """ // Create organization and contact nodes @@ -158,8 +156,8 @@ def setUp(self): // Create relationships - (contact1)-[:Works_for {name: 'IT-Manager', handle_id: 122 }]->(organization1), - (contact2)-[:Works_for {name: 'Abuse Management', handle_id: 123 }]->(organization2), + (contact1)-[:Works_for {name: 'IT-Manager' }]->(organization1), + (contact2)-[:Works_for {name: 'Abuse Management' }]->(organization2), (organization1)-[:Uses_a]->(procedure1) """ @@ -583,7 +581,7 @@ def test_get_outgoing_relations(self): relations = contact1.get_outgoing_relations() self.assertIsInstance(relations['Works_for'][0]['node'], models.OrganizationModel) - expected_value = { 'name': self.role_name_1, 'handle_id': self.role_handle_id_1} + expected_value = { 'name': self.role_name_1 } self.assertEquals(relations['Works_for'][0]['relationship'], expected_value) def test_contact_role_org(self): @@ -592,31 +590,31 @@ def test_contact_role_org(self): # unlink models.RoleRelationship.unlink_contact_with_role_organization(contact1.handle_id, - organization1.handle_id, self.role_handle_id_1, self.neo4jdb) + organization1.handle_id, self.role_name_1, self.neo4jdb) relations = contact1.get_outgoing_relations() self.assertEquals(relations, {}) # relink models.RoleRelationship.link_contact_organization(contact1.handle_id, - organization1.handle_id, self.role_handle_id_1, self.role_name_1, self.neo4jdb) + organization1.handle_id, self.role_name_1, self.neo4jdb) relations = contact1.get_outgoing_relations() - expected_value = { 'name': self.role_name_1, 'handle_id': self.role_handle_id_1} + expected_value = { 'name': self.role_name_1 } self.assertEquals(relations['Works_for'][0]['relationship'], expected_value) # get contact which holds this role in this organization contact_handle_id = models.RoleRelationship.get_contact_with_role_in_organization( - organization1.handle_id, self.role_handle_id_1, self.neo4jdb) + organization1.handle_id, self.role_name_1, self.neo4jdb) self.assertEqual(contact_handle_id, contact1.handle_id) # get the relation of a organization with a specific role relation = models.RoleRelationship.get_role_relation_from_organization( - organization1.handle_id, self.role_handle_id_1, self.neo4jdb) + organization1.handle_id, self.role_name_1, self.neo4jdb) self.assertEqual(relations['Works_for'][0]['relationship_id'], relation.id) # get the relation between contact and organization with a specific role relation = models.RoleRelationship.get_role_relation_from_contact_organization( - organization1.handle_id, self.role_handle_id_1, contact1.handle_id, self.neo4jdb) + organization1.handle_id, self.role_name_1, contact1.handle_id, self.neo4jdb) self.assertEqual(relations['Works_for'][0]['relationship_id'], relation.id) # check role list @@ -625,13 +623,13 @@ def test_contact_role_org(self): # role name change new_role_name = u"Abuse Manager" - models.RoleRelationship.update_roles_withid(self.role_handle_id_2, + models.RoleRelationship.update_roles_withname(self.role_name_2, new_role_name, self.neo4jdb) role_list = models.RoleRelationship.get_all_role_names(self.neo4jdb) self.assertEquals(role_list, [self.role_name_1, new_role_name]) # delete role - models.RoleRelationship.delete_roles_withid(self.role_handle_id_2, + models.RoleRelationship.delete_roles_withname(new_role_name, self.neo4jdb) role_list = models.RoleRelationship.get_all_role_names(self.neo4jdb) self.assertEquals(role_list, [self.role_name_1]) From 6d3c9f46904c64a62fe01194c5129ba593758c80 Mon Sep 17 00:00:00 2001 From: Johan Lundberg Date: Mon, 29 Jul 2019 14:36:35 +0200 Subject: [PATCH 33/34] Relationships returned are now Relationship objects not dicts --- norduniclient/tests/test_models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/norduniclient/tests/test_models.py b/norduniclient/tests/test_models.py index afd53d2..bce0378 100644 --- a/norduniclient/tests/test_models.py +++ b/norduniclient/tests/test_models.py @@ -606,8 +606,8 @@ def test_get_outgoing_relations(self): relations = contact1.get_outgoing_relations() self.assertIsInstance(relations['Works_for'][0]['node'], models.OrganizationModel) - expected_value = { 'name': self.role_name_1 } - self.assertEquals(relations['Works_for'][0]['relationship'], expected_value) + expected_value = self.role_name_1 + self.assertEquals(relations['Works_for'][0]['relationship']['name'], expected_value) def test_contact_role_org(self): contact1 = core.get_node_model(self.neo4jdb, handle_id='115') @@ -624,8 +624,8 @@ def test_contact_role_org(self): models.RoleRelationship.link_contact_organization(contact1.handle_id, organization1.handle_id, self.role_name_1, self.neo4jdb) relations = contact1.get_outgoing_relations() - expected_value = { 'name': self.role_name_1 } - self.assertEquals(relations['Works_for'][0]['relationship'], expected_value) + expected_value = self.role_name_1 + self.assertEquals(relations['Works_for'][0]['relationship']['name'], expected_value) # get contact which holds this role in this organization contact_handle_id = models.RoleRelationship.get_contact_with_role_in_organization( From 29b7aed720ae22d5feb71dba9160ee822a720dba Mon Sep 17 00:00:00 2001 From: Johan Lundberg Date: Mon, 29 Jul 2019 14:38:55 +0200 Subject: [PATCH 34/34] Remove SUNET specific files --- .jenkins.yaml | 19 ------------------- .travis.yml | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 21 deletions(-) delete mode 100644 .jenkins.yaml diff --git a/.jenkins.yaml b/.jenkins.yaml deleted file mode 100644 index e3f8010..0000000 --- a/.jenkins.yaml +++ /dev/null @@ -1,19 +0,0 @@ -builders: - - script -triggers: - cron: "@weekly" -environment_variables: - NEO4J_VERSION: "latest" -pre_build_script: - - "docker pull neo4j:${NEO4J_VERSION}" -script: - - "python3.7 -m venv venv" - - ". venv/bin/activate" - - "pip install -U setuptools wheel mypy" - - "python setup.py testing" - - "pip freeze" - - "python setup.py test" - - "python setup.py sdist bdist_wheel --universal" -publish_over_ssh: - - pypi.sunet.se -clean_workspace: true diff --git a/.travis.yml b/.travis.yml index 06527b7..a19a5ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ sudo: required -dist: xenial services: - docker @@ -8,7 +7,7 @@ language: python python: - '2.7' - - '3.7' + - '3.5' env: - NEO4J_VERSION=3.3.2 @@ -21,3 +20,14 @@ install: python setup.py testing script: python setup.py test +deploy: + provider: pypi + distributions: sdist bdist_wheel + user: Lundberg + password: + secure: pDqWOp0OZE9/uzRBcuWr/FgsKl7y1cpDW4GdBPRPstVMdJ42G1Vf8n5F+kJrpd8aSmG4G0+tw7iUN+SSn29Zpw3eTNJqClu4eKEILXKXO50Jr+w1c4hgpGrzbwi+q9IEMy0VJ/gTPFFAgJhY82R+Cp+6YZ0FJ6JkmwxpTkVVaTbiCXlDNhzLH7l1O1iWK6UpVORiYgJvuGkNvV7THU+z6KEwfCnXxV38bXhxYJKbBkXlgT5Te712OqEyBxMYAMZB+Pkoju94Dvd3dqBQpOyNUTe451PzVyWY2KZOiXE18/+CqB/es9xfXTH+hThwAGcms60/zmoQIFA0/1MKeze0jaO6Zlp00Djo91KIxQEkNAn93dt3xDhEStSgfqVgKN2tHqTO2gWASc7U3Om1O5CAyHOfOHNLYf1G7PFZDKVPA19pLgidIu7YNcr71jSuGyp2Cbw/o4BdiXiKPhQMYoHpjvxBbCURa1j8XwpxK9lWQymzXEaJrTeW2iHyyKwIOM8xH4oWBoCdAcjdySKx8vkrFnBJZIWd8NIKIp3xPSm0chzU7ohDEJiC1ucN+KUlHOwUW/aLRyQhhiETCdP42Tdw5yyfenhRwA9eVEepmh6V0CZT4JrKjO3lOiM+wdL/xzK8xEV9jwvueE5HFNh7VMF3UGCdEbQTIb3yrE7TelQfzWo= + on: + tags: true + repo: NORDUnet/python-norduniclient + condition: "$NEO4J_VERSION = 3.3.2" + python: '2.7'