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,366 @@
1
+ """Typed describe verb — face structure inspection."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ from pydantic import BaseModel, Field
9
+
10
+ from dataface.core.compile.models.chart.compiled import (
11
+ Chart,
12
+ )
13
+ from dataface.core.compile.models.face.compiled import Layout
14
+ from dataface.core.compile.models.query.compiled import (
15
+ CsvQuery,
16
+ DbtModelQuery,
17
+ HttpQuery,
18
+ MetricFlowQuery,
19
+ Query,
20
+ SqlQuery,
21
+ ValuesQuery,
22
+ )
23
+ from dataface.core.errors import DF_UNKNOWN_INTERNAL, StructuredError
24
+
25
+ # Chart-encoding fields surfaced to agents. Covers the stable channel fields
26
+ # across chart families. `label` is excluded — it's a KPI-specific render hint,
27
+ # not an encoding channel that binds a column.
28
+ _ENCODING_FIELDS: tuple[str, ...] = (
29
+ "x",
30
+ "y",
31
+ "color",
32
+ "size",
33
+ "shape",
34
+ "theta",
35
+ "value",
36
+ )
37
+
38
+
39
+ # ---------------------------------------------------------------------------
40
+ # Sub-models
41
+ # ---------------------------------------------------------------------------
42
+
43
+
44
+ class QueryDescription(BaseModel):
45
+ name: str
46
+ type: str
47
+ summary: str
48
+ source: str | None = None
49
+ sql: str | None = None
50
+
51
+
52
+ class ChartDescription(BaseModel):
53
+ name: str
54
+ type: str
55
+ query: str
56
+ title: str | None = None
57
+ encoding: dict[str, Any] = Field(
58
+ default_factory=dict, description="Vega-Lite encoding channels keyed by role."
59
+ )
60
+
61
+
62
+ class VariableDescription(BaseModel):
63
+ name: str
64
+ type: str
65
+ default: Any | None = None
66
+ options: list[str] | None = None
67
+
68
+
69
+ class LayoutDescription(BaseModel):
70
+ primitive: str
71
+ items: list[str] = Field(
72
+ default_factory=list,
73
+ description="Layout item identifiers (chart IDs, text keys).",
74
+ )
75
+
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # Result models
79
+ # ---------------------------------------------------------------------------
80
+
81
+
82
+ class DescribeFaceArgs(BaseModel):
83
+ """Describe the structure of a face file: queries (with type and source), charts (with query bindings and encoding), variables, and layout. Use this for orientation when picking up an unfamiliar dashboard — it reads the YAML and returns a curated narrative summary without executing any queries."""
84
+
85
+ path: Path = Field(description="Path to the dashboard YAML file to describe")
86
+ project_dir: Path | None = Field(
87
+ None, description="Project root for resolving relative paths"
88
+ )
89
+
90
+
91
+ class DescribeFaceResult(BaseModel):
92
+ success: bool
93
+ path: Path
94
+ title: str | None = None
95
+ description: str | None = None
96
+ queries: list[QueryDescription] = Field(
97
+ default_factory=list, description="Queries defined in the face."
98
+ )
99
+ charts: list[ChartDescription] = Field(
100
+ default_factory=list, description="Charts defined in the face."
101
+ )
102
+ variables: list[VariableDescription] = Field(
103
+ default_factory=list, description="Variables defined in the face."
104
+ )
105
+ layout: LayoutDescription | None = None
106
+ errors: list[StructuredError] = Field(default_factory=list)
107
+
108
+
109
+ # ---------------------------------------------------------------------------
110
+ # Helpers
111
+ # ---------------------------------------------------------------------------
112
+
113
+
114
+ def _build_query_description(name: str, query: Query) -> QueryDescription:
115
+ """Map an AnyQuery union variant onto a typed description."""
116
+ match query:
117
+ case SqlQuery():
118
+ # SqlQuery.source can be a dict for inline configs; only surface the
119
+ # name when it's a plain string reference.
120
+ source = query.source if isinstance(query.source, str) else None
121
+ sql = query.sql or None
122
+ summary = f"SQL query{f' against `{source}`' if source else ''}"
123
+ return QueryDescription(
124
+ name=name, type="sql", summary=summary, source=source, sql=sql
125
+ )
126
+ case CsvQuery():
127
+ return QueryDescription(
128
+ name=name, type="csv", summary=f"CSV file: {query.file}"
129
+ )
130
+ case DbtModelQuery():
131
+ return QueryDescription(
132
+ name=name, type="dbt_model", summary=f"dbt model: {query.model}"
133
+ )
134
+ case HttpQuery():
135
+ return QueryDescription(
136
+ name=name, type="http", summary=f"HTTP request: {query.url}"
137
+ )
138
+ case MetricFlowQuery():
139
+ return QueryDescription(
140
+ name=name, type="metricflow", summary="MetricFlow query"
141
+ )
142
+ case ValuesQuery():
143
+ return QueryDescription(name=name, type="values", summary="Inline values")
144
+ case _:
145
+ return QueryDescription(
146
+ name=name, type=query.query_type, summary=f"{query.query_type} query"
147
+ )
148
+
149
+
150
+ def _collect_layout_items(layout: Layout, prefix: str = "") -> list[str]:
151
+ """Walk a Layout, returning chart names in display order.
152
+
153
+ Nested faces recurse with a prefix so the caller can tell layers apart.
154
+ """
155
+ out: list[str] = []
156
+ for item in layout.items:
157
+ if item.type == "chart" and item.chart is not None:
158
+ out.append(f"{prefix}{item.chart.id}" if prefix else item.chart.id)
159
+ elif item.type == "face" and item.face is not None:
160
+ sub_prefix = f"{item.face.id or '<nested>'}."
161
+ out.extend(_collect_layout_items(item.face.layout, sub_prefix))
162
+ return out
163
+
164
+
165
+ def _encoding_for_chart(chart: Chart) -> dict[str, Any]:
166
+ """Surface chart encoding bindings (column names) as JSON-friendly values.
167
+
168
+ `y` is `str | list[str]` (multi-series), and `color` accepts
169
+ dicts. Pass scalars and lists through unchanged so multi-series faces
170
+ don't get their `y: [revenue, profit]` flattened into Python repr. The
171
+ `value` is always a column reference string; pass through unchanged.
172
+ """
173
+ enc: dict[str, Any] = {}
174
+ for field in _ENCODING_FIELDS:
175
+ # No default on getattr — a typo in _ENCODING_FIELDS should raise
176
+ # loudly, not be silently skipped.
177
+ v = getattr(chart, field)
178
+ if v is None or v == "":
179
+ continue
180
+ enc[field] = v
181
+ return enc
182
+
183
+
184
+ # ---------------------------------------------------------------------------
185
+ # Public API
186
+ # ---------------------------------------------------------------------------
187
+
188
+
189
+ def describe_face(path: Path, project_dir: Path | None = None) -> DescribeFaceResult:
190
+ """Describe the structure of a face: queries, charts, variables, layout."""
191
+ from dataface.agent_api._paths import no_project_hint, resolve_scoped_path
192
+ from dataface.core.compile.compiler import compile_file
193
+ from dataface.core.compile.errors import DatafaceError
194
+
195
+ try:
196
+ resolved = resolve_scoped_path(path, project_dir)
197
+ except ValueError as exc:
198
+ return DescribeFaceResult(
199
+ success=False,
200
+ path=path,
201
+ errors=[
202
+ DatafaceError.from_code(
203
+ DF_UNKNOWN_INTERNAL, message=str(exc)
204
+ ).to_structured()
205
+ ],
206
+ )
207
+
208
+ if not resolved.exists():
209
+ hint = no_project_hint(project_dir)
210
+ return DescribeFaceResult(
211
+ success=False,
212
+ path=path,
213
+ errors=[
214
+ DatafaceError.from_code(
215
+ DF_UNKNOWN_INTERNAL,
216
+ message=f"File not found: {resolved}{hint}",
217
+ ).to_structured()
218
+ ],
219
+ )
220
+
221
+ try:
222
+ result = compile_file(resolved)
223
+ except OSError as exc:
224
+ return DescribeFaceResult(
225
+ success=False,
226
+ path=resolved,
227
+ errors=[
228
+ DatafaceError.from_code(
229
+ DF_UNKNOWN_INTERNAL, message=str(exc)
230
+ ).to_structured(file=str(resolved))
231
+ ],
232
+ )
233
+
234
+ if result.errors:
235
+ return DescribeFaceResult(
236
+ success=False,
237
+ path=resolved,
238
+ errors=list(result.errors),
239
+ )
240
+
241
+ face = result.face
242
+ if face is None:
243
+ return DescribeFaceResult(
244
+ success=False,
245
+ path=resolved,
246
+ errors=[
247
+ DatafaceError.from_code(
248
+ DF_UNKNOWN_INTERNAL, message="Compilation produced no face"
249
+ ).to_structured(file=str(resolved))
250
+ ],
251
+ )
252
+
253
+ query_descs = [
254
+ _build_query_description(name, query) for name, query in face.queries.items()
255
+ ]
256
+
257
+ chart_descs = [
258
+ ChartDescription(
259
+ name=name,
260
+ type=chart.type,
261
+ query=chart.query_name or name,
262
+ title=chart.title or None,
263
+ encoding=_encoding_for_chart(chart),
264
+ )
265
+ for name, chart in face.charts.items()
266
+ ]
267
+
268
+ var_descs: list[VariableDescription] = []
269
+ for name, var in face.variables.items():
270
+ static = var.options.static if var.options is not None else None
271
+ var_descs.append(
272
+ VariableDescription(
273
+ name=name,
274
+ type=str(var.input),
275
+ default=var.default,
276
+ options=[str(o) for o in static] if static else None,
277
+ )
278
+ )
279
+
280
+ layout_type = face.layout.type
281
+ layout_primitive = (
282
+ layout_type.value if hasattr(layout_type, "value") else str(layout_type)
283
+ )
284
+ layout_desc = LayoutDescription(
285
+ primitive=layout_primitive,
286
+ items=_collect_layout_items(face.layout),
287
+ )
288
+
289
+ return DescribeFaceResult(
290
+ success=True,
291
+ path=resolved,
292
+ title=face.title or None,
293
+ description=face.description or None,
294
+ queries=query_descs,
295
+ charts=chart_descs,
296
+ variables=var_descs,
297
+ layout=layout_desc,
298
+ )
299
+
300
+
301
+ def describe_paths(
302
+ paths: list[Path],
303
+ project_dir: Path | None = None,
304
+ ) -> list[DescribeFaceResult]:
305
+ """Describe N face files / directories.
306
+
307
+ Each argv path expands like the single-path verb: a file describes directly,
308
+ a directory walks recursively (skipping ``_*.yml`` partials and ejected
309
+ inspect-template directories). Results are concatenated in argv order.
310
+ """
311
+ out: list[DescribeFaceResult] = []
312
+ for p in paths:
313
+ out.extend(_describe_one_path(p, project_dir=project_dir))
314
+ return out
315
+
316
+
317
+ def _describe_one_path(
318
+ path: Path,
319
+ project_dir: Path | None = None,
320
+ ) -> list[DescribeFaceResult]:
321
+ """Per-argv expansion: file → [one], dir → walk."""
322
+ # WHY: dataface.core.inspect.manifest_utils triggers the inspect package
323
+ # __init__, which eagerly imports TableInspector + grain/quality/semantic
324
+ # detectors. Keep this lazy so `dft --help` doesn't pay that startup cost.
325
+ from dataface.agent_api._paths import resolve_scoped_path
326
+ from dataface.core.compile.errors import DatafaceError
327
+ from dataface.core.inspect.manifest_utils import INSPECT_TEMPLATE_MANIFEST
328
+
329
+ try:
330
+ resolved = resolve_scoped_path(path, project_dir)
331
+ except ValueError as exc:
332
+ return [
333
+ DescribeFaceResult(
334
+ success=False,
335
+ path=path,
336
+ errors=[
337
+ DatafaceError.from_code(
338
+ DF_UNKNOWN_INTERNAL, message=str(exc)
339
+ ).to_structured()
340
+ ],
341
+ )
342
+ ]
343
+
344
+ if not resolved.is_dir():
345
+ return [describe_face(resolved, project_dir=project_dir)]
346
+
347
+ template_dirs = {m.parent for m in resolved.glob(f"**/{INSPECT_TEMPLATE_MANIFEST}")}
348
+ yaml_files = sorted(
349
+ f
350
+ for f in (list(resolved.glob("**/*.yml")) + list(resolved.glob("**/*.yaml")))
351
+ if not f.name.startswith("_") and f.parent not in template_dirs
352
+ )
353
+ if not yaml_files:
354
+ return [
355
+ DescribeFaceResult(
356
+ success=False,
357
+ path=resolved,
358
+ errors=[
359
+ DatafaceError.from_code(
360
+ DF_UNKNOWN_INTERNAL,
361
+ message=f"No face files found in {resolved}",
362
+ ).to_structured()
363
+ ],
364
+ )
365
+ ]
366
+ return [describe_face(f, project_dir=project_dir) for f in yaml_files]
@@ -0,0 +1,120 @@
1
+ """describe_query verb — return column schema for a SQL string without fetching rows."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+ from dataface.core.execute.adapters import AdapterRegistry
8
+ from dataface.core.execute.adapters.dbt_adapter_factory import build_adapter
9
+ from dataface.core.inspect.query_validator import validate_query
10
+
11
+
12
+ class DescribeQueryArgs(BaseModel):
13
+ """Return the column schema (names + types) for a SQL string without executing it for data.
14
+
15
+ Gates on validate_query first — short-circuits on parse errors and missing join
16
+ predicates with actionable diagnostics; otherwise returns columns alongside any
17
+ non-error diagnostics (e.g. fanout_risk warnings) so the agent can read them
18
+ without being blocked from the column shape.
19
+ """
20
+
21
+ sql: str = Field(..., description="SQL query to describe.")
22
+ source: str | None = Field(
23
+ None, description="Data source name to describe against."
24
+ )
25
+ dialect: str | None = Field(
26
+ None, description="SQL dialect hint for the validator (duckdb, bigquery, etc.)."
27
+ )
28
+
29
+
30
+ class DescribeQueryColumn(BaseModel):
31
+ name: str
32
+ type: str
33
+ char_size: int | None = None
34
+ numeric_precision: int | None = None
35
+ numeric_scale: int | None = None
36
+
37
+
38
+ class DescribeQueryResult(BaseModel):
39
+ success: bool
40
+ columns: list[DescribeQueryColumn] | None = None
41
+ diagnostics: list[dict] = Field(
42
+ default_factory=list,
43
+ description="Dialect-specific diagnostic messages from the query runner.",
44
+ )
45
+ error: str | None = None
46
+
47
+
48
+ def describe_query(
49
+ sql: str,
50
+ *,
51
+ source: str | None = None,
52
+ dialect: str | None = None,
53
+ adapter_registry: AdapterRegistry,
54
+ ) -> DescribeQueryResult:
55
+ """Return the column schema for a SQL string using the dbt adapter.
56
+
57
+ Runs validate_query first; short-circuits on error-severity diagnostics
58
+ (parse_error, missing_join_predicate) without calling the warehouse.
59
+ Non-error diagnostics are surfaced on the result alongside the column schema.
60
+ """
61
+ try:
62
+ diags = validate_query(sql, dialect=dialect)
63
+
64
+ error_diags = [d for d in diags if d.severity == "error"]
65
+ if error_diags:
66
+ return DescribeQueryResult(
67
+ success=False,
68
+ columns=None,
69
+ diagnostics=[d.to_dict() for d in diags],
70
+ error=error_diags[0].message,
71
+ )
72
+
73
+ cfg = adapter_registry.resolve_source_config(source)
74
+
75
+ if cfg.get("type") == "duckdb":
76
+ # Run DESCRIBE via the registry's existing read-only SqlAdapter so
77
+ # we don't open a writable dbt-duckdb connection that would conflict
78
+ # with dft serve.
79
+ cols = _duckdb_describe(sql, source, adapter_registry)
80
+ else:
81
+ adapter = build_adapter(cfg, read_only=True)
82
+ with adapter.connection_named("dataface_describe"):
83
+ raw = adapter.get_column_schema_from_query(sql)
84
+ cols = [
85
+ DescribeQueryColumn(
86
+ name=c.name,
87
+ type=c.dtype,
88
+ char_size=c.char_size,
89
+ numeric_precision=c.numeric_precision,
90
+ numeric_scale=c.numeric_scale,
91
+ )
92
+ for c in raw
93
+ ]
94
+
95
+ return DescribeQueryResult(
96
+ success=True,
97
+ columns=cols,
98
+ diagnostics=[d.to_dict() for d in diags],
99
+ )
100
+
101
+ except Exception as e: # noqa: BLE001 — adapter boundary, mirrors execute_query
102
+ return DescribeQueryResult(
103
+ success=False,
104
+ error=str(e),
105
+ )
106
+
107
+
108
+ def _duckdb_describe(
109
+ sql: str, source: str | None, adapter_registry: AdapterRegistry
110
+ ) -> list[DescribeQueryColumn]:
111
+ """Run DESCRIBE ({sql}) via the registry's read-only SqlAdapter."""
112
+ from dataface.core.compile.models.query.compiled import SqlQuery
113
+
114
+ result = adapter_registry.execute(SqlQuery(sql=f"DESCRIBE ({sql})", source=source))
115
+ if result.error:
116
+ raise RuntimeError(result.error)
117
+ return [
118
+ DescribeQueryColumn(name=row["column_name"], type=row["column_type"])
119
+ for row in result.data
120
+ ]
@@ -0,0 +1,25 @@
1
+ """dataface.agent_api.docs — single-file syntax reference, sliced by H2."""
2
+
3
+ from dataface.agent_api.docs._loader import (
4
+ DocsArgs,
5
+ DocsCorpusMissingError,
6
+ DocsResult,
7
+ DocsSearchHit,
8
+ Topic,
9
+ TopicEntry,
10
+ docs,
11
+ read_full_text,
12
+ slugify,
13
+ )
14
+
15
+ __all__ = [
16
+ "docs",
17
+ "read_full_text",
18
+ "slugify",
19
+ "TopicEntry",
20
+ "DocsArgs",
21
+ "DocsCorpusMissingError",
22
+ "DocsResult",
23
+ "DocsSearchHit",
24
+ "Topic",
25
+ ]