sql-dag-flow 0.6.0__tar.gz → 0.6.1__tar.gz

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.
Files changed (22) hide show
  1. {sql_dag_flow-0.6.0/src/sql_dag_flow.egg-info → sql_dag_flow-0.6.1}/PKG-INFO +1 -1
  2. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/pyproject.toml +1 -1
  3. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/main.py +17 -3
  4. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/parser.py +8 -3
  5. sql_dag_flow-0.6.0/src/sql_dag_flow/static/assets/index-BRMQHj2Z.js → sql_dag_flow-0.6.1/src/sql_dag_flow/static/assets/index-KdnHXpnR.js +33 -33
  6. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/static/index.html +1 -1
  7. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1/src/sql_dag_flow.egg-info}/PKG-INFO +1 -1
  8. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow.egg-info/SOURCES.txt +2 -2
  9. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/LICENSE +0 -0
  10. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/MANIFEST.in +0 -0
  11. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/README.md +0 -0
  12. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/setup.cfg +0 -0
  13. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/__init__.py +0 -0
  14. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/static/assets/index-HIS38g9M.css +0 -0
  15. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/static/vite.svg +0 -0
  16. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/test_api_endpoints.py +0 -0
  17. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/test_parser.py +0 -0
  18. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow/verify_counts.py +0 -0
  19. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow.egg-info/dependency_links.txt +0 -0
  20. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow.egg-info/entry_points.txt +0 -0
  21. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow.egg-info/requires.txt +0 -0
  22. {sql_dag_flow-0.6.0 → sql_dag_flow-0.6.1}/src/sql_dag_flow.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-dag-flow
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: A sophisticated SQL lineage visualization tool for Medallion Architectures.
5
5
  Author-email: Flavio Sandoval <dsandovalflavio@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sql-dag-flow"
7
- version = "0.6.0"
7
+ version = "0.6.1"
8
8
  description = "A sophisticated SQL lineage visualization tool for Medallion Architectures."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -60,11 +60,22 @@ def get_graph(dialect: str = "bigquery", discovery: bool = False, expanded_nodes
60
60
  if not os.path.exists(CURRENT_DIRECTORY):
61
61
  return {"nodes": [], "edges": [], "cycles": [], "error": "Directory not found"}
62
62
 
63
- exp_nodes_list = [n.strip() for n in expanded_nodes.split(",")] if expanded_nodes else []
63
+ # Parse expanded_nodes as dict {node_id: mode}
64
+ exp_nodes_dict = {}
65
+ if expanded_nodes:
66
+ for item in expanded_nodes.split(","):
67
+ item = item.strip()
68
+ if not item:
69
+ continue
70
+ parts = item.rsplit(":", 1)
71
+ if len(parts) == 2 and parts[1] in ("all", "external", "cte"):
72
+ exp_nodes_dict[parts[0]] = parts[1]
73
+ else:
74
+ exp_nodes_dict[item] = "all"
64
75
  visible_list = [n.strip() for n in visible_node_ids.split(",")] if visible_node_ids else None
65
76
  try:
66
77
  tables = _cached_parse(CURRENT_DIRECTORY, None, dialect, visible_node_ids=visible_list)
67
- nodes, edges, cycles = build_graph(tables, discovery_mode=discovery, expanded_nodes=exp_nodes_list, discovery_filter=discovery_filter)
78
+ nodes, edges, cycles = build_graph(tables, discovery_mode=discovery, expanded_nodes=exp_nodes_dict, discovery_filter=discovery_filter)
68
79
  return {"nodes": nodes, "edges": edges, "cycles": cycles}
69
80
  except Exception as e:
70
81
  import traceback
@@ -121,7 +132,10 @@ def get_filtered_graph(data: dict = Body(...)):
121
132
  subfolders = data.get("subfolders")
122
133
  dialect = data.get("dialect", "bigquery")
123
134
  discovery = data.get("discovery", False)
124
- expanded_nodes = data.get("expanded_nodes", [])
135
+ expanded_nodes = data.get("expanded_nodes", {})
136
+ # Normalize: if frontend sends a list (legacy), convert to dict
137
+ if isinstance(expanded_nodes, list):
138
+ expanded_nodes = {n: 'all' for n in expanded_nodes}
125
139
  visible_node_ids = data.get("visible_node_ids", None)
126
140
  discovery_filter = data.get("discovery_filter", "all")
127
141
 
@@ -830,9 +830,12 @@ def build_graph(tables, discovery_mode=False, expanded_nodes=None, discovery_fil
830
830
  Constructs nodes and edges for React Flow.
831
831
  If discovery_mode is True, creates 'ghost' nodes for dependencies
832
832
  that are not found in the parsed tables.
833
- Also creates ghost nodes for any node whose ID is in expanded_nodes list.
833
+ expanded_nodes: dict {node_id: 'all'|'external'|'cte'} or list (legacy, treated as 'all').
834
834
  discovery_filter: 'all' | 'external' | 'cte' — controls which ghost types to show.
835
835
  """
836
+ # Normalize legacy list format to dict
837
+ if isinstance(expanded_nodes, list):
838
+ expanded_nodes = {n: 'all' for n in expanded_nodes}
836
839
  nodes = []
837
840
  edges = []
838
841
 
@@ -891,7 +894,8 @@ def build_graph(tables, discovery_mode=False, expanded_nodes=None, discovery_fil
891
894
  cte_name = ":".join(parts[2:])
892
895
  cte_internal_deps = tables[source_id].get("cte_deps", {}).get(cte_name, {})
893
896
 
894
- if (discovery_mode and discovery_filter in ('all', 'cte')) or (expanded_nodes and source_id in expanded_nodes):
897
+ expand_mode = expanded_nodes.get(source_id, None) if expanded_nodes else None
898
+ if (discovery_mode and discovery_filter in ('all', 'cte')) or (expand_mode and expand_mode in ('all', 'cte')):
895
899
  # Discovery Mode or Expanded: Create CTE ghost node with incoming edges
896
900
  cte_id = dep
897
901
 
@@ -986,7 +990,8 @@ def build_graph(tables, discovery_mode=False, expanded_nodes=None, discovery_fil
986
990
  continue
987
991
 
988
992
  # Handle missing external nodes (discovery mode or expanded node only)
989
- if ((discovery_mode and discovery_filter in ('all', 'external')) or (expanded_nodes and source_id in expanded_nodes)) and not target_id:
993
+ expand_mode_ext = expanded_nodes.get(source_id, None) if expanded_nodes else None
994
+ if ((discovery_mode and discovery_filter in ('all', 'external')) or (expand_mode_ext and expand_mode_ext in ('all', 'external'))) and not target_id:
990
995
  # Create a unique ID for the missing node
991
996
  # Use the full dependency name as the ID
992
997
  ghost_id = dep