graflo 1.3.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of graflo might be problematic. Click here for more details.
- graflo/README.md +18 -0
- graflo/__init__.py +70 -0
- graflo/architecture/__init__.py +38 -0
- graflo/architecture/actor.py +1276 -0
- graflo/architecture/actor_util.py +450 -0
- graflo/architecture/edge.py +418 -0
- graflo/architecture/onto.py +376 -0
- graflo/architecture/onto_sql.py +54 -0
- graflo/architecture/resource.py +163 -0
- graflo/architecture/schema.py +135 -0
- graflo/architecture/transform.py +292 -0
- graflo/architecture/util.py +89 -0
- graflo/architecture/vertex.py +562 -0
- graflo/caster.py +736 -0
- graflo/cli/__init__.py +14 -0
- graflo/cli/ingest.py +203 -0
- graflo/cli/manage_dbs.py +197 -0
- graflo/cli/plot_schema.py +132 -0
- graflo/cli/xml2json.py +93 -0
- graflo/data_source/__init__.py +48 -0
- graflo/data_source/api.py +339 -0
- graflo/data_source/base.py +95 -0
- graflo/data_source/factory.py +304 -0
- graflo/data_source/file.py +148 -0
- graflo/data_source/memory.py +70 -0
- graflo/data_source/registry.py +82 -0
- graflo/data_source/sql.py +183 -0
- graflo/db/__init__.py +44 -0
- graflo/db/arango/__init__.py +22 -0
- graflo/db/arango/conn.py +1025 -0
- graflo/db/arango/query.py +180 -0
- graflo/db/arango/util.py +88 -0
- graflo/db/conn.py +377 -0
- graflo/db/connection/__init__.py +6 -0
- graflo/db/connection/config_mapping.py +18 -0
- graflo/db/connection/onto.py +717 -0
- graflo/db/connection/wsgi.py +29 -0
- graflo/db/manager.py +119 -0
- graflo/db/neo4j/__init__.py +16 -0
- graflo/db/neo4j/conn.py +639 -0
- graflo/db/postgres/__init__.py +37 -0
- graflo/db/postgres/conn.py +948 -0
- graflo/db/postgres/fuzzy_matcher.py +281 -0
- graflo/db/postgres/heuristics.py +133 -0
- graflo/db/postgres/inference_utils.py +428 -0
- graflo/db/postgres/resource_mapping.py +273 -0
- graflo/db/postgres/schema_inference.py +372 -0
- graflo/db/postgres/types.py +148 -0
- graflo/db/postgres/util.py +87 -0
- graflo/db/tigergraph/__init__.py +9 -0
- graflo/db/tigergraph/conn.py +2365 -0
- graflo/db/tigergraph/onto.py +26 -0
- graflo/db/util.py +49 -0
- graflo/filter/__init__.py +21 -0
- graflo/filter/onto.py +525 -0
- graflo/logging.conf +22 -0
- graflo/onto.py +312 -0
- graflo/plot/__init__.py +17 -0
- graflo/plot/plotter.py +616 -0
- graflo/util/__init__.py +23 -0
- graflo/util/chunker.py +807 -0
- graflo/util/merge.py +150 -0
- graflo/util/misc.py +37 -0
- graflo/util/onto.py +422 -0
- graflo/util/transform.py +454 -0
- graflo-1.3.7.dist-info/METADATA +243 -0
- graflo-1.3.7.dist-info/RECORD +70 -0
- graflo-1.3.7.dist-info/WHEEL +4 -0
- graflo-1.3.7.dist-info/entry_points.txt +5 -0
- graflo-1.3.7.dist-info/licenses/LICENSE +126 -0
graflo/onto.py
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"""Core ontology and base classes for graph database operations.
|
|
2
|
+
|
|
3
|
+
This module provides the fundamental data structures and base classes used throughout
|
|
4
|
+
the graph database system. It includes base classes for enums, dataclasses, and
|
|
5
|
+
database-specific configurations.
|
|
6
|
+
|
|
7
|
+
Key Components:
|
|
8
|
+
- BaseEnum: Base class for string-based enumerations with flexible membership testing
|
|
9
|
+
- BaseDataclass: Base class for dataclasses with JSON/YAML serialization support
|
|
10
|
+
- DBFlavor: Enum for supported database types (ArangoDB, Neo4j)
|
|
11
|
+
- ExpressionFlavor: Enum for expression language types
|
|
12
|
+
- AggregationType: Enum for supported aggregation operations
|
|
13
|
+
|
|
14
|
+
Example:
|
|
15
|
+
>>> class MyEnum(BaseEnum):
|
|
16
|
+
... VALUE1 = "value1"
|
|
17
|
+
... VALUE2 = "value2"
|
|
18
|
+
>>> "value1" in MyEnum # True
|
|
19
|
+
>>> "invalid" in MyEnum # False
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import dataclasses
|
|
23
|
+
from copy import deepcopy
|
|
24
|
+
from enum import EnumMeta
|
|
25
|
+
from strenum import StrEnum
|
|
26
|
+
from dataclass_wizard import JSONWizard, YAMLWizard
|
|
27
|
+
from dataclass_wizard.enums import DateTimeTo
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MetaEnum(EnumMeta):
|
|
31
|
+
"""Metaclass for flexible enumeration membership testing.
|
|
32
|
+
|
|
33
|
+
This metaclass allows checking if a value is a valid member of an enum
|
|
34
|
+
using the `in` operator, even if the value hasn't been instantiated as
|
|
35
|
+
an enum member.
|
|
36
|
+
|
|
37
|
+
Example:
|
|
38
|
+
>>> class MyEnum(BaseEnum):
|
|
39
|
+
... VALUE = "value"
|
|
40
|
+
>>> "value" in MyEnum # True
|
|
41
|
+
>>> "invalid" in MyEnum # False
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __contains__(cls, item, **kwargs):
|
|
45
|
+
"""Check if an item is a valid member of the enum.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
item: Value to check for membership
|
|
49
|
+
**kwargs: Additional keyword arguments
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
bool: True if the item is a valid enum member, False otherwise
|
|
53
|
+
"""
|
|
54
|
+
try:
|
|
55
|
+
cls(item, **kwargs)
|
|
56
|
+
except ValueError:
|
|
57
|
+
return False
|
|
58
|
+
return True
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class BaseEnum(StrEnum, metaclass=MetaEnum):
|
|
62
|
+
"""Base class for string-based enumerations.
|
|
63
|
+
|
|
64
|
+
This class provides a foundation for string-based enums with flexible
|
|
65
|
+
membership testing through the MetaEnum metaclass.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __str__(self) -> str:
|
|
69
|
+
"""Return the enum value as string for proper serialization."""
|
|
70
|
+
return self.value
|
|
71
|
+
|
|
72
|
+
def __repr__(self) -> str:
|
|
73
|
+
"""Return the enum value as string for proper serialization."""
|
|
74
|
+
return self.value
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Register custom YAML representer for BaseEnum to serialize as string values
|
|
78
|
+
def _register_yaml_representer():
|
|
79
|
+
"""Register YAML representer for BaseEnum and all its subclasses to serialize as string values."""
|
|
80
|
+
try:
|
|
81
|
+
import yaml
|
|
82
|
+
|
|
83
|
+
def base_enum_representer(dumper, data):
|
|
84
|
+
"""Custom YAML representer for BaseEnum - serializes as string value."""
|
|
85
|
+
return dumper.represent_scalar("tag:yaml.org,2002:str", str(data.value))
|
|
86
|
+
|
|
87
|
+
# Register for BaseEnum and use multi_representer for all subclasses
|
|
88
|
+
yaml.add_representer(BaseEnum, base_enum_representer)
|
|
89
|
+
yaml.add_multi_representer(BaseEnum, base_enum_representer)
|
|
90
|
+
except ImportError:
|
|
91
|
+
# yaml not available, skip registration
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# Register the representer at module import time (after BaseEnum is defined)
|
|
96
|
+
_register_yaml_representer()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class DBFlavor(BaseEnum):
|
|
100
|
+
"""Supported database types.
|
|
101
|
+
|
|
102
|
+
This enum defines the supported graph database types in the system.
|
|
103
|
+
|
|
104
|
+
Attributes:
|
|
105
|
+
ARANGO: ArangoDB database
|
|
106
|
+
NEO4J: Neo4j database
|
|
107
|
+
TIGERGRAPH: TigerGraph database
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
ARANGO = "arango"
|
|
111
|
+
NEO4J = "neo4j"
|
|
112
|
+
TIGERGRAPH = "tigergraph"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class ExpressionFlavor(BaseEnum):
|
|
116
|
+
"""Supported expression language types.
|
|
117
|
+
|
|
118
|
+
This enum defines the supported expression languages for querying and
|
|
119
|
+
filtering data.
|
|
120
|
+
|
|
121
|
+
Attributes:
|
|
122
|
+
ARANGO: ArangoDB AQL expressions
|
|
123
|
+
NEO4J: Neo4j Cypher expressions
|
|
124
|
+
TIGERGRAPH: TigerGraph GSQL expressions
|
|
125
|
+
PYTHON: Python expressions
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
ARANGO = "arango"
|
|
129
|
+
NEO4J = "neo4j"
|
|
130
|
+
TIGERGRAPH = "tigergraph"
|
|
131
|
+
PYTHON = "python"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class AggregationType(BaseEnum):
|
|
135
|
+
"""Supported aggregation operations.
|
|
136
|
+
|
|
137
|
+
This enum defines the supported aggregation operations for data analysis.
|
|
138
|
+
|
|
139
|
+
Attributes:
|
|
140
|
+
COUNT: Count operation
|
|
141
|
+
MAX: Maximum value
|
|
142
|
+
MIN: Minimum value
|
|
143
|
+
AVERAGE: Average value
|
|
144
|
+
SORTED_UNIQUE: Sorted unique values
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
COUNT = "COUNT"
|
|
148
|
+
MAX = "MAX"
|
|
149
|
+
MIN = "MIN"
|
|
150
|
+
AVERAGE = "AVERAGE"
|
|
151
|
+
SORTED_UNIQUE = "SORTED_UNIQUE"
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@dataclasses.dataclass
|
|
155
|
+
class BaseDataclass(JSONWizard, JSONWizard.Meta, YAMLWizard):
|
|
156
|
+
"""Base class for dataclasses with serialization support.
|
|
157
|
+
|
|
158
|
+
This class provides a foundation for dataclasses with JSON and YAML
|
|
159
|
+
serialization capabilities. It includes methods for updating instances
|
|
160
|
+
and accessing field members.
|
|
161
|
+
|
|
162
|
+
Attributes:
|
|
163
|
+
marshal_date_time_as: Format for datetime serialization
|
|
164
|
+
key_transform_with_dump: Key transformation style for serialization
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
class _(JSONWizard.Meta):
|
|
168
|
+
"""Meta configuration for serialization.
|
|
169
|
+
|
|
170
|
+
Set skip_defaults=True here to exclude fields with default values
|
|
171
|
+
by default when serializing. Can still be overridden per-call.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
skip_defaults = True
|
|
175
|
+
|
|
176
|
+
marshal_date_time_as = DateTimeTo.ISO_FORMAT
|
|
177
|
+
key_transform_with_dump = "SNAKE"
|
|
178
|
+
|
|
179
|
+
def to_dict(self, skip_defaults: bool | None = None, **kwargs):
|
|
180
|
+
"""Convert instance to dictionary with enums serialized as strings.
|
|
181
|
+
|
|
182
|
+
This method overrides the default to_dict to ensure that all BaseEnum
|
|
183
|
+
instances are automatically converted to their string values during
|
|
184
|
+
serialization, making YAML/JSON output cleaner and more portable.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
skip_defaults: If True, fields with default values are excluded.
|
|
188
|
+
If None, uses the Meta class skip_defaults setting.
|
|
189
|
+
**kwargs: Additional arguments passed to parent to_dict method
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
dict: Dictionary representation with enums as strings
|
|
193
|
+
"""
|
|
194
|
+
result = super().to_dict(skip_defaults=skip_defaults, **kwargs)
|
|
195
|
+
return self._convert_enums_to_strings(result)
|
|
196
|
+
|
|
197
|
+
def to_yaml(self, skip_defaults: bool | None = None, **kwargs) -> str:
|
|
198
|
+
"""Convert instance to YAML string with enums serialized as strings.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
skip_defaults: If True, fields with default values are excluded.
|
|
202
|
+
If None, uses the Meta class skip_defaults setting.
|
|
203
|
+
**kwargs: Additional arguments passed to yaml.safe_dump
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
str: YAML string representation with enums as strings
|
|
207
|
+
"""
|
|
208
|
+
# Convert to dict first (with enum conversion), then to YAML
|
|
209
|
+
data = self.to_dict(skip_defaults=skip_defaults)
|
|
210
|
+
try:
|
|
211
|
+
import yaml
|
|
212
|
+
|
|
213
|
+
return yaml.safe_dump(data, **kwargs)
|
|
214
|
+
except ImportError:
|
|
215
|
+
# Fallback to parent method if yaml not available
|
|
216
|
+
return super().to_yaml(skip_defaults=skip_defaults, **kwargs)
|
|
217
|
+
|
|
218
|
+
def to_yaml_file(
|
|
219
|
+
self, file_path: str, skip_defaults: bool | None = None, **kwargs
|
|
220
|
+
) -> None:
|
|
221
|
+
"""Write instance to YAML file with enums serialized as strings.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
file_path: Path to the YAML file to write
|
|
225
|
+
skip_defaults: If True, fields with default values are excluded.
|
|
226
|
+
If None, uses the Meta class skip_defaults setting.
|
|
227
|
+
**kwargs: Additional arguments passed to yaml.safe_dump
|
|
228
|
+
"""
|
|
229
|
+
# Convert to dict first (with enum conversion), then write to file
|
|
230
|
+
data = self.to_dict(skip_defaults=skip_defaults)
|
|
231
|
+
try:
|
|
232
|
+
import yaml
|
|
233
|
+
|
|
234
|
+
with open(file_path, "w") as f:
|
|
235
|
+
yaml.safe_dump(data, f, **kwargs)
|
|
236
|
+
except ImportError:
|
|
237
|
+
# Fallback to parent method if yaml not available
|
|
238
|
+
super().to_yaml_file(file_path, skip_defaults=skip_defaults, **kwargs)
|
|
239
|
+
|
|
240
|
+
@staticmethod
|
|
241
|
+
def _convert_enums_to_strings(obj):
|
|
242
|
+
"""Recursively convert BaseEnum instances to their string values.
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
obj: Object to convert (dict, list, enum, or other)
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
Object with BaseEnum instances converted to strings
|
|
249
|
+
"""
|
|
250
|
+
if isinstance(obj, BaseEnum):
|
|
251
|
+
return obj.value
|
|
252
|
+
elif isinstance(obj, dict):
|
|
253
|
+
return {
|
|
254
|
+
k: BaseDataclass._convert_enums_to_strings(v) for k, v in obj.items()
|
|
255
|
+
}
|
|
256
|
+
elif isinstance(obj, list):
|
|
257
|
+
return [BaseDataclass._convert_enums_to_strings(item) for item in obj]
|
|
258
|
+
elif isinstance(obj, tuple):
|
|
259
|
+
return tuple(BaseDataclass._convert_enums_to_strings(item) for item in obj)
|
|
260
|
+
elif isinstance(obj, set):
|
|
261
|
+
return {BaseDataclass._convert_enums_to_strings(item) for item in obj}
|
|
262
|
+
else:
|
|
263
|
+
return obj
|
|
264
|
+
|
|
265
|
+
def update(self, other):
|
|
266
|
+
"""Update this instance with values from another instance.
|
|
267
|
+
|
|
268
|
+
This method performs a deep update of the instance's attributes using
|
|
269
|
+
values from another instance of the same type. It handles different
|
|
270
|
+
types of attributes (sets, lists, dicts, dataclasses) appropriately.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
other: Another instance of the same type to update from
|
|
274
|
+
|
|
275
|
+
Raises:
|
|
276
|
+
TypeError: If other is not an instance of the same type
|
|
277
|
+
"""
|
|
278
|
+
if not isinstance(other, type(self)):
|
|
279
|
+
raise TypeError(
|
|
280
|
+
f"Expected {type(self).__name__} instance, got {type(other).__name__}"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
for field in dataclasses.fields(self):
|
|
284
|
+
name = field.name
|
|
285
|
+
current_value = getattr(self, name)
|
|
286
|
+
other_value = getattr(other, name)
|
|
287
|
+
|
|
288
|
+
if other_value is None:
|
|
289
|
+
pass
|
|
290
|
+
elif isinstance(other_value, set):
|
|
291
|
+
setattr(self, name, current_value | deepcopy(other_value))
|
|
292
|
+
elif isinstance(other_value, list):
|
|
293
|
+
setattr(self, name, current_value + deepcopy(other_value))
|
|
294
|
+
elif isinstance(other_value, dict):
|
|
295
|
+
setattr(self, name, {**current_value, **deepcopy(other_value)})
|
|
296
|
+
elif dataclasses.is_dataclass(type(other_value)):
|
|
297
|
+
if current_value is not None:
|
|
298
|
+
current_value.update(other_value)
|
|
299
|
+
else:
|
|
300
|
+
setattr(self, name, deepcopy(other_value))
|
|
301
|
+
else:
|
|
302
|
+
if current_value is None:
|
|
303
|
+
setattr(self, name, other_value)
|
|
304
|
+
|
|
305
|
+
@classmethod
|
|
306
|
+
def get_fields_members(cls):
|
|
307
|
+
"""Get list of field members excluding private ones.
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
list[str]: List of public field names
|
|
311
|
+
"""
|
|
312
|
+
return [k for k in cls.__annotations__ if not k.startswith("_")]
|
graflo/plot/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Plotting utilities for graph visualization.
|
|
2
|
+
|
|
3
|
+
This module provides tools for visualizing graph schemas and structures.
|
|
4
|
+
It includes functionality for creating visual representations of graph
|
|
5
|
+
databases, their vertices, edges, and relationships.
|
|
6
|
+
|
|
7
|
+
Key Components:
|
|
8
|
+
- SchemaPlotter: Creates visual representations of graph schemas
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
>>> plotter = SchemaPlotter(schema)
|
|
12
|
+
>>> plotter.plot("schema.png")
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .plotter import SchemaPlotter
|
|
16
|
+
|
|
17
|
+
__all__ = ["SchemaPlotter"]
|