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,135 @@
1
+ """Pluggable cache-backend Protocol for query result storage.
2
+
3
+ Stage: EXECUTE (Cache)
4
+ Purpose: Define the abstract surface that any query-result cache backend must
5
+ implement. The only current implementation is DuckDBCache. Future alternatives
6
+ (Redis, S3, in-memory) can plug in by satisfying this Protocol.
7
+
8
+ Cache keys are always (source_hash, query_hash, variables_hash):
9
+ - source_hash — stable identity of the data source (connection string, project, etc.)
10
+ - query_hash — hash of the SQL/query after static resolution
11
+ - variables_hash — hash of the variables that materially affect the result
12
+
13
+ face_slug and query_name are METADATA, not key components. They are passed
14
+ as keyword-only arguments to put/put_failure so backends can build internal
15
+ indexes for {{ results.X }} cross-query references and snapshot history.
16
+
17
+ Backend selection: today DuckDBCache is the only implementation. A future
18
+ DFT_CACHE_BACKEND env-var hook can route to alternatives when a second
19
+ backend exists. This Protocol is also the seam for a future
20
+ `pip install dataface[duckdb]` extras-packaging effort.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from dataclasses import dataclass
26
+ from datetime import datetime
27
+ from typing import Any, Protocol, runtime_checkable
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class CachedQueryFailure(Exception):
32
+ """A query failure retrieved from the cache.
33
+
34
+ Raised instead of re-running a query that already failed within the TTL window.
35
+ Consumers can distinguish cached failures from fresh failures by catching this type.
36
+ """
37
+
38
+ error_class: str
39
+ error_message: str
40
+ traceback: str | None
41
+ failed_at: datetime
42
+
43
+
44
+ @runtime_checkable
45
+ class QueryResultCache(Protocol):
46
+ """Pluggable backend for persistent query-result caching.
47
+
48
+ All operations are keyed by (source_hash, query_hash, variables_hash).
49
+ face_slug and query_name are metadata passed on writes; they are NOT key
50
+ components. This keeps the key free of app-layer noise so two faces with
51
+ identical queries against identical sources share one cache entry.
52
+
53
+ Implementations may use any storage: DuckDB, Redis, S3, in-memory, etc.
54
+ The only current implementation is DuckDBCache.
55
+ """
56
+
57
+ def get(
58
+ self, source_hash: str, query_hash: str, variables_hash: str
59
+ ) -> list[dict[str, Any]] | None:
60
+ """Return cached rows, or None on miss."""
61
+ ...
62
+
63
+ def put(
64
+ self,
65
+ source_hash: str,
66
+ query_hash: str,
67
+ variables_hash: str,
68
+ data: list[dict[str, Any]],
69
+ *,
70
+ face_slug: str,
71
+ query_name: str,
72
+ variables: dict[str, Any],
73
+ ) -> None:
74
+ """Store rows under the given key; record face/query as metadata."""
75
+ ...
76
+
77
+ def get_failure(
78
+ self, source_hash: str, query_hash: str, variables_hash: str
79
+ ) -> CachedQueryFailure | None:
80
+ """Return a cached failure if one exists and is within TTL, else None."""
81
+ ...
82
+
83
+ def put_failure(
84
+ self,
85
+ source_hash: str,
86
+ query_hash: str,
87
+ variables_hash: str,
88
+ exception: Exception,
89
+ *,
90
+ face_slug: str,
91
+ query_name: str,
92
+ ) -> None:
93
+ """Store a query failure under the given key; record face/query as metadata."""
94
+ ...
95
+
96
+ def clear(self, source_hash: str, query_hash: str, variables_hash: str) -> None:
97
+ """Remove both success and failure entries for the given key."""
98
+ ...
99
+
100
+ def close(self) -> None:
101
+ """Release any held resources (connections, file handles, etc.)."""
102
+ ...
103
+
104
+ def supports_results_refs(self) -> bool:
105
+ """Return True if this backend can execute {{ results.X }} SQL queries.
106
+
107
+ DuckDBCache returns True (it has an embedded SQL engine).
108
+ Backends without a SQL engine return False; callers raise a clear error
109
+ ("{{ results.X }} requires a SQL-engine cache backend") in that case.
110
+ """
111
+ ...
112
+
113
+ def rewrite_results_refs(self, face_slug: str, sql: str) -> str:
114
+ """Rewrite {{ results.X }} references to backend-specific view/table names.
115
+
116
+ Args:
117
+ face_slug: Face identifier (for view name prefix)
118
+ sql: SQL containing {{ results.X }} references
119
+
120
+ Returns:
121
+ SQL with references substituted for backend-native names
122
+ """
123
+ ...
124
+
125
+ def execute_results_query(self, face_slug: str, sql: str) -> list[dict[str, Any]]:
126
+ """Execute a SQL query against cached result views.
127
+
128
+ Args:
129
+ face_slug: Face identifier
130
+ sql: SQL with {{ results.X }} already rewritten
131
+
132
+ Returns:
133
+ Result rows
134
+ """
135
+ ...
@@ -0,0 +1,66 @@
1
+ """Cache key helpers — produce identity payloads for source-aware hashing.
2
+
3
+ Stage: EXECUTE (Cache)
4
+ Purpose: Reduce a source reference to its cache identity, stripping secrets.
5
+
6
+ Secrets are NEVER included in cache hash inputs. Two users connecting to the
7
+ same source name with different credentials must produce different hashes
8
+ (so they don't share cache entries when their DB-side row-level access
9
+ differs); but a password rotation alone must NOT invalidate the cache.
10
+
11
+ `source_identity(source)` is the single transformation. The executor calls
12
+ it (via `compute_source_hash`) after resolving named source references
13
+ through the project's `face.sources` map.
14
+
15
+ See also:
16
+ - dataface/core/execute/duckdb_cache.py — `compute_source_hash` consumer
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from typing import Any
22
+
23
+ # Field names that must NEVER appear in cache hash inputs. Match by case-
24
+ # insensitive exact name. Conservative: anything that looks secret-shaped
25
+ # is dropped. Adding a new auth field elsewhere in the codebase? Add the
26
+ # name here.
27
+ SECRET_FIELDS: frozenset[str] = frozenset(
28
+ {
29
+ "password",
30
+ "passwd",
31
+ "secret",
32
+ "token",
33
+ "api_key",
34
+ "apikey",
35
+ "access_key",
36
+ "access_token",
37
+ "private_key",
38
+ "client_secret",
39
+ "auth",
40
+ "authorization",
41
+ }
42
+ )
43
+
44
+
45
+ def source_identity(
46
+ source: str | dict[str, Any] | None,
47
+ ) -> str | dict[str, Any] | None:
48
+ """Reduce a source reference to its identity for cache hashing.
49
+
50
+ String names and ``None`` pass through unchanged — they carry no
51
+ secrets and the caller hashes them as-is. Dict configs (from inline
52
+ YAML or resolved from `face.sources`) have every secret-shaped field
53
+ dropped, so passwords never reach cache table names or hash inputs.
54
+ Identity-bearing fields (user, host, project, dataset, keyfile, etc.)
55
+ are preserved so two users with the same source name but different
56
+ credentials get distinct cache entries.
57
+
58
+ Args:
59
+ source: ``str`` name reference, ``dict`` config, or ``None``.
60
+
61
+ Returns:
62
+ Same type, with secrets stripped from dicts.
63
+ """
64
+ if source is None or isinstance(source, str):
65
+ return source
66
+ return {k: v for k, v in source.items() if k.lower() not in SECRET_FIELDS}
@@ -0,0 +1,21 @@
1
+ """Shared dbt Jinja detection patterns.
2
+
3
+ Single source of truth for identifying SQL that contains dbt-specific
4
+ Jinja calls (ref(), source()). Used by both DbtAdapter and SqlAdapter
5
+ to route queries correctly.
6
+
7
+ The patterns handle:
8
+ - Standard spacing: {{ ref( and {{ source(
9
+ - No spacing: {{ref( and {{source(
10
+ - Whitespace trim: {{- ref( and {{- source(
11
+ """
12
+
13
+ import re
14
+
15
+ _DBT_REF_RE = re.compile(r"\{\{-?\s*ref\(")
16
+ _DBT_SOURCE_RE = re.compile(r"\{\{-?\s*source\(")
17
+
18
+
19
+ def has_dbt_jinja(sql: str) -> bool:
20
+ """Return True if sql contains a dbt ref() or source() Jinja call."""
21
+ return bool(_DBT_REF_RE.search(sql) or _DBT_SOURCE_RE.search(sql))
@@ -0,0 +1,121 @@
1
+ """SQL dialect registry for database-specific behavior.
2
+
3
+ This module provides a registry of SQL dialects for different database backends.
4
+ Use get_dialect() to obtain the appropriate dialect instance for a given
5
+ database profile type.
6
+
7
+ Example:
8
+ >>> from dataface.core.execute.dialects import get_dialect
9
+ >>> dialect = get_dialect('postgres')
10
+ >>> dialect.param(1)
11
+ '$1'
12
+ >>> dialect = get_dialect('mysql')
13
+ >>> dialect.param(1)
14
+ '%s'
15
+ """
16
+
17
+ from dataface.core.execute.dialects.athena import AthenaDialect
18
+ from dataface.core.execute.dialects.base import VALID_OPERATORS, SQLDialect
19
+ from dataface.core.execute.dialects.bigquery import BigQueryDialect
20
+ from dataface.core.execute.dialects.databricks import DatabricksDialect
21
+ from dataface.core.execute.dialects.duckdb import DuckDBDialect
22
+ from dataface.core.execute.dialects.mysql import MySQLDialect
23
+ from dataface.core.execute.dialects.postgres import PostgresDialect
24
+ from dataface.core.execute.dialects.redshift import RedshiftDialect
25
+ from dataface.core.execute.dialects.snowflake import SnowflakeDialect
26
+ from dataface.core.execute.dialects.sqlserver import SQLServerDialect
27
+
28
+ # Singleton instances for each dialect
29
+ _postgres_dialect = PostgresDialect()
30
+ _duckdb_dialect = DuckDBDialect()
31
+ _mysql_dialect = MySQLDialect()
32
+ _snowflake_dialect = SnowflakeDialect()
33
+ _bigquery_dialect = BigQueryDialect()
34
+ _redshift_dialect = RedshiftDialect()
35
+ _sqlserver_dialect = SQLServerDialect()
36
+ _databricks_dialect = DatabricksDialect()
37
+ _athena_dialect = AthenaDialect()
38
+
39
+ # Registry mapping profile types to dialect instances
40
+ DIALECTS: dict[str, SQLDialect] = {
41
+ # PostgreSQL (default)
42
+ "postgres": _postgres_dialect,
43
+ "postgresql": _postgres_dialect,
44
+ # DuckDB
45
+ "duckdb": _duckdb_dialect,
46
+ # MySQL / MariaDB
47
+ "mysql": _mysql_dialect,
48
+ "mariadb": _mysql_dialect,
49
+ # Snowflake
50
+ "snowflake": _snowflake_dialect,
51
+ # BigQuery
52
+ "bigquery": _bigquery_dialect,
53
+ # Redshift
54
+ "redshift": _redshift_dialect,
55
+ # SQL Server
56
+ "sqlserver": _sqlserver_dialect,
57
+ "mssql": _sqlserver_dialect,
58
+ # Databricks
59
+ "databricks": _databricks_dialect,
60
+ "spark": _databricks_dialect,
61
+ # Athena
62
+ "athena": _athena_dialect,
63
+ "presto": _athena_dialect,
64
+ "trino": _athena_dialect,
65
+ }
66
+
67
+ # Default dialect when profile type is unknown
68
+ DEFAULT_DIALECT = _postgres_dialect
69
+
70
+
71
+ def get_dialect(profile_type: str) -> SQLDialect:
72
+ """Get the appropriate SQL dialect for a database profile type.
73
+
74
+ Returns a singleton dialect instance for the given profile type.
75
+ Falls back to PostgreSQL dialect for unknown types.
76
+
77
+ Args:
78
+ profile_type: Database type string (e.g., 'postgres', 'mysql', 'snowflake')
79
+
80
+ Returns:
81
+ SQLDialect instance for the specified database type
82
+
83
+ Example:
84
+ >>> dialect = get_dialect('postgres')
85
+ >>> dialect.param(1)
86
+ '$1'
87
+ >>> dialect = get_dialect('unknown') # Falls back to PostgreSQL
88
+ >>> dialect.name
89
+ 'postgres'
90
+ """
91
+ return DIALECTS.get(profile_type.lower(), DEFAULT_DIALECT)
92
+
93
+
94
+ def list_dialects() -> list[str]:
95
+ """List all supported dialect profile types.
96
+
97
+ Returns:
98
+ List of profile type strings that are supported.
99
+ """
100
+ return sorted(set(DIALECTS.keys()))
101
+
102
+
103
+ __all__ = [
104
+ # Base class and constants
105
+ "SQLDialect",
106
+ "VALID_OPERATORS",
107
+ # Dialect implementations
108
+ "PostgresDialect",
109
+ "DuckDBDialect",
110
+ "MySQLDialect",
111
+ "SnowflakeDialect",
112
+ "BigQueryDialect",
113
+ "RedshiftDialect",
114
+ "SQLServerDialect",
115
+ "DatabricksDialect",
116
+ "AthenaDialect",
117
+ # Registry
118
+ "DIALECTS",
119
+ "get_dialect",
120
+ "list_dialects",
121
+ ]
@@ -0,0 +1,75 @@
1
+ """Athena dialect implementation.
2
+
3
+ Athena uses:
4
+ - ? for positional parameters
5
+ - NO temp table support (raises NotImplementedError)
6
+ """
7
+
8
+ from dataface.core.execute.dialects.base import SQLDialect
9
+
10
+
11
+ class AthenaDialect(SQLDialect):
12
+ """Athena dialect with ? parameter style and no temp table support.
13
+
14
+ AWS Athena is based on Presto/Trino and does not support temporary tables.
15
+ Calling temp_table() will raise NotImplementedError.
16
+
17
+ Example:
18
+ >>> dialect = AthenaDialect()
19
+ >>> dialect.param()
20
+ '?'
21
+ >>> dialect.supports_temp_tables
22
+ False
23
+ >>> dialect.filter('category', '=', 1)
24
+ 'category = ?'
25
+ """
26
+
27
+ name = "athena"
28
+
29
+ @property
30
+ def supports_temp_tables(self) -> bool:
31
+ """Athena does not support temporary tables.
32
+
33
+ Returns:
34
+ Always False for Athena.
35
+ """
36
+ return False
37
+
38
+ def param(self, index: int) -> str:
39
+ """Generate Athena parameter placeholder.
40
+
41
+ Athena uses ? for positional parameters.
42
+
43
+ Args:
44
+ index: 1-based parameter index (ignored for positional)
45
+
46
+ Returns:
47
+ Parameter placeholder '?'
48
+ """
49
+ return "?"
50
+
51
+ def temp_table(self, name: str, sql: str) -> str:
52
+ """Athena does not support temporary tables.
53
+
54
+ Args:
55
+ name: Name of the temporary table
56
+ sql: SQL query to populate the table
57
+
58
+ Raises:
59
+ NotImplementedError: Always, as Athena doesn't support temp tables
60
+ """
61
+ raise NotImplementedError(
62
+ "Athena does not support temporary tables. "
63
+ "Consider using CTEs or materializing to S3."
64
+ )
65
+
66
+ def drop_temp_table(self, name: str) -> str:
67
+ """Athena does not support temporary tables.
68
+
69
+ Args:
70
+ name: Name of the temporary table
71
+
72
+ Raises:
73
+ NotImplementedError: Always, as Athena doesn't support temp tables
74
+ """
75
+ raise NotImplementedError("Athena does not support temporary tables.")