forked from amundsen-io/amundsendatabuilder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph_serializable.py
91 lines (68 loc) · 3.04 KB
/
graph_serializable.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Copyright Contributors to the Amundsen project.
# SPDX-License-Identifier: Apache-2.0
import abc
from typing import Union # noqa: F401
from databuilder.models.graph_node import GraphNode
from databuilder.models.graph_relationship import GraphRelationship
NODE_KEY = 'KEY'
NODE_LABEL = 'LABEL'
RELATION_START_KEY = 'START_KEY'
RELATION_START_LABEL = 'START_LABEL'
RELATION_END_KEY = 'END_KEY'
RELATION_END_LABEL = 'END_LABEL'
RELATION_TYPE = 'TYPE'
RELATION_REVERSE_TYPE = 'REVERSE_TYPE'
class GraphSerializable(object, metaclass=abc.ABCMeta):
"""
A Serializable abstract class asks subclass to implement next node or
next relation in dict form so that it can be serialized to CSV file.
Any model class that needs to be pushed to a graph database should inherit this class.
"""
def __init__(self) -> None:
pass
@abc.abstractmethod
def create_next_node(self) -> Union[GraphNode, None]:
"""
Creates GraphNode the process that consumes this class takes the output
serializes to the desired graph database.
:return: a GraphNode or None if no more records to serialize
"""
raise NotImplementedError
@abc.abstractmethod
def create_next_relation(self) -> Union[GraphRelationship, None]:
"""
Creates GraphRelationship the process that consumes this class takes the output
serializes to the desired graph database.
:return: a GraphRelationship or None if no more record to serialize
"""
raise NotImplementedError
def next_node(self) -> Union[GraphNode, None]:
node_dict = self.create_next_node()
if not node_dict:
return None
self._validate_node(node_dict)
return node_dict
def next_relation(self) -> Union[GraphRelationship, None]:
relation_dict = self.create_next_relation()
if not relation_dict:
return None
self._validate_relation(relation_dict)
return relation_dict
def _validate_node(self, node: GraphNode) -> None:
node_id, node_label, _ = node
if node_id is None:
raise RuntimeError('Required header missing. Required attributes id and label , Missing: id')
if node_label is None:
raise RuntimeError('Required header missing. Required attributes id and label , Missing: label')
self._validate_label_value(node_label)
def _validate_relation(self, relation: GraphRelationship) -> None:
self._validate_label_value(relation.start_label)
self._validate_label_value(relation.end_label)
self._validate_relation_type_value(relation.type)
self._validate_relation_type_value(relation.reverse_type)
def _validate_relation_type_value(self, value: str) -> None:
if not value.isupper():
raise RuntimeError(f'TYPE needs to be upper case: {value}')
def _validate_label_value(self, value: str) -> None:
if not value.istitle():
raise RuntimeError(f'LABEL should only have upper case character on its first one: {value}')