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,398 @@
|
|
|
1
|
+
"""Compiled chart types: Chart, ChartDependencies, is_chart.
|
|
2
|
+
|
|
3
|
+
Stage: COMPILE (Output)
|
|
4
|
+
Purpose: Define the compiled Chart type (output of compilation, input to execute/render)
|
|
5
|
+
and its dependency tracker.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Any, TypeGuard
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
14
|
+
|
|
15
|
+
from dataface.core.compile.custom_chart_types import BUILTIN_CHART_TYPE_VALUES
|
|
16
|
+
from dataface.core.compile.models.chart.authored import (
|
|
17
|
+
ChartDataTable,
|
|
18
|
+
ChartLabels,
|
|
19
|
+
ChartSort,
|
|
20
|
+
ChartTotal,
|
|
21
|
+
FieldConditionalFormatting,
|
|
22
|
+
FilterDef,
|
|
23
|
+
KpiSupportConfig,
|
|
24
|
+
Layer,
|
|
25
|
+
)
|
|
26
|
+
from dataface.core.compile.models.primitives import FormatConfig
|
|
27
|
+
from dataface.core.compile.models.query.compiled import AnyQuery
|
|
28
|
+
from dataface.core.compile.models.style.authored import ChartStylePatch
|
|
29
|
+
from dataface.core.compile.models.vega_lite.contracts import Projection
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# CHART TYPE SETS
|
|
33
|
+
# ============================================================================
|
|
34
|
+
|
|
35
|
+
# SVG-family chart types that use hand-crafted SVG renderers instead of Vega-Lite.
|
|
36
|
+
# Used for renderer-family classification and to exclude these types from:
|
|
37
|
+
# - aspect-ratio-driven sizing (they don't use width/aspect_ratio for height)
|
|
38
|
+
# - Vega render-first sizing (not Vega charts)
|
|
39
|
+
# - cols height alignment re-renders (non-Vega, don't benefit from re-render)
|
|
40
|
+
# Each renderer owns its own sizing contract — there is no shared fixed height for this group.
|
|
41
|
+
NON_ASPECT_RATIO_TYPES = frozenset({"table", "kpi", "spark_bar", "callout"})
|
|
42
|
+
SVG_LAYOUT_PADDED_TYPES = frozenset({"table", "kpi", "spark_bar"})
|
|
43
|
+
|
|
44
|
+
# ============================================================================
|
|
45
|
+
# DEPENDENCY TRACKING
|
|
46
|
+
# ============================================================================
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class ChartDependencies:
|
|
51
|
+
"""Dependencies required by a chart for rendering.
|
|
52
|
+
|
|
53
|
+
Tracks all sources, variables, and queries that a chart needs.
|
|
54
|
+
Used for extracting minimal preview faces.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
sources: frozenset[str] = field(default_factory=frozenset)
|
|
58
|
+
variables: frozenset[str] = field(default_factory=frozenset)
|
|
59
|
+
queries: frozenset[str] = field(default_factory=frozenset)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# ============================================================================
|
|
63
|
+
# COMPILED CHART
|
|
64
|
+
# ============================================================================
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class Chart(BaseModel):
|
|
68
|
+
"""Compiled chart ready for execution and rendering.
|
|
69
|
+
|
|
70
|
+
All data-mapping, geo, interaction, and compiled-specific fields
|
|
71
|
+
declared directly on this model (no shared base with authored patches).
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
model_config = ConfigDict(extra="forbid")
|
|
75
|
+
|
|
76
|
+
# --- Identity ---
|
|
77
|
+
id: str = Field(description="Unique identifier within the dashboard.")
|
|
78
|
+
query: AnyQuery | None = Field(
|
|
79
|
+
default=None,
|
|
80
|
+
description="Resolved query object (SqlQuery, CsvQuery, etc.). None for blank/placeholder charts.",
|
|
81
|
+
)
|
|
82
|
+
query_name: str | None = Field(
|
|
83
|
+
default=None,
|
|
84
|
+
description="String name for executor lookup. None for blank/placeholder charts.",
|
|
85
|
+
)
|
|
86
|
+
type: str = Field(description="Chart type (line, bar, table, kpi, etc.).")
|
|
87
|
+
|
|
88
|
+
@field_validator("type", mode="before")
|
|
89
|
+
@classmethod
|
|
90
|
+
def _validate_chart_type(cls, v: object) -> str:
|
|
91
|
+
from dataface.core.compile.custom_chart_types import (
|
|
92
|
+
_NAME_RE as _CHART_CUSTOM_NAME_RE,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if not isinstance(v, str):
|
|
96
|
+
raise ValueError(f"chart type must be a string, got {type(v).__name__}")
|
|
97
|
+
if v in BUILTIN_CHART_TYPE_VALUES:
|
|
98
|
+
return v
|
|
99
|
+
if _CHART_CUSTOM_NAME_RE.match(v): # custom chart type name
|
|
100
|
+
return v
|
|
101
|
+
raise ValueError(
|
|
102
|
+
f"Unknown chart type {v!r}. Must be a known chart type or a valid "
|
|
103
|
+
f"custom type name (lowercase letters, digits, and underscores)."
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
title: str = Field(
|
|
107
|
+
default="", description="Display title. Empty string if not provided."
|
|
108
|
+
)
|
|
109
|
+
subtitle: str = Field(
|
|
110
|
+
default="", description="Secondary title line. Empty string if not provided."
|
|
111
|
+
)
|
|
112
|
+
description: str = Field(
|
|
113
|
+
default="", description="Description text. Empty string if not provided."
|
|
114
|
+
)
|
|
115
|
+
label: str = Field(
|
|
116
|
+
default="",
|
|
117
|
+
description="KPI label rendered above the headline value. Empty for non-KPI.",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Styling — typed chart-local style patch
|
|
121
|
+
style: ChartStylePatch | None = Field(
|
|
122
|
+
default=None,
|
|
123
|
+
description="Chart-local style patch (orientation, columns, spark-bar overrides, etc.).",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Variable dependencies - computed during normalization
|
|
127
|
+
variable_dependencies: set[str] = Field(
|
|
128
|
+
default_factory=set,
|
|
129
|
+
description="Variable names this chart depends on (from title, filters, query SQL).",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Source location in YAML for edit-back support
|
|
133
|
+
source_path: str | None = Field(
|
|
134
|
+
default=None,
|
|
135
|
+
description="YAML path for edit-back support (e.g., 'charts.revenue', 'rows[0]').",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Whether the query is inline (defined in chart) vs named (reference)
|
|
139
|
+
query_is_inline: bool = Field(
|
|
140
|
+
default=False,
|
|
141
|
+
description="True if query is defined inline in chart; False if it's a named reference.",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# --- Data mapping fields ---
|
|
145
|
+
x: str | None = Field(
|
|
146
|
+
default=None, description="X-axis field name from the query result."
|
|
147
|
+
)
|
|
148
|
+
y: str | list[str] | None = Field(
|
|
149
|
+
default=None,
|
|
150
|
+
description="Y-axis field name(s). Accepts a single field or list for multi-series charts.",
|
|
151
|
+
)
|
|
152
|
+
color: str | None = Field(
|
|
153
|
+
default=None, description="Color data channel: bare field name only."
|
|
154
|
+
)
|
|
155
|
+
size: str | None = Field(
|
|
156
|
+
default=None,
|
|
157
|
+
description="Field used to size-encode data points (quantitative).",
|
|
158
|
+
)
|
|
159
|
+
shape: str | None = Field(
|
|
160
|
+
default=None,
|
|
161
|
+
description="Field used to shape-encode data points (categorical).",
|
|
162
|
+
)
|
|
163
|
+
theta: str | None = Field(
|
|
164
|
+
default=None, description="Field for angular encoding in pie (arc) charts."
|
|
165
|
+
)
|
|
166
|
+
total: ChartTotal | None = Field(
|
|
167
|
+
default=None, description="Donut center total config."
|
|
168
|
+
)
|
|
169
|
+
labels: ChartLabels | None = Field(
|
|
170
|
+
default=None, description="Per-row text annotations near each data anchor."
|
|
171
|
+
)
|
|
172
|
+
x_label: str | None = Field(
|
|
173
|
+
default=None, description="Custom label for the X axis."
|
|
174
|
+
)
|
|
175
|
+
y_label: str | None = Field(
|
|
176
|
+
default=None, description="Custom label for the Y axis."
|
|
177
|
+
)
|
|
178
|
+
format: str | FormatConfig | None = Field(
|
|
179
|
+
default=None,
|
|
180
|
+
description="Number format: D3 format string, preset name, or FormatConfig object.",
|
|
181
|
+
)
|
|
182
|
+
message: str | None = Field(
|
|
183
|
+
default=None,
|
|
184
|
+
description="Static error message content for explicit error charts.",
|
|
185
|
+
)
|
|
186
|
+
geo: str | dict[str, Any] | None = Field(
|
|
187
|
+
default=None,
|
|
188
|
+
description="GeoJSON field name or inline GeoJSON spec for geoshape charts.",
|
|
189
|
+
)
|
|
190
|
+
geo_source: str | None = Field(
|
|
191
|
+
default=None,
|
|
192
|
+
description="Named geographic data source for loading GeoJSON boundaries.",
|
|
193
|
+
)
|
|
194
|
+
lookup: str | None = Field(
|
|
195
|
+
default=None,
|
|
196
|
+
description="Data field to join against the geographic data (map join key).",
|
|
197
|
+
)
|
|
198
|
+
value: str | None = Field(
|
|
199
|
+
default=None,
|
|
200
|
+
description="For map: data field mapped to the fill color. For KPI: column reference for the headline number/text.",
|
|
201
|
+
)
|
|
202
|
+
support: KpiSupportConfig | None = Field(
|
|
203
|
+
default=None, description="Optional support line beneath the KPI value."
|
|
204
|
+
)
|
|
205
|
+
projection: str | Projection | None = Field(
|
|
206
|
+
default=None, description="Map projection name or Vega-Lite projection config."
|
|
207
|
+
)
|
|
208
|
+
latitude: str | None = Field(
|
|
209
|
+
default=None,
|
|
210
|
+
description="Field containing latitude values for point/bubble maps.",
|
|
211
|
+
)
|
|
212
|
+
longitude: str | None = Field(
|
|
213
|
+
default=None,
|
|
214
|
+
description="Field containing longitude values for point/bubble maps.",
|
|
215
|
+
)
|
|
216
|
+
basemap: dict[str, Any] | None = Field(
|
|
217
|
+
default=None,
|
|
218
|
+
description="Tile-layer configuration for point_map / bubble_map charts.",
|
|
219
|
+
)
|
|
220
|
+
sort: ChartSort | None = Field(
|
|
221
|
+
default=None,
|
|
222
|
+
description="Sort configuration: field to sort by and direction (asc/desc).",
|
|
223
|
+
)
|
|
224
|
+
stack: bool | str | None = Field(
|
|
225
|
+
default=None, description="Stack mode for marks that stack by default."
|
|
226
|
+
)
|
|
227
|
+
link: str | None = Field(
|
|
228
|
+
default=None, description="Click-through URL template for drill-down links."
|
|
229
|
+
)
|
|
230
|
+
filters: dict[str, FilterDef] | None = Field(
|
|
231
|
+
default=None,
|
|
232
|
+
description="Declarative column filters applied to chart data after query execution.",
|
|
233
|
+
)
|
|
234
|
+
layers: list[Layer] | None = Field(
|
|
235
|
+
default=None, description="Layers for multi-mark charts (layered type)."
|
|
236
|
+
)
|
|
237
|
+
x_domain: str | None = Field(
|
|
238
|
+
default=None,
|
|
239
|
+
description="Controls how x-values from multiple layer queries are combined on the shared x-axis.",
|
|
240
|
+
)
|
|
241
|
+
conditional_formatting: dict[str, FieldConditionalFormatting] | None = Field(
|
|
242
|
+
default=None,
|
|
243
|
+
description="Discrete rule-driven style overrides indexed by column name.",
|
|
244
|
+
)
|
|
245
|
+
data_table: ChartDataTable | None = Field(
|
|
246
|
+
default=None, description="Optional mini data-grid attached to the chart."
|
|
247
|
+
)
|
|
248
|
+
# Box geometry — set at chart root in the authored surface for cartesian charts.
|
|
249
|
+
# aspect_ratio, min_height, max_height are promoted from per-chart style during normalization.
|
|
250
|
+
height: int | float | None = Field(
|
|
251
|
+
default=None,
|
|
252
|
+
description="Explicit chart height in pixels. None defers to aspect_ratio or theme.",
|
|
253
|
+
)
|
|
254
|
+
width: int | float | None = Field(
|
|
255
|
+
default=None,
|
|
256
|
+
description=(
|
|
257
|
+
"Chart width hint in pixels. Feeds the label-overlap heuristic. "
|
|
258
|
+
"None falls back to the chart rendering config default_width."
|
|
259
|
+
),
|
|
260
|
+
)
|
|
261
|
+
aspect_ratio: float | None = Field(
|
|
262
|
+
default=None,
|
|
263
|
+
description="Chart aspect ratio (width / height). Used when height is not set. Promoted from per-chart style at compile time.",
|
|
264
|
+
)
|
|
265
|
+
min_height: float | None = Field(
|
|
266
|
+
default=None,
|
|
267
|
+
description=(
|
|
268
|
+
"Per-chart minimum height in pixels for aspect-ratio-derived sizing. "
|
|
269
|
+
"Overrides face/theme style.charts.min_height for this chart. "
|
|
270
|
+
"Has no effect when chart.height is set. Promoted from per-chart style at compile time."
|
|
271
|
+
),
|
|
272
|
+
)
|
|
273
|
+
max_height: float | None = Field(
|
|
274
|
+
default=None,
|
|
275
|
+
description=(
|
|
276
|
+
"Per-chart maximum height in pixels for aspect-ratio-derived sizing. "
|
|
277
|
+
"Overrides face/theme style.charts.max_height for this chart. "
|
|
278
|
+
"Has no effect when chart.height is set. Promoted from per-chart style at compile time."
|
|
279
|
+
),
|
|
280
|
+
)
|
|
281
|
+
warnings_ignore: list[str] = Field(
|
|
282
|
+
default_factory=list,
|
|
283
|
+
description="Codes of render warnings to suppress for this chart.",
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def to_dict(self) -> dict[str, Any]:
|
|
287
|
+
"""Convert chart to YAML-compatible dict."""
|
|
288
|
+
from dataface.core.render.chart.presentation import to_plain_dict
|
|
289
|
+
|
|
290
|
+
result: dict[str, Any] = {}
|
|
291
|
+
|
|
292
|
+
if self.title:
|
|
293
|
+
result["title"] = self.title
|
|
294
|
+
if self.label:
|
|
295
|
+
result["label"] = self.label
|
|
296
|
+
if self.type:
|
|
297
|
+
result["type"] = self.type
|
|
298
|
+
|
|
299
|
+
if self.query:
|
|
300
|
+
query_dict: dict[str, Any] = {}
|
|
301
|
+
if hasattr(self.query, "sql") and self.query.sql:
|
|
302
|
+
query_dict["sql"] = self.query.sql
|
|
303
|
+
if (
|
|
304
|
+
hasattr(self.query, "source")
|
|
305
|
+
and self.query.source
|
|
306
|
+
and isinstance(self.query.source, str)
|
|
307
|
+
):
|
|
308
|
+
query_dict["source"] = self.query.source
|
|
309
|
+
if hasattr(self.query, "file") and self.query.file:
|
|
310
|
+
query_dict["file"] = self.query.file
|
|
311
|
+
if query_dict:
|
|
312
|
+
result["query"] = query_dict
|
|
313
|
+
|
|
314
|
+
if self.x:
|
|
315
|
+
result["x"] = self.x
|
|
316
|
+
if self.y:
|
|
317
|
+
result["y"] = self.y
|
|
318
|
+
if self.color:
|
|
319
|
+
result["color"] = self.color
|
|
320
|
+
if self.size:
|
|
321
|
+
result["size"] = self.size
|
|
322
|
+
if self.shape:
|
|
323
|
+
result["shape"] = self.shape
|
|
324
|
+
if self.theta:
|
|
325
|
+
result["theta"] = self.theta
|
|
326
|
+
if self.format:
|
|
327
|
+
if hasattr(self.format, "model_dump"):
|
|
328
|
+
result["format"] = self.format.model_dump(exclude_none=True)
|
|
329
|
+
else:
|
|
330
|
+
result["format"] = self.format
|
|
331
|
+
if self.message:
|
|
332
|
+
result["message"] = self.message
|
|
333
|
+
|
|
334
|
+
if self.geo:
|
|
335
|
+
result["geo"] = self.geo
|
|
336
|
+
if self.geo_source:
|
|
337
|
+
result["geo_source"] = self.geo_source
|
|
338
|
+
if self.lookup:
|
|
339
|
+
result["lookup"] = self.lookup
|
|
340
|
+
if self.value is not None:
|
|
341
|
+
result["value"] = self.value
|
|
342
|
+
if self.support is not None:
|
|
343
|
+
result["support"] = self.support.model_dump(exclude_none=True)
|
|
344
|
+
if self.projection:
|
|
345
|
+
result["projection"] = (
|
|
346
|
+
self.projection
|
|
347
|
+
if isinstance(self.projection, str)
|
|
348
|
+
else to_plain_dict(self.projection)
|
|
349
|
+
)
|
|
350
|
+
if self.latitude:
|
|
351
|
+
result["latitude"] = self.latitude
|
|
352
|
+
if self.longitude:
|
|
353
|
+
result["longitude"] = self.longitude
|
|
354
|
+
if self.basemap:
|
|
355
|
+
result["basemap"] = self.basemap
|
|
356
|
+
if self.sort:
|
|
357
|
+
result["sort"] = self.sort.model_dump(exclude_none=True)
|
|
358
|
+
|
|
359
|
+
if self.style:
|
|
360
|
+
result["style"] = self.style.model_dump(exclude_none=True)
|
|
361
|
+
|
|
362
|
+
if self.link:
|
|
363
|
+
result["link"] = self.link
|
|
364
|
+
|
|
365
|
+
if self.filters:
|
|
366
|
+
result["filters"] = {
|
|
367
|
+
col: fd.to_yaml_form() for col, fd in self.filters.items()
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return result
|
|
371
|
+
|
|
372
|
+
def get_dependencies(self) -> ChartDependencies:
|
|
373
|
+
"""Get all dependencies required to render this chart."""
|
|
374
|
+
variables: set[str] = self.variable_dependencies.copy()
|
|
375
|
+
if self.query and hasattr(self.query, "variable_dependencies"):
|
|
376
|
+
variables |= self.query.variable_dependencies
|
|
377
|
+
|
|
378
|
+
sources: set[str] = set()
|
|
379
|
+
if self.query:
|
|
380
|
+
source = getattr(self.query, "source", None)
|
|
381
|
+
if isinstance(source, str):
|
|
382
|
+
sources.add(source)
|
|
383
|
+
|
|
384
|
+
return ChartDependencies(
|
|
385
|
+
sources=frozenset(sources),
|
|
386
|
+
variables=frozenset(variables),
|
|
387
|
+
queries=frozenset(),
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
# ============================================================================
|
|
392
|
+
# TYPE GUARD
|
|
393
|
+
# ============================================================================
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def is_chart(item: Any) -> TypeGuard[Chart]:
|
|
397
|
+
"""Type guard for Chart."""
|
|
398
|
+
return isinstance(item, Chart)
|