Spaces:
Running
Running
Update entity_relationship_generator.py
Browse files- entity_relationship_generator.py +9 -244
entity_relationship_generator.py
CHANGED
@@ -1,239 +1,3 @@
|
|
1 |
-
# import graphviz
|
2 |
-
# import json
|
3 |
-
# from tempfile import NamedTemporaryFile
|
4 |
-
# import os
|
5 |
-
|
6 |
-
# def generate_entity_relationship_diagram(json_input: str, output_format: str) -> str:
|
7 |
-
# try:
|
8 |
-
# if not json_input.strip():
|
9 |
-
# return "Error: Empty input"
|
10 |
-
|
11 |
-
# data = json.loads(json_input)
|
12 |
-
|
13 |
-
# if 'entities' not in data:
|
14 |
-
# raise ValueError("Missing required field: entities")
|
15 |
-
|
16 |
-
# dot = graphviz.Graph(comment='ER Diagram', engine='neato')
|
17 |
-
# dot.attr(
|
18 |
-
# bgcolor='white',
|
19 |
-
# pad='1.5',
|
20 |
-
# overlap='false',
|
21 |
-
# splines='true',
|
22 |
-
# sep='+25',
|
23 |
-
# esep='+15'
|
24 |
-
# )
|
25 |
-
# dot.attr('node', fontname='Arial', fontsize='10', color='#404040')
|
26 |
-
# dot.attr('edge', fontname='Arial', fontsize='9', color='#404040')
|
27 |
-
|
28 |
-
# entities = data.get('entities', [])
|
29 |
-
# relationships = data.get('relationships', [])
|
30 |
-
|
31 |
-
# for entity in entities:
|
32 |
-
# entity_name = entity.get('name')
|
33 |
-
# entity_type = entity.get('type', 'strong')
|
34 |
-
# attributes = entity.get('attributes', [])
|
35 |
-
|
36 |
-
# if not entity_name:
|
37 |
-
# continue
|
38 |
-
|
39 |
-
# if entity_type == 'weak':
|
40 |
-
# dot.node(
|
41 |
-
# entity_name,
|
42 |
-
# entity_name,
|
43 |
-
# shape='box',
|
44 |
-
# style='filled',
|
45 |
-
# fillcolor='#f0f0f0',
|
46 |
-
# color='#404040',
|
47 |
-
# penwidth='3',
|
48 |
-
# width='1.8',
|
49 |
-
# height='0.8'
|
50 |
-
# )
|
51 |
-
# else:
|
52 |
-
# dot.node(
|
53 |
-
# entity_name,
|
54 |
-
# entity_name,
|
55 |
-
# shape='box',
|
56 |
-
# style='filled',
|
57 |
-
# fillcolor='#e8e8e8',
|
58 |
-
# color='#404040',
|
59 |
-
# penwidth='1',
|
60 |
-
# width='1.8',
|
61 |
-
# height='0.8'
|
62 |
-
# )
|
63 |
-
|
64 |
-
# for i, attr in enumerate(attributes):
|
65 |
-
# attr_name = attr.get('name', '')
|
66 |
-
# attr_type = attr.get('type', 'regular')
|
67 |
-
|
68 |
-
# attr_id = f"{entity_name}_attr_{i}"
|
69 |
-
|
70 |
-
# # CAMBIO CLAVE: Removemos HTML markup que puede causar problemas
|
71 |
-
# if attr_type == 'primary_key':
|
72 |
-
# dot.node(
|
73 |
-
# attr_id,
|
74 |
-
# f'{attr_name} (PK)',
|
75 |
-
# shape='ellipse',
|
76 |
-
# style='filled',
|
77 |
-
# fillcolor='#d8d8d8',
|
78 |
-
# color='#404040',
|
79 |
-
# width='1.2',
|
80 |
-
# height='0.6'
|
81 |
-
# )
|
82 |
-
# elif attr_type == 'partial_key':
|
83 |
-
# dot.node(
|
84 |
-
# attr_id,
|
85 |
-
# f'{attr_name} (Partial)',
|
86 |
-
# shape='ellipse',
|
87 |
-
# style='filled,dashed',
|
88 |
-
# fillcolor='#d8d8d8',
|
89 |
-
# color='#404040',
|
90 |
-
# width='1.2',
|
91 |
-
# height='0.6'
|
92 |
-
# )
|
93 |
-
# elif attr_type == 'multivalued':
|
94 |
-
# dot.node(
|
95 |
-
# attr_id,
|
96 |
-
# attr_name,
|
97 |
-
# shape='ellipse',
|
98 |
-
# style='filled',
|
99 |
-
# fillcolor='#d8d8d8',
|
100 |
-
# color='#404040',
|
101 |
-
# penwidth='3',
|
102 |
-
# width='1.2',
|
103 |
-
# height='0.6'
|
104 |
-
# )
|
105 |
-
# elif attr_type == 'derived':
|
106 |
-
# dot.node(
|
107 |
-
# attr_id,
|
108 |
-
# f'/{attr_name}/',
|
109 |
-
# shape='ellipse',
|
110 |
-
# style='filled,dashed',
|
111 |
-
# fillcolor='#d8d8d8',
|
112 |
-
# color='#404040',
|
113 |
-
# width='1.2',
|
114 |
-
# height='0.6'
|
115 |
-
# )
|
116 |
-
# elif attr_type == 'composite':
|
117 |
-
# dot.node(
|
118 |
-
# attr_id,
|
119 |
-
# attr_name,
|
120 |
-
# shape='ellipse',
|
121 |
-
# style='filled',
|
122 |
-
# fillcolor='#d8d8d8',
|
123 |
-
# color='#404040',
|
124 |
-
# width='1.2',
|
125 |
-
# height='0.6'
|
126 |
-
# )
|
127 |
-
# else:
|
128 |
-
# dot.node(
|
129 |
-
# attr_id,
|
130 |
-
# attr_name,
|
131 |
-
# shape='ellipse',
|
132 |
-
# style='filled',
|
133 |
-
# fillcolor='#d8d8d8',
|
134 |
-
# color='#404040',
|
135 |
-
# width='1.2',
|
136 |
-
# height='0.6'
|
137 |
-
# )
|
138 |
-
|
139 |
-
# dot.edge(entity_name, attr_id, color='#404040', len='1.5')
|
140 |
-
|
141 |
-
# for relationship in relationships:
|
142 |
-
# rel_name = relationship.get('name')
|
143 |
-
# rel_type = relationship.get('type', 'regular')
|
144 |
-
# entities_involved = relationship.get('entities', [])
|
145 |
-
# cardinalities = relationship.get('cardinalities', {})
|
146 |
-
# rel_attributes = relationship.get('attributes', [])
|
147 |
-
|
148 |
-
# if not rel_name:
|
149 |
-
# continue
|
150 |
-
|
151 |
-
# if rel_type == 'isa':
|
152 |
-
# parent = relationship.get('parent')
|
153 |
-
# children = relationship.get('children', [])
|
154 |
-
|
155 |
-
# if parent and children:
|
156 |
-
# isa_id = f"isa_{rel_name}"
|
157 |
-
# dot.node(
|
158 |
-
# isa_id,
|
159 |
-
# 'ISA',
|
160 |
-
# shape='triangle',
|
161 |
-
# style='filled',
|
162 |
-
# fillcolor='#d0d0d0',
|
163 |
-
# color='#404040',
|
164 |
-
# penwidth='2',
|
165 |
-
# width='1.0',
|
166 |
-
# height='0.8'
|
167 |
-
# )
|
168 |
-
|
169 |
-
# dot.edge(parent, isa_id, color='#404040', len='2.0')
|
170 |
-
|
171 |
-
# for child in children:
|
172 |
-
# dot.edge(isa_id, child, color='#404040', len='2.0')
|
173 |
-
|
174 |
-
# elif len(entities_involved) >= 2:
|
175 |
-
# if rel_type == 'identifying':
|
176 |
-
# dot.node(
|
177 |
-
# rel_name,
|
178 |
-
# rel_name,
|
179 |
-
# shape='diamond',
|
180 |
-
# style='filled',
|
181 |
-
# fillcolor='#c8c8c8',
|
182 |
-
# color='#404040',
|
183 |
-
# penwidth='3',
|
184 |
-
# width='1.8',
|
185 |
-
# height='1.0'
|
186 |
-
# )
|
187 |
-
# else:
|
188 |
-
# dot.node(
|
189 |
-
# rel_name,
|
190 |
-
# rel_name,
|
191 |
-
# shape='diamond',
|
192 |
-
# style='filled',
|
193 |
-
# fillcolor='#c8c8c8',
|
194 |
-
# color='#404040',
|
195 |
-
# penwidth='1',
|
196 |
-
# width='1.8',
|
197 |
-
# height='1.0'
|
198 |
-
# )
|
199 |
-
|
200 |
-
# for j, attr in enumerate(rel_attributes):
|
201 |
-
# attr_name = attr.get('name', '')
|
202 |
-
# attr_id = f"{rel_name}_attr_{j}"
|
203 |
-
|
204 |
-
# dot.node(
|
205 |
-
# attr_id,
|
206 |
-
# attr_name,
|
207 |
-
# shape='ellipse',
|
208 |
-
# style='filled',
|
209 |
-
# fillcolor='#d8d8d8',
|
210 |
-
# color='#404040',
|
211 |
-
# width='1.0',
|
212 |
-
# height='0.5'
|
213 |
-
# )
|
214 |
-
# dot.edge(rel_name, attr_id, color='#404040', len='1.0')
|
215 |
-
|
216 |
-
# for entity in entities_involved:
|
217 |
-
# cardinality = cardinalities.get(entity, '1')
|
218 |
-
# dot.edge(
|
219 |
-
# entity,
|
220 |
-
# rel_name,
|
221 |
-
# label=f' {cardinality} ',
|
222 |
-
# color='#404040',
|
223 |
-
# len='2.5',
|
224 |
-
# fontcolor='#000000',
|
225 |
-
# fontsize='11'
|
226 |
-
# )
|
227 |
-
|
228 |
-
# with NamedTemporaryFile(delete=False, suffix=f'.{output_format}') as tmp:
|
229 |
-
# dot.render(tmp.name, format=output_format, cleanup=True)
|
230 |
-
# return f"{tmp.name}.{output_format}"
|
231 |
-
|
232 |
-
# except json.JSONDecodeError:
|
233 |
-
# return "Error: Invalid JSON format"
|
234 |
-
# except Exception as e:
|
235 |
-
# return f"Error: {str(e)}"
|
236 |
-
|
237 |
import graphviz
|
238 |
import json
|
239 |
from tempfile import NamedTemporaryFile
|
@@ -261,14 +25,14 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
|
|
261 |
dot.attr('node', fontname='Arial', fontsize='10', color='#404040')
|
262 |
dot.attr('edge', fontname='Arial', fontsize='9', color='#4a4a4a')
|
263 |
|
264 |
-
# Base color system
|
265 |
-
base_color = '#
|
266 |
-
lightening_factor = 0.
|
267 |
|
268 |
-
def get_gradient_color(depth, base_hex_color, lightening_factor=0.
|
269 |
-
"""Get lightened color based on depth
|
270 |
if not isinstance(base_hex_color, str) or not base_hex_color.startswith('#') or len(base_hex_color) != 7:
|
271 |
-
base_hex_color = '#
|
272 |
|
273 |
base_r = int(base_hex_color[1:3], 16)
|
274 |
base_g = int(base_hex_color[3:5], 16)
|
@@ -284,9 +48,10 @@ def generate_entity_relationship_diagram(json_input: str, output_format: str) ->
|
|
284 |
|
285 |
return f'#{current_r:02x}{current_g:02x}{current_b:02x}'
|
286 |
|
287 |
-
def get_font_color_for_background(depth, lightening_factor=0.
|
288 |
"""Get appropriate font color based on background lightness"""
|
289 |
-
|
|
|
290 |
|
291 |
entities = data.get('entities', [])
|
292 |
relationships = data.get('relationships', [])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import graphviz
|
2 |
import json
|
3 |
from tempfile import NamedTemporaryFile
|
|
|
25 |
dot.attr('node', fontname='Arial', fontsize='10', color='#404040')
|
26 |
dot.attr('edge', fontname='Arial', fontsize='9', color='#4a4a4a')
|
27 |
|
28 |
+
# Base color system - much lighter grays starting from #BEBEBE
|
29 |
+
base_color = '#BEBEBE' # Much lighter base color
|
30 |
+
lightening_factor = 0.08 # Smaller factor for subtle gradations
|
31 |
|
32 |
+
def get_gradient_color(depth, base_hex_color, lightening_factor=0.08):
|
33 |
+
"""Get lightened color based on depth - much lighter grays"""
|
34 |
if not isinstance(base_hex_color, str) or not base_hex_color.startswith('#') or len(base_hex_color) != 7:
|
35 |
+
base_hex_color = '#BEBEBE' # Light gray fallback
|
36 |
|
37 |
base_r = int(base_hex_color[1:3], 16)
|
38 |
base_g = int(base_hex_color[3:5], 16)
|
|
|
48 |
|
49 |
return f'#{current_r:02x}{current_g:02x}{current_b:02x}'
|
50 |
|
51 |
+
def get_font_color_for_background(depth, lightening_factor=0.08):
|
52 |
"""Get appropriate font color based on background lightness"""
|
53 |
+
# With lighter base colors, we'll use black text for better readability
|
54 |
+
return 'black'
|
55 |
|
56 |
entities = data.get('entities', [])
|
57 |
relationships = data.get('relationships', [])
|