graphlagoon 0.8.4__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.
- graphlagoon-0.8.4/.env.databricks +17 -0
- graphlagoon-0.8.4/.env.databricks-localdb +18 -0
- graphlagoon-0.8.4/.env.example +24 -0
- graphlagoon-0.8.4/.gitignore +105 -0
- graphlagoon-0.8.4/Makefile +22 -0
- graphlagoon-0.8.4/PKG-INFO +92 -0
- graphlagoon-0.8.4/README.md +47 -0
- graphlagoon-0.8.4/alembic/env.py +87 -0
- graphlagoon-0.8.4/alembic/script.py.mako +26 -0
- graphlagoon-0.8.4/alembic.ini +40 -0
- graphlagoon-0.8.4/graphlagoon/__init__.py +114 -0
- graphlagoon-0.8.4/graphlagoon/app.py +598 -0
- graphlagoon-0.8.4/graphlagoon/cli.py +45 -0
- graphlagoon-0.8.4/graphlagoon/config.py +211 -0
- graphlagoon-0.8.4/graphlagoon/db/__init__.py +0 -0
- graphlagoon-0.8.4/graphlagoon/db/database.py +194 -0
- graphlagoon-0.8.4/graphlagoon/db/lakebase.py +308 -0
- graphlagoon-0.8.4/graphlagoon/db/memory_store.py +418 -0
- graphlagoon-0.8.4/graphlagoon/db/models.py +155 -0
- graphlagoon-0.8.4/graphlagoon/main.py +24 -0
- graphlagoon-0.8.4/graphlagoon/middleware/__init__.py +0 -0
- graphlagoon-0.8.4/graphlagoon/middleware/auth.py +185 -0
- graphlagoon-0.8.4/graphlagoon/models/__init__.py +0 -0
- graphlagoon-0.8.4/graphlagoon/models/schemas.py +696 -0
- graphlagoon-0.8.4/graphlagoon/routers/__init__.py +0 -0
- graphlagoon-0.8.4/graphlagoon/routers/catalog.py +144 -0
- graphlagoon-0.8.4/graphlagoon/routers/config.py +33 -0
- graphlagoon-0.8.4/graphlagoon/routers/explorations.py +664 -0
- graphlagoon-0.8.4/graphlagoon/routers/graph.py +891 -0
- graphlagoon-0.8.4/graphlagoon/routers/graph_contexts.py +505 -0
- graphlagoon-0.8.4/graphlagoon/routers/query_templates.py +281 -0
- graphlagoon-0.8.4/graphlagoon/services/__init__.py +0 -0
- graphlagoon-0.8.4/graphlagoon/services/cte_prefilter.py +145 -0
- graphlagoon-0.8.4/graphlagoon/services/cypher.py +254 -0
- graphlagoon-0.8.4/graphlagoon/services/graph_operations.py +335 -0
- graphlagoon-0.8.4/graphlagoon/services/sql_validation.py +102 -0
- graphlagoon-0.8.4/graphlagoon/services/warehouse.py +1015 -0
- graphlagoon-0.8.4/graphlagoon/static/.vite/manifest.json +19 -0
- graphlagoon-0.8.4/graphlagoon/static/assets/main-tAVfrLyt.js +8455 -0
- graphlagoon-0.8.4/graphlagoon/static/assets/metricsWorker-0-sYkgie.js +1 -0
- graphlagoon-0.8.4/graphlagoon/static/assets/roboto-msdf-DyXWe5ZU.png +0 -0
- graphlagoon-0.8.4/graphlagoon/static/assets/style-l778HQOh.css +1 -0
- graphlagoon-0.8.4/graphlagoon/static/index.html +14 -0
- graphlagoon-0.8.4/graphlagoon/templates/index.html +43 -0
- graphlagoon-0.8.4/graphlagoon/utils/__init__.py +0 -0
- graphlagoon-0.8.4/graphlagoon/utils/sharing.py +72 -0
- graphlagoon-0.8.4/pyproject.toml +73 -0
- graphlagoon-0.8.4/pyproject.toml.bak +75 -0
- graphlagoon-0.8.4/tests/__init__.py +0 -0
- graphlagoon-0.8.4/tests/test_catalog_schemas.py +395 -0
- graphlagoon-0.8.4/tests/test_cte_prefilter.py +254 -0
- graphlagoon-0.8.4/tests/test_graph_error_handling.py +549 -0
- graphlagoon-0.8.4/tests/test_sharing_utils.py +184 -0
- graphlagoon-0.8.4/tests/test_sql_validation.py +205 -0
- graphlagoon-0.8.4/uv.lock +1379 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Databricks mode WITHOUT local PostgreSQL
|
|
2
|
+
# Copy to .env and fill in your values
|
|
3
|
+
|
|
4
|
+
# Disable local sql-warehouse - connect directly to Databricks
|
|
5
|
+
GRAPH_LAGOON_DATABRICKS_MODE=true
|
|
6
|
+
GRAPH_LAGOON_DATABRICKS_HOST=adb-XXXXX.X.azuredatabricks.net
|
|
7
|
+
GRAPH_LAGOON_DATABRICKS_TOKEN=dapi-XXXXXXXXXXXXX
|
|
8
|
+
GRAPH_LAGOON_DATABRICKS_WAREHOUSE_ID=XXXXXXXXXXXXXXXX
|
|
9
|
+
GRAPH_LAGOON_DATABRICKS_CATALOG=main
|
|
10
|
+
GRAPH_LAGOON_DATABRICKS_SCHEMA=default
|
|
11
|
+
|
|
12
|
+
# Disable PostgreSQL (contexts/explorations stored in browser localStorage)
|
|
13
|
+
GRAPH_LAGOON_DATABASE_ENABLED=false
|
|
14
|
+
|
|
15
|
+
# General settings
|
|
16
|
+
GRAPH_LAGOON_DEV_MODE=false
|
|
17
|
+
GRAPH_LAGOON_PORT=8000
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Databricks mode WITH local PostgreSQL
|
|
2
|
+
# Copy to .env and fill in your values
|
|
3
|
+
|
|
4
|
+
# Connect directly to Databricks SQL Warehouse
|
|
5
|
+
GRAPH_LAGOON_DATABRICKS_MODE=true
|
|
6
|
+
GRAPH_LAGOON_DATABRICKS_HOST=adb-XXXXX.X.azuredatabricks.net
|
|
7
|
+
GRAPH_LAGOON_DATABRICKS_TOKEN=dapi-XXXXXXXXXXXXX
|
|
8
|
+
GRAPH_LAGOON_DATABRICKS_WAREHOUSE_ID=XXXXXXXXXXXXXXXX
|
|
9
|
+
GRAPH_LAGOON_DATABRICKS_CATALOG=main
|
|
10
|
+
GRAPH_LAGOON_DATABRICKS_SCHEMA=default
|
|
11
|
+
|
|
12
|
+
# Use local PostgreSQL for storing contexts/explorations
|
|
13
|
+
GRAPH_LAGOON_DATABASE_ENABLED=true
|
|
14
|
+
GRAPH_LAGOON_DATABASE_URL=postgresql+asyncpg://sgraph:sgraph@localhost:5432/sgraph
|
|
15
|
+
|
|
16
|
+
# General settings
|
|
17
|
+
GRAPH_LAGOON_DEV_MODE=false
|
|
18
|
+
GRAPH_LAGOON_PORT=8000
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Graph Lagoon Studio Configuration
|
|
2
|
+
# All variables use GRAPH_LAGOON_ prefix to avoid conflicts with other applications
|
|
3
|
+
|
|
4
|
+
# Local sql-warehouse (dev mode)
|
|
5
|
+
GRAPH_LAGOON_SQL_WAREHOUSE_URL=http://localhost:8001
|
|
6
|
+
|
|
7
|
+
# Database (optional - disabled by default, uses localStorage on frontend)
|
|
8
|
+
# Set GRAPH_LAGOON_DATABASE_ENABLED=true to enable PostgreSQL persistence
|
|
9
|
+
GRAPH_LAGOON_DATABASE_URL=postgresql+asyncpg://sgraph:sgraph@localhost:5432/sgraph
|
|
10
|
+
GRAPH_LAGOON_DATABASE_ENABLED=false
|
|
11
|
+
|
|
12
|
+
# General settings
|
|
13
|
+
GRAPH_LAGOON_DEV_MODE=true
|
|
14
|
+
GRAPH_LAGOON_PORT=8000
|
|
15
|
+
|
|
16
|
+
# Databricks connection (production mode)
|
|
17
|
+
# Set GRAPH_LAGOON_DATABRICKS_MODE=true to connect directly to Databricks
|
|
18
|
+
# When GRAPH_LAGOON_DATABRICKS_MODE=true, CATALOG and SCHEMA are required
|
|
19
|
+
GRAPH_LAGOON_DATABRICKS_MODE=false
|
|
20
|
+
GRAPH_LAGOON_DATABRICKS_HOST=
|
|
21
|
+
GRAPH_LAGOON_DATABRICKS_TOKEN=
|
|
22
|
+
GRAPH_LAGOON_DATABRICKS_WAREHOUSE_ID=
|
|
23
|
+
GRAPH_LAGOON_DATABRICKS_CATALOG=
|
|
24
|
+
GRAPH_LAGOON_DATABRICKS_SCHEMA=
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
scripts/ieee_cis_fraud/data/
|
|
2
|
+
frontend/playwright-report-integration/trace/
|
|
3
|
+
.vitepres
|
|
4
|
+
frontend/ext-3d-force_raw
|
|
5
|
+
frontend/playwright-report-integration/data
|
|
6
|
+
frontend/test-results-integration/.last-run.json
|
|
7
|
+
frontend/test-results-integration
|
|
8
|
+
docs/dew
|
|
9
|
+
|
|
10
|
+
# =============================================================================
|
|
11
|
+
# Project-specific
|
|
12
|
+
# =============================================================================
|
|
13
|
+
frontend/ext-3d-force/exp
|
|
14
|
+
.logs
|
|
15
|
+
.pids
|
|
16
|
+
uv.toml
|
|
17
|
+
metastore_db/
|
|
18
|
+
derby.log
|
|
19
|
+
spark-warehouse/
|
|
20
|
+
alembic/versions/
|
|
21
|
+
|
|
22
|
+
# IDE / Editor
|
|
23
|
+
.vscode
|
|
24
|
+
.idea
|
|
25
|
+
*.swp
|
|
26
|
+
|
|
27
|
+
# Claude Code
|
|
28
|
+
.claude
|
|
29
|
+
|
|
30
|
+
# =============================================================================
|
|
31
|
+
# Python
|
|
32
|
+
# =============================================================================
|
|
33
|
+
__pycache__/
|
|
34
|
+
*.py[codz]
|
|
35
|
+
*$py.class
|
|
36
|
+
*.so
|
|
37
|
+
.Python
|
|
38
|
+
build/
|
|
39
|
+
dist/
|
|
40
|
+
*.egg-info/
|
|
41
|
+
*.egg
|
|
42
|
+
.installed.cfg
|
|
43
|
+
MANIFEST
|
|
44
|
+
.venv
|
|
45
|
+
venv/
|
|
46
|
+
env/
|
|
47
|
+
|
|
48
|
+
# Testing
|
|
49
|
+
htmlcov/
|
|
50
|
+
.tox/
|
|
51
|
+
.nox/
|
|
52
|
+
.coverage
|
|
53
|
+
.coverage.*
|
|
54
|
+
.cache
|
|
55
|
+
.pytest_cache/
|
|
56
|
+
coverage/
|
|
57
|
+
nosetests.xml
|
|
58
|
+
coverage.xml
|
|
59
|
+
|
|
60
|
+
# Type checkers
|
|
61
|
+
.mypy_cache/
|
|
62
|
+
.pytype/
|
|
63
|
+
.ruff_cache/
|
|
64
|
+
|
|
65
|
+
# =============================================================================
|
|
66
|
+
# Node.js
|
|
67
|
+
# =============================================================================
|
|
68
|
+
node_modules/
|
|
69
|
+
|
|
70
|
+
# =============================================================================
|
|
71
|
+
# Environment
|
|
72
|
+
# =============================================================================
|
|
73
|
+
.env
|
|
74
|
+
.envrc
|
|
75
|
+
*.log
|
|
76
|
+
|
|
77
|
+
# =============================================================================
|
|
78
|
+
# OS
|
|
79
|
+
# =============================================================================
|
|
80
|
+
**/.DS_Store
|
|
81
|
+
|
|
82
|
+
# =============================================================================
|
|
83
|
+
# Playwright
|
|
84
|
+
# =============================================================================
|
|
85
|
+
playwright-report/
|
|
86
|
+
test-results/
|
|
87
|
+
frontend/e2e/screenshots/
|
|
88
|
+
|
|
89
|
+
# =============================================================================
|
|
90
|
+
# Performance reports
|
|
91
|
+
# =============================================================================
|
|
92
|
+
frontend/perf-report.json
|
|
93
|
+
|
|
94
|
+
# =============================================================================
|
|
95
|
+
# Build artifacts (generated by make build)
|
|
96
|
+
# =============================================================================
|
|
97
|
+
api/graphlagoon/static/assets/
|
|
98
|
+
api/graphlagoon/static/.vite/
|
|
99
|
+
api/graphlagoon/static/index.html
|
|
100
|
+
CHANGELOG-release.md
|
|
101
|
+
|
|
102
|
+
# =============================================================================
|
|
103
|
+
# Data (warehouse)
|
|
104
|
+
# =============================================================================
|
|
105
|
+
warehouse/data
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.PHONY: install run dev test clean migrate migrate-create
|
|
2
|
+
|
|
3
|
+
install:
|
|
4
|
+
uv sync
|
|
5
|
+
|
|
6
|
+
run:
|
|
7
|
+
uv run uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload
|
|
8
|
+
|
|
9
|
+
dev: run
|
|
10
|
+
|
|
11
|
+
test:
|
|
12
|
+
uv run pytest -v
|
|
13
|
+
|
|
14
|
+
migrate:
|
|
15
|
+
uv run alembic upgrade head
|
|
16
|
+
|
|
17
|
+
migrate-create:
|
|
18
|
+
uv run alembic revision --autogenerate -m "$(name)"
|
|
19
|
+
|
|
20
|
+
clean:
|
|
21
|
+
rm -rf .venv __pycache__ .pytest_cache
|
|
22
|
+
find . -type d -name "__pycache__" -exec rm -rf {} +
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: graphlagoon
|
|
3
|
+
Version: 0.8.4
|
|
4
|
+
Summary: Graph visualization and exploration tool with FastAPI backend
|
|
5
|
+
Project-URL: Homepage, https://github.com/graphlagoon/graphlagoon
|
|
6
|
+
Project-URL: Documentation, https://github.com/graphlagoon/graphlagoon#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/graphlagoon/graphlagoon
|
|
8
|
+
Author-email: Bruno Messias <devmessias@gmail.com>
|
|
9
|
+
License: AGPL-3.0
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Framework :: FastAPI
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Requires-Dist: asyncpg>=0.31.0
|
|
20
|
+
Requires-Dist: fastapi>=0.109.0
|
|
21
|
+
Requires-Dist: gsql2rsql
|
|
22
|
+
Requires-Dist: httpx>=0.26.0
|
|
23
|
+
Requires-Dist: jinja2>=3.1.0
|
|
24
|
+
Requires-Dist: pydantic-settings>=2.1.0
|
|
25
|
+
Requires-Dist: pydantic>=2.5.0
|
|
26
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
27
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.0
|
|
28
|
+
Requires-Dist: sqlglot>=26.0.0
|
|
29
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
30
|
+
Provides-Extra: all
|
|
31
|
+
Requires-Dist: alembic>=1.13.0; extra == 'all'
|
|
32
|
+
Requires-Dist: asyncpg>=0.29.0; extra == 'all'
|
|
33
|
+
Requires-Dist: databricks-sdk>=0.38.0; extra == 'all'
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: debugpy>=1.8.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
39
|
+
Provides-Extra: lakebase
|
|
40
|
+
Requires-Dist: databricks-sdk>=0.38.0; extra == 'lakebase'
|
|
41
|
+
Provides-Extra: postgres
|
|
42
|
+
Requires-Dist: alembic>=1.13.0; extra == 'postgres'
|
|
43
|
+
Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# Graph Lagoon Studio
|
|
47
|
+
|
|
48
|
+
Graph visualization and exploration tool with FastAPI backend.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install graphlagoon
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Start the server
|
|
60
|
+
uvicorn graphlagoon.app:app --host 0.0.0.0 --port 8000
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
### Standalone Mode
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from graphlagoon import create_app
|
|
69
|
+
|
|
70
|
+
app = create_app()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Embedded Mode
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from fastapi import FastAPI
|
|
77
|
+
from graphlagoon import create_api_router
|
|
78
|
+
|
|
79
|
+
app = FastAPI()
|
|
80
|
+
app.include_router(create_api_router(), prefix="/graphlagoon")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
Environment variables:
|
|
86
|
+
|
|
87
|
+
- `DATABASE_ENABLED` - Enable/disable PostgreSQL (default: true)
|
|
88
|
+
- `DATABASE_URL` - PostgreSQL connection string
|
|
89
|
+
- `DATABRICKS_MODE` - Connect to Databricks directly (default: false)
|
|
90
|
+
- `DATABRICKS_HOST` - Databricks workspace host
|
|
91
|
+
- `DATABRICKS_TOKEN` - Databricks access token
|
|
92
|
+
- `DATABRICKS_WAREHOUSE_ID` - SQL warehouse ID
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Graph Lagoon Studio
|
|
2
|
+
|
|
3
|
+
Graph visualization and exploration tool with FastAPI backend.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install graphlagoon
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Start the server
|
|
15
|
+
uvicorn graphlagoon.app:app --host 0.0.0.0 --port 8000
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Standalone Mode
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from graphlagoon import create_app
|
|
24
|
+
|
|
25
|
+
app = create_app()
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Embedded Mode
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from fastapi import FastAPI
|
|
32
|
+
from graphlagoon import create_api_router
|
|
33
|
+
|
|
34
|
+
app = FastAPI()
|
|
35
|
+
app.include_router(create_api_router(), prefix="/graphlagoon")
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Configuration
|
|
39
|
+
|
|
40
|
+
Environment variables:
|
|
41
|
+
|
|
42
|
+
- `DATABASE_ENABLED` - Enable/disable PostgreSQL (default: true)
|
|
43
|
+
- `DATABASE_URL` - PostgreSQL connection string
|
|
44
|
+
- `DATABRICKS_MODE` - Connect to Databricks directly (default: false)
|
|
45
|
+
- `DATABRICKS_HOST` - Databricks workspace host
|
|
46
|
+
- `DATABRICKS_TOKEN` - Databricks access token
|
|
47
|
+
- `DATABRICKS_WAREHOUSE_ID` - SQL warehouse ID
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from logging.config import fileConfig
|
|
3
|
+
|
|
4
|
+
from sqlalchemy import pool
|
|
5
|
+
from sqlalchemy.engine import Connection
|
|
6
|
+
from sqlalchemy.ext.asyncio import async_engine_from_config
|
|
7
|
+
|
|
8
|
+
from alembic import context
|
|
9
|
+
|
|
10
|
+
from graphlagoon.config import get_settings
|
|
11
|
+
from graphlagoon.db.database import Base
|
|
12
|
+
|
|
13
|
+
config = context.config
|
|
14
|
+
|
|
15
|
+
if config.config_file_name is not None:
|
|
16
|
+
fileConfig(config.config_file_name)
|
|
17
|
+
|
|
18
|
+
target_metadata = Base.metadata
|
|
19
|
+
|
|
20
|
+
settings = get_settings()
|
|
21
|
+
|
|
22
|
+
if settings.lakebase_enabled:
|
|
23
|
+
from graphlagoon.db.lakebase import build_lakebase_url
|
|
24
|
+
|
|
25
|
+
config.set_main_option("sqlalchemy.url", build_lakebase_url(settings))
|
|
26
|
+
else:
|
|
27
|
+
config.set_main_option("sqlalchemy.url", settings.database_url)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def run_migrations_offline() -> None:
|
|
31
|
+
"""Run migrations in 'offline' mode."""
|
|
32
|
+
url = config.get_main_option("sqlalchemy.url")
|
|
33
|
+
context.configure(
|
|
34
|
+
url=url,
|
|
35
|
+
target_metadata=target_metadata,
|
|
36
|
+
literal_binds=True,
|
|
37
|
+
dialect_opts={"paramstyle": "named"},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
with context.begin_transaction():
|
|
41
|
+
context.run_migrations()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def do_run_migrations(connection: Connection) -> None:
|
|
45
|
+
context.configure(connection=connection, target_metadata=target_metadata)
|
|
46
|
+
|
|
47
|
+
with context.begin_transaction():
|
|
48
|
+
context.run_migrations()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def run_async_migrations() -> None:
|
|
52
|
+
"""Run migrations in 'online' mode with async engine."""
|
|
53
|
+
engine_kwargs = {}
|
|
54
|
+
if settings.lakebase_enabled:
|
|
55
|
+
server_settings = {"application_name": "graphlagoon-alembic"}
|
|
56
|
+
if settings.default_postgres_schema:
|
|
57
|
+
server_settings["search_path"] = settings.default_postgres_schema
|
|
58
|
+
engine_kwargs["connect_args"] = {
|
|
59
|
+
"ssl": "require",
|
|
60
|
+
"server_settings": server_settings,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
connectable = async_engine_from_config(
|
|
64
|
+
config.get_section(config.config_ini_section, {}),
|
|
65
|
+
prefix="sqlalchemy.",
|
|
66
|
+
poolclass=pool.NullPool,
|
|
67
|
+
**engine_kwargs,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async with connectable.connect() as connection:
|
|
71
|
+
await connection.run_sync(do_run_migrations)
|
|
72
|
+
|
|
73
|
+
await connectable.dispose()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def run_migrations_online() -> None:
|
|
77
|
+
"""Run migrations in 'online' mode."""
|
|
78
|
+
asyncio.run(run_async_migrations())
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
if "connection" in config.attributes:
|
|
82
|
+
# Called programmatically from create_tables() — connection already exists
|
|
83
|
+
do_run_migrations(config.attributes["connection"])
|
|
84
|
+
elif context.is_offline_mode():
|
|
85
|
+
run_migrations_offline()
|
|
86
|
+
else:
|
|
87
|
+
run_migrations_online()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""${message}
|
|
2
|
+
|
|
3
|
+
Revision ID: ${up_revision}
|
|
4
|
+
Revises: ${down_revision | comma,n}
|
|
5
|
+
Create Date: ${create_date}
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from typing import Sequence, Union
|
|
9
|
+
|
|
10
|
+
from alembic import op
|
|
11
|
+
import sqlalchemy as sa
|
|
12
|
+
${imports if imports else ""}
|
|
13
|
+
|
|
14
|
+
# revision identifiers, used by Alembic.
|
|
15
|
+
revision: str = ${repr(up_revision)}
|
|
16
|
+
down_revision: Union[str, None] = ${repr(down_revision)}
|
|
17
|
+
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
18
|
+
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def upgrade() -> None:
|
|
22
|
+
${upgrades if upgrades else "pass"}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def downgrade() -> None:
|
|
26
|
+
${downgrades if downgrades else "pass"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[alembic]
|
|
2
|
+
script_location = alembic
|
|
3
|
+
prepend_sys_path = .
|
|
4
|
+
version_path_separator = os
|
|
5
|
+
|
|
6
|
+
[post_write_hooks]
|
|
7
|
+
|
|
8
|
+
[loggers]
|
|
9
|
+
keys = root,sqlalchemy,alembic
|
|
10
|
+
|
|
11
|
+
[handlers]
|
|
12
|
+
keys = console
|
|
13
|
+
|
|
14
|
+
[formatters]
|
|
15
|
+
keys = generic
|
|
16
|
+
|
|
17
|
+
[logger_root]
|
|
18
|
+
level = WARN
|
|
19
|
+
handlers = console
|
|
20
|
+
qualname =
|
|
21
|
+
|
|
22
|
+
[logger_sqlalchemy]
|
|
23
|
+
level = WARN
|
|
24
|
+
handlers =
|
|
25
|
+
qualname = sqlalchemy.engine
|
|
26
|
+
|
|
27
|
+
[logger_alembic]
|
|
28
|
+
level = INFO
|
|
29
|
+
handlers =
|
|
30
|
+
qualname = alembic
|
|
31
|
+
|
|
32
|
+
[handler_console]
|
|
33
|
+
class = StreamHandler
|
|
34
|
+
args = (sys.stderr,)
|
|
35
|
+
level = NOTSET
|
|
36
|
+
formatter = generic
|
|
37
|
+
|
|
38
|
+
[formatter_generic]
|
|
39
|
+
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
40
|
+
datefmt = %H:%M:%S
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Graph Lagoon Studio - Graph visualization and exploration tool for Spark.
|
|
2
|
+
|
|
3
|
+
Usage as standalone app:
|
|
4
|
+
uvicorn graphlagoon.app:app --host 0.0.0.0 --port 8000
|
|
5
|
+
|
|
6
|
+
Usage as importable module (API only):
|
|
7
|
+
from fastapi import FastAPI
|
|
8
|
+
from graphlagoon import create_api_router
|
|
9
|
+
|
|
10
|
+
app = FastAPI()
|
|
11
|
+
app.include_router(create_api_router(), prefix="/api")
|
|
12
|
+
|
|
13
|
+
Usage as mountable sub-app (API + Frontend):
|
|
14
|
+
from fastapi import FastAPI
|
|
15
|
+
from graphlagoon import create_mountable_app, add_mount_redirect
|
|
16
|
+
|
|
17
|
+
app = FastAPI()
|
|
18
|
+
sgraph_app = create_mountable_app(mount_prefix="/graphlagoon")
|
|
19
|
+
|
|
20
|
+
# Add redirect for /graphlagoon -> /graphlagoon/
|
|
21
|
+
add_mount_redirect(app, "/graphlagoon")
|
|
22
|
+
|
|
23
|
+
app.mount("/graphlagoon", sgraph_app)
|
|
24
|
+
# Access at: http://localhost:8000/graphlagoon/
|
|
25
|
+
|
|
26
|
+
Usage with Databricks (specifying catalog and schema):
|
|
27
|
+
from fastapi import FastAPI
|
|
28
|
+
from graphlagoon import create_mountable_app
|
|
29
|
+
|
|
30
|
+
app = FastAPI()
|
|
31
|
+
app.mount("/graphlagoon", create_mountable_app(
|
|
32
|
+
databricks_catalog="my_catalog",
|
|
33
|
+
databricks_schema="my_schema",
|
|
34
|
+
))
|
|
35
|
+
|
|
36
|
+
Usage with multiple catalog.schema pairs:
|
|
37
|
+
from fastapi import FastAPI
|
|
38
|
+
from graphlagoon import create_mountable_app
|
|
39
|
+
|
|
40
|
+
app = FastAPI()
|
|
41
|
+
app.mount("/graphlagoon", create_mountable_app(
|
|
42
|
+
catalog_schemas=[
|
|
43
|
+
("catalog_a", "schema_1"),
|
|
44
|
+
("catalog_b", "schema_2"),
|
|
45
|
+
],
|
|
46
|
+
))
|
|
47
|
+
|
|
48
|
+
Usage with dynamic header provider (token refresh):
|
|
49
|
+
from fastapi import FastAPI
|
|
50
|
+
from graphlagoon import create_mountable_app, HeaderProvider
|
|
51
|
+
|
|
52
|
+
# Provider retorna o token (str), não o dict de headers
|
|
53
|
+
async def get_fresh_token() -> str:
|
|
54
|
+
return await my_token_service.get_token()
|
|
55
|
+
|
|
56
|
+
app = FastAPI()
|
|
57
|
+
app.mount("/graphlagoon", create_mountable_app(
|
|
58
|
+
header_provider=get_fresh_token, # Token é convertido para Authorization: Bearer
|
|
59
|
+
databricks_catalog="my_catalog",
|
|
60
|
+
databricks_schema="my_schema",
|
|
61
|
+
))
|
|
62
|
+
|
|
63
|
+
Usage with custom user provider (integrate with parent app's auth):
|
|
64
|
+
from fastapi import FastAPI, Request
|
|
65
|
+
from graphlagoon import create_mountable_app, UserProvider
|
|
66
|
+
|
|
67
|
+
def get_user_from_parent(request: Request) -> str:
|
|
68
|
+
# Parent app's middleware sets request.state.current_user
|
|
69
|
+
return request.state.current_user.email
|
|
70
|
+
|
|
71
|
+
app = FastAPI()
|
|
72
|
+
app.mount("/graphlagoon", create_mountable_app(
|
|
73
|
+
user_provider=get_user_from_parent,
|
|
74
|
+
databricks_catalog="my_catalog",
|
|
75
|
+
databricks_schema="my_schema",
|
|
76
|
+
))
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
from graphlagoon.app import (
|
|
80
|
+
create_app,
|
|
81
|
+
create_api_router,
|
|
82
|
+
create_frontend_router,
|
|
83
|
+
create_mountable_app,
|
|
84
|
+
add_mount_redirect,
|
|
85
|
+
)
|
|
86
|
+
from graphlagoon.config import Settings, get_settings
|
|
87
|
+
from graphlagoon.services.warehouse import HeaderProvider
|
|
88
|
+
from graphlagoon.middleware.auth import UserProvider, configure_auth
|
|
89
|
+
|
|
90
|
+
__all__ = [
|
|
91
|
+
"create_app",
|
|
92
|
+
"create_api_router",
|
|
93
|
+
"create_frontend_router",
|
|
94
|
+
"create_mountable_app",
|
|
95
|
+
"add_mount_redirect",
|
|
96
|
+
"Settings",
|
|
97
|
+
"get_settings",
|
|
98
|
+
"HeaderProvider",
|
|
99
|
+
"UserProvider",
|
|
100
|
+
"configure_auth",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _get_version() -> str:
|
|
105
|
+
"""Read version from pyproject.toml (single source of truth)."""
|
|
106
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
return version("graphlagoon")
|
|
110
|
+
except PackageNotFoundError:
|
|
111
|
+
return "0.0.0-dev"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
__version__ = _get_version()
|