dataface 0.1.2__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.
- d3_format/__init__.py +14 -0
- d3_format/errors.py +19 -0
- d3_format/format.py +551 -0
- d3_format/spec.py +159 -0
- dataface/DATAFACE_SYNTAX.md +1135 -0
- dataface/__init__.py +93 -0
- dataface/_docs_site.py +20 -0
- dataface/_install_hint.py +26 -0
- dataface/agent_api/__init__.py +79 -0
- dataface/agent_api/_init_templates/__init__.py +0 -0
- dataface/agent_api/_init_templates/agents_dft_snippet.md +26 -0
- dataface/agent_api/_init_templates/dataface.yml +15 -0
- dataface/agent_api/_init_templates/faces-dataface.yml +144 -0
- dataface/agent_api/_init_templates/index.md +24 -0
- dataface/agent_api/_paths.py +118 -0
- dataface/agent_api/_project_agents_md.py +43 -0
- dataface/agent_api/_session_store.py +486 -0
- dataface/agent_api/_state.py +28 -0
- dataface/agent_api/chat.py +221 -0
- dataface/agent_api/dashboards.py +257 -0
- dataface/agent_api/describe.py +366 -0
- dataface/agent_api/describe_query.py +120 -0
- dataface/agent_api/docs/__init__.py +25 -0
- dataface/agent_api/docs/_loader.py +292 -0
- dataface/agent_api/docs/yaml-reference.md +2757 -0
- dataface/agent_api/file_refs.py +118 -0
- dataface/agent_api/init.py +126 -0
- dataface/agent_api/inspect.py +128 -0
- dataface/agent_api/mcp_install.py +170 -0
- dataface/agent_api/query.py +274 -0
- dataface/agent_api/schema.py +658 -0
- dataface/agent_api/schema_search.py +284 -0
- dataface/agent_api/search.py +270 -0
- dataface/agent_api/skill_install.py +141 -0
- dataface/agent_api/skill_render.py +90 -0
- dataface/agent_api/skills.py +293 -0
- dataface/agent_api/surface_aliases.yaml +128 -0
- dataface/agent_api/validate.py +175 -0
- dataface/agent_api/validate_query.py +84 -0
- dataface/ai/__init__.py +39 -0
- dataface/ai/agent.py +139 -0
- dataface/ai/context.py +45 -0
- dataface/ai/events.py +62 -0
- dataface/ai/external_mcp.py +610 -0
- dataface/ai/generate_sql.py +96 -0
- dataface/ai/llm.py +403 -0
- dataface/ai/mcp/__init__.py +51 -0
- dataface/ai/mcp/server.py +289 -0
- dataface/ai/memories.py +85 -0
- dataface/ai/prompts.py +177 -0
- dataface/ai/schema_context.py +138 -0
- dataface/ai/skills/before-after-comparison/SKILL.md +102 -0
- dataface/ai/skills/before-after-comparison/examples/before-after-comparison.yml +24 -0
- dataface/ai/skills/dashboard-build/SKILL.md +212 -0
- dataface/ai/skills/dashboard-build/examples/_smoke.yml +15 -0
- dataface/ai/skills/dashboard-design/SKILL.md +182 -0
- dataface/ai/skills/dashboard-review/SKILL.md +113 -0
- dataface/ai/skills/dashboard-structural-review/SKILL.md +173 -0
- dataface/ai/skills/dashboard-visual-review/SKILL.md +139 -0
- dataface/ai/skills/dataface-mcp-setup/SKILL.md +177 -0
- dataface/ai/skills/dataface-troubleshooting/SKILL.md +225 -0
- dataface/ai/skills/drill-down-link/SKILL.md +112 -0
- dataface/ai/skills/drill-down-link/examples/drill-down-link.yml +27 -0
- dataface/ai/skills/faceted-small-multiples/SKILL.md +116 -0
- dataface/ai/skills/faceted-small-multiples/examples/faceted-small-multiples.yml +33 -0
- dataface/ai/skills/filter-bar-with-variables/SKILL.md +105 -0
- dataface/ai/skills/filter-bar-with-variables/examples/filter-bar-with-variables.yml +49 -0
- dataface/ai/skills/kpi-row/SKILL.md +101 -0
- dataface/ai/skills/kpi-row/examples/kpi-row.yml +55 -0
- dataface/ai/skills/report-design/SKILL.md +184 -0
- dataface/ai/skills/single-metric-bignum/SKILL.md +90 -0
- dataface/ai/skills/single-metric-bignum/examples/single-metric-bignum.yml +27 -0
- dataface/ai/skills/table-heavy-ops-dashboard/SKILL.md +114 -0
- dataface/ai/skills/table-heavy-ops-dashboard/examples/table-heavy-ops-dashboard.yml +48 -0
- dataface/ai/skills/time-series-trend/SKILL.md +93 -0
- dataface/ai/skills/time-series-trend/examples/time-series-trend.yml +26 -0
- dataface/ai/skills/top-n-with-detail/SKILL.md +98 -0
- dataface/ai/skills/top-n-with-detail/examples/top-n-with-detail.yml +45 -0
- dataface/ai/skills/two-by-two-grid-overview/SKILL.md +78 -0
- dataface/ai/skills/two-by-two-grid-overview/examples/two-by-two-grid-overview.yml +64 -0
- dataface/ai/tool_schemas.py +132 -0
- dataface/ai/tools/__init__.py +312 -0
- dataface/ai/yaml_utils.py +57 -0
- dataface/cli/__init__.py +3 -0
- dataface/cli/_console.py +48 -0
- dataface/cli/_error_format.py +83 -0
- dataface/cli/_extras.py +190 -0
- dataface/cli/_json_output.py +8 -0
- dataface/cli/_parsing.py +17 -0
- dataface/cli/_version_info.py +56 -0
- dataface/cli/commands/__init__.py +3 -0
- dataface/cli/commands/_agent_input.py +205 -0
- dataface/cli/commands/_agent_server.py +115 -0
- dataface/cli/commands/chat.py +645 -0
- dataface/cli/commands/describe.py +107 -0
- dataface/cli/commands/docs.py +131 -0
- dataface/cli/commands/extension.py +179 -0
- dataface/cli/commands/init.py +240 -0
- dataface/cli/commands/inspect.py +94 -0
- dataface/cli/commands/mcp_init.py +167 -0
- dataface/cli/commands/query.py +386 -0
- dataface/cli/commands/render.py +291 -0
- dataface/cli/commands/schema.py +411 -0
- dataface/cli/commands/search.py +49 -0
- dataface/cli/commands/serve.py +114 -0
- dataface/cli/commands/skills.py +133 -0
- dataface/cli/commands/skills_init.py +161 -0
- dataface/cli/commands/validate.py +63 -0
- dataface/cli/main.py +1501 -0
- dataface/core/__init__.py +75 -0
- dataface/core/compile/__init__.py +244 -0
- dataface/core/compile/_jinja_helpers.py +78 -0
- dataface/core/compile/channel.py +222 -0
- dataface/core/compile/chart_focus.py +101 -0
- dataface/core/compile/chart_resolved.py +169 -0
- dataface/core/compile/chart_type_detection.py +489 -0
- dataface/core/compile/chart_update.py +261 -0
- dataface/core/compile/colors.py +64 -0
- dataface/core/compile/compiler.py +904 -0
- dataface/core/compile/config.py +823 -0
- dataface/core/compile/custom_chart_types.py +208 -0
- dataface/core/compile/data_table_attachment.py +1287 -0
- dataface/core/compile/detect.py +110 -0
- dataface/core/compile/errors.py +302 -0
- dataface/core/compile/filter_injection.py +319 -0
- dataface/core/compile/introspection.py +527 -0
- dataface/core/compile/jinja.py +511 -0
- dataface/core/compile/labels_env.py +52 -0
- dataface/core/compile/markdown.py +154 -0
- dataface/core/compile/meta.py +388 -0
- dataface/core/compile/models/__init__.py +0 -0
- dataface/core/compile/models/chart/__init__.py +0 -0
- dataface/core/compile/models/chart/authored.py +2137 -0
- dataface/core/compile/models/chart/compiled.py +398 -0
- dataface/core/compile/models/config.py +347 -0
- dataface/core/compile/models/face/__init__.py +0 -0
- dataface/core/compile/models/face/authored.py +659 -0
- dataface/core/compile/models/face/compiled.py +522 -0
- dataface/core/compile/models/factories.py +201 -0
- dataface/core/compile/models/markers.py +40 -0
- dataface/core/compile/models/palette.py +36 -0
- dataface/core/compile/models/primitives.py +415 -0
- dataface/core/compile/models/query/__init__.py +0 -0
- dataface/core/compile/models/query/authored.py +246 -0
- dataface/core/compile/models/query/compiled.py +710 -0
- dataface/core/compile/models/refs.py +137 -0
- dataface/core/compile/models/source.py +611 -0
- dataface/core/compile/models/style/__init__.py +0 -0
- dataface/core/compile/models/style/authored.py +481 -0
- dataface/core/compile/models/style/compiled.py +3399 -0
- dataface/core/compile/models/style/merged.py +1682 -0
- dataface/core/compile/models/theme.py +362 -0
- dataface/core/compile/models/variable/__init__.py +0 -0
- dataface/core/compile/models/variable/authored.py +254 -0
- dataface/core/compile/models/vega_lite/__init__.py +0 -0
- dataface/core/compile/models/vega_lite/config.py +510 -0
- dataface/core/compile/models/vega_lite/contracts.py +171 -0
- dataface/core/compile/normalize_charts.py +494 -0
- dataface/core/compile/normalize_layout.py +1000 -0
- dataface/core/compile/normalize_queries.py +297 -0
- dataface/core/compile/normalize_variables.py +489 -0
- dataface/core/compile/normalizer.py +543 -0
- dataface/core/compile/palette.py +1100 -0
- dataface/core/compile/parameterized.py +658 -0
- dataface/core/compile/parser.py +228 -0
- dataface/core/compile/schema.py +20 -0
- dataface/core/compile/schema_renderers/__init__.py +0 -0
- dataface/core/compile/schema_renderers/json_schema.py +163 -0
- dataface/core/compile/schema_renderers/prompt.py +152 -0
- dataface/core/compile/schema_renderers/vscode_schema.py +301 -0
- dataface/core/compile/sizing.py +2126 -0
- dataface/core/compile/sources.py +518 -0
- dataface/core/compile/sql_authoring_lint.py +56 -0
- dataface/core/compile/style_cascade.py +471 -0
- dataface/core/compile/typography.py +299 -0
- dataface/core/compile/validator.py +301 -0
- dataface/core/compile/variables.py +53 -0
- dataface/core/compile/vega_config.py +98 -0
- dataface/core/compile/vega_lite/__init__.py +6 -0
- dataface/core/compile/vega_lite/validation.py +95 -0
- dataface/core/compile/yaml_error_formatter.py +838 -0
- dataface/core/connections.py +38 -0
- dataface/core/dashboard.py +358 -0
- dataface/core/defaults/default_config.yml +101 -0
- dataface/core/defaults/palettes/categorical/category-10-dark.yml +32 -0
- dataface/core/defaults/palettes/categorical/category-10-light.yml +43 -0
- dataface/core/defaults/palettes/categorical/category-10.yml +31 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-blue.yml +22 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-brown.yml +29 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-green.yml +20 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-orange.yml +21 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-purple.yml +20 -0
- dataface/core/defaults/palettes/categorical/editorial-10-dark.yml +32 -0
- dataface/core/defaults/palettes/categorical/editorial-10.yml +40 -0
- dataface/core/defaults/palettes/categorical/hero-6.yml +17 -0
- dataface/core/defaults/palettes/categorical/single-blue.yml +11 -0
- dataface/core/defaults/palettes/categorical/tableau.yml +20 -0
- dataface/core/defaults/palettes/data/xkcd_colors.json +3803 -0
- dataface/core/defaults/palettes/diverging/blue-red.yml +25 -0
- dataface/core/defaults/palettes/diverging/coolwarm.yml +24 -0
- dataface/core/defaults/palettes/diverging/crimson-green.yml +23 -0
- dataface/core/defaults/palettes/diverging/orange-teal.yml +23 -0
- dataface/core/defaults/palettes/diverging/sunset.yml +24 -0
- dataface/core/defaults/palettes/scaffold/dft-creams.yml +38 -0
- dataface/core/defaults/palettes/scaffold/dft-grays.yml +53 -0
- dataface/core/defaults/palettes/sequential/amber.yml +22 -0
- dataface/core/defaults/palettes/sequential/blue.yml +22 -0
- dataface/core/defaults/palettes/sequential/brown.yml +22 -0
- dataface/core/defaults/palettes/sequential/gray.yml +22 -0
- dataface/core/defaults/palettes/sequential/green.yml +22 -0
- dataface/core/defaults/palettes/sequential/purple.yml +22 -0
- dataface/core/defaults/palettes/sequential/rust.yml +22 -0
- dataface/core/defaults/palettes/sequential/teal.yml +22 -0
- dataface/core/defaults/palettes/tone/negative.yml +32 -0
- dataface/core/defaults/palettes/tone/positive.yml +22 -0
- dataface/core/defaults/palettes/tone/warning.yml +22 -0
- dataface/core/defaults/themes/_base.yaml +786 -0
- dataface/core/defaults/themes/bi.yaml +16 -0
- dataface/core/defaults/themes/carbong100.yaml +41 -0
- dataface/core/defaults/themes/cream.yaml +122 -0
- dataface/core/defaults/themes/dark.yaml +40 -0
- dataface/core/defaults/themes/diagnostics-title-angle-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-baseline-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-baseline.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-center.yaml +8 -0
- dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +25 -0
- dataface/core/defaults/themes/diagnostics-title-left.yaml +8 -0
- dataface/core/defaults/themes/diagnostics-title-offset-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +24 -0
- dataface/core/defaults/themes/editorial.yaml +147 -0
- dataface/core/defaults/themes/light.yaml +30 -0
- dataface/core/defaults/themes/looker.yaml +17 -0
- dataface/core/defaults/themes/stark.yaml +134 -0
- dataface/core/errors/__init__.py +67 -0
- dataface/core/errors/codes_compile.py +56 -0
- dataface/core/errors/codes_execute.py +177 -0
- dataface/core/errors/codes_render.py +106 -0
- dataface/core/errors/codes_unknown.py +15 -0
- dataface/core/errors/hints.py +74 -0
- dataface/core/errors/registry.py +42 -0
- dataface/core/errors/structured.py +92 -0
- dataface/core/execute/__init__.py +91 -0
- dataface/core/execute/adapters/__init__.py +49 -0
- dataface/core/execute/adapters/adapter_registry.py +400 -0
- dataface/core/execute/adapters/base.py +245 -0
- dataface/core/execute/adapters/csv_adapter.py +239 -0
- dataface/core/execute/adapters/dbt_adapter.py +283 -0
- dataface/core/execute/adapters/dbt_adapter_factory.py +212 -0
- dataface/core/execute/adapters/dbt_macro_loader.py +95 -0
- dataface/core/execute/adapters/dbt_utils.py +150 -0
- dataface/core/execute/adapters/http_adapter.py +224 -0
- dataface/core/execute/adapters/metricflow_adapter.py +94 -0
- dataface/core/execute/adapters/schema_resolver_adapter.py +144 -0
- dataface/core/execute/adapters/sql_adapter.py +710 -0
- dataface/core/execute/adapters/values_adapter.py +58 -0
- dataface/core/execute/batch.py +744 -0
- dataface/core/execute/cache_backend.py +135 -0
- dataface/core/execute/cache_keys.py +66 -0
- dataface/core/execute/dbt_jinja.py +21 -0
- dataface/core/execute/dialects/__init__.py +121 -0
- dataface/core/execute/dialects/athena.py +75 -0
- dataface/core/execute/dialects/base.py +302 -0
- dataface/core/execute/dialects/bigquery.py +38 -0
- dataface/core/execute/dialects/databricks.py +68 -0
- dataface/core/execute/dialects/duckdb.py +35 -0
- dataface/core/execute/dialects/mysql.py +68 -0
- dataface/core/execute/dialects/postgres.py +39 -0
- dataface/core/execute/dialects/redshift.py +12 -0
- dataface/core/execute/dialects/snowflake.py +51 -0
- dataface/core/execute/dialects/sqlserver.py +92 -0
- dataface/core/execute/duckdb_cache.py +712 -0
- dataface/core/execute/duckdb_config.py +26 -0
- dataface/core/execute/errors.py +213 -0
- dataface/core/execute/executor.py +1249 -0
- dataface/core/execute/parallel.py +162 -0
- dataface/core/execute/setup_sql.py +58 -0
- dataface/core/execute/source_registry.py +72 -0
- dataface/core/execute/source_resolver.py +255 -0
- dataface/core/execute/sql_guard.py +387 -0
- dataface/core/execute/sql_literals.py +199 -0
- dataface/core/fonts.py +52 -0
- dataface/core/inspect/__init__.py +32 -0
- dataface/core/inspect/cache_factory.py +98 -0
- dataface/core/inspect/db_types.py +162 -0
- dataface/core/inspect/dbt_schema.py +96 -0
- dataface/core/inspect/defaults.yml +37 -0
- dataface/core/inspect/fanout_risk.py +109 -0
- dataface/core/inspect/manifest_utils.py +77 -0
- dataface/core/inspect/partials/categorical.yml +40 -0
- dataface/core/inspect/partials/date.yml +40 -0
- dataface/core/inspect/partials/numeric.yml +55 -0
- dataface/core/inspect/partition_types.py +38 -0
- dataface/core/inspect/query_validator.py +975 -0
- dataface/core/inspect/renderer.py +354 -0
- dataface/core/inspect/resolver.py +808 -0
- dataface/core/inspect/search.py +461 -0
- dataface/core/inspect/sources/__init__.py +32 -0
- dataface/core/inspect/sources/dbt.py +738 -0
- dataface/core/inspect/sources/duckdb_utils.py +66 -0
- dataface/core/inspect/templates/__init__.py +1 -0
- dataface/core/inspect/templates/categorical_column.yml +196 -0
- dataface/core/inspect/templates/charts.yml +109 -0
- dataface/core/inspect/templates/date_column.yml +248 -0
- dataface/core/inspect/templates/model.yml +138 -0
- dataface/core/inspect/templates/numeric_column.yml +261 -0
- dataface/core/inspect/templates/quality.yml +80 -0
- dataface/core/inspect/templates/string_column.yml +263 -0
- dataface/core/project_roots.py +165 -0
- dataface/core/render/__init__.py +87 -0
- dataface/core/render/board_links.py +176 -0
- dataface/core/render/chart/__init__.py +27 -0
- dataface/core/render/chart/arc_attached_table.py +251 -0
- dataface/core/render/chart/artifacts.py +16 -0
- dataface/core/render/chart/callout.py +225 -0
- dataface/core/render/chart/decisions.py +358 -0
- dataface/core/render/chart/geo.py +700 -0
- dataface/core/render/chart/kpi.py +916 -0
- dataface/core/render/chart/labels.py +76 -0
- dataface/core/render/chart/pipeline.py +818 -0
- dataface/core/render/chart/presentation.py +36 -0
- dataface/core/render/chart/profile.py +3438 -0
- dataface/core/render/chart/render_single.py +347 -0
- dataface/core/render/chart/renderers.py +193 -0
- dataface/core/render/chart/rendering.py +565 -0
- dataface/core/render/chart/serialization.py +90 -0
- dataface/core/render/chart/spark.py +496 -0
- dataface/core/render/chart/spark_bar.py +370 -0
- dataface/core/render/chart/spec_builders.py +154 -0
- dataface/core/render/chart/standard_renderer.py +2645 -0
- dataface/core/render/chart/table.py +2957 -0
- dataface/core/render/chart/table_support.py +1452 -0
- dataface/core/render/chart/tick_values.py +66 -0
- dataface/core/render/chart/time_unit_detect.py +809 -0
- dataface/core/render/chart/title_overflow.py +157 -0
- dataface/core/render/chart/type_inference.py +122 -0
- dataface/core/render/chart/validation.py +99 -0
- dataface/core/render/chart/vega_lite.py +125 -0
- dataface/core/render/chart/vega_lite_types.py +268 -0
- dataface/core/render/chart/vl_field_maps.py +346 -0
- dataface/core/render/chart_interactivity.py +24 -0
- dataface/core/render/control_registry.py +287 -0
- dataface/core/render/converters/__init__.py +24 -0
- dataface/core/render/converters/chart.py +276 -0
- dataface/core/render/converters/html.py +98 -0
- dataface/core/render/converters/pdf.py +40 -0
- dataface/core/render/converters/png.py +41 -0
- dataface/core/render/errors.py +144 -0
- dataface/core/render/face_api.py +160 -0
- dataface/core/render/faces.py +1194 -0
- dataface/core/render/font_measurement.py +48 -0
- dataface/core/render/font_support.py +197 -0
- dataface/core/render/fonts/DFTSansTabular-Regular.ttf +0 -0
- dataface/core/render/fonts/DFTSansTabular-Regular.woff2 +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.ttf +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.ttf +0 -0
- dataface/core/render/fonts/InterVariable.ttf +0 -0
- dataface/core/render/fonts/InterVariable.woff2 +0 -0
- dataface/core/render/fonts/NOTO_COLOR_EMOJI_LICENSE.txt +93 -0
- dataface/core/render/fonts/NOTO_EMOJI_LICENSE.txt +93 -0
- dataface/core/render/fonts/NotoColorEmoji-Regular.ttf +0 -0
- dataface/core/render/fonts/NotoColorEmoji-Regular.woff2 +0 -0
- dataface/core/render/fonts/NotoEmoji-Regular.ttf +0 -0
- dataface/core/render/fonts/NotoEmoji-Regular.woff2 +0 -0
- dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -0
- dataface/core/render/fonts/SOURCE_SERIF_4_LICENSE.txt +98 -0
- dataface/core/render/fonts/SourceCodePro-Regular.ttf +0 -0
- dataface/core/render/fonts/SourceSerif4-Regular.ttf +0 -0
- dataface/core/render/fonts/_emoji_font_face.css +43 -0
- dataface/core/render/fonts/source-serif-4-variable-latin.woff2 +0 -0
- dataface/core/render/format_utils.py +329 -0
- dataface/core/render/geo_defaults.yml +28 -0
- dataface/core/render/json_format.py +146 -0
- dataface/core/render/layout_sizing.py +865 -0
- dataface/core/render/layouts.py +541 -0
- dataface/core/render/markdown_defaults.yml +16 -0
- dataface/core/render/missing_vars_prompt.py +79 -0
- dataface/core/render/placeholder.py +389 -0
- dataface/core/render/render_result.py +14 -0
- dataface/core/render/renderer.py +467 -0
- dataface/core/render/script_embedding.py +16 -0
- dataface/core/render/svg_utils.py +212 -0
- dataface/core/render/template_loader.py +69 -0
- dataface/core/render/templates/controls/_styles.css +606 -0
- dataface/core/render/templates/controls/checkbox.html +16 -0
- dataface/core/render/templates/controls/date.html +16 -0
- dataface/core/render/templates/controls/number.html +19 -0
- dataface/core/render/templates/controls/readonly.html +9 -0
- dataface/core/render/templates/controls/select.html +21 -0
- dataface/core/render/templates/controls/slider.html +22 -0
- dataface/core/render/templates/controls/text.html +16 -0
- dataface/core/render/templates/scripts/chart_interactivity.js +191 -0
- dataface/core/render/templates/scripts/variables.js +976 -0
- dataface/core/render/templates/svg/grid_pattern.svg +3 -0
- dataface/core/render/templates/svg/styles.css +51 -0
- dataface/core/render/terminal.py +311 -0
- dataface/core/render/terminal_charts.py +563 -0
- dataface/core/render/terminal_defaults.yml +2 -0
- dataface/core/render/terminal_layouts.py +299 -0
- dataface/core/render/terminal_text.py +31 -0
- dataface/core/render/text/__init__.py +1 -0
- dataface/core/render/text/case.py +113 -0
- dataface/core/render/text_format.py +129 -0
- dataface/core/render/utils.py +106 -0
- dataface/core/render/variable_controls.py +946 -0
- dataface/core/render/variable_input_refinement.py +140 -0
- dataface/core/render/warnings/__init__.py +15 -0
- dataface/core/render/warnings/bar_color_1_to_1_with_x.py +80 -0
- dataface/core/render/warnings/base.py +44 -0
- dataface/core/render/warnings/fanout_risk.py +15 -0
- dataface/core/render/warnings/from_query_diagnostic.py +56 -0
- dataface/core/render/warnings/missing_join_predicate.py +13 -0
- dataface/core/render/warnings/query_parse_error.py +14 -0
- dataface/core/render/warnings/query_returned_zero_rows.py +42 -0
- dataface/core/render/warnings/reaggregation.py +14 -0
- dataface/core/render/warnings/registry.py +45 -0
- dataface/core/render/warnings/suppression.py +46 -0
- dataface/core/render/warnings/temporal_single_point.py +63 -0
- dataface/core/render/warnings/unreferenced_chart.py +15 -0
- dataface/core/render/warnings/y_encoding_mostly_null.py +76 -0
- dataface/core/render/yaml_format.py +167 -0
- dataface/core/resolve_face.py +195 -0
- dataface/core/schema/__init__.py +0 -0
- dataface/core/schema/guidance.py +151 -0
- dataface/core/scoped_paths.py +59 -0
- dataface/core/serve/__init__.py +14 -0
- dataface/core/serve/bootstrap.py +39 -0
- dataface/core/serve/embedded.py +57 -0
- dataface/core/serve/port.py +129 -0
- dataface/core/serve/server.py +938 -0
- dataface/core/serve/templates/__init__.py +0 -0
- dataface/core/serve/templates/directory.yml +6 -0
- dataface/core/serve/templates/error.html.j2 +217 -0
- dataface/core/utils.py +121 -0
- dataface/core/validate.py +64 -0
- dataface/integrations/__init__.py +0 -0
- dataface/integrations/highlighting.py +351 -0
- dataface/integrations/markdown.py +537 -0
- dataface/py.typed +0 -0
- dataface-0.1.2.dist-info/METADATA +375 -0
- dataface-0.1.2.dist-info/RECORD +455 -0
- dataface-0.1.2.dist-info/WHEEL +4 -0
- dataface-0.1.2.dist-info/entry_points.txt +2 -0
- dataface-0.1.2.dist-info/licenses/LICENSE +202 -0
- mdsvg/__init__.py +168 -0
- mdsvg/fonts.py +656 -0
- mdsvg/images.py +299 -0
- mdsvg/parser.py +629 -0
- mdsvg/playground.py +284 -0
- mdsvg/py.typed +2 -0
- mdsvg/renderer.py +1623 -0
- mdsvg/style.py +355 -0
- mdsvg/types.py +200 -0
- mdsvg/utils.py +86 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Pluggable cache-backend Protocol for query result storage.
|
|
2
|
+
|
|
3
|
+
Stage: EXECUTE (Cache)
|
|
4
|
+
Purpose: Define the abstract surface that any query-result cache backend must
|
|
5
|
+
implement. The only current implementation is DuckDBCache. Future alternatives
|
|
6
|
+
(Redis, S3, in-memory) can plug in by satisfying this Protocol.
|
|
7
|
+
|
|
8
|
+
Cache keys are always (source_hash, query_hash, variables_hash):
|
|
9
|
+
- source_hash — stable identity of the data source (connection string, project, etc.)
|
|
10
|
+
- query_hash — hash of the SQL/query after static resolution
|
|
11
|
+
- variables_hash — hash of the variables that materially affect the result
|
|
12
|
+
|
|
13
|
+
face_slug and query_name are METADATA, not key components. They are passed
|
|
14
|
+
as keyword-only arguments to put/put_failure so backends can build internal
|
|
15
|
+
indexes for {{ results.X }} cross-query references and snapshot history.
|
|
16
|
+
|
|
17
|
+
Backend selection: today DuckDBCache is the only implementation. A future
|
|
18
|
+
DFT_CACHE_BACKEND env-var hook can route to alternatives when a second
|
|
19
|
+
backend exists. This Protocol is also the seam for a future
|
|
20
|
+
`pip install dataface[duckdb]` extras-packaging effort.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from dataclasses import dataclass
|
|
26
|
+
from datetime import datetime
|
|
27
|
+
from typing import Any, Protocol, runtime_checkable
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True)
|
|
31
|
+
class CachedQueryFailure(Exception):
|
|
32
|
+
"""A query failure retrieved from the cache.
|
|
33
|
+
|
|
34
|
+
Raised instead of re-running a query that already failed within the TTL window.
|
|
35
|
+
Consumers can distinguish cached failures from fresh failures by catching this type.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
error_class: str
|
|
39
|
+
error_message: str
|
|
40
|
+
traceback: str | None
|
|
41
|
+
failed_at: datetime
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@runtime_checkable
|
|
45
|
+
class QueryResultCache(Protocol):
|
|
46
|
+
"""Pluggable backend for persistent query-result caching.
|
|
47
|
+
|
|
48
|
+
All operations are keyed by (source_hash, query_hash, variables_hash).
|
|
49
|
+
face_slug and query_name are metadata passed on writes; they are NOT key
|
|
50
|
+
components. This keeps the key free of app-layer noise so two faces with
|
|
51
|
+
identical queries against identical sources share one cache entry.
|
|
52
|
+
|
|
53
|
+
Implementations may use any storage: DuckDB, Redis, S3, in-memory, etc.
|
|
54
|
+
The only current implementation is DuckDBCache.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def get(
|
|
58
|
+
self, source_hash: str, query_hash: str, variables_hash: str
|
|
59
|
+
) -> list[dict[str, Any]] | None:
|
|
60
|
+
"""Return cached rows, or None on miss."""
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def put(
|
|
64
|
+
self,
|
|
65
|
+
source_hash: str,
|
|
66
|
+
query_hash: str,
|
|
67
|
+
variables_hash: str,
|
|
68
|
+
data: list[dict[str, Any]],
|
|
69
|
+
*,
|
|
70
|
+
face_slug: str,
|
|
71
|
+
query_name: str,
|
|
72
|
+
variables: dict[str, Any],
|
|
73
|
+
) -> None:
|
|
74
|
+
"""Store rows under the given key; record face/query as metadata."""
|
|
75
|
+
...
|
|
76
|
+
|
|
77
|
+
def get_failure(
|
|
78
|
+
self, source_hash: str, query_hash: str, variables_hash: str
|
|
79
|
+
) -> CachedQueryFailure | None:
|
|
80
|
+
"""Return a cached failure if one exists and is within TTL, else None."""
|
|
81
|
+
...
|
|
82
|
+
|
|
83
|
+
def put_failure(
|
|
84
|
+
self,
|
|
85
|
+
source_hash: str,
|
|
86
|
+
query_hash: str,
|
|
87
|
+
variables_hash: str,
|
|
88
|
+
exception: Exception,
|
|
89
|
+
*,
|
|
90
|
+
face_slug: str,
|
|
91
|
+
query_name: str,
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Store a query failure under the given key; record face/query as metadata."""
|
|
94
|
+
...
|
|
95
|
+
|
|
96
|
+
def clear(self, source_hash: str, query_hash: str, variables_hash: str) -> None:
|
|
97
|
+
"""Remove both success and failure entries for the given key."""
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
def close(self) -> None:
|
|
101
|
+
"""Release any held resources (connections, file handles, etc.)."""
|
|
102
|
+
...
|
|
103
|
+
|
|
104
|
+
def supports_results_refs(self) -> bool:
|
|
105
|
+
"""Return True if this backend can execute {{ results.X }} SQL queries.
|
|
106
|
+
|
|
107
|
+
DuckDBCache returns True (it has an embedded SQL engine).
|
|
108
|
+
Backends without a SQL engine return False; callers raise a clear error
|
|
109
|
+
("{{ results.X }} requires a SQL-engine cache backend") in that case.
|
|
110
|
+
"""
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
def rewrite_results_refs(self, face_slug: str, sql: str) -> str:
|
|
114
|
+
"""Rewrite {{ results.X }} references to backend-specific view/table names.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
face_slug: Face identifier (for view name prefix)
|
|
118
|
+
sql: SQL containing {{ results.X }} references
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
SQL with references substituted for backend-native names
|
|
122
|
+
"""
|
|
123
|
+
...
|
|
124
|
+
|
|
125
|
+
def execute_results_query(self, face_slug: str, sql: str) -> list[dict[str, Any]]:
|
|
126
|
+
"""Execute a SQL query against cached result views.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
face_slug: Face identifier
|
|
130
|
+
sql: SQL with {{ results.X }} already rewritten
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Result rows
|
|
134
|
+
"""
|
|
135
|
+
...
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Cache key helpers — produce identity payloads for source-aware hashing.
|
|
2
|
+
|
|
3
|
+
Stage: EXECUTE (Cache)
|
|
4
|
+
Purpose: Reduce a source reference to its cache identity, stripping secrets.
|
|
5
|
+
|
|
6
|
+
Secrets are NEVER included in cache hash inputs. Two users connecting to the
|
|
7
|
+
same source name with different credentials must produce different hashes
|
|
8
|
+
(so they don't share cache entries when their DB-side row-level access
|
|
9
|
+
differs); but a password rotation alone must NOT invalidate the cache.
|
|
10
|
+
|
|
11
|
+
`source_identity(source)` is the single transformation. The executor calls
|
|
12
|
+
it (via `compute_source_hash`) after resolving named source references
|
|
13
|
+
through the project's `face.sources` map.
|
|
14
|
+
|
|
15
|
+
See also:
|
|
16
|
+
- dataface/core/execute/duckdb_cache.py — `compute_source_hash` consumer
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
# Field names that must NEVER appear in cache hash inputs. Match by case-
|
|
24
|
+
# insensitive exact name. Conservative: anything that looks secret-shaped
|
|
25
|
+
# is dropped. Adding a new auth field elsewhere in the codebase? Add the
|
|
26
|
+
# name here.
|
|
27
|
+
SECRET_FIELDS: frozenset[str] = frozenset(
|
|
28
|
+
{
|
|
29
|
+
"password",
|
|
30
|
+
"passwd",
|
|
31
|
+
"secret",
|
|
32
|
+
"token",
|
|
33
|
+
"api_key",
|
|
34
|
+
"apikey",
|
|
35
|
+
"access_key",
|
|
36
|
+
"access_token",
|
|
37
|
+
"private_key",
|
|
38
|
+
"client_secret",
|
|
39
|
+
"auth",
|
|
40
|
+
"authorization",
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def source_identity(
|
|
46
|
+
source: str | dict[str, Any] | None,
|
|
47
|
+
) -> str | dict[str, Any] | None:
|
|
48
|
+
"""Reduce a source reference to its identity for cache hashing.
|
|
49
|
+
|
|
50
|
+
String names and ``None`` pass through unchanged — they carry no
|
|
51
|
+
secrets and the caller hashes them as-is. Dict configs (from inline
|
|
52
|
+
YAML or resolved from `face.sources`) have every secret-shaped field
|
|
53
|
+
dropped, so passwords never reach cache table names or hash inputs.
|
|
54
|
+
Identity-bearing fields (user, host, project, dataset, keyfile, etc.)
|
|
55
|
+
are preserved so two users with the same source name but different
|
|
56
|
+
credentials get distinct cache entries.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
source: ``str`` name reference, ``dict`` config, or ``None``.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Same type, with secrets stripped from dicts.
|
|
63
|
+
"""
|
|
64
|
+
if source is None or isinstance(source, str):
|
|
65
|
+
return source
|
|
66
|
+
return {k: v for k, v in source.items() if k.lower() not in SECRET_FIELDS}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Shared dbt Jinja detection patterns.
|
|
2
|
+
|
|
3
|
+
Single source of truth for identifying SQL that contains dbt-specific
|
|
4
|
+
Jinja calls (ref(), source()). Used by both DbtAdapter and SqlAdapter
|
|
5
|
+
to route queries correctly.
|
|
6
|
+
|
|
7
|
+
The patterns handle:
|
|
8
|
+
- Standard spacing: {{ ref( and {{ source(
|
|
9
|
+
- No spacing: {{ref( and {{source(
|
|
10
|
+
- Whitespace trim: {{- ref( and {{- source(
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
|
|
15
|
+
_DBT_REF_RE = re.compile(r"\{\{-?\s*ref\(")
|
|
16
|
+
_DBT_SOURCE_RE = re.compile(r"\{\{-?\s*source\(")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def has_dbt_jinja(sql: str) -> bool:
|
|
20
|
+
"""Return True if sql contains a dbt ref() or source() Jinja call."""
|
|
21
|
+
return bool(_DBT_REF_RE.search(sql) or _DBT_SOURCE_RE.search(sql))
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""SQL dialect registry for database-specific behavior.
|
|
2
|
+
|
|
3
|
+
This module provides a registry of SQL dialects for different database backends.
|
|
4
|
+
Use get_dialect() to obtain the appropriate dialect instance for a given
|
|
5
|
+
database profile type.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from dataface.core.execute.dialects import get_dialect
|
|
9
|
+
>>> dialect = get_dialect('postgres')
|
|
10
|
+
>>> dialect.param(1)
|
|
11
|
+
'$1'
|
|
12
|
+
>>> dialect = get_dialect('mysql')
|
|
13
|
+
>>> dialect.param(1)
|
|
14
|
+
'%s'
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from dataface.core.execute.dialects.athena import AthenaDialect
|
|
18
|
+
from dataface.core.execute.dialects.base import VALID_OPERATORS, SQLDialect
|
|
19
|
+
from dataface.core.execute.dialects.bigquery import BigQueryDialect
|
|
20
|
+
from dataface.core.execute.dialects.databricks import DatabricksDialect
|
|
21
|
+
from dataface.core.execute.dialects.duckdb import DuckDBDialect
|
|
22
|
+
from dataface.core.execute.dialects.mysql import MySQLDialect
|
|
23
|
+
from dataface.core.execute.dialects.postgres import PostgresDialect
|
|
24
|
+
from dataface.core.execute.dialects.redshift import RedshiftDialect
|
|
25
|
+
from dataface.core.execute.dialects.snowflake import SnowflakeDialect
|
|
26
|
+
from dataface.core.execute.dialects.sqlserver import SQLServerDialect
|
|
27
|
+
|
|
28
|
+
# Singleton instances for each dialect
|
|
29
|
+
_postgres_dialect = PostgresDialect()
|
|
30
|
+
_duckdb_dialect = DuckDBDialect()
|
|
31
|
+
_mysql_dialect = MySQLDialect()
|
|
32
|
+
_snowflake_dialect = SnowflakeDialect()
|
|
33
|
+
_bigquery_dialect = BigQueryDialect()
|
|
34
|
+
_redshift_dialect = RedshiftDialect()
|
|
35
|
+
_sqlserver_dialect = SQLServerDialect()
|
|
36
|
+
_databricks_dialect = DatabricksDialect()
|
|
37
|
+
_athena_dialect = AthenaDialect()
|
|
38
|
+
|
|
39
|
+
# Registry mapping profile types to dialect instances
|
|
40
|
+
DIALECTS: dict[str, SQLDialect] = {
|
|
41
|
+
# PostgreSQL (default)
|
|
42
|
+
"postgres": _postgres_dialect,
|
|
43
|
+
"postgresql": _postgres_dialect,
|
|
44
|
+
# DuckDB
|
|
45
|
+
"duckdb": _duckdb_dialect,
|
|
46
|
+
# MySQL / MariaDB
|
|
47
|
+
"mysql": _mysql_dialect,
|
|
48
|
+
"mariadb": _mysql_dialect,
|
|
49
|
+
# Snowflake
|
|
50
|
+
"snowflake": _snowflake_dialect,
|
|
51
|
+
# BigQuery
|
|
52
|
+
"bigquery": _bigquery_dialect,
|
|
53
|
+
# Redshift
|
|
54
|
+
"redshift": _redshift_dialect,
|
|
55
|
+
# SQL Server
|
|
56
|
+
"sqlserver": _sqlserver_dialect,
|
|
57
|
+
"mssql": _sqlserver_dialect,
|
|
58
|
+
# Databricks
|
|
59
|
+
"databricks": _databricks_dialect,
|
|
60
|
+
"spark": _databricks_dialect,
|
|
61
|
+
# Athena
|
|
62
|
+
"athena": _athena_dialect,
|
|
63
|
+
"presto": _athena_dialect,
|
|
64
|
+
"trino": _athena_dialect,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Default dialect when profile type is unknown
|
|
68
|
+
DEFAULT_DIALECT = _postgres_dialect
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_dialect(profile_type: str) -> SQLDialect:
|
|
72
|
+
"""Get the appropriate SQL dialect for a database profile type.
|
|
73
|
+
|
|
74
|
+
Returns a singleton dialect instance for the given profile type.
|
|
75
|
+
Falls back to PostgreSQL dialect for unknown types.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
profile_type: Database type string (e.g., 'postgres', 'mysql', 'snowflake')
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
SQLDialect instance for the specified database type
|
|
82
|
+
|
|
83
|
+
Example:
|
|
84
|
+
>>> dialect = get_dialect('postgres')
|
|
85
|
+
>>> dialect.param(1)
|
|
86
|
+
'$1'
|
|
87
|
+
>>> dialect = get_dialect('unknown') # Falls back to PostgreSQL
|
|
88
|
+
>>> dialect.name
|
|
89
|
+
'postgres'
|
|
90
|
+
"""
|
|
91
|
+
return DIALECTS.get(profile_type.lower(), DEFAULT_DIALECT)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def list_dialects() -> list[str]:
|
|
95
|
+
"""List all supported dialect profile types.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
List of profile type strings that are supported.
|
|
99
|
+
"""
|
|
100
|
+
return sorted(set(DIALECTS.keys()))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
__all__ = [
|
|
104
|
+
# Base class and constants
|
|
105
|
+
"SQLDialect",
|
|
106
|
+
"VALID_OPERATORS",
|
|
107
|
+
# Dialect implementations
|
|
108
|
+
"PostgresDialect",
|
|
109
|
+
"DuckDBDialect",
|
|
110
|
+
"MySQLDialect",
|
|
111
|
+
"SnowflakeDialect",
|
|
112
|
+
"BigQueryDialect",
|
|
113
|
+
"RedshiftDialect",
|
|
114
|
+
"SQLServerDialect",
|
|
115
|
+
"DatabricksDialect",
|
|
116
|
+
"AthenaDialect",
|
|
117
|
+
# Registry
|
|
118
|
+
"DIALECTS",
|
|
119
|
+
"get_dialect",
|
|
120
|
+
"list_dialects",
|
|
121
|
+
]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Athena dialect implementation.
|
|
2
|
+
|
|
3
|
+
Athena uses:
|
|
4
|
+
- ? for positional parameters
|
|
5
|
+
- NO temp table support (raises NotImplementedError)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataface.core.execute.dialects.base import SQLDialect
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AthenaDialect(SQLDialect):
|
|
12
|
+
"""Athena dialect with ? parameter style and no temp table support.
|
|
13
|
+
|
|
14
|
+
AWS Athena is based on Presto/Trino and does not support temporary tables.
|
|
15
|
+
Calling temp_table() will raise NotImplementedError.
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
>>> dialect = AthenaDialect()
|
|
19
|
+
>>> dialect.param()
|
|
20
|
+
'?'
|
|
21
|
+
>>> dialect.supports_temp_tables
|
|
22
|
+
False
|
|
23
|
+
>>> dialect.filter('category', '=', 1)
|
|
24
|
+
'category = ?'
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
name = "athena"
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def supports_temp_tables(self) -> bool:
|
|
31
|
+
"""Athena does not support temporary tables.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Always False for Athena.
|
|
35
|
+
"""
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
def param(self, index: int) -> str:
|
|
39
|
+
"""Generate Athena parameter placeholder.
|
|
40
|
+
|
|
41
|
+
Athena uses ? for positional parameters.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
index: 1-based parameter index (ignored for positional)
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Parameter placeholder '?'
|
|
48
|
+
"""
|
|
49
|
+
return "?"
|
|
50
|
+
|
|
51
|
+
def temp_table(self, name: str, sql: str) -> str:
|
|
52
|
+
"""Athena does not support temporary tables.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
name: Name of the temporary table
|
|
56
|
+
sql: SQL query to populate the table
|
|
57
|
+
|
|
58
|
+
Raises:
|
|
59
|
+
NotImplementedError: Always, as Athena doesn't support temp tables
|
|
60
|
+
"""
|
|
61
|
+
raise NotImplementedError(
|
|
62
|
+
"Athena does not support temporary tables. "
|
|
63
|
+
"Consider using CTEs or materializing to S3."
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def drop_temp_table(self, name: str) -> str:
|
|
67
|
+
"""Athena does not support temporary tables.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
name: Name of the temporary table
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
NotImplementedError: Always, as Athena doesn't support temp tables
|
|
74
|
+
"""
|
|
75
|
+
raise NotImplementedError("Athena does not support temporary tables.")
|