sql-glider 0.1.8__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.
- sql_glider-0.1.8.dist-info/METADATA +893 -0
- sql_glider-0.1.8.dist-info/RECORD +34 -0
- sql_glider-0.1.8.dist-info/WHEEL +4 -0
- sql_glider-0.1.8.dist-info/entry_points.txt +9 -0
- sql_glider-0.1.8.dist-info/licenses/LICENSE +201 -0
- sqlglider/__init__.py +3 -0
- sqlglider/_version.py +34 -0
- sqlglider/catalog/__init__.py +30 -0
- sqlglider/catalog/base.py +99 -0
- sqlglider/catalog/databricks.py +255 -0
- sqlglider/catalog/registry.py +121 -0
- sqlglider/cli.py +1589 -0
- sqlglider/dissection/__init__.py +17 -0
- sqlglider/dissection/analyzer.py +767 -0
- sqlglider/dissection/formatters.py +222 -0
- sqlglider/dissection/models.py +112 -0
- sqlglider/global_models.py +17 -0
- sqlglider/graph/__init__.py +42 -0
- sqlglider/graph/builder.py +349 -0
- sqlglider/graph/merge.py +136 -0
- sqlglider/graph/models.py +289 -0
- sqlglider/graph/query.py +287 -0
- sqlglider/graph/serialization.py +107 -0
- sqlglider/lineage/__init__.py +10 -0
- sqlglider/lineage/analyzer.py +1631 -0
- sqlglider/lineage/formatters.py +335 -0
- sqlglider/templating/__init__.py +51 -0
- sqlglider/templating/base.py +103 -0
- sqlglider/templating/jinja.py +163 -0
- sqlglider/templating/registry.py +124 -0
- sqlglider/templating/variables.py +295 -0
- sqlglider/utils/__init__.py +11 -0
- sqlglider/utils/config.py +155 -0
- sqlglider/utils/file_utils.py +38 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Catalog registry with plugin discovery via entry points.
|
|
2
|
+
|
|
3
|
+
This module handles discovering and instantiating catalog providers from
|
|
4
|
+
Python entry points, allowing third-party packages to register
|
|
5
|
+
custom catalogs.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from typing import Dict, List, Type
|
|
10
|
+
|
|
11
|
+
from sqlglider.catalog.base import Catalog, CatalogError
|
|
12
|
+
|
|
13
|
+
# Cache for discovered catalogs
|
|
14
|
+
_catalog_cache: Dict[str, Type[Catalog]] = {}
|
|
15
|
+
_discovery_done: bool = False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _discover_catalogs() -> None:
|
|
19
|
+
"""Discover catalogs from entry points.
|
|
20
|
+
|
|
21
|
+
Uses importlib.metadata to find all registered catalogs
|
|
22
|
+
in the 'sqlglider.catalogs' entry point group.
|
|
23
|
+
"""
|
|
24
|
+
global _discovery_done, _catalog_cache
|
|
25
|
+
|
|
26
|
+
if _discovery_done:
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
if sys.version_info >= (3, 10):
|
|
30
|
+
from importlib.metadata import entry_points
|
|
31
|
+
|
|
32
|
+
eps = entry_points(group="sqlglider.catalogs")
|
|
33
|
+
else:
|
|
34
|
+
from importlib.metadata import entry_points
|
|
35
|
+
|
|
36
|
+
all_eps = entry_points()
|
|
37
|
+
eps = all_eps.get("sqlglider.catalogs", [])
|
|
38
|
+
|
|
39
|
+
for ep in eps:
|
|
40
|
+
try:
|
|
41
|
+
catalog_class = ep.load()
|
|
42
|
+
if isinstance(catalog_class, type) and issubclass(catalog_class, Catalog):
|
|
43
|
+
_catalog_cache[ep.name] = catalog_class
|
|
44
|
+
except Exception:
|
|
45
|
+
# Skip catalogs that fail to load
|
|
46
|
+
# This allows graceful handling of missing optional dependencies
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
_discovery_done = True
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_catalog(name: str) -> Catalog:
|
|
53
|
+
"""Get a catalog instance by name.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
name: The name of the catalog (e.g., "databricks").
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
An instance of the requested catalog.
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
CatalogError: If the catalog is not found.
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
>>> catalog = get_catalog("databricks")
|
|
66
|
+
>>> ddl = catalog.get_ddl("my_catalog.my_schema.my_table")
|
|
67
|
+
"""
|
|
68
|
+
_discover_catalogs()
|
|
69
|
+
|
|
70
|
+
if name not in _catalog_cache:
|
|
71
|
+
available = ", ".join(sorted(_catalog_cache.keys()))
|
|
72
|
+
raise CatalogError(
|
|
73
|
+
f"Unknown catalog '{name}'. Available catalogs: {available or 'none'}. "
|
|
74
|
+
f"You may need to install an optional dependency (e.g., pip install sql-glider[databricks])."
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return _catalog_cache[name]()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def list_catalogs() -> List[str]:
|
|
81
|
+
"""List all available catalog names.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
A sorted list of available catalog names.
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
>>> catalogs = list_catalogs()
|
|
88
|
+
>>> print(catalogs)
|
|
89
|
+
['databricks']
|
|
90
|
+
"""
|
|
91
|
+
_discover_catalogs()
|
|
92
|
+
return sorted(_catalog_cache.keys())
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def register_catalog(name: str, catalog_class: Type[Catalog]) -> None:
|
|
96
|
+
"""Register a catalog programmatically.
|
|
97
|
+
|
|
98
|
+
This is primarily useful for testing or for registering catalogs
|
|
99
|
+
that aren't installed via entry points.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
name: The name to register the catalog under.
|
|
103
|
+
catalog_class: The catalog class to register.
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
ValueError: If catalog_class is not a subclass of Catalog.
|
|
107
|
+
"""
|
|
108
|
+
if not isinstance(catalog_class, type) or not issubclass(catalog_class, Catalog):
|
|
109
|
+
raise ValueError(f"{catalog_class} must be a subclass of Catalog")
|
|
110
|
+
|
|
111
|
+
_catalog_cache[name] = catalog_class
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def clear_registry() -> None:
|
|
115
|
+
"""Clear the catalog registry.
|
|
116
|
+
|
|
117
|
+
This is primarily useful for testing.
|
|
118
|
+
"""
|
|
119
|
+
global _discovery_done, _catalog_cache
|
|
120
|
+
_catalog_cache.clear()
|
|
121
|
+
_discovery_done = False
|