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,40 @@
|
|
|
1
|
+
"""PDF format conversion.
|
|
2
|
+
|
|
3
|
+
Stage: RENDER
|
|
4
|
+
Purpose: Convert SVG output to PDF using vl-convert.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataface.core.render.errors import FormatError
|
|
8
|
+
from dataface.core.render.font_support import (
|
|
9
|
+
normalize_svg_font_families_for_vl_convert,
|
|
10
|
+
register_vl_convert_fonts,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def to_pdf(svg_content: str) -> bytes:
|
|
15
|
+
"""Convert SVG to PDF using vl-convert.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
svg_content: SVG string to convert
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
PDF document as bytes
|
|
22
|
+
|
|
23
|
+
Raises:
|
|
24
|
+
FormatError: If conversion fails or dependencies missing
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
import vl_convert as vlc
|
|
28
|
+
|
|
29
|
+
register_vl_convert_fonts(vlc)
|
|
30
|
+
normalized_svg = normalize_svg_font_families_for_vl_convert(svg_content)
|
|
31
|
+
return vlc.svg_to_pdf(normalized_svg)
|
|
32
|
+
except ImportError:
|
|
33
|
+
raise FormatError(
|
|
34
|
+
"PDF export requires vl-convert-python: pip install vl-convert-python",
|
|
35
|
+
"pdf",
|
|
36
|
+
) from None
|
|
37
|
+
except FormatError:
|
|
38
|
+
raise
|
|
39
|
+
except Exception as e:
|
|
40
|
+
raise FormatError(f"PDF conversion failed: {e}", "pdf") from e
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""PNG format conversion.
|
|
2
|
+
|
|
3
|
+
Stage: RENDER
|
|
4
|
+
Purpose: Convert SVG output to PNG using vl-convert.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataface.core.render.errors import FormatError
|
|
8
|
+
from dataface.core.render.font_support import (
|
|
9
|
+
normalize_svg_font_families_for_vl_convert,
|
|
10
|
+
register_vl_convert_fonts,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def to_png(svg_content: str, scale: float = 1.0) -> bytes:
|
|
15
|
+
"""Convert SVG to PNG using vl-convert.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
svg_content: SVG string to convert
|
|
19
|
+
scale: Scale factor for the output image
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
PNG image as bytes
|
|
23
|
+
|
|
24
|
+
Raises:
|
|
25
|
+
FormatError: If conversion fails or dependencies missing
|
|
26
|
+
"""
|
|
27
|
+
try:
|
|
28
|
+
import vl_convert as vlc
|
|
29
|
+
|
|
30
|
+
register_vl_convert_fonts(vlc)
|
|
31
|
+
normalized_svg = normalize_svg_font_families_for_vl_convert(svg_content)
|
|
32
|
+
return vlc.svg_to_png(normalized_svg, scale=scale)
|
|
33
|
+
except ImportError:
|
|
34
|
+
raise FormatError(
|
|
35
|
+
"PNG export requires vl-convert-python: pip install vl-convert-python",
|
|
36
|
+
"png",
|
|
37
|
+
) from None
|
|
38
|
+
except FormatError:
|
|
39
|
+
raise
|
|
40
|
+
except Exception as e:
|
|
41
|
+
raise FormatError(f"PNG conversion failed: {e}", "png") from e
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Rendering error types.
|
|
2
|
+
|
|
3
|
+
Stage: RENDER
|
|
4
|
+
Purpose: Define error types for rendering failures.
|
|
5
|
+
|
|
6
|
+
These errors are raised during:
|
|
7
|
+
- General rendering failures (RenderError)
|
|
8
|
+
- Format conversion (FormatError)
|
|
9
|
+
- Pre-render required-variable validation (MissingRequiredVariablesError)
|
|
10
|
+
|
|
11
|
+
All errors inherit from RenderError → DatafaceError for easy catching.
|
|
12
|
+
|
|
13
|
+
Note: Many render errors are displayed IN the output rather than thrown,
|
|
14
|
+
so users see helpful error messages in the rendered dataface.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from dataface.core.compile.errors import DatafaceError
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class RenderError(DatafaceError):
|
|
24
|
+
"""Base error for all rendering failures.
|
|
25
|
+
|
|
26
|
+
This is the parent class for all rendering-related errors.
|
|
27
|
+
Catch this to handle any rendering error.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
message: Human-readable error description
|
|
31
|
+
element: Element that failed to render (if applicable)
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# Class-level None default so `from_code`-constructed instances (which
|
|
35
|
+
# bypass __init__) still satisfy `e.element` access.
|
|
36
|
+
element: str | None = None
|
|
37
|
+
|
|
38
|
+
def __init__(self, message: str, element: str | None = None):
|
|
39
|
+
self.message = message
|
|
40
|
+
self.element = element
|
|
41
|
+
self.fields: dict[str, Any] = {}
|
|
42
|
+
super().__init__(self._format_message())
|
|
43
|
+
if self.code is None:
|
|
44
|
+
from dataface.core.errors.codes_unknown import DF_UNKNOWN_INTERNAL
|
|
45
|
+
|
|
46
|
+
self.code = DF_UNKNOWN_INTERNAL
|
|
47
|
+
|
|
48
|
+
def _format_message(self) -> str:
|
|
49
|
+
"""Format error message with optional element."""
|
|
50
|
+
if self.element:
|
|
51
|
+
return f"{self.message} (element: {self.element})"
|
|
52
|
+
return self.message
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ChartDataError(RenderError):
|
|
56
|
+
"""Chart received data that doesn't match its requirements.
|
|
57
|
+
|
|
58
|
+
Raised when:
|
|
59
|
+
- KPI chart receives more than 1 row
|
|
60
|
+
- Chart references a column not present in the data
|
|
61
|
+
- Data shape doesn't match chart type expectations
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
chart_id: str | None = None
|
|
65
|
+
|
|
66
|
+
def __init__(self, message: str, chart_id: str | None = None):
|
|
67
|
+
self.chart_id = chart_id
|
|
68
|
+
super().__init__(message, chart_id)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class UnknownChartType(RenderError):
|
|
72
|
+
"""Render dispatch received a chart type not in the known registry.
|
|
73
|
+
|
|
74
|
+
Raised by both the top-level dispatch and the mark-lookup layer so
|
|
75
|
+
the caller sees a structured error rather than a bare ValueError.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
chart_type: str | None = None
|
|
79
|
+
|
|
80
|
+
def __init__(self, chart_type: str):
|
|
81
|
+
self.chart_type = chart_type
|
|
82
|
+
super().__init__(f"Unknown chart type: {chart_type!r}", chart_type)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class FormatError(RenderError):
|
|
86
|
+
"""Error during format conversion.
|
|
87
|
+
|
|
88
|
+
Raised when:
|
|
89
|
+
- Unknown format requested
|
|
90
|
+
- SVG to PNG/PDF conversion fails
|
|
91
|
+
- HTML template error
|
|
92
|
+
|
|
93
|
+
Example:
|
|
94
|
+
>>> try:
|
|
95
|
+
... render(face, executor, format="unknown")
|
|
96
|
+
... except FormatError as e:
|
|
97
|
+
... print(f"Format error: {e}")
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
format: str | None = None
|
|
101
|
+
|
|
102
|
+
def __init__(self, message: str, format: str | None = None):
|
|
103
|
+
self.format = format
|
|
104
|
+
super().__init__(f"Format conversion failed: {message}", format)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass
|
|
108
|
+
class MissingVariable:
|
|
109
|
+
"""Metadata for a single required variable that was not provided at render time."""
|
|
110
|
+
|
|
111
|
+
key: str
|
|
112
|
+
label: str | None
|
|
113
|
+
description: str | None
|
|
114
|
+
input_type: str | None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class MissingRequiredVariablesError(RenderError):
|
|
118
|
+
"""Raised before any query executes when required variables have no value.
|
|
119
|
+
|
|
120
|
+
Carries a structured list so callers can render a blocking prompt
|
|
121
|
+
without parsing the error message. Inherits from ``RenderError`` so
|
|
122
|
+
existing ``except RenderError`` handlers (markdown integration, activity
|
|
123
|
+
dashboards, etc.) degrade to a string error block; surfaces that need
|
|
124
|
+
the structured ``missing`` list catch it explicitly first.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
def __init__(self, missing: list[MissingVariable]) -> None:
|
|
128
|
+
self.missing = missing
|
|
129
|
+
descriptions = ", ".join(
|
|
130
|
+
f"{mv.key} ({mv.label})" if mv.label else mv.key for mv in missing
|
|
131
|
+
)
|
|
132
|
+
super().__init__(f"Missing required variables: {descriptions}")
|
|
133
|
+
# Populate fields so to_structured() carries per-variable metadata.
|
|
134
|
+
self.fields = {
|
|
135
|
+
"missing": [
|
|
136
|
+
{
|
|
137
|
+
"key": mv.key,
|
|
138
|
+
"label": mv.label,
|
|
139
|
+
"description": mv.description,
|
|
140
|
+
"input_type": mv.input_type,
|
|
141
|
+
}
|
|
142
|
+
for mv in missing
|
|
143
|
+
]
|
|
144
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Face rendering API for external integrations.
|
|
2
|
+
|
|
3
|
+
Exposes ``render_face`` (file-oriented public API) and
|
|
4
|
+
``compile_and_render`` (shared compile → execute → render pipeline).
|
|
5
|
+
|
|
6
|
+
External integrations should use ``render_face``. The CLI uses
|
|
7
|
+
``compile_and_render`` directly for stdin input where no file is involved.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from dataface.core.compile import compile
|
|
14
|
+
from dataface.core.compile.markdown import is_markdown_face, markdown_to_yaml
|
|
15
|
+
from dataface.core.execute import Executor
|
|
16
|
+
from dataface.core.execute.adapters import build_adapter_registry
|
|
17
|
+
from dataface.core.execute.duckdb_cache import open_cache_from_env
|
|
18
|
+
from dataface.core.project_roots import (
|
|
19
|
+
discover_render_context,
|
|
20
|
+
discovery_boundary_for_face,
|
|
21
|
+
)
|
|
22
|
+
from dataface.core.render.renderer import render
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def compile_and_render(
|
|
26
|
+
yaml_content: str,
|
|
27
|
+
project_root: Path,
|
|
28
|
+
dbt_project_path: Path | None,
|
|
29
|
+
base_dir: Path | None = None,
|
|
30
|
+
format: str = "svg",
|
|
31
|
+
variables: dict[str, str] | None = None,
|
|
32
|
+
use_cache: bool = True,
|
|
33
|
+
**options: Any,
|
|
34
|
+
) -> str | bytes:
|
|
35
|
+
"""Compile YAML, build an executor, and render.
|
|
36
|
+
|
|
37
|
+
This is the shared pipeline that both ``render_face`` and the CLI
|
|
38
|
+
``render_command`` call. External integrations should prefer
|
|
39
|
+
``render_face`` which adds file I/O and project discovery on top.
|
|
40
|
+
|
|
41
|
+
Raises:
|
|
42
|
+
ValueError: On compilation errors.
|
|
43
|
+
RenderError: On rendering or format conversion failures.
|
|
44
|
+
"""
|
|
45
|
+
result = compile(
|
|
46
|
+
yaml_content,
|
|
47
|
+
base_dir=base_dir or project_root,
|
|
48
|
+
project_dir=project_root,
|
|
49
|
+
)
|
|
50
|
+
if result.errors:
|
|
51
|
+
errors_str = "\n ".join(e.message for e in result.errors)
|
|
52
|
+
raise ValueError(f"Compilation errors:\n {errors_str}")
|
|
53
|
+
if not result.face:
|
|
54
|
+
raise ValueError("Compilation produced no face")
|
|
55
|
+
|
|
56
|
+
adapter_registry = build_adapter_registry(
|
|
57
|
+
project_root,
|
|
58
|
+
read_only=True,
|
|
59
|
+
dbt_project_path=dbt_project_path,
|
|
60
|
+
)
|
|
61
|
+
cache = open_cache_from_env()
|
|
62
|
+
try:
|
|
63
|
+
executor = Executor(
|
|
64
|
+
result.face,
|
|
65
|
+
adapter_registry=adapter_registry,
|
|
66
|
+
query_registry=result.query_registry,
|
|
67
|
+
use_cache=use_cache,
|
|
68
|
+
duckdb_cache=cache,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
output = render(
|
|
72
|
+
result.face,
|
|
73
|
+
executor,
|
|
74
|
+
format=format,
|
|
75
|
+
variables=variables or {},
|
|
76
|
+
**options,
|
|
77
|
+
).output
|
|
78
|
+
if output is None:
|
|
79
|
+
raise ValueError("Render produced no output")
|
|
80
|
+
return output
|
|
81
|
+
finally:
|
|
82
|
+
adapter_registry.close()
|
|
83
|
+
if cache is not None:
|
|
84
|
+
cache.close()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def render_face(
|
|
88
|
+
face_path: str | Path,
|
|
89
|
+
format: str = "svg",
|
|
90
|
+
project_dir: str | Path | None = None,
|
|
91
|
+
base_dir: str | Path | None = None,
|
|
92
|
+
variables: dict[str, str] | None = None,
|
|
93
|
+
use_cache: bool = True,
|
|
94
|
+
**options: Any,
|
|
95
|
+
) -> str | bytes:
|
|
96
|
+
"""Render a Dataface face file to an embeddable output.
|
|
97
|
+
|
|
98
|
+
This is the public API that external integrations (MkDocs plugin,
|
|
99
|
+
Sphinx directive, etc.) should call. It handles the full
|
|
100
|
+
compile → execute → render pipeline and returns the rendered output.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
face_path: Path to a ``.yml`` or ``.md`` face file.
|
|
104
|
+
format: Output format — ``"svg"`` (default), ``"html"``, ``"png"``, ``"pdf"``.
|
|
105
|
+
project_dir: Override project root for resolving project-level data paths.
|
|
106
|
+
When ``None``, discovery walks up from the face file.
|
|
107
|
+
base_dir: Override the base directory for resolving relative file references
|
|
108
|
+
inside the face content. Defaults to the face file's parent directory.
|
|
109
|
+
variables: Variable values to pass into the render.
|
|
110
|
+
use_cache: Whether to use cached query results. False bypasses all caches.
|
|
111
|
+
**options: Passed through to the renderer (e.g. ``background``, ``scale``).
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Rendered content — ``str`` for svg/html, ``bytes`` for png/pdf.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
FileNotFoundError: If *face_path* does not exist.
|
|
118
|
+
ValueError: On compilation errors.
|
|
119
|
+
RenderError: On chart data or rendering failures.
|
|
120
|
+
"""
|
|
121
|
+
face_file = Path(face_path).resolve()
|
|
122
|
+
if not face_file.exists():
|
|
123
|
+
raise FileNotFoundError(f"Face file not found: {face_file}")
|
|
124
|
+
|
|
125
|
+
# Read and optionally transform markdown → YAML
|
|
126
|
+
raw = face_file.read_text(encoding="utf-8")
|
|
127
|
+
if face_file.suffix.lower() == ".md":
|
|
128
|
+
if not is_markdown_face(face_file):
|
|
129
|
+
raise ValueError(
|
|
130
|
+
"Not a Dataface face file: .md files require YAML frontmatter "
|
|
131
|
+
"with at least one of: queries, charts, variables, source, sources"
|
|
132
|
+
)
|
|
133
|
+
yaml_content = markdown_to_yaml(raw)
|
|
134
|
+
else:
|
|
135
|
+
yaml_content = raw
|
|
136
|
+
|
|
137
|
+
# Discovery always runs to find dbt_project_path (needed for SQL adapter).
|
|
138
|
+
# When project_dir is explicitly set, we override project_root but keep
|
|
139
|
+
# the discovered dbt_project_path.
|
|
140
|
+
project_root, dbt_project_path = discover_render_context(
|
|
141
|
+
face_file.parent,
|
|
142
|
+
discovery_boundary_for_face(
|
|
143
|
+
face_file.parent,
|
|
144
|
+
str(project_dir) if project_dir else None,
|
|
145
|
+
),
|
|
146
|
+
)
|
|
147
|
+
if project_dir:
|
|
148
|
+
project_root = Path(project_dir).resolve()
|
|
149
|
+
resolved_base_dir = Path(base_dir).resolve() if base_dir else face_file.parent
|
|
150
|
+
|
|
151
|
+
return compile_and_render(
|
|
152
|
+
yaml_content,
|
|
153
|
+
project_root=project_root,
|
|
154
|
+
dbt_project_path=dbt_project_path,
|
|
155
|
+
base_dir=resolved_base_dir,
|
|
156
|
+
format=format,
|
|
157
|
+
variables=variables,
|
|
158
|
+
use_cache=use_cache,
|
|
159
|
+
**options,
|
|
160
|
+
)
|