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.
Files changed (455) hide show
  1. d3_format/__init__.py +14 -0
  2. d3_format/errors.py +19 -0
  3. d3_format/format.py +551 -0
  4. d3_format/spec.py +159 -0
  5. dataface/DATAFACE_SYNTAX.md +1135 -0
  6. dataface/__init__.py +93 -0
  7. dataface/_docs_site.py +20 -0
  8. dataface/_install_hint.py +26 -0
  9. dataface/agent_api/__init__.py +79 -0
  10. dataface/agent_api/_init_templates/__init__.py +0 -0
  11. dataface/agent_api/_init_templates/agents_dft_snippet.md +26 -0
  12. dataface/agent_api/_init_templates/dataface.yml +15 -0
  13. dataface/agent_api/_init_templates/faces-dataface.yml +144 -0
  14. dataface/agent_api/_init_templates/index.md +24 -0
  15. dataface/agent_api/_paths.py +118 -0
  16. dataface/agent_api/_project_agents_md.py +43 -0
  17. dataface/agent_api/_session_store.py +486 -0
  18. dataface/agent_api/_state.py +28 -0
  19. dataface/agent_api/chat.py +221 -0
  20. dataface/agent_api/dashboards.py +257 -0
  21. dataface/agent_api/describe.py +366 -0
  22. dataface/agent_api/describe_query.py +120 -0
  23. dataface/agent_api/docs/__init__.py +25 -0
  24. dataface/agent_api/docs/_loader.py +292 -0
  25. dataface/agent_api/docs/yaml-reference.md +2757 -0
  26. dataface/agent_api/file_refs.py +118 -0
  27. dataface/agent_api/init.py +126 -0
  28. dataface/agent_api/inspect.py +128 -0
  29. dataface/agent_api/mcp_install.py +170 -0
  30. dataface/agent_api/query.py +274 -0
  31. dataface/agent_api/schema.py +658 -0
  32. dataface/agent_api/schema_search.py +284 -0
  33. dataface/agent_api/search.py +270 -0
  34. dataface/agent_api/skill_install.py +141 -0
  35. dataface/agent_api/skill_render.py +90 -0
  36. dataface/agent_api/skills.py +293 -0
  37. dataface/agent_api/surface_aliases.yaml +128 -0
  38. dataface/agent_api/validate.py +175 -0
  39. dataface/agent_api/validate_query.py +84 -0
  40. dataface/ai/__init__.py +39 -0
  41. dataface/ai/agent.py +139 -0
  42. dataface/ai/context.py +45 -0
  43. dataface/ai/events.py +62 -0
  44. dataface/ai/external_mcp.py +610 -0
  45. dataface/ai/generate_sql.py +96 -0
  46. dataface/ai/llm.py +403 -0
  47. dataface/ai/mcp/__init__.py +51 -0
  48. dataface/ai/mcp/server.py +289 -0
  49. dataface/ai/memories.py +85 -0
  50. dataface/ai/prompts.py +177 -0
  51. dataface/ai/schema_context.py +138 -0
  52. dataface/ai/skills/before-after-comparison/SKILL.md +102 -0
  53. dataface/ai/skills/before-after-comparison/examples/before-after-comparison.yml +24 -0
  54. dataface/ai/skills/dashboard-build/SKILL.md +212 -0
  55. dataface/ai/skills/dashboard-build/examples/_smoke.yml +15 -0
  56. dataface/ai/skills/dashboard-design/SKILL.md +182 -0
  57. dataface/ai/skills/dashboard-review/SKILL.md +113 -0
  58. dataface/ai/skills/dashboard-structural-review/SKILL.md +173 -0
  59. dataface/ai/skills/dashboard-visual-review/SKILL.md +139 -0
  60. dataface/ai/skills/dataface-mcp-setup/SKILL.md +177 -0
  61. dataface/ai/skills/dataface-troubleshooting/SKILL.md +225 -0
  62. dataface/ai/skills/drill-down-link/SKILL.md +112 -0
  63. dataface/ai/skills/drill-down-link/examples/drill-down-link.yml +27 -0
  64. dataface/ai/skills/faceted-small-multiples/SKILL.md +116 -0
  65. dataface/ai/skills/faceted-small-multiples/examples/faceted-small-multiples.yml +33 -0
  66. dataface/ai/skills/filter-bar-with-variables/SKILL.md +105 -0
  67. dataface/ai/skills/filter-bar-with-variables/examples/filter-bar-with-variables.yml +49 -0
  68. dataface/ai/skills/kpi-row/SKILL.md +101 -0
  69. dataface/ai/skills/kpi-row/examples/kpi-row.yml +55 -0
  70. dataface/ai/skills/report-design/SKILL.md +184 -0
  71. dataface/ai/skills/single-metric-bignum/SKILL.md +90 -0
  72. dataface/ai/skills/single-metric-bignum/examples/single-metric-bignum.yml +27 -0
  73. dataface/ai/skills/table-heavy-ops-dashboard/SKILL.md +114 -0
  74. dataface/ai/skills/table-heavy-ops-dashboard/examples/table-heavy-ops-dashboard.yml +48 -0
  75. dataface/ai/skills/time-series-trend/SKILL.md +93 -0
  76. dataface/ai/skills/time-series-trend/examples/time-series-trend.yml +26 -0
  77. dataface/ai/skills/top-n-with-detail/SKILL.md +98 -0
  78. dataface/ai/skills/top-n-with-detail/examples/top-n-with-detail.yml +45 -0
  79. dataface/ai/skills/two-by-two-grid-overview/SKILL.md +78 -0
  80. dataface/ai/skills/two-by-two-grid-overview/examples/two-by-two-grid-overview.yml +64 -0
  81. dataface/ai/tool_schemas.py +132 -0
  82. dataface/ai/tools/__init__.py +312 -0
  83. dataface/ai/yaml_utils.py +57 -0
  84. dataface/cli/__init__.py +3 -0
  85. dataface/cli/_console.py +48 -0
  86. dataface/cli/_error_format.py +83 -0
  87. dataface/cli/_extras.py +190 -0
  88. dataface/cli/_json_output.py +8 -0
  89. dataface/cli/_parsing.py +17 -0
  90. dataface/cli/_version_info.py +56 -0
  91. dataface/cli/commands/__init__.py +3 -0
  92. dataface/cli/commands/_agent_input.py +205 -0
  93. dataface/cli/commands/_agent_server.py +115 -0
  94. dataface/cli/commands/chat.py +645 -0
  95. dataface/cli/commands/describe.py +107 -0
  96. dataface/cli/commands/docs.py +131 -0
  97. dataface/cli/commands/extension.py +179 -0
  98. dataface/cli/commands/init.py +240 -0
  99. dataface/cli/commands/inspect.py +94 -0
  100. dataface/cli/commands/mcp_init.py +167 -0
  101. dataface/cli/commands/query.py +386 -0
  102. dataface/cli/commands/render.py +291 -0
  103. dataface/cli/commands/schema.py +411 -0
  104. dataface/cli/commands/search.py +49 -0
  105. dataface/cli/commands/serve.py +114 -0
  106. dataface/cli/commands/skills.py +133 -0
  107. dataface/cli/commands/skills_init.py +161 -0
  108. dataface/cli/commands/validate.py +63 -0
  109. dataface/cli/main.py +1501 -0
  110. dataface/core/__init__.py +75 -0
  111. dataface/core/compile/__init__.py +244 -0
  112. dataface/core/compile/_jinja_helpers.py +78 -0
  113. dataface/core/compile/channel.py +222 -0
  114. dataface/core/compile/chart_focus.py +101 -0
  115. dataface/core/compile/chart_resolved.py +169 -0
  116. dataface/core/compile/chart_type_detection.py +489 -0
  117. dataface/core/compile/chart_update.py +261 -0
  118. dataface/core/compile/colors.py +64 -0
  119. dataface/core/compile/compiler.py +904 -0
  120. dataface/core/compile/config.py +823 -0
  121. dataface/core/compile/custom_chart_types.py +208 -0
  122. dataface/core/compile/data_table_attachment.py +1287 -0
  123. dataface/core/compile/detect.py +110 -0
  124. dataface/core/compile/errors.py +302 -0
  125. dataface/core/compile/filter_injection.py +319 -0
  126. dataface/core/compile/introspection.py +527 -0
  127. dataface/core/compile/jinja.py +511 -0
  128. dataface/core/compile/labels_env.py +52 -0
  129. dataface/core/compile/markdown.py +154 -0
  130. dataface/core/compile/meta.py +388 -0
  131. dataface/core/compile/models/__init__.py +0 -0
  132. dataface/core/compile/models/chart/__init__.py +0 -0
  133. dataface/core/compile/models/chart/authored.py +2137 -0
  134. dataface/core/compile/models/chart/compiled.py +398 -0
  135. dataface/core/compile/models/config.py +347 -0
  136. dataface/core/compile/models/face/__init__.py +0 -0
  137. dataface/core/compile/models/face/authored.py +659 -0
  138. dataface/core/compile/models/face/compiled.py +522 -0
  139. dataface/core/compile/models/factories.py +201 -0
  140. dataface/core/compile/models/markers.py +40 -0
  141. dataface/core/compile/models/palette.py +36 -0
  142. dataface/core/compile/models/primitives.py +415 -0
  143. dataface/core/compile/models/query/__init__.py +0 -0
  144. dataface/core/compile/models/query/authored.py +246 -0
  145. dataface/core/compile/models/query/compiled.py +710 -0
  146. dataface/core/compile/models/refs.py +137 -0
  147. dataface/core/compile/models/source.py +611 -0
  148. dataface/core/compile/models/style/__init__.py +0 -0
  149. dataface/core/compile/models/style/authored.py +481 -0
  150. dataface/core/compile/models/style/compiled.py +3399 -0
  151. dataface/core/compile/models/style/merged.py +1682 -0
  152. dataface/core/compile/models/theme.py +362 -0
  153. dataface/core/compile/models/variable/__init__.py +0 -0
  154. dataface/core/compile/models/variable/authored.py +254 -0
  155. dataface/core/compile/models/vega_lite/__init__.py +0 -0
  156. dataface/core/compile/models/vega_lite/config.py +510 -0
  157. dataface/core/compile/models/vega_lite/contracts.py +171 -0
  158. dataface/core/compile/normalize_charts.py +494 -0
  159. dataface/core/compile/normalize_layout.py +1000 -0
  160. dataface/core/compile/normalize_queries.py +297 -0
  161. dataface/core/compile/normalize_variables.py +489 -0
  162. dataface/core/compile/normalizer.py +543 -0
  163. dataface/core/compile/palette.py +1100 -0
  164. dataface/core/compile/parameterized.py +658 -0
  165. dataface/core/compile/parser.py +228 -0
  166. dataface/core/compile/schema.py +20 -0
  167. dataface/core/compile/schema_renderers/__init__.py +0 -0
  168. dataface/core/compile/schema_renderers/json_schema.py +163 -0
  169. dataface/core/compile/schema_renderers/prompt.py +152 -0
  170. dataface/core/compile/schema_renderers/vscode_schema.py +301 -0
  171. dataface/core/compile/sizing.py +2126 -0
  172. dataface/core/compile/sources.py +518 -0
  173. dataface/core/compile/sql_authoring_lint.py +56 -0
  174. dataface/core/compile/style_cascade.py +471 -0
  175. dataface/core/compile/typography.py +299 -0
  176. dataface/core/compile/validator.py +301 -0
  177. dataface/core/compile/variables.py +53 -0
  178. dataface/core/compile/vega_config.py +98 -0
  179. dataface/core/compile/vega_lite/__init__.py +6 -0
  180. dataface/core/compile/vega_lite/validation.py +95 -0
  181. dataface/core/compile/yaml_error_formatter.py +838 -0
  182. dataface/core/connections.py +38 -0
  183. dataface/core/dashboard.py +358 -0
  184. dataface/core/defaults/default_config.yml +101 -0
  185. dataface/core/defaults/palettes/categorical/category-10-dark.yml +32 -0
  186. dataface/core/defaults/palettes/categorical/category-10-light.yml +43 -0
  187. dataface/core/defaults/palettes/categorical/category-10.yml +31 -0
  188. dataface/core/defaults/palettes/categorical/category-6-tonal-blue.yml +22 -0
  189. dataface/core/defaults/palettes/categorical/category-6-tonal-brown.yml +29 -0
  190. dataface/core/defaults/palettes/categorical/category-6-tonal-green.yml +20 -0
  191. dataface/core/defaults/palettes/categorical/category-6-tonal-orange.yml +21 -0
  192. dataface/core/defaults/palettes/categorical/category-6-tonal-purple.yml +20 -0
  193. dataface/core/defaults/palettes/categorical/editorial-10-dark.yml +32 -0
  194. dataface/core/defaults/palettes/categorical/editorial-10.yml +40 -0
  195. dataface/core/defaults/palettes/categorical/hero-6.yml +17 -0
  196. dataface/core/defaults/palettes/categorical/single-blue.yml +11 -0
  197. dataface/core/defaults/palettes/categorical/tableau.yml +20 -0
  198. dataface/core/defaults/palettes/data/xkcd_colors.json +3803 -0
  199. dataface/core/defaults/palettes/diverging/blue-red.yml +25 -0
  200. dataface/core/defaults/palettes/diverging/coolwarm.yml +24 -0
  201. dataface/core/defaults/palettes/diverging/crimson-green.yml +23 -0
  202. dataface/core/defaults/palettes/diverging/orange-teal.yml +23 -0
  203. dataface/core/defaults/palettes/diverging/sunset.yml +24 -0
  204. dataface/core/defaults/palettes/scaffold/dft-creams.yml +38 -0
  205. dataface/core/defaults/palettes/scaffold/dft-grays.yml +53 -0
  206. dataface/core/defaults/palettes/sequential/amber.yml +22 -0
  207. dataface/core/defaults/palettes/sequential/blue.yml +22 -0
  208. dataface/core/defaults/palettes/sequential/brown.yml +22 -0
  209. dataface/core/defaults/palettes/sequential/gray.yml +22 -0
  210. dataface/core/defaults/palettes/sequential/green.yml +22 -0
  211. dataface/core/defaults/palettes/sequential/purple.yml +22 -0
  212. dataface/core/defaults/palettes/sequential/rust.yml +22 -0
  213. dataface/core/defaults/palettes/sequential/teal.yml +22 -0
  214. dataface/core/defaults/palettes/tone/negative.yml +32 -0
  215. dataface/core/defaults/palettes/tone/positive.yml +22 -0
  216. dataface/core/defaults/palettes/tone/warning.yml +22 -0
  217. dataface/core/defaults/themes/_base.yaml +786 -0
  218. dataface/core/defaults/themes/bi.yaml +16 -0
  219. dataface/core/defaults/themes/carbong100.yaml +41 -0
  220. dataface/core/defaults/themes/cream.yaml +122 -0
  221. dataface/core/defaults/themes/dark.yaml +40 -0
  222. dataface/core/defaults/themes/diagnostics-title-angle-extreme.yaml +9 -0
  223. dataface/core/defaults/themes/diagnostics-title-baseline-extreme.yaml +9 -0
  224. dataface/core/defaults/themes/diagnostics-title-baseline.yaml +24 -0
  225. dataface/core/defaults/themes/diagnostics-title-center.yaml +8 -0
  226. dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +24 -0
  227. dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +25 -0
  228. dataface/core/defaults/themes/diagnostics-title-left.yaml +8 -0
  229. dataface/core/defaults/themes/diagnostics-title-offset-extreme.yaml +9 -0
  230. dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +24 -0
  231. dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +24 -0
  232. dataface/core/defaults/themes/editorial.yaml +147 -0
  233. dataface/core/defaults/themes/light.yaml +30 -0
  234. dataface/core/defaults/themes/looker.yaml +17 -0
  235. dataface/core/defaults/themes/stark.yaml +134 -0
  236. dataface/core/errors/__init__.py +67 -0
  237. dataface/core/errors/codes_compile.py +56 -0
  238. dataface/core/errors/codes_execute.py +177 -0
  239. dataface/core/errors/codes_render.py +106 -0
  240. dataface/core/errors/codes_unknown.py +15 -0
  241. dataface/core/errors/hints.py +74 -0
  242. dataface/core/errors/registry.py +42 -0
  243. dataface/core/errors/structured.py +92 -0
  244. dataface/core/execute/__init__.py +91 -0
  245. dataface/core/execute/adapters/__init__.py +49 -0
  246. dataface/core/execute/adapters/adapter_registry.py +400 -0
  247. dataface/core/execute/adapters/base.py +245 -0
  248. dataface/core/execute/adapters/csv_adapter.py +239 -0
  249. dataface/core/execute/adapters/dbt_adapter.py +283 -0
  250. dataface/core/execute/adapters/dbt_adapter_factory.py +212 -0
  251. dataface/core/execute/adapters/dbt_macro_loader.py +95 -0
  252. dataface/core/execute/adapters/dbt_utils.py +150 -0
  253. dataface/core/execute/adapters/http_adapter.py +224 -0
  254. dataface/core/execute/adapters/metricflow_adapter.py +94 -0
  255. dataface/core/execute/adapters/schema_resolver_adapter.py +144 -0
  256. dataface/core/execute/adapters/sql_adapter.py +710 -0
  257. dataface/core/execute/adapters/values_adapter.py +58 -0
  258. dataface/core/execute/batch.py +744 -0
  259. dataface/core/execute/cache_backend.py +135 -0
  260. dataface/core/execute/cache_keys.py +66 -0
  261. dataface/core/execute/dbt_jinja.py +21 -0
  262. dataface/core/execute/dialects/__init__.py +121 -0
  263. dataface/core/execute/dialects/athena.py +75 -0
  264. dataface/core/execute/dialects/base.py +302 -0
  265. dataface/core/execute/dialects/bigquery.py +38 -0
  266. dataface/core/execute/dialects/databricks.py +68 -0
  267. dataface/core/execute/dialects/duckdb.py +35 -0
  268. dataface/core/execute/dialects/mysql.py +68 -0
  269. dataface/core/execute/dialects/postgres.py +39 -0
  270. dataface/core/execute/dialects/redshift.py +12 -0
  271. dataface/core/execute/dialects/snowflake.py +51 -0
  272. dataface/core/execute/dialects/sqlserver.py +92 -0
  273. dataface/core/execute/duckdb_cache.py +712 -0
  274. dataface/core/execute/duckdb_config.py +26 -0
  275. dataface/core/execute/errors.py +213 -0
  276. dataface/core/execute/executor.py +1249 -0
  277. dataface/core/execute/parallel.py +162 -0
  278. dataface/core/execute/setup_sql.py +58 -0
  279. dataface/core/execute/source_registry.py +72 -0
  280. dataface/core/execute/source_resolver.py +255 -0
  281. dataface/core/execute/sql_guard.py +387 -0
  282. dataface/core/execute/sql_literals.py +199 -0
  283. dataface/core/fonts.py +52 -0
  284. dataface/core/inspect/__init__.py +32 -0
  285. dataface/core/inspect/cache_factory.py +98 -0
  286. dataface/core/inspect/db_types.py +162 -0
  287. dataface/core/inspect/dbt_schema.py +96 -0
  288. dataface/core/inspect/defaults.yml +37 -0
  289. dataface/core/inspect/fanout_risk.py +109 -0
  290. dataface/core/inspect/manifest_utils.py +77 -0
  291. dataface/core/inspect/partials/categorical.yml +40 -0
  292. dataface/core/inspect/partials/date.yml +40 -0
  293. dataface/core/inspect/partials/numeric.yml +55 -0
  294. dataface/core/inspect/partition_types.py +38 -0
  295. dataface/core/inspect/query_validator.py +975 -0
  296. dataface/core/inspect/renderer.py +354 -0
  297. dataface/core/inspect/resolver.py +808 -0
  298. dataface/core/inspect/search.py +461 -0
  299. dataface/core/inspect/sources/__init__.py +32 -0
  300. dataface/core/inspect/sources/dbt.py +738 -0
  301. dataface/core/inspect/sources/duckdb_utils.py +66 -0
  302. dataface/core/inspect/templates/__init__.py +1 -0
  303. dataface/core/inspect/templates/categorical_column.yml +196 -0
  304. dataface/core/inspect/templates/charts.yml +109 -0
  305. dataface/core/inspect/templates/date_column.yml +248 -0
  306. dataface/core/inspect/templates/model.yml +138 -0
  307. dataface/core/inspect/templates/numeric_column.yml +261 -0
  308. dataface/core/inspect/templates/quality.yml +80 -0
  309. dataface/core/inspect/templates/string_column.yml +263 -0
  310. dataface/core/project_roots.py +165 -0
  311. dataface/core/render/__init__.py +87 -0
  312. dataface/core/render/board_links.py +176 -0
  313. dataface/core/render/chart/__init__.py +27 -0
  314. dataface/core/render/chart/arc_attached_table.py +251 -0
  315. dataface/core/render/chart/artifacts.py +16 -0
  316. dataface/core/render/chart/callout.py +225 -0
  317. dataface/core/render/chart/decisions.py +358 -0
  318. dataface/core/render/chart/geo.py +700 -0
  319. dataface/core/render/chart/kpi.py +916 -0
  320. dataface/core/render/chart/labels.py +76 -0
  321. dataface/core/render/chart/pipeline.py +818 -0
  322. dataface/core/render/chart/presentation.py +36 -0
  323. dataface/core/render/chart/profile.py +3438 -0
  324. dataface/core/render/chart/render_single.py +347 -0
  325. dataface/core/render/chart/renderers.py +193 -0
  326. dataface/core/render/chart/rendering.py +565 -0
  327. dataface/core/render/chart/serialization.py +90 -0
  328. dataface/core/render/chart/spark.py +496 -0
  329. dataface/core/render/chart/spark_bar.py +370 -0
  330. dataface/core/render/chart/spec_builders.py +154 -0
  331. dataface/core/render/chart/standard_renderer.py +2645 -0
  332. dataface/core/render/chart/table.py +2957 -0
  333. dataface/core/render/chart/table_support.py +1452 -0
  334. dataface/core/render/chart/tick_values.py +66 -0
  335. dataface/core/render/chart/time_unit_detect.py +809 -0
  336. dataface/core/render/chart/title_overflow.py +157 -0
  337. dataface/core/render/chart/type_inference.py +122 -0
  338. dataface/core/render/chart/validation.py +99 -0
  339. dataface/core/render/chart/vega_lite.py +125 -0
  340. dataface/core/render/chart/vega_lite_types.py +268 -0
  341. dataface/core/render/chart/vl_field_maps.py +346 -0
  342. dataface/core/render/chart_interactivity.py +24 -0
  343. dataface/core/render/control_registry.py +287 -0
  344. dataface/core/render/converters/__init__.py +24 -0
  345. dataface/core/render/converters/chart.py +276 -0
  346. dataface/core/render/converters/html.py +98 -0
  347. dataface/core/render/converters/pdf.py +40 -0
  348. dataface/core/render/converters/png.py +41 -0
  349. dataface/core/render/errors.py +144 -0
  350. dataface/core/render/face_api.py +160 -0
  351. dataface/core/render/faces.py +1194 -0
  352. dataface/core/render/font_measurement.py +48 -0
  353. dataface/core/render/font_support.py +197 -0
  354. dataface/core/render/fonts/DFTSansTabular-Regular.ttf +0 -0
  355. dataface/core/render/fonts/DFTSansTabular-Regular.woff2 +0 -0
  356. dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.ttf +0 -0
  357. dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.ttf +0 -0
  358. dataface/core/render/fonts/InterVariable.ttf +0 -0
  359. dataface/core/render/fonts/InterVariable.woff2 +0 -0
  360. dataface/core/render/fonts/NOTO_COLOR_EMOJI_LICENSE.txt +93 -0
  361. dataface/core/render/fonts/NOTO_EMOJI_LICENSE.txt +93 -0
  362. dataface/core/render/fonts/NotoColorEmoji-Regular.ttf +0 -0
  363. dataface/core/render/fonts/NotoColorEmoji-Regular.woff2 +0 -0
  364. dataface/core/render/fonts/NotoEmoji-Regular.ttf +0 -0
  365. dataface/core/render/fonts/NotoEmoji-Regular.woff2 +0 -0
  366. dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -0
  367. dataface/core/render/fonts/SOURCE_SERIF_4_LICENSE.txt +98 -0
  368. dataface/core/render/fonts/SourceCodePro-Regular.ttf +0 -0
  369. dataface/core/render/fonts/SourceSerif4-Regular.ttf +0 -0
  370. dataface/core/render/fonts/_emoji_font_face.css +43 -0
  371. dataface/core/render/fonts/source-serif-4-variable-latin.woff2 +0 -0
  372. dataface/core/render/format_utils.py +329 -0
  373. dataface/core/render/geo_defaults.yml +28 -0
  374. dataface/core/render/json_format.py +146 -0
  375. dataface/core/render/layout_sizing.py +865 -0
  376. dataface/core/render/layouts.py +541 -0
  377. dataface/core/render/markdown_defaults.yml +16 -0
  378. dataface/core/render/missing_vars_prompt.py +79 -0
  379. dataface/core/render/placeholder.py +389 -0
  380. dataface/core/render/render_result.py +14 -0
  381. dataface/core/render/renderer.py +467 -0
  382. dataface/core/render/script_embedding.py +16 -0
  383. dataface/core/render/svg_utils.py +212 -0
  384. dataface/core/render/template_loader.py +69 -0
  385. dataface/core/render/templates/controls/_styles.css +606 -0
  386. dataface/core/render/templates/controls/checkbox.html +16 -0
  387. dataface/core/render/templates/controls/date.html +16 -0
  388. dataface/core/render/templates/controls/number.html +19 -0
  389. dataface/core/render/templates/controls/readonly.html +9 -0
  390. dataface/core/render/templates/controls/select.html +21 -0
  391. dataface/core/render/templates/controls/slider.html +22 -0
  392. dataface/core/render/templates/controls/text.html +16 -0
  393. dataface/core/render/templates/scripts/chart_interactivity.js +191 -0
  394. dataface/core/render/templates/scripts/variables.js +976 -0
  395. dataface/core/render/templates/svg/grid_pattern.svg +3 -0
  396. dataface/core/render/templates/svg/styles.css +51 -0
  397. dataface/core/render/terminal.py +311 -0
  398. dataface/core/render/terminal_charts.py +563 -0
  399. dataface/core/render/terminal_defaults.yml +2 -0
  400. dataface/core/render/terminal_layouts.py +299 -0
  401. dataface/core/render/terminal_text.py +31 -0
  402. dataface/core/render/text/__init__.py +1 -0
  403. dataface/core/render/text/case.py +113 -0
  404. dataface/core/render/text_format.py +129 -0
  405. dataface/core/render/utils.py +106 -0
  406. dataface/core/render/variable_controls.py +946 -0
  407. dataface/core/render/variable_input_refinement.py +140 -0
  408. dataface/core/render/warnings/__init__.py +15 -0
  409. dataface/core/render/warnings/bar_color_1_to_1_with_x.py +80 -0
  410. dataface/core/render/warnings/base.py +44 -0
  411. dataface/core/render/warnings/fanout_risk.py +15 -0
  412. dataface/core/render/warnings/from_query_diagnostic.py +56 -0
  413. dataface/core/render/warnings/missing_join_predicate.py +13 -0
  414. dataface/core/render/warnings/query_parse_error.py +14 -0
  415. dataface/core/render/warnings/query_returned_zero_rows.py +42 -0
  416. dataface/core/render/warnings/reaggregation.py +14 -0
  417. dataface/core/render/warnings/registry.py +45 -0
  418. dataface/core/render/warnings/suppression.py +46 -0
  419. dataface/core/render/warnings/temporal_single_point.py +63 -0
  420. dataface/core/render/warnings/unreferenced_chart.py +15 -0
  421. dataface/core/render/warnings/y_encoding_mostly_null.py +76 -0
  422. dataface/core/render/yaml_format.py +167 -0
  423. dataface/core/resolve_face.py +195 -0
  424. dataface/core/schema/__init__.py +0 -0
  425. dataface/core/schema/guidance.py +151 -0
  426. dataface/core/scoped_paths.py +59 -0
  427. dataface/core/serve/__init__.py +14 -0
  428. dataface/core/serve/bootstrap.py +39 -0
  429. dataface/core/serve/embedded.py +57 -0
  430. dataface/core/serve/port.py +129 -0
  431. dataface/core/serve/server.py +938 -0
  432. dataface/core/serve/templates/__init__.py +0 -0
  433. dataface/core/serve/templates/directory.yml +6 -0
  434. dataface/core/serve/templates/error.html.j2 +217 -0
  435. dataface/core/utils.py +121 -0
  436. dataface/core/validate.py +64 -0
  437. dataface/integrations/__init__.py +0 -0
  438. dataface/integrations/highlighting.py +351 -0
  439. dataface/integrations/markdown.py +537 -0
  440. dataface/py.typed +0 -0
  441. dataface-0.1.2.dist-info/METADATA +375 -0
  442. dataface-0.1.2.dist-info/RECORD +455 -0
  443. dataface-0.1.2.dist-info/WHEEL +4 -0
  444. dataface-0.1.2.dist-info/entry_points.txt +2 -0
  445. dataface-0.1.2.dist-info/licenses/LICENSE +202 -0
  446. mdsvg/__init__.py +168 -0
  447. mdsvg/fonts.py +656 -0
  448. mdsvg/images.py +299 -0
  449. mdsvg/parser.py +629 -0
  450. mdsvg/playground.py +284 -0
  451. mdsvg/py.typed +2 -0
  452. mdsvg/renderer.py +1623 -0
  453. mdsvg/style.py +355 -0
  454. mdsvg/types.py +200 -0
  455. 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