prismiq 0.1.0__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.
prismiq/__init__.py ADDED
@@ -0,0 +1,543 @@
1
+ """
2
+ Prismiq - Open-source embedded analytics platform.
3
+
4
+ A Python backend for building embeddable analytics dashboards
5
+ with direct PostgreSQL table access and visual query building.
6
+
7
+ Example:
8
+ >>> from prismiq import PrismiqEngine, create_router
9
+ >>> from fastapi import FastAPI
10
+ >>>
11
+ >>> app = FastAPI()
12
+ >>> engine = PrismiqEngine(
13
+ ... database_url="postgresql://user:pass@localhost/db",
14
+ ... exposed_tables=["users", "orders"],
15
+ ... )
16
+ >>>
17
+ >>> @app.on_event("startup")
18
+ >>> async def startup():
19
+ ... await engine.startup()
20
+ ... app.include_router(create_router(engine), prefix="/api/analytics")
21
+ >>>
22
+ >>> @app.on_event("shutdown")
23
+ >>> async def shutdown():
24
+ ... await engine.shutdown()
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import TYPE_CHECKING
30
+
31
+ __version__ = "0.1.0"
32
+
33
+ # =============================================================================
34
+ # Lightweight imports (no heavy dependencies like asyncpg)
35
+ # These are always loaded when the package is imported
36
+ # =============================================================================
37
+
38
+ # Authentication (no external dependencies)
39
+ from prismiq.auth import AuthContext, SimpleAuthContext, create_header_auth_dependency
40
+
41
+ # Calculated field processor (no external dependencies)
42
+ from prismiq.calculated_field_processor import preprocess_calculated_fields
43
+
44
+ # Calculated fields (no external dependencies)
45
+ from prismiq.calculated_fields import ExpressionParser, has_aggregation, resolve_calculated_fields
46
+
47
+ # Dashboard store interface (no external dependencies)
48
+ from prismiq.dashboard_store import DashboardStore, InMemoryDashboardStore
49
+
50
+ # Dashboard models (pydantic only)
51
+ from prismiq.dashboards import (
52
+ Dashboard,
53
+ DashboardCreate,
54
+ DashboardExport,
55
+ DashboardFilter,
56
+ DashboardFilterType,
57
+ DashboardLayout,
58
+ DashboardUpdate,
59
+ Widget,
60
+ WidgetConfig,
61
+ WidgetCreate,
62
+ WidgetPosition,
63
+ WidgetType,
64
+ WidgetUpdate,
65
+ )
66
+
67
+ # Date utilities (no external dependencies)
68
+ from prismiq.dates import DatePreset, date_add, date_trunc, get_date_range_sql, resolve_date_preset
69
+
70
+ # Filter merge utilities (no external dependencies)
71
+ from prismiq.filter_merge import (
72
+ FilterValue,
73
+ filter_to_query_filter,
74
+ filter_to_query_filters,
75
+ get_applicable_filters,
76
+ merge_filters,
77
+ resolve_date_filter,
78
+ )
79
+
80
+ # Formatting utilities (no external dependencies)
81
+ from prismiq.formatting import (
82
+ NumberFormat,
83
+ format_compact,
84
+ format_currency,
85
+ format_number,
86
+ format_percent,
87
+ parse_number,
88
+ )
89
+
90
+ # Permissions (no external dependencies)
91
+ from prismiq.permissions import (
92
+ can_delete_dashboard,
93
+ can_edit_dashboard,
94
+ can_edit_widget,
95
+ can_view_dashboard,
96
+ )
97
+
98
+ # Pin models (no external dependencies)
99
+ from prismiq.pins import PinnedDashboard, PinRequest, ReorderPinsRequest, UnpinRequest
100
+
101
+ # Schema configuration (no external dependencies)
102
+ from prismiq.schema_config import (
103
+ ColumnConfig,
104
+ EnhancedColumnSchema,
105
+ EnhancedDatabaseSchema,
106
+ EnhancedTableSchema,
107
+ SchemaConfig,
108
+ SchemaConfigManager,
109
+ TableConfig,
110
+ )
111
+
112
+ # SQL utilities (no external dependencies)
113
+ from prismiq.sql_utils import (
114
+ ALLOWED_AGGREGATIONS,
115
+ ALLOWED_DATE_TRUNCS,
116
+ ALLOWED_JOIN_TYPES,
117
+ ALLOWED_OPERATORS,
118
+ ALLOWED_ORDER_DIRECTIONS,
119
+ convert_java_date_format_to_postgres,
120
+ quote_identifier,
121
+ validate_identifier,
122
+ )
123
+
124
+ # SQLAlchemy builder (only depends on sql_utils)
125
+ from prismiq.sqlalchemy_builder import build_sql_from_dict
126
+
127
+ # Time series utilities (no external dependencies)
128
+ from prismiq.timeseries import (
129
+ TimeBucket,
130
+ TimeInterval,
131
+ fill_missing_buckets,
132
+ generate_time_buckets,
133
+ get_date_trunc_sql,
134
+ get_interval_format,
135
+ )
136
+
137
+ # Transform utilities (no external dependencies)
138
+ from prismiq.transforms import (
139
+ calculate_percent_of_total,
140
+ calculate_running_total,
141
+ fill_nulls,
142
+ limit_result,
143
+ pivot_data,
144
+ sort_result,
145
+ transpose_data,
146
+ )
147
+
148
+ # Trend utilities (no external dependencies)
149
+ from prismiq.trends import (
150
+ ComparisonPeriod,
151
+ TrendDirection,
152
+ TrendResult,
153
+ add_trend_column,
154
+ calculate_moving_average,
155
+ calculate_period_comparison,
156
+ calculate_trend,
157
+ calculate_year_over_year,
158
+ )
159
+
160
+ # Types (pydantic only)
161
+ from prismiq.types import (
162
+ AggregationType,
163
+ ColumnSchema,
164
+ ColumnSelection,
165
+ DatabaseSchema,
166
+ FilterDefinition,
167
+ FilterOperator,
168
+ GroupByDefinition,
169
+ JoinDefinition,
170
+ JoinType,
171
+ PrismiqError,
172
+ QueryDefinition,
173
+ QueryExecutionError,
174
+ QueryResult,
175
+ QueryTable,
176
+ QueryTimeoutError,
177
+ QueryValidationError,
178
+ Relationship,
179
+ SortDefinition,
180
+ SortDirection,
181
+ TableNotFoundError,
182
+ TableSchema,
183
+ TimeSeriesConfig,
184
+ )
185
+
186
+ # =============================================================================
187
+ # Lazy imports for heavy modules (require asyncpg, redis, etc.)
188
+ # These are only loaded when explicitly accessed
189
+ # =============================================================================
190
+
191
+ # Map of lazy attribute names to their module and attribute
192
+ _LAZY_IMPORTS: dict[str, tuple[str, str]] = {
193
+ # Engine (requires asyncpg)
194
+ "PrismiqEngine": ("prismiq.engine", "PrismiqEngine"),
195
+ # Executor (requires asyncpg)
196
+ "QueryExecutor": ("prismiq.executor", "QueryExecutor"),
197
+ # Schema introspector (requires asyncpg)
198
+ "SchemaIntrospector": ("prismiq.schema", "SchemaIntrospector"),
199
+ # Query builder (requires asyncpg for schema validation)
200
+ "QueryBuilder": ("prismiq.query", "QueryBuilder"),
201
+ "ValidationError": ("prismiq.query", "ValidationError"),
202
+ "ValidationResult": ("prismiq.query", "ValidationResult"),
203
+ # API router (requires fastapi)
204
+ "create_router": ("prismiq.api", "create_router"),
205
+ "HealthCheck": ("prismiq.api", "HealthCheck"),
206
+ "HealthStatus": ("prismiq.api", "HealthStatus"),
207
+ "LivenessResponse": ("prismiq.api", "LivenessResponse"),
208
+ "ReadinessResponse": ("prismiq.api", "ReadinessResponse"),
209
+ # Cache backends (redis is optional)
210
+ "CacheBackend": ("prismiq.cache", "CacheBackend"),
211
+ "CacheConfig": ("prismiq.cache", "CacheConfig"),
212
+ "InMemoryCache": ("prismiq.cache", "InMemoryCache"),
213
+ "QueryCache": ("prismiq.cache", "QueryCache"),
214
+ "RedisCache": ("prismiq.cache", "RedisCache"),
215
+ "SchemaCache": ("prismiq.cache", "SchemaCache"),
216
+ # Persistence (requires asyncpg for async, sqlalchemy for sync)
217
+ "PostgresDashboardStore": ("prismiq.persistence", "PostgresDashboardStore"),
218
+ "PrismiqBase": ("prismiq.persistence", "PrismiqBase"),
219
+ "PrismiqDashboard": ("prismiq.persistence", "PrismiqDashboard"),
220
+ "PrismiqSavedQuery": ("prismiq.persistence", "PrismiqSavedQuery"),
221
+ "PrismiqPinnedDashboard": ("prismiq.persistence", "PrismiqPinnedDashboard"),
222
+ "PrismiqWidget": ("prismiq.persistence", "PrismiqWidget"),
223
+ "TableCreationError": ("prismiq.persistence", "TableCreationError"),
224
+ "drop_tables": ("prismiq.persistence", "drop_tables"),
225
+ "ensure_tables": ("prismiq.persistence", "ensure_tables"),
226
+ "ensure_tables_sync": ("prismiq.persistence", "ensure_tables_sync"),
227
+ # SQL validator (requires sqlglot)
228
+ "SQLValidationError": ("prismiq.sql_validator", "SQLValidationError"),
229
+ "SQLValidationResult": ("prismiq.sql_validator", "SQLValidationResult"),
230
+ "SQLValidator": ("prismiq.sql_validator", "SQLValidator"),
231
+ # Logging utilities
232
+ "LogConfig": ("prismiq.logging", "LogConfig"),
233
+ "LogContext": ("prismiq.logging", "LogContext"),
234
+ "Logger": ("prismiq.logging", "Logger"),
235
+ "QueryLog": ("prismiq.logging", "QueryLog"),
236
+ "QueryLogger": ("prismiq.logging", "QueryLogger"),
237
+ "RequestLoggingMiddleware": ("prismiq.logging", "RequestLoggingMiddleware"),
238
+ "StructuredFormatter": ("prismiq.logging", "StructuredFormatter"),
239
+ "TextFormatter": ("prismiq.logging", "TextFormatter"),
240
+ "configure_logging": ("prismiq.logging", "configure_logging"),
241
+ "get_logger": ("prismiq.logging", "get_logger"),
242
+ "get_request_id": ("prismiq.logging", "get_request_id"),
243
+ "set_request_id": ("prismiq.logging", "set_request_id"),
244
+ # Metrics
245
+ "DEFAULT_BUCKETS": ("prismiq.metrics", "DEFAULT_BUCKETS"),
246
+ "HistogramValue": ("prismiq.metrics", "HistogramValue"),
247
+ "Metrics": ("prismiq.metrics", "Metrics"),
248
+ "MetricValue": ("prismiq.metrics", "MetricValue"),
249
+ "Timer": ("prismiq.metrics", "Timer"),
250
+ "create_metrics_router": ("prismiq.metrics", "create_metrics_router"),
251
+ "metrics": ("prismiq.metrics", "metrics"),
252
+ "record_cache_hit": ("prismiq.metrics", "record_cache_hit"),
253
+ "record_query_execution": ("prismiq.metrics", "record_query_execution"),
254
+ "record_request": ("prismiq.metrics", "record_request"),
255
+ "set_active_connections": ("prismiq.metrics", "set_active_connections"),
256
+ # Middleware
257
+ "RateLimitConfig": ("prismiq.middleware", "RateLimitConfig"),
258
+ "RateLimiter": ("prismiq.middleware", "RateLimiter"),
259
+ "RateLimitMiddleware": ("prismiq.middleware", "RateLimitMiddleware"),
260
+ "SlidingWindowCounter": ("prismiq.middleware", "SlidingWindowCounter"),
261
+ "TokenBucket": ("prismiq.middleware", "TokenBucket"),
262
+ "create_rate_limiter": ("prismiq.middleware", "create_rate_limiter"),
263
+ }
264
+
265
+
266
+ def __getattr__(name: str):
267
+ """Lazy import for heavy modules."""
268
+ if name in _LAZY_IMPORTS:
269
+ module_path, attr_name = _LAZY_IMPORTS[name]
270
+ import importlib
271
+
272
+ module = importlib.import_module(module_path)
273
+ return getattr(module, attr_name)
274
+ raise AttributeError(f"module 'prismiq' has no attribute '{name}'")
275
+
276
+
277
+ # Type hints for lazy imports (only used by type checkers, not at runtime)
278
+ if TYPE_CHECKING:
279
+ from prismiq.api import (
280
+ HealthCheck,
281
+ HealthStatus,
282
+ LivenessResponse,
283
+ ReadinessResponse,
284
+ create_router,
285
+ )
286
+ from prismiq.cache import (
287
+ CacheBackend,
288
+ CacheConfig,
289
+ InMemoryCache,
290
+ QueryCache,
291
+ RedisCache,
292
+ SchemaCache,
293
+ )
294
+ from prismiq.engine import PrismiqEngine
295
+ from prismiq.executor import QueryExecutor
296
+ from prismiq.logging import (
297
+ LogConfig,
298
+ LogContext,
299
+ Logger,
300
+ QueryLog,
301
+ QueryLogger,
302
+ RequestLoggingMiddleware,
303
+ StructuredFormatter,
304
+ TextFormatter,
305
+ configure_logging,
306
+ get_logger,
307
+ get_request_id,
308
+ set_request_id,
309
+ )
310
+ from prismiq.metrics import (
311
+ DEFAULT_BUCKETS,
312
+ HistogramValue,
313
+ Metrics,
314
+ MetricValue,
315
+ Timer,
316
+ create_metrics_router,
317
+ metrics,
318
+ record_cache_hit,
319
+ record_query_execution,
320
+ record_request,
321
+ set_active_connections,
322
+ )
323
+ from prismiq.middleware import (
324
+ RateLimitConfig,
325
+ RateLimiter,
326
+ RateLimitMiddleware,
327
+ SlidingWindowCounter,
328
+ TokenBucket,
329
+ create_rate_limiter,
330
+ )
331
+ from prismiq.persistence import (
332
+ PostgresDashboardStore,
333
+ PrismiqBase,
334
+ PrismiqDashboard,
335
+ PrismiqPinnedDashboard,
336
+ PrismiqSavedQuery,
337
+ PrismiqWidget,
338
+ TableCreationError,
339
+ drop_tables,
340
+ ensure_tables,
341
+ ensure_tables_sync,
342
+ )
343
+ from prismiq.query import QueryBuilder, ValidationError, ValidationResult
344
+ from prismiq.schema import SchemaIntrospector
345
+ from prismiq.sql_validator import SQLValidationError, SQLValidationResult, SQLValidator
346
+
347
+
348
+ __all__ = [
349
+ # SQL utilities (lightweight)
350
+ "ALLOWED_AGGREGATIONS",
351
+ "ALLOWED_DATE_TRUNCS",
352
+ "ALLOWED_JOIN_TYPES",
353
+ "ALLOWED_OPERATORS",
354
+ "ALLOWED_ORDER_DIRECTIONS",
355
+ # Metrics
356
+ "DEFAULT_BUCKETS",
357
+ # Types (lightweight)
358
+ "AggregationType",
359
+ # Authentication (lightweight)
360
+ "AuthContext",
361
+ # Cache backends (redis optional)
362
+ "CacheBackend",
363
+ "CacheConfig",
364
+ # Schema configuration (lightweight)
365
+ "ColumnConfig",
366
+ "ColumnSchema",
367
+ "ColumnSelection",
368
+ # Trend utilities (lightweight)
369
+ "ComparisonPeriod",
370
+ # Dashboard models (lightweight)
371
+ "Dashboard",
372
+ "DashboardCreate",
373
+ "DashboardExport",
374
+ "DashboardFilter",
375
+ "DashboardFilterType",
376
+ "DashboardLayout",
377
+ # Dashboard store (lightweight)
378
+ "DashboardStore",
379
+ "DashboardUpdate",
380
+ "DatabaseSchema",
381
+ # Date utilities (lightweight)
382
+ "DatePreset",
383
+ "EnhancedColumnSchema",
384
+ "EnhancedDatabaseSchema",
385
+ "EnhancedTableSchema",
386
+ # Calculated fields (lightweight)
387
+ "ExpressionParser",
388
+ "FilterDefinition",
389
+ "FilterOperator",
390
+ # Filter merge utilities (lightweight)
391
+ "FilterValue",
392
+ "GroupByDefinition",
393
+ "HealthCheck",
394
+ "HealthStatus",
395
+ "HistogramValue",
396
+ "InMemoryCache",
397
+ "InMemoryDashboardStore",
398
+ "JoinDefinition",
399
+ "JoinType",
400
+ "LivenessResponse",
401
+ # Logging utilities
402
+ "LogConfig",
403
+ "LogContext",
404
+ "Logger",
405
+ "MetricValue",
406
+ "Metrics",
407
+ # Formatting utilities (lightweight)
408
+ "NumberFormat",
409
+ # Pin models (lightweight)
410
+ "PinRequest",
411
+ "PinnedDashboard",
412
+ # Persistence (asyncpg for async, sqlalchemy for sync)
413
+ "PostgresDashboardStore",
414
+ "PrismiqBase",
415
+ "PrismiqDashboard",
416
+ # === Lazy imports (heavy dependencies) ===
417
+ # Engine (asyncpg)
418
+ "PrismiqEngine",
419
+ "PrismiqError",
420
+ "PrismiqPinnedDashboard",
421
+ "PrismiqSavedQuery",
422
+ "PrismiqWidget",
423
+ # Query builder (asyncpg)
424
+ "QueryBuilder",
425
+ "QueryCache",
426
+ "QueryDefinition",
427
+ "QueryExecutionError",
428
+ # Executor (asyncpg)
429
+ "QueryExecutor",
430
+ "QueryLog",
431
+ "QueryLogger",
432
+ "QueryResult",
433
+ "QueryTable",
434
+ "QueryTimeoutError",
435
+ "QueryValidationError",
436
+ # Middleware
437
+ "RateLimitConfig",
438
+ "RateLimitMiddleware",
439
+ "RateLimiter",
440
+ "ReadinessResponse",
441
+ "RedisCache",
442
+ "Relationship",
443
+ "ReorderPinsRequest",
444
+ "RequestLoggingMiddleware",
445
+ # SQL validator (sqlglot)
446
+ "SQLValidationError",
447
+ "SQLValidationResult",
448
+ "SQLValidator",
449
+ "SchemaCache",
450
+ "SchemaConfig",
451
+ "SchemaConfigManager",
452
+ # Schema introspector (asyncpg)
453
+ "SchemaIntrospector",
454
+ "SimpleAuthContext",
455
+ "SlidingWindowCounter",
456
+ "SortDefinition",
457
+ "SortDirection",
458
+ "StructuredFormatter",
459
+ "TableConfig",
460
+ "TableCreationError",
461
+ "TableNotFoundError",
462
+ "TableSchema",
463
+ "TextFormatter",
464
+ # Time series utilities (lightweight)
465
+ "TimeBucket",
466
+ "TimeInterval",
467
+ "TimeSeriesConfig",
468
+ "Timer",
469
+ "TokenBucket",
470
+ "TrendDirection",
471
+ "TrendResult",
472
+ "UnpinRequest",
473
+ "ValidationError",
474
+ "ValidationResult",
475
+ "Widget",
476
+ "WidgetConfig",
477
+ "WidgetCreate",
478
+ "WidgetPosition",
479
+ "WidgetType",
480
+ "WidgetUpdate",
481
+ # Version
482
+ "__version__",
483
+ "add_trend_column",
484
+ "build_sql_from_dict",
485
+ "calculate_moving_average",
486
+ # Transform utilities (lightweight)
487
+ "calculate_percent_of_total",
488
+ "calculate_period_comparison",
489
+ "calculate_running_total",
490
+ "calculate_trend",
491
+ "calculate_year_over_year",
492
+ # Permissions (lightweight)
493
+ "can_delete_dashboard",
494
+ "can_edit_dashboard",
495
+ "can_edit_widget",
496
+ "can_view_dashboard",
497
+ "configure_logging",
498
+ "convert_java_date_format_to_postgres",
499
+ "create_header_auth_dependency",
500
+ "create_metrics_router",
501
+ "create_rate_limiter",
502
+ # API router (fastapi)
503
+ "create_router",
504
+ "date_add",
505
+ "date_trunc",
506
+ "drop_tables",
507
+ "ensure_tables",
508
+ "ensure_tables_sync",
509
+ "fill_missing_buckets",
510
+ "fill_nulls",
511
+ "filter_to_query_filter",
512
+ "filter_to_query_filters",
513
+ "format_compact",
514
+ "format_currency",
515
+ "format_number",
516
+ "format_percent",
517
+ "generate_time_buckets",
518
+ "get_applicable_filters",
519
+ "get_date_range_sql",
520
+ "get_date_trunc_sql",
521
+ "get_interval_format",
522
+ "get_logger",
523
+ "get_request_id",
524
+ "has_aggregation",
525
+ "limit_result",
526
+ "merge_filters",
527
+ "metrics",
528
+ "parse_number",
529
+ "pivot_data",
530
+ "preprocess_calculated_fields",
531
+ "quote_identifier",
532
+ "record_cache_hit",
533
+ "record_query_execution",
534
+ "record_request",
535
+ "resolve_calculated_fields",
536
+ "resolve_date_filter",
537
+ "resolve_date_preset",
538
+ "set_active_connections",
539
+ "set_request_id",
540
+ "sort_result",
541
+ "transpose_data",
542
+ "validate_identifier",
543
+ ]