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,481 @@
|
|
|
1
|
+
"""Style authored models — all-Optional *Patch overlays for YAML authoring.
|
|
2
|
+
|
|
3
|
+
Patch classes are either:
|
|
4
|
+
- hand-written (class XxxPatch(BaseModel): ...)
|
|
5
|
+
- generated mechanically (XxxPatch = build_patch_model(XxxStyle))
|
|
6
|
+
|
|
7
|
+
Generated patches depend on their compiled counterparts imported from .compiled.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
15
|
+
|
|
16
|
+
from dataface.core.compile.models.factories import (
|
|
17
|
+
build_patch_model,
|
|
18
|
+
build_patch_model_ext,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Fields with cartesian/aspect-ratio sizing semantics — excluded from chart types
|
|
22
|
+
# that use a fixed sizing contract (kpi, table) to prevent silent no-ops.
|
|
23
|
+
_CHART_STYLE_SIZING: frozenset[str] = frozenset(
|
|
24
|
+
{"aspect_ratio", "min_height", "max_height"}
|
|
25
|
+
)
|
|
26
|
+
from dataface.core.compile.models.primitives import (
|
|
27
|
+
StyleColorConfig as StyleColorConfig,
|
|
28
|
+
)
|
|
29
|
+
from dataface.core.compile.models.style.compiled import (
|
|
30
|
+
AreaChartStyle,
|
|
31
|
+
AreaMarkStyle,
|
|
32
|
+
AxisDomainStyle,
|
|
33
|
+
AxisElementStyle,
|
|
34
|
+
AxisGridStyle,
|
|
35
|
+
AxisStylePatch as AxisStylePatch,
|
|
36
|
+
AxisTicksStyle,
|
|
37
|
+
BarChartStyle,
|
|
38
|
+
BarMarkStyle,
|
|
39
|
+
CalloutChartStyle,
|
|
40
|
+
DataTableStylePatch as DataTableStylePatch,
|
|
41
|
+
EndpointLabelsConfig,
|
|
42
|
+
GeoshapeChartStyle,
|
|
43
|
+
GlobalMarksStyle,
|
|
44
|
+
HeatmapChartStyle,
|
|
45
|
+
InferenceStyle,
|
|
46
|
+
KpiChartStyle,
|
|
47
|
+
LegendStyle,
|
|
48
|
+
LineChartStyle,
|
|
49
|
+
LineMarkStyle,
|
|
50
|
+
PaddingStyle,
|
|
51
|
+
PieChartStyle,
|
|
52
|
+
PointMapChartStyle,
|
|
53
|
+
PointMarkStyle,
|
|
54
|
+
RangeStylePatch as RangeStylePatch,
|
|
55
|
+
ScaleStyle,
|
|
56
|
+
ScatterChartStyle,
|
|
57
|
+
SparkBarBarStyle,
|
|
58
|
+
SparkBarChartLabelStyle,
|
|
59
|
+
SparkBarChartStyle,
|
|
60
|
+
SparkBarCountStyle,
|
|
61
|
+
SparkStyle,
|
|
62
|
+
Style,
|
|
63
|
+
TableChartStylePatch,
|
|
64
|
+
TableColumnDefaultsConfig as TableColumnDefaultsConfig,
|
|
65
|
+
TitleStyle,
|
|
66
|
+
TooltipStyle,
|
|
67
|
+
TotalStyle,
|
|
68
|
+
_CartesianChartStyle,
|
|
69
|
+
_coerce_gap,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if TYPE_CHECKING:
|
|
73
|
+
|
|
74
|
+
class TitleStylePatch(TitleStyle):
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
else:
|
|
78
|
+
TitleStylePatch = build_patch_model(TitleStyle)
|
|
79
|
+
|
|
80
|
+
# ScaleStyle is already all-Optional — auto-generated patch is identical and
|
|
81
|
+
# ensures AxisStylePatch.scale and tests share the same class identity.
|
|
82
|
+
# TYPE_CHECKING stub mirrors the DataTable/Table/AxisStylePatch pattern:
|
|
83
|
+
# mypy sees a proper class; runtime uses the dynamically-created patch model.
|
|
84
|
+
if TYPE_CHECKING:
|
|
85
|
+
|
|
86
|
+
class ScaleStylePatch(ScaleStyle):
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
else:
|
|
90
|
+
ScaleStylePatch = build_patch_model(ScaleStyle)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
_StylePatchBase = build_patch_model(Style)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class StylePatch(_StylePatchBase): # type: ignore[misc,valid-type]
|
|
97
|
+
"""Authored overlay for Style — all fields optional. Adds CSS shorthand coercers."""
|
|
98
|
+
|
|
99
|
+
@field_validator("gap", mode="before")
|
|
100
|
+
@classmethod
|
|
101
|
+
def _coerce_gap_value(cls, v: Any) -> Any:
|
|
102
|
+
return _coerce_gap(v)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
AxisGridStylePatch = build_patch_model(AxisGridStyle)
|
|
106
|
+
AxisDomainStylePatch = build_patch_model(AxisDomainStyle)
|
|
107
|
+
AxisTicksStylePatch = build_patch_model(AxisTicksStyle)
|
|
108
|
+
AxisElementStylePatch = build_patch_model(AxisElementStyle)
|
|
109
|
+
if TYPE_CHECKING:
|
|
110
|
+
|
|
111
|
+
class PointMarkStylePatch(PointMarkStyle):
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
else:
|
|
115
|
+
PointMarkStylePatch = build_patch_model(PointMarkStyle)
|
|
116
|
+
|
|
117
|
+
# Per-family chart style patches used as Pydantic field annotations in authored
|
|
118
|
+
# *Chart classes. The TYPE_CHECKING stub gives mypy a proper class identity while
|
|
119
|
+
# the runtime uses the dynamically-created patch model from build_patch_model().
|
|
120
|
+
# Pattern mirrors ScaleStylePatch / LegendStylePatch / TableChartStylePatch.
|
|
121
|
+
if TYPE_CHECKING:
|
|
122
|
+
|
|
123
|
+
class BarChartStylePatch(BarChartStyle): # noqa: F811
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
class LineChartStylePatch(LineChartStyle): # noqa: F811
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
class AreaChartStylePatch(AreaChartStyle): # noqa: F811
|
|
130
|
+
pass
|
|
131
|
+
|
|
132
|
+
class ScatterChartStylePatch(ScatterChartStyle): # noqa: F811
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
class HeatmapChartStylePatch(HeatmapChartStyle): # noqa: F811
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
class GeoshapeChartStylePatch(GeoshapeChartStyle): # noqa: F811
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
class PointMapChartStylePatch(PointMapChartStyle): # noqa: F811
|
|
142
|
+
pass
|
|
143
|
+
|
|
144
|
+
class PieChartStylePatch(PieChartStyle): # noqa: F811
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
else:
|
|
148
|
+
BarChartStylePatch = build_patch_model(BarChartStyle)
|
|
149
|
+
LineChartStylePatch = build_patch_model(LineChartStyle)
|
|
150
|
+
AreaChartStylePatch = build_patch_model(AreaChartStyle)
|
|
151
|
+
ScatterChartStylePatch = build_patch_model(ScatterChartStyle)
|
|
152
|
+
HeatmapChartStylePatch = build_patch_model(HeatmapChartStyle)
|
|
153
|
+
GeoshapeChartStylePatch = build_patch_model(GeoshapeChartStyle)
|
|
154
|
+
PointMapChartStylePatch = build_patch_model(PointMapChartStyle)
|
|
155
|
+
PieChartStylePatch = build_patch_model(PieChartStyle)
|
|
156
|
+
TotalStylePatch = build_patch_model(TotalStyle)
|
|
157
|
+
GlobalMarksStylePatch = build_patch_model(GlobalMarksStyle)
|
|
158
|
+
SparkBarBarStylePatch = build_patch_model(SparkBarBarStyle)
|
|
159
|
+
SparkBarChartLabelStylePatch = build_patch_model(SparkBarChartLabelStyle)
|
|
160
|
+
SparkBarCountStylePatch = build_patch_model(SparkBarCountStyle)
|
|
161
|
+
|
|
162
|
+
if TYPE_CHECKING:
|
|
163
|
+
|
|
164
|
+
class KpiChartStylePatch(KpiChartStyle): # noqa: F811
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
class SparkBarChartStylePatch(SparkBarChartStyle): # noqa: F811
|
|
168
|
+
pass
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
KpiChartStylePatch = build_patch_model_ext(
|
|
172
|
+
KpiChartStyle, exclude=_CHART_STYLE_SIZING
|
|
173
|
+
)
|
|
174
|
+
SparkBarChartStylePatch = build_patch_model(SparkBarChartStyle)
|
|
175
|
+
SparkStylePatch = build_patch_model(SparkStyle)
|
|
176
|
+
if TYPE_CHECKING:
|
|
177
|
+
|
|
178
|
+
class CalloutChartStylePatch(CalloutChartStyle): # noqa: F811
|
|
179
|
+
pass
|
|
180
|
+
|
|
181
|
+
else:
|
|
182
|
+
CalloutChartStylePatch = build_patch_model(CalloutChartStyle)
|
|
183
|
+
# AxisStylePatch is generated earlier (after AxisStyle) so chart-type
|
|
184
|
+
# styles can reference it as a sentinel field.
|
|
185
|
+
if TYPE_CHECKING:
|
|
186
|
+
|
|
187
|
+
class InferenceStylePatch(InferenceStyle):
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
else:
|
|
191
|
+
InferenceStylePatch = build_patch_model(InferenceStyle)
|
|
192
|
+
|
|
193
|
+
# TYPE_CHECKING stub mirrors the AxisStylePatch pattern — gives mypy a proper
|
|
194
|
+
# class (with accurate field names from LegendStyle) while the runtime uses
|
|
195
|
+
# the dynamically created patch model from build_patch_model().
|
|
196
|
+
if TYPE_CHECKING:
|
|
197
|
+
|
|
198
|
+
class LegendStylePatch(LegendStyle):
|
|
199
|
+
pass
|
|
200
|
+
|
|
201
|
+
else:
|
|
202
|
+
LegendStylePatch = build_patch_model(LegendStyle)
|
|
203
|
+
|
|
204
|
+
# Individual mark-type patches used in LayeredMarksStyle and LayeredChartStyle.
|
|
205
|
+
if TYPE_CHECKING:
|
|
206
|
+
|
|
207
|
+
class BarMarkStylePatch(BarMarkStyle):
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
class LineMarkStylePatch(LineMarkStyle):
|
|
211
|
+
pass
|
|
212
|
+
|
|
213
|
+
class AreaMarkStylePatch(AreaMarkStyle):
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
class TooltipStylePatch(TooltipStyle):
|
|
217
|
+
pass
|
|
218
|
+
|
|
219
|
+
class EndpointLabelsConfigPatch(EndpointLabelsConfig):
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
class PaddingStylePatch(PaddingStyle):
|
|
223
|
+
pass
|
|
224
|
+
|
|
225
|
+
else:
|
|
226
|
+
BarMarkStylePatch = build_patch_model(BarMarkStyle)
|
|
227
|
+
LineMarkStylePatch = build_patch_model(LineMarkStyle)
|
|
228
|
+
AreaMarkStylePatch = build_patch_model(AreaMarkStyle)
|
|
229
|
+
TooltipStylePatch = build_patch_model(TooltipStyle)
|
|
230
|
+
EndpointLabelsConfigPatch = build_patch_model(EndpointLabelsConfig)
|
|
231
|
+
PaddingStylePatch = build_patch_model(PaddingStyle)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# =============================================================================
|
|
235
|
+
# LAYEREDCHARTSTYLE — flat authored overlay for layered multi-mark charts
|
|
236
|
+
# =============================================================================
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class LayeredMarksStyle(BaseModel):
|
|
240
|
+
"""Per-mark-type style overrides for layered charts.
|
|
241
|
+
|
|
242
|
+
Keys match the VL mark types emitted by layered layers. All fields default
|
|
243
|
+
to None (inherit global marks defaults). ``point`` controls the dot marker
|
|
244
|
+
on line and area layers; ``bar``, ``line``, ``area`` control their
|
|
245
|
+
respective marks directly.
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
model_config = ConfigDict(extra="forbid")
|
|
249
|
+
|
|
250
|
+
bar: BarMarkStylePatch | None = Field(
|
|
251
|
+
default=None, description="Bar mark overrides for bar layers."
|
|
252
|
+
)
|
|
253
|
+
line: LineMarkStylePatch | None = Field(
|
|
254
|
+
default=None, description="Line mark overrides for line layers."
|
|
255
|
+
)
|
|
256
|
+
area: AreaMarkStylePatch | None = Field(
|
|
257
|
+
default=None, description="Area mark overrides for area layers."
|
|
258
|
+
)
|
|
259
|
+
point: PointMarkStylePatch | None = Field(
|
|
260
|
+
default=None,
|
|
261
|
+
description="Point/dot mark overrides shared across line and area layers.",
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class LayeredChartStyle(_CartesianChartStyle):
|
|
266
|
+
"""Flat style patch for layered multi-mark charts.
|
|
267
|
+
|
|
268
|
+
Inherits all cartesian chart-level and shared axis/legend fields from
|
|
269
|
+
``_CartesianChartStyle`` (which itself inherits ``_ChartStyleBaseAllOptional``).
|
|
270
|
+
Only adds layered-specific behavior fields and per-mark-type overrides.
|
|
271
|
+
|
|
272
|
+
Some nested compiled types from ``_ChartStyleBaseAllOptional`` are overridden
|
|
273
|
+
with their ``*Patch`` equivalents so that partial dicts (e.g.
|
|
274
|
+
``legend: {disable: true}``) are accepted without requiring all required fields
|
|
275
|
+
of the compiled model.
|
|
276
|
+
|
|
277
|
+
``ChartStylePatch.layered`` holds this type; the cascade reads shared fields
|
|
278
|
+
from it directly and distributes ``marks.*`` overrides to the bar/line/area
|
|
279
|
+
family slots in ``MergedChartsStyle``.
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
# Override compiled → patch types for nested models that have required fields.
|
|
283
|
+
# _CartesianChartStyle inherits these as their compiled (non-optional) variants;
|
|
284
|
+
# we narrow them back to their patch equivalents so partial dicts validate cleanly.
|
|
285
|
+
legend: LegendStylePatch | None = Field( # type: ignore[assignment]
|
|
286
|
+
default=None, description="Chart legend style overrides."
|
|
287
|
+
)
|
|
288
|
+
tooltip: TooltipStylePatch | None = Field( # type: ignore[assignment]
|
|
289
|
+
default=None, description="Chart tooltip style overrides."
|
|
290
|
+
)
|
|
291
|
+
padding: PaddingStylePatch | None = Field( # type: ignore[assignment]
|
|
292
|
+
default=None, description="Chart inner padding overrides."
|
|
293
|
+
)
|
|
294
|
+
title: TitleStylePatch | None = Field(
|
|
295
|
+
default=None,
|
|
296
|
+
description="Chart-level title style override; None inherits the theme title style.",
|
|
297
|
+
)
|
|
298
|
+
inference: InferenceStylePatch | None = Field( # type: ignore[assignment]
|
|
299
|
+
default=None, description="Engine inference behavior flags."
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# Family behavior fields (bar/area share orientation/stack; all share endpoint labels).
|
|
303
|
+
orientation: Literal["horizontal", "vertical", "auto"] | None = Field(
|
|
304
|
+
default=None,
|
|
305
|
+
description="Preferred bar orientation; None uses the renderer default (vertical).",
|
|
306
|
+
)
|
|
307
|
+
stack: bool | Literal["zero", "normalize", "center"] | None = Field(
|
|
308
|
+
default=None,
|
|
309
|
+
description="Default stack mode for bar/area charts.",
|
|
310
|
+
)
|
|
311
|
+
stack_order: Literal["value", "data", "alphabetical"] | None = Field(
|
|
312
|
+
default=None,
|
|
313
|
+
description="Z-order of stacked segments.",
|
|
314
|
+
)
|
|
315
|
+
endpoint_labels: EndpointLabelsConfigPatch | None = Field(
|
|
316
|
+
default=None,
|
|
317
|
+
description="Endpoint label pane configuration.",
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
# Mark overrides — keyed by mark type rather than by chart family.
|
|
321
|
+
marks: LayeredMarksStyle | None = Field(
|
|
322
|
+
default=None,
|
|
323
|
+
description="Per-mark-type style overrides (bar/line/area/point).",
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# =============================================================================
|
|
328
|
+
# CHARTSTYLEPATCH — chart-local authored overlay
|
|
329
|
+
# =============================================================================
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class ChartStylePatch(BaseModel):
|
|
333
|
+
"""Chart-local style patch — chart-level sizing fields plus per-family sub-patches.
|
|
334
|
+
|
|
335
|
+
Each family key (bar, line, area, …) holds the fully-typed patch for that
|
|
336
|
+
chart family. The render layer reads only the family that matches the chart
|
|
337
|
+
type; other families are ignored.
|
|
338
|
+
|
|
339
|
+
For layered charts that mix multiple mark families, multiple keys may be set.
|
|
340
|
+
|
|
341
|
+
``aspect_ratio``, ``min_height``, and ``max_height`` live here (not in a
|
|
342
|
+
family sub-patch) so layered charts can author them at the top of their
|
|
343
|
+
``style:`` block. For single-family charts the equivalent fields are on the
|
|
344
|
+
per-family patch (e.g. ``BarChartStylePatch``); the normalizer promotes them
|
|
345
|
+
to ``Chart.aspect_ratio`` etc. before the compiled ``ChartStylePatch`` is
|
|
346
|
+
built, so these fields are always ``None`` in the final compiled model.
|
|
347
|
+
"""
|
|
348
|
+
|
|
349
|
+
model_config = ConfigDict(extra="forbid")
|
|
350
|
+
|
|
351
|
+
# Chart-level sizing — valid on all chart types that support aspect-ratio
|
|
352
|
+
# sizing (i.e. not kpi / table / callout / spark_bar which use fixed sizing).
|
|
353
|
+
# Normalizer promotes these to Chart.aspect_ratio / min_height / max_height.
|
|
354
|
+
aspect_ratio: float | None = Field(
|
|
355
|
+
default=None,
|
|
356
|
+
description="Chart aspect ratio (width/height). Overrides the theme default for this chart.",
|
|
357
|
+
)
|
|
358
|
+
min_height: float | None = Field(
|
|
359
|
+
default=None,
|
|
360
|
+
description="Minimum chart height in pixels.",
|
|
361
|
+
)
|
|
362
|
+
max_height: float | None = Field(
|
|
363
|
+
default=None,
|
|
364
|
+
description="Maximum chart height in pixels.",
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
# Per-chart-type authored overlay patches.
|
|
368
|
+
bar: BarChartStylePatch | None = Field(
|
|
369
|
+
default=None, description="Bar chart-specific style overrides."
|
|
370
|
+
)
|
|
371
|
+
line: LineChartStylePatch | None = Field(
|
|
372
|
+
default=None, description="Line chart-specific style overrides."
|
|
373
|
+
)
|
|
374
|
+
area: AreaChartStylePatch | None = Field(
|
|
375
|
+
default=None, description="Area chart-specific style overrides."
|
|
376
|
+
)
|
|
377
|
+
scatter: ScatterChartStylePatch | None = Field(
|
|
378
|
+
default=None, description="Scatter chart-specific style overrides."
|
|
379
|
+
)
|
|
380
|
+
pie: PieChartStylePatch | None = Field(
|
|
381
|
+
default=None,
|
|
382
|
+
description="Pie/donut chart style overrides.",
|
|
383
|
+
)
|
|
384
|
+
kpi: KpiChartStylePatch | None = Field(
|
|
385
|
+
default=None, description="KPI chart-specific style overrides."
|
|
386
|
+
)
|
|
387
|
+
spark_bar: SparkBarChartStylePatch | None = Field(
|
|
388
|
+
default=None, description="Spark bar chart-specific style overrides."
|
|
389
|
+
)
|
|
390
|
+
spark: SparkStylePatch | None = Field(default=None, description="Spark line/area chart-specific style overrides.") # type: ignore[valid-type]
|
|
391
|
+
heatmap: HeatmapChartStylePatch | None = Field(
|
|
392
|
+
default=None, description="Heatmap chart-specific style overrides."
|
|
393
|
+
)
|
|
394
|
+
geoshape: GeoshapeChartStylePatch | None = Field(
|
|
395
|
+
default=None, description="Geoshape/map chart-specific style overrides."
|
|
396
|
+
)
|
|
397
|
+
point_map: PointMapChartStylePatch | None = Field(
|
|
398
|
+
default=None, description="Point map chart-specific style overrides."
|
|
399
|
+
)
|
|
400
|
+
table: TableChartStylePatch | None = Field(
|
|
401
|
+
default=None, description="Table chart-specific style overrides."
|
|
402
|
+
)
|
|
403
|
+
callout: CalloutChartStylePatch | None = Field(
|
|
404
|
+
default=None, description="Callout chart-specific style overrides (tone)."
|
|
405
|
+
)
|
|
406
|
+
layered: LayeredChartStyle | None = Field(
|
|
407
|
+
default=None, description="Layered chart-specific style overrides."
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
@classmethod
|
|
411
|
+
def coerce_chart_style(cls, raw_style: Any) -> ChartStylePatch:
|
|
412
|
+
if isinstance(raw_style, cls):
|
|
413
|
+
return raw_style
|
|
414
|
+
if isinstance(raw_style, dict):
|
|
415
|
+
return cls.model_validate(raw_style)
|
|
416
|
+
return cls()
|
|
417
|
+
|
|
418
|
+
@model_validator(mode="before")
|
|
419
|
+
@classmethod
|
|
420
|
+
def _reject_stale_pie_keys(cls, data: Any) -> Any:
|
|
421
|
+
"""Catch authors using removed flat pie keys, old arc key, or chart-root geometry in style."""
|
|
422
|
+
if not isinstance(data, dict):
|
|
423
|
+
return data
|
|
424
|
+
# height and width belong at chart root, not in style:.
|
|
425
|
+
for geo_key in ("height", "width"):
|
|
426
|
+
if geo_key in data:
|
|
427
|
+
raise ValueError(
|
|
428
|
+
f"style.{geo_key} is not valid on a chart's style block. "
|
|
429
|
+
f"Chart sizing fields live at the chart root, not in style:.\n\n"
|
|
430
|
+
f" charts:\n"
|
|
431
|
+
f" my_chart:\n"
|
|
432
|
+
f" type: bar\n"
|
|
433
|
+
f" {geo_key}: ... # ← move here\n"
|
|
434
|
+
f" style:\n"
|
|
435
|
+
f" # paint only"
|
|
436
|
+
)
|
|
437
|
+
# For layered charts, sizing fields must be at the top of style:, not
|
|
438
|
+
# nested inside a family sub-patch (e.g. style.bar.aspect_ratio).
|
|
439
|
+
# The normalizer only promotes top-level style sizing; nested forms are
|
|
440
|
+
# silently ignored, so reject them here.
|
|
441
|
+
_SIZING_KEYS = {"aspect_ratio", "min_height", "max_height"}
|
|
442
|
+
_FAMILY_KEYS = {
|
|
443
|
+
"bar",
|
|
444
|
+
"line",
|
|
445
|
+
"area",
|
|
446
|
+
"scatter",
|
|
447
|
+
"heatmap",
|
|
448
|
+
"geoshape",
|
|
449
|
+
"point_map",
|
|
450
|
+
"pie",
|
|
451
|
+
"spark_bar",
|
|
452
|
+
"spark",
|
|
453
|
+
}
|
|
454
|
+
for family in _FAMILY_KEYS:
|
|
455
|
+
family_patch = data.get(family)
|
|
456
|
+
if isinstance(family_patch, dict):
|
|
457
|
+
for sizing_key in _SIZING_KEYS:
|
|
458
|
+
if sizing_key in family_patch:
|
|
459
|
+
raise ValueError(
|
|
460
|
+
f"style.{family}.{sizing_key} is not valid. "
|
|
461
|
+
f"Sizing fields must be at the top of the style: block, "
|
|
462
|
+
f"not nested inside a family sub-patch:\n\n"
|
|
463
|
+
f" style:\n"
|
|
464
|
+
f" {sizing_key}: ... # ← move here\n"
|
|
465
|
+
f" {family}:\n"
|
|
466
|
+
f" # mark paint only"
|
|
467
|
+
)
|
|
468
|
+
stale: dict[str, str] = {
|
|
469
|
+
"arc": "style.pie.marks.slice",
|
|
470
|
+
"slice": "style.pie.marks.slice",
|
|
471
|
+
"inner_radius": "style.pie.inner_radius",
|
|
472
|
+
"total": "style.pie.total",
|
|
473
|
+
}
|
|
474
|
+
for key, new_path in stale.items():
|
|
475
|
+
if key in data:
|
|
476
|
+
raise ValueError(
|
|
477
|
+
f"style.{key} has been removed. "
|
|
478
|
+
f"Pie style is now under style.pie.*. "
|
|
479
|
+
f"Move it to {new_path}."
|
|
480
|
+
)
|
|
481
|
+
return data
|