From c68117d38eb54db12be9a0b0318c78f9b405c2fd Mon Sep 17 00:00:00 2001 From: Julian Minder Date: Tue, 22 Mar 2022 17:42:26 +0100 Subject: [PATCH] fixed bug occuring when no node/relation is specified for an entity --- rel2graph/core/config_parser.py | 73 ++++++++++--------- rel2graph/core/factories/factory.py | 1 + .../unit/core/resources/duplicated_nodes.yaml | 9 +++ tests/unit/core/resources/empty_entity.yaml | 1 + tests/unit/core/test_config_parser.py | 7 +- 5 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 tests/unit/core/resources/duplicated_nodes.yaml create mode 100644 tests/unit/core/resources/empty_entity.yaml diff --git a/rel2graph/core/config_parser.py b/rel2graph/core/config_parser.py index 85c7f73..7db3955 100644 --- a/rel2graph/core/config_parser.py +++ b/rel2graph/core/config_parser.py @@ -389,42 +389,43 @@ def compile(self, entity_type, config_data): precompiled_entity = [] - for element_config, attributes in config_data.items(): - # Grab id - match = re.search("[\)]\s*(\w+)\s*$", element_config) - id = None - if match is not None: - id = match.group(1) - self._ids.add(id) - - # Precompile attributes - precompiled_attributes = [] - primary_key = "&None" - if attributes is not None: - for attribute in attributes: - config, key, primary = self._precompile_attribute(attribute) - precompiled_attributes.append(config) - # if an id exist we save this attribute for later reference - if id is not None: - self._saved_attributes[f"{id}.{key}"] = config - - # if primary key we save it - if primary: - if primary_key == "&None": - primary_key = key - else: - raise ConfigError(f"Error in config for entity '{self._entity_type}'{' in graph element with identifier - ' + id if id is not None else ''}: Only 1 primary key allowed") - precompiled_graph_element = self._precompile_graph_element(element_config) - - # Add attributes to the string - precompiled_attributes_str = "[" + ",".join(precompiled_attributes) + "]" - precompiled_graph_element = precompiled_graph_element.format(attributes=precompiled_attributes_str, parent=self._entity_type, id=id, primary_key = primary_key) - - # Remove compile markers - precompiled_graph_element = precompiled_graph_element.replace("&", "") - - # append to list - precompiled_entity.append(precompiled_graph_element) + if config_data is not None: + for element_config, attributes in config_data.items(): + # Grab id + match = re.search("[\)]\s*(\w+)\s*$", element_config) + id = None + if match is not None: + id = match.group(1) + self._ids.add(id) + + # Precompile attributes + precompiled_attributes = [] + primary_key = "&None" + if attributes is not None: + for attribute in attributes: + config, key, primary = self._precompile_attribute(attribute) + precompiled_attributes.append(config) + # if an id exist we save this attribute for later reference + if id is not None: + self._saved_attributes[f"{id}.{key}"] = config + + # if primary key we save it + if primary: + if primary_key == "&None": + primary_key = key + else: + raise ConfigError(f"Error in config for entity '{self._entity_type}'{' in graph element with identifier - ' + id if id is not None else ''}: Only 1 primary key allowed") + precompiled_graph_element = self._precompile_graph_element(element_config) + + # Add attributes to the string + precompiled_attributes_str = "[" + ",".join(precompiled_attributes) + "]" + precompiled_graph_element = precompiled_graph_element.format(attributes=precompiled_attributes_str, parent=self._entity_type, id=id, primary_key = primary_key) + + # Remove compile markers + precompiled_graph_element = precompiled_graph_element.replace("&", "") + + # append to list + precompiled_entity.append(precompiled_graph_element) # Convert to instructions node_instructions, relation_instructions = _parse_to_instructions(precompiled_entity) diff --git a/rel2graph/core/factories/factory.py b/rel2graph/core/factories/factory.py index 2f18aed..c88ad56 100644 --- a/rel2graph/core/factories/factory.py +++ b/rel2graph/core/factories/factory.py @@ -232,6 +232,7 @@ def construct(self, resource: Resource) -> Subgraph: type = self._type.construct(resource) logger.debug(f"For relation type {type.value} matched {len(from_nodes)} from_nodes and {len(to_nodes)} to nodes") attributes = [attr_factory.construct(resource) for attr_factory in self._attributes] + attributes = [attr for attr in attributes if attr is not None] relations = Subgraph() for from_node in from_nodes: for to_node in to_nodes: diff --git a/tests/unit/core/resources/duplicated_nodes.yaml b/tests/unit/core/resources/duplicated_nodes.yaml new file mode 100644 index 0000000..5583eb7 --- /dev/null +++ b/tests/unit/core/resources/duplicated_nodes.yaml @@ -0,0 +1,9 @@ +ENTITY("entity"): + NODE("label"): + + uid = "First" + + NODE("label"): + + uid = "Second" + + NODE("label"): + + uid = "Third" diff --git a/tests/unit/core/resources/empty_entity.yaml b/tests/unit/core/resources/empty_entity.yaml new file mode 100644 index 0000000..d93239d --- /dev/null +++ b/tests/unit/core/resources/empty_entity.yaml @@ -0,0 +1 @@ +ENTITY("entity"): diff --git a/tests/unit/core/test_config_parser.py b/tests/unit/core/test_config_parser.py index a394f14..5c84ec4 100644 --- a/tests/unit/core/test_config_parser.py +++ b/tests/unit/core/test_config_parser.py @@ -120,4 +120,9 @@ def test_dynkeys(): for rf in relation_supplychain.factories: assert(rf._type._entity_attribute == "dynamic_key") for attr in nf._attributes: - assert(attr._entity_attribute == "dynamic_key") \ No newline at end of file + assert(attr._entity_attribute == "dynamic_key") + +def test_empty_entity(): + node_supplychain, relation_supplychain = parse(get_filepath("empty_entity"))["entity"] + assert(len(node_supplychain.factories) == 0) + assert(len(relation_supplychain.factories) == 0) \ No newline at end of file