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,110 @@
1
+ """
2
+ Dataface file detection utilities.
3
+
4
+ Determines whether a file is a Dataface YAML (or markdown report) by path
5
+ conventions or content analysis.
6
+
7
+ IMPORTANT: This detection logic is duplicated in the VS Code extension for performance.
8
+ If you update the detection rules here, also update:
9
+ - apps/ide/vscode-extension/src/detection.ts (pathSegmentsIncludeFaces, hasDatafaceKeys)
10
+ - apps/ide/vscode-extension/src/extension.ts (autoDetectDatafaceFile, isDatafaceFile)
11
+
12
+ Detection methods (in order of precedence):
13
+ 1. File extension: *.dataface.yml, *.dataface.yaml
14
+ 2. Directory convention: faces/*.yml, faces/*.yaml, faces/*.md
15
+ 3. Content detection: YAML with (queries: OR charts:) AND (rows: OR cols: OR grid: OR tabs:)
16
+ 4. Markdown reports: .md files with Dataface YAML frontmatter
17
+ """
18
+
19
+ import re
20
+ from pathlib import Path
21
+
22
+
23
+ def is_dataface_file(path: Path | str) -> bool:
24
+ """
25
+ Check if a file is a Dataface YAML or markdown report by path or content.
26
+
27
+ Args:
28
+ path: Path to the file to check
29
+
30
+ Returns:
31
+ True if the file is detected as a Dataface file
32
+ """
33
+ path = Path(path)
34
+
35
+ # Markdown report files
36
+ if path.suffix.lower() == ".md":
37
+ from dataface.core.compile.markdown import is_markdown_face
38
+
39
+ return is_markdown_face(path)
40
+
41
+ # Must be a YAML file
42
+ if path.suffix.lower() not in (".yml", ".yaml"):
43
+ return False
44
+
45
+ # Check file extension pattern: *.dataface.yml
46
+ if path.name.endswith(".dataface.yml") or path.name.endswith(".dataface.yaml"):
47
+ return True
48
+
49
+ # Check exact filename: dataface.yml
50
+ if path.name.lower() in ("dataface.yml", "dataface.yaml"):
51
+ return True
52
+
53
+ # Check directory convention: faces/*.yml
54
+ if "faces" in path.parts:
55
+ return True
56
+
57
+ # Content detection: check for Dataface-specific keys
58
+ if path.exists():
59
+ try:
60
+ content = path.read_text(encoding="utf-8")
61
+ return has_dataface_keys(content)
62
+ except (OSError, UnicodeDecodeError):
63
+ return False
64
+
65
+ return False
66
+
67
+
68
+ def has_dataface_keys(content: str) -> bool:
69
+ """
70
+ Check if YAML content contains Dataface-specific key patterns.
71
+
72
+ A file is considered Dataface if it has:
73
+ - (queries: OR charts:) AND (rows: OR cols: OR grid: OR tabs:)
74
+
75
+ This combination is distinctive enough to avoid false positives with
76
+ other YAML formats (dbt, Kubernetes, Docker Compose, etc.)
77
+
78
+ Args:
79
+ content: YAML file content as string
80
+
81
+ Returns:
82
+ True if content appears to be a Dataface file
83
+ """
84
+ # Check for data definition keys
85
+ has_queries = bool(re.search(r"^queries:", content, re.MULTILINE))
86
+ has_charts = bool(re.search(r"^charts:", content, re.MULTILINE))
87
+
88
+ # Check for layout keys
89
+ has_layout = bool(re.search(r"^(rows|cols|grid|tabs):", content, re.MULTILINE))
90
+
91
+ return (has_queries or has_charts) and has_layout
92
+
93
+
94
+ def find_dataface_files(directory: Path | str, recursive: bool = True) -> list[Path]:
95
+ """
96
+ Find all Dataface files in a directory.
97
+
98
+ Args:
99
+ directory: Directory to search
100
+ recursive: Whether to search subdirectories (default: True)
101
+
102
+ Returns:
103
+ List of paths to Dataface files
104
+ """
105
+ directory = Path(directory)
106
+ yaml_pattern = "**/*.y*ml" if recursive else "*.y*ml"
107
+ md_pattern = "**/*.md" if recursive else "*.md"
108
+
109
+ candidates = list(directory.glob(yaml_pattern)) + list(directory.glob(md_pattern))
110
+ return [p for p in candidates if is_dataface_file(p)]
@@ -0,0 +1,302 @@
1
+ """Compilation error types.
2
+
3
+ Stage: COMPILE
4
+ Purpose: Define error types for all compilation failures.
5
+
6
+ These errors are raised during:
7
+ - YAML parsing (ParseError, YAMLError)
8
+ - Schema validation (ValidationError)
9
+ - Reference resolution (ReferenceError)
10
+ - Jinja template rendering (JinjaError)
11
+
12
+ All errors inherit from CompilationError for easy catching.
13
+
14
+ Enhanced error messages include:
15
+ - Line numbers where errors occur
16
+ - YAML context showing the problematic snippet
17
+ - Helpful suggestions ("Did you mean 'bar'?")
18
+
19
+ Refs #94
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import sys
25
+ from typing import TYPE_CHECKING, Any
26
+
27
+ if sys.version_info >= (3, 11):
28
+ from typing import Self
29
+ else:
30
+ from typing_extensions import Self
31
+
32
+ if TYPE_CHECKING:
33
+ from dataface.core.errors.registry import ErrorCode
34
+ from dataface.core.errors.structured import StructuredError
35
+
36
+
37
+ class DatafaceError(Exception):
38
+ """Base error for all Dataface errors."""
39
+
40
+ code: ErrorCode | None = None
41
+ fields: dict[str, Any]
42
+
43
+ @classmethod
44
+ def from_code(cls, ec: ErrorCode, **fields: Any) -> Self:
45
+ """Construct an instance carrying a registry ErrorCode + structured fields.
46
+
47
+ Bypasses the subclass __init__ (and its `_format_message` decoration);
48
+ the rendered message is exactly `ec.message_template.format(**fields)`.
49
+ Reserved field names (`code`, `message`, `fields`) are skipped so the
50
+ registry-set values can't be clobbered by a caller-supplied field.
51
+ """
52
+ message = ec.message_template.format(**fields)
53
+ inst: Self = cls.__new__(cls)
54
+ Exception.__init__(inst, message)
55
+ inst.message = message # type: ignore[attr-defined]
56
+ inst.code = ec
57
+ inst.fields = dict(fields)
58
+ # Mirror fields onto typed subclass attributes so callers reading
59
+ # e.chart_id / e.chart_type / e.format / e.element get the same value
60
+ # whether the error was raised via legacy __init__ or from_code.
61
+ # Class-level None defaults on every subclass attr make setattr safe.
62
+ _reserved = {"code", "message", "fields"}
63
+ for key, value in fields.items():
64
+ if key in _reserved:
65
+ continue
66
+ setattr(inst, key, value)
67
+ return inst
68
+
69
+ def to_structured(self, *, file: str | None = None) -> StructuredError:
70
+ from dataface.core.errors.structured import build_structured
71
+
72
+ return build_structured(self, file=file)
73
+
74
+
75
+ class CompilationError(DatafaceError):
76
+ """Base error for all compilation failures.
77
+
78
+ This is the parent class for all compilation-related errors.
79
+ Catch this to handle any compilation error.
80
+
81
+ Attributes:
82
+ message: Human-readable error description
83
+ location: Optional location in source (line number, path, etc.)
84
+ line: Optional line number in the YAML file
85
+ column: Optional column number in the YAML file
86
+ context: Optional YAML snippet showing the error location
87
+ suggestion: Optional helpful suggestion for fixing the error
88
+ """
89
+
90
+ # Class-level None defaults so `from_code`-constructed instances (which
91
+ # bypass __init__) still satisfy `e.line` / `e.column` access without
92
+ # crashing. Mirrors the same pattern on RenderError / ExecutionError
93
+ # subclasses.
94
+ location: str | None = None
95
+ line: int | None = None
96
+ column: int | None = None
97
+ context: str | None = None
98
+ suggestion: str | None = None
99
+
100
+ def __init__(
101
+ self,
102
+ message: str,
103
+ location: str | None = None,
104
+ line: int | None = None,
105
+ column: int | None = None,
106
+ context: str | None = None,
107
+ suggestion: str | None = None,
108
+ ):
109
+ self.message = message
110
+ self.location = location
111
+ self.line = line
112
+ self.column = column
113
+ self.context = context
114
+ self.suggestion = suggestion
115
+ self.fields: dict[str, Any] = {}
116
+ super().__init__(self._format_message())
117
+ if self.code is None:
118
+ from dataface.core.errors.codes_unknown import DF_UNKNOWN_INTERNAL
119
+
120
+ self.code = DF_UNKNOWN_INTERNAL
121
+
122
+ def _format_message(self) -> str:
123
+ """Format error message with location, context, and suggestion."""
124
+ parts = []
125
+
126
+ # Add line/column header if available
127
+ if self.line:
128
+ if self.column:
129
+ parts.append(f"Error at line {self.line}, column {self.column}:")
130
+ else:
131
+ parts.append(f"Error at line {self.line}:")
132
+ elif self.location:
133
+ parts.append(f"Error at {self.location}:")
134
+
135
+ # Add YAML context if available
136
+ if self.context:
137
+ parts.append(self.context)
138
+ parts.append("") # Blank line after context
139
+
140
+ # Add the main message
141
+ parts.append(f" {self.message}" if parts else self.message)
142
+
143
+ # Add suggestion if available
144
+ if self.suggestion:
145
+ parts.append(f"\n {self.suggestion}")
146
+
147
+ return (
148
+ "\n".join(parts) if len(parts) > 1 else parts[0] if parts else self.message
149
+ )
150
+
151
+
152
+ class ParseError(CompilationError):
153
+ """Error during YAML parsing.
154
+
155
+ Raised when:
156
+ - YAML syntax is invalid
157
+ - YAML structure cannot be parsed
158
+
159
+ Attributes:
160
+ line: Line number where the error occurred
161
+ context: YAML snippet showing the error location
162
+ suggestion: Helpful fix suggestion
163
+
164
+ Example:
165
+ >>> try:
166
+ ... compile("invalid: yaml: content")
167
+ ... except ParseError as e:
168
+ ... print(f"Parse failed at line {e.line}: {e}")
169
+ """
170
+
171
+ def __init__(
172
+ self,
173
+ message: str,
174
+ line: int | None = None,
175
+ context: str | None = None,
176
+ suggestion: str | None = None,
177
+ ):
178
+ # Don't double-prefix if message already has "YAML parse error"
179
+ if not message.startswith("YAML parse error"):
180
+ message = f"YAML parse error: {message}"
181
+ super().__init__(
182
+ message,
183
+ location=f"line {line}" if line and not context else None,
184
+ line=line,
185
+ context=context,
186
+ suggestion=suggestion,
187
+ )
188
+
189
+
190
+ class ValidationError(CompilationError):
191
+ """Error during schema validation.
192
+
193
+ Raised when:
194
+ - Required fields are missing
195
+ - Field values are invalid type
196
+ - Enum values are not recognized
197
+ - Schema constraints are violated
198
+
199
+ Attributes:
200
+ field_path: Path to the field that failed validation
201
+ invalid_value: The value that caused the error
202
+ valid_values: List of valid values (if applicable)
203
+ line: Line number where the error occurred
204
+ context: YAML snippet showing the error location
205
+ suggestion: Helpful fix suggestion
206
+
207
+ Example:
208
+ >>> try:
209
+ ... compile("charts:\\n my_chart:\\n type: invalid_type")
210
+ ... except ValidationError as e:
211
+ ... print(f"Validation failed at line {e.line}: {e}")
212
+ """
213
+
214
+ field_path: str | None = None
215
+ invalid_value: str | None = None
216
+ valid_values: list | None = None
217
+
218
+ def __init__(
219
+ self,
220
+ message: str,
221
+ location: str | None = None,
222
+ line: int | None = None,
223
+ context: str | None = None,
224
+ suggestion: str | None = None,
225
+ field_path: str | None = None,
226
+ invalid_value: str | None = None,
227
+ valid_values: list | None = None,
228
+ ):
229
+ self.field_path = field_path
230
+ self.invalid_value = invalid_value
231
+ self.valid_values = valid_values
232
+
233
+ # Don't double-prefix if message already has "Validation error"
234
+ if not message.startswith("Validation error"):
235
+ message = f"Validation error: {message}"
236
+
237
+ super().__init__(
238
+ message,
239
+ location=location if not context else None,
240
+ line=line,
241
+ context=context,
242
+ suggestion=suggestion,
243
+ )
244
+
245
+
246
+ class ReferenceError(CompilationError):
247
+ """Error resolving a reference.
248
+
249
+ Raised when:
250
+ - Chart references unknown query
251
+ - Layout references unknown chart
252
+ - Remote reference cannot be resolved
253
+ - Partial file not found
254
+
255
+ Attributes:
256
+ ref: The reference that could not be resolved
257
+ context: Where the reference was used
258
+
259
+ Example:
260
+ >>> try:
261
+ ... compile("charts:\\n my_chart:\\n query: unknown_query")
262
+ ... except ReferenceError as e:
263
+ ... print(f"Reference '{e.ref}' not found")
264
+ """
265
+
266
+ ref: str | None = None
267
+
268
+ def __init__(self, ref: str, context: str | None = None):
269
+ self.ref = ref
270
+ message = f"Reference '{ref}' not found"
271
+ location = f"in {context}" if context else None
272
+ super().__init__(message, location)
273
+
274
+
275
+ class JinjaError(CompilationError):
276
+ """Error during Jinja template resolution.
277
+
278
+ Raised when:
279
+ - Jinja syntax is invalid
280
+ - Variable not found in template context
281
+ - Filter not found
282
+
283
+ Attributes:
284
+ template: The template that caused the error (if available)
285
+
286
+ Example:
287
+ >>> try:
288
+ ... compile("queries:\\n q: SELECT * FROM {{ undefined_var }}")
289
+ ... except JinjaError as e:
290
+ ... print(f"Template error: {e}")
291
+ """
292
+
293
+ template: str | None = None
294
+
295
+ def __init__(self, message: str, template: str | None = None):
296
+ self.template = template
297
+ location = (
298
+ f"template: {template[:50]}..."
299
+ if template and len(template) > 50
300
+ else template
301
+ )
302
+ super().__init__(f"Jinja error: {message}", location)