dataface 0.2.1.dev691__py3-none-any.whl → 0.3.0__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.
- dataface/DATAFACE_SYNTAX.md +1 -1
- dataface/agent_api/dashboards.py +13 -4
- dataface/agent_api/describe.py +6 -12
- dataface/agent_api/docs/yaml-reference.md +129 -16
- dataface/agent_api/pack.py +1 -2
- dataface/agent_api/project_session.py +15 -20
- dataface/agent_api/search.py +7 -10
- dataface/agent_api/skill_install.py +8 -1
- dataface/agent_api/skills.py +121 -70
- dataface/agent_api/surface_aliases.yaml +18 -0
- dataface/agent_api/validate.py +15 -26
- dataface/ai/events.py +11 -1
- dataface/ai/llm.py +18 -14
- dataface/ai/prompts.py +8 -2
- dataface/ai/skills/analyst-runbook/SKILL.md +25 -8
- dataface/ai/skills/dashboard-build/SKILL.md +14 -6
- dataface/ai/skills/dashboard-pack-scaffolding/SKILL.md +2 -2
- dataface/ai/skills/dashboard-replicate/SKILL.md +6 -5
- dataface/ai/skills/table-heavy-ops-dashboard/SKILL.md +1 -2
- dataface/ai/tools/__init__.py +0 -1
- dataface/cli/commands/render.py +10 -6
- dataface/cli/filesystem_project.py +64 -3
- dataface/cli/main.py +1 -1
- dataface/core/compile/authoring_warnings.py +1 -1
- dataface/core/compile/compiler.py +100 -67
- dataface/core/compile/config.py +3 -3
- dataface/core/compile/face_warnings.py +210 -0
- dataface/core/compile/models/config.py +9 -0
- dataface/core/compile/models/dbt_credential_contract.py +130 -0
- dataface/core/compile/models/source.py +747 -61
- dataface/core/compile/models/style/resolved/_base.py +3 -3
- dataface/core/compile/models/style/resolved/_cascade.py +6 -1
- dataface/core/compile/models/style/resolved/callout.py +1 -0
- dataface/core/compile/models/style/theme/__init__.py +2 -0
- dataface/core/compile/models/style/theme/axis.py +12 -12
- dataface/core/compile/models/style/theme/board.py +23 -0
- dataface/core/compile/models/style/theme/page.py +30 -3
- dataface/core/compile/models/style/theme/style.py +1 -1
- dataface/core/compile/normalize_layout.py +1 -1
- dataface/core/compile/normalizer.py +4 -1
- dataface/core/compile/resolve/_resolve.py +93 -43
- dataface/core/connections.py +103 -3
- dataface/core/dashboard.py +8 -5
- dataface/core/defaults/default_config.yml +4 -1
- dataface/core/defaults/themes/_base.yaml +13 -4
- dataface/core/diagnostics/__init__.py +6 -0
- dataface/core/diagnostics/codes_compile.py +63 -1
- dataface/core/diagnostics/codes_render.py +48 -0
- dataface/core/execute/adapters/adapter_registry.py +27 -13
- dataface/core/execute/executor.py +3 -3
- dataface/core/inspect/templates/categorical_column.yml +0 -2
- dataface/core/inspect/templates/date_column.yml +0 -2
- dataface/core/inspect/templates/model.yml +0 -3
- dataface/core/inspect/templates/numeric_column.yml +0 -3
- dataface/core/inspect/templates/quality.yml +0 -1
- dataface/core/inspect/templates/string_column.yml +0 -4
- dataface/core/project.py +62 -85
- dataface/core/registered_views/expander.py +9 -19
- dataface/core/registered_views/loader.py +3 -1
- dataface/core/registered_views/templates/inspector/column.yaml +0 -1
- dataface/core/registered_views/templates/inspector/table.yaml +1 -1
- dataface/core/render/chart/callout.py +4 -0
- dataface/core/render/chart/data_table_attachment.py +44 -121
- dataface/core/render/chart/emitters/_cartesian.py +18 -4
- dataface/core/render/chart/emitters/_label_overlap.py +378 -251
- dataface/core/render/chart/emitters/_layers.py +235 -27
- dataface/core/render/chart/emitters/_measured_label_padding.py +1 -1
- dataface/core/render/chart/emitters/_overlay.py +88 -63
- dataface/core/render/chart/emitters/area.py +9 -2
- dataface/core/render/chart/emitters/bar.py +62 -24
- dataface/core/render/chart/emitters/heatmap.py +7 -2
- dataface/core/render/chart/emitters/line.py +8 -1
- dataface/core/render/chart/features/__init__.py +0 -3
- dataface/core/render/chart/rendering.py +2 -1
- dataface/core/render/chart/table.py +61 -21
- dataface/core/render/chart/table_support.py +144 -82
- dataface/core/render/chart/time_unit_detect.py +178 -227
- dataface/core/render/chart/type_inference.py +115 -108
- dataface/core/render/chart/validation.py +44 -1
- dataface/core/render/chart/vega_lite.py +9 -1
- dataface/core/render/chart/vl_field_maps.py +4 -1
- dataface/core/render/data_format.py +198 -0
- dataface/core/render/dir_context.py +5 -4
- dataface/core/render/face_to_dict.py +133 -8
- dataface/core/render/faces.py +8 -18
- dataface/core/render/json_format.py +10 -1
- dataface/core/render/layout_sizing.py +9 -3
- dataface/core/render/renderer.py +44 -42
- dataface/core/render/shared_y_datasets.py +33 -0
- dataface/core/render/sizing.py +2 -0
- dataface/core/render/stable_domain.py +9 -1
- dataface/core/render/templates/nav/nav.css +4 -1
- dataface/core/render/templates/nav/nav.html +10 -0
- dataface/core/render/templates/nav/nav.js +24 -0
- dataface/core/render/templates/page.css +24 -0
- dataface/core/render/warnings/value_labels_crowd_width.py +2 -2
- dataface/core/render/yaml_format.py +19 -98
- dataface/core/serve/alias_index.py +5 -8
- dataface/core/serve/server.py +1 -1
- dataface/integrations/markdown.py +39 -35
- {dataface-0.2.1.dev691.dist-info → dataface-0.3.0.dist-info}/METADATA +1 -1
- {dataface-0.2.1.dev691.dist-info → dataface-0.3.0.dist-info}/RECORD +109 -106
- mdsvg/__init__.py +1 -1
- mdsvg/playground.py +5 -18
- mdsvg/renderer.py +5 -6
- mdsvg/style.py +7 -0
- dataface/core/render/chart/features/grouped_bar.py +0 -67
- {dataface-0.2.1.dev691.dist-info → dataface-0.3.0.dist-info}/WHEEL +0 -0
- {dataface-0.2.1.dev691.dist-info → dataface-0.3.0.dist-info}/entry_points.txt +0 -0
- {dataface-0.2.1.dev691.dist-info → dataface-0.3.0.dist-info}/licenses/LICENSE +0 -0
dataface/DATAFACE_SYNTAX.md
CHANGED
|
@@ -676,7 +676,7 @@ style:
|
|
|
676
676
|
label: Amount
|
|
677
677
|
format: currency_whole
|
|
678
678
|
align: right # left | center | right
|
|
679
|
-
header_overflow: wrap-two # clip | truncate | wrap-two | wrap
|
|
679
|
+
header_overflow: wrap-two # clip | truncate | wrap-two (default) | wrap
|
|
680
680
|
header_link: "/columns/amount"
|
|
681
681
|
link: "/orders?id={{ order_id }}"
|
|
682
682
|
background: "#fafafa"
|
dataface/agent_api/dashboards.py
CHANGED
|
@@ -115,11 +115,20 @@ class RenderDashboardArgs(BaseModel):
|
|
|
115
115
|
variables: dict[str, Any] | None = Field(
|
|
116
116
|
None, description="Variable values to apply to the dashboard"
|
|
117
117
|
)
|
|
118
|
-
format: Literal["json", "text", "yaml", "svg", "terminal"] | None = Field(
|
|
118
|
+
format: Literal["json", "text", "yaml", "svg", "terminal", "data"] | None = Field(
|
|
119
119
|
None,
|
|
120
120
|
description=(
|
|
121
|
-
"Output format. 'json' (default) returns resolved chart "
|
|
122
|
-
"semantics and executed data as structured JSON
|
|
121
|
+
"Output format. 'json' (default) returns the full resolved chart "
|
|
122
|
+
"semantics and executed data as structured JSON, nested by "
|
|
123
|
+
"layout. 'data' returns a flatter, narrower view: 'queries' "
|
|
124
|
+
"keyed by query name (sql, plus one copy of the rows) and "
|
|
125
|
+
"'charts' keyed by slug carrying title/description/type and "
|
|
126
|
+
"encoding, each referencing its query by name. It drops the "
|
|
127
|
+
"layout nesting, repeats no rows across charts that share a "
|
|
128
|
+
"query, and reports the variable values the rows were produced "
|
|
129
|
+
"with — but emits only the authored chart fields, not every "
|
|
130
|
+
"resolved one, so prefer 'json' when you need the full chart. "
|
|
131
|
+
"'text' "
|
|
123
132
|
"returns a compact markdown summary of charts and data "
|
|
124
133
|
"(most token-efficient). 'yaml' returns resolved Dataface "
|
|
125
134
|
"YAML with inline data — valid input for re-compilation, "
|
|
@@ -165,7 +174,7 @@ def list_dashboards(
|
|
|
165
174
|
continue
|
|
166
175
|
if not any(key in content for key in DASHBOARD_KEYS):
|
|
167
176
|
continue
|
|
168
|
-
stem =
|
|
177
|
+
stem = pf.stem
|
|
169
178
|
dashboards.append(
|
|
170
179
|
DashboardSummary(
|
|
171
180
|
file=pf,
|
dataface/agent_api/describe.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from pathlib import Path
|
|
5
|
+
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
8
|
from pydantic import BaseModel, ConfigDict, Field
|
|
@@ -352,17 +352,11 @@ def _describe_one_path(
|
|
|
352
352
|
return [_describe_resolved(resolved, project=project)]
|
|
353
353
|
|
|
354
354
|
faces = sorted(
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
and not (pf.parent / INSPECT_TEMPLATE_MANIFEST).exists()
|
|
361
|
-
),
|
|
362
|
-
# Relpaths under `under` share a common prefix, so a PurePosixPath key
|
|
363
|
-
# reproduces the old absolute-Path sort order exactly on 3.10 and
|
|
364
|
-
# 3.13 — don't "simplify" this to a str/.parts key.
|
|
365
|
-
key=lambda pf: PurePosixPath(pf.relpath),
|
|
355
|
+
pf
|
|
356
|
+
for pf in project.iter_faces(under=resolved.relpath, recursive=True)
|
|
357
|
+
if pf.is_yaml
|
|
358
|
+
and not pf.is_private
|
|
359
|
+
and not (pf.parent / INSPECT_TEMPLATE_MANIFEST).exists()
|
|
366
360
|
)
|
|
367
361
|
if not faces:
|
|
368
362
|
return [
|
|
@@ -533,7 +533,7 @@ Authored overlay for Style — all fields optional. Adds CSS shorthand coercers.
|
|
|
533
533
|
| `variables` | [VariablesStyle](#variablesstyle) | ✓ | Variable controls chrome style. |
|
|
534
534
|
| `page` | [PageStyle](#pagestyle) | ✓ | Page-level canvas style (behind the board). |
|
|
535
535
|
| `footer` | [FooterStyle](#footerstyle) | ✓ | Page footer chrome visibility. |
|
|
536
|
-
| `timestamp` | [TimestampStyle](#timestampstyle) | ✓ |
|
|
536
|
+
| `timestamp` | [TimestampStyle](#timestampstyle) | ✓ | Data-freshness chrome: visibility, placement, format, and font. |
|
|
537
537
|
| `formats` | dict[str, str] | ✓ | Format alias map; None means no aliases at this cascade level. |
|
|
538
538
|
| `palettes` | dict[str, str] | ✓ | Theme palette role assignments: open dict mapping role name to palette file name. Default seed: chrome, info, negative, positive, warning, category, sequence, diverge. |
|
|
539
539
|
| `roles` | dict[str, str] | ✓ | Optional top-level theme role aliases: bare name → role.alias. e.g. ink: chrome.heading |
|
|
@@ -1126,6 +1126,7 @@ Authored overlay for TextStyle. Markdown / plain text content.
|
|
|
1126
1126
|
| `column` | [TextColumnStyle](#textcolumnstyle) | ✓ | Multi-column layout for the face body-text block. |
|
|
1127
1127
|
| `code` | [TextCodeStyle](#textcodestyle) | ✓ | Inline + fenced code box styling (font, background, border). |
|
|
1128
1128
|
| `blockquote` | [TextBlockquoteStyle](#textblockquotestyle) | ✓ | Blockquote box styling (font, background, border/left-rule). |
|
|
1129
|
+
| `bold` | [TextBoldStyle](#textboldstyle) | ✓ | Inline bold-run styling (weight), distinct from heading weight. |
|
|
1129
1130
|
|
|
1130
1131
|
<a id="placeholderstyle"></a>
|
|
1131
1132
|
## PlaceholderStyle
|
|
@@ -1241,14 +1242,14 @@ Authored overlay for FooterStyle. Page footer chrome: visibility, attribution te
|
|
|
1241
1242
|
|
|
1242
1243
|
<a id="timestampstyle"></a>
|
|
1243
1244
|
## TimestampStyle
|
|
1244
|
-
Authored overlay for TimestampStyle. Authored
|
|
1245
|
+
Authored overlay for TimestampStyle. Authored data-freshness chrome: visibility, placement, strftime format, font, and y-offset.
|
|
1245
1246
|
|
|
1246
1247
|
| Field | Type | Optional | Description |
|
|
1247
1248
|
|-------|------|:--------:|-------------|
|
|
1248
|
-
| `visible` | bool | ✓ | Show the
|
|
1249
|
+
| `visible` | bool | ✓ | Show the data-freshness line. |
|
|
1249
1250
|
| `position` | enum: "top", "footer" | ✓ | Timestamp row: top page chrome or footer baseline. |
|
|
1250
1251
|
| `align` | enum: "left", "right" | ✓ | Timestamp horizontal alignment within its row. |
|
|
1251
|
-
| `format` | str | ✓ | strftime format
|
|
1252
|
+
| `format` | str | ✓ | strftime format for the data-freshness line, including any literal label text (e.g. '%H:%M %Z on %-d %b %Y'). The value is always UTC; a format that prints a clock must disclose the zone (%Z or a literal 'UTC'), else compile rejects it — an unlabeled clock reads as local. |
|
|
1252
1253
|
| `y` | float | ✓ | Y-coordinate for top-positioned timestamp in pixels. |
|
|
1253
1254
|
| `font` | [FontStyle](#fontstyle) | ✓ | Timestamp font style overrides (size, color, weight, ...). |
|
|
1254
1255
|
|
|
@@ -1937,6 +1938,14 @@ Authored overlay for TextBlockquoteStyle. Blockquote prose. Box group; border is
|
|
|
1937
1938
|
| `background` | str | ✓ | Box background fill. |
|
|
1938
1939
|
| `border` | [BorderStyle](#borderstyle) | ✓ | Box border (width, color, radius). |
|
|
1939
1940
|
|
|
1941
|
+
<a id="textboldstyle"></a>
|
|
1942
|
+
## TextBoldStyle
|
|
1943
|
+
Authored overlay for TextBoldStyle. Inline **bold** text runs in markdown prose, distinct from heading weight.
|
|
1944
|
+
|
|
1945
|
+
| Field | Type | Optional | Description |
|
|
1946
|
+
|-------|------|:--------:|-------------|
|
|
1947
|
+
| `weight` | str \| float | ✓ | CSS font-weight for bold text runs and bold table cells. |
|
|
1948
|
+
|
|
1940
1949
|
<a id="placeholderoverlay"></a>
|
|
1941
1950
|
## PlaceholderOverlay
|
|
1942
1951
|
Authored overlay for PlaceholderOverlay.
|
|
@@ -2237,7 +2246,7 @@ Authored overlay for AxisElementStyle. Axis label or title: font + padding + VL-
|
|
|
2237
2246
|
| `angle` | float | ✓ | Label rotation angle in degrees; None uses Vega-Lite's default. |
|
|
2238
2247
|
| `align` | enum: "left", "right", "center", "inward", "outward" | ✓ | Horizontal text alignment of labels. 'left'/'right'/'center' are absolute. 'inward' hugs the plot (own-side: left on a left axis, right on a right axis); 'outward' hugs away from the plot (Vega-Lite's default growth direction). inward/outward are a no-op on an axis with no left/right edge. None uses Vega-Lite's default. |
|
|
2239
2248
|
| `baseline` | str | ✓ | Vertical text baseline of labels; None uses Vega-Lite's default. |
|
|
2240
|
-
| `overlap` | [AxisLabelOverlapConfig](#axislabeloverlapconfig) | ✓ | Label overlap strategy enablement. None inherits from the theme cascade. Set individual bools to enable/disable; the resolver applies them in fixed order tilt
|
|
2249
|
+
| `overlap` | [AxisLabelOverlapConfig](#axislabeloverlapconfig) | ✓ | Label overlap strategy enablement. None inherits from the theme cascade. Set individual bools to enable/disable; the resolver applies them in fixed order skip→tilt. On bucketed temporal axes, skip thins label visibility to a coarser calendar period without changing the axis or label time unit. |
|
|
2241
2250
|
| `separation` | float | ✓ | Minimum pixel separation between labels; None uses Vega-Lite's default (0px). |
|
|
2242
2251
|
| `visible` | bool | ✓ | Show axis labels; None uses Vega-Lite's default (labels shown). |
|
|
2243
2252
|
| `time_unit` | enum: "auto", "year", "yearquarter", "yearmonth", "yearweek", "yearmonthdate", "monthofyear", "dayofweek", "dayofmonth", "dayofyear", "hourofday", "none" | ✓ | Label cadence for temporal axes; None inherits from the parent axis time_unit. |
|
|
@@ -2654,12 +2663,12 @@ Authored overlay for AxisGridZeroStyle. Zero-baseline gridline color and width o
|
|
|
2654
2663
|
|
|
2655
2664
|
<a id="axislabeloverlapconfig"></a>
|
|
2656
2665
|
## AxisLabelOverlapConfig
|
|
2657
|
-
Authored overlay for AxisLabelOverlapConfig. Two-bool overlap strategy enablement for
|
|
2666
|
+
Authored overlay for AxisLabelOverlapConfig. Two-bool overlap strategy enablement for x-axis labels.
|
|
2658
2667
|
|
|
2659
2668
|
| Field | Type | Optional | Description |
|
|
2660
2669
|
|-------|------|:--------:|-------------|
|
|
2661
2670
|
| `tilt` | bool | ✓ | Enable label tilt strategy; None inherits from parent axis. |
|
|
2662
|
-
| `skip` | bool | ✓ | Enable
|
|
2671
|
+
| `skip` | bool | ✓ | Enable temporal label thinning; ignored on categorical axes; None inherits from parent axis. |
|
|
2663
2672
|
|
|
2664
2673
|
<a id="datatablerowpaddingstyle"></a>
|
|
2665
2674
|
## DataTableRowPaddingStyle
|
|
@@ -2804,15 +2813,25 @@ Postgres source configuration.
|
|
|
2804
2813
|
|-------|------|:--------:|-------------|
|
|
2805
2814
|
| `type` | enum: "postgres" | | Source type identifier. |
|
|
2806
2815
|
| `host` | str | | Database host name or IP address. |
|
|
2807
|
-
| `dbname` | str | | Database name (
|
|
2816
|
+
| `dbname` | str | | Database name (dbt accepts database as an input alias). |
|
|
2808
2817
|
| `user` | str | | Database user name. |
|
|
2809
|
-
| `password` | str | | Database password. |
|
|
2818
|
+
| `password` | str | | Database password (dbt accepts pass as an input alias). |
|
|
2810
2819
|
| `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
|
|
2820
|
+
| `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
|
|
2811
2821
|
| `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
|
|
2812
2822
|
| `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
|
|
2813
2823
|
| `port` | int | ✓ | Database port number. |
|
|
2814
2824
|
| `schema` | str | ✓ | Default schema for queries. |
|
|
2825
|
+
| `connect_timeout` | int | ✓ | Connection timeout in seconds. |
|
|
2826
|
+
| `role` | str | ✓ | PostgreSQL role to assume after connecting. |
|
|
2827
|
+
| `search_path` | str | ✓ | PostgreSQL search_path for the connection. |
|
|
2828
|
+
| `keepalives_idle` | int | ✓ | Idle seconds before TCP keepalives begin. |
|
|
2815
2829
|
| `sslmode` | enum: "disable", "allow", "prefer", "require", "verify-ca", "verify-full" | ✓ | libpq SSL mode forwarded to psycopg2. None lets libpq decide its default. |
|
|
2830
|
+
| `sslcert` | str | ✓ | Path to the client SSL certificate. |
|
|
2831
|
+
| `sslkey` | str | ✓ | Path to the client SSL private key. |
|
|
2832
|
+
| `sslrootcert` | str | ✓ | Path to the trusted SSL certificate authority file. |
|
|
2833
|
+
| `application_name` | str | ✓ | Application name reported to PostgreSQL. |
|
|
2834
|
+
| `retries` | int | ✓ | Number of connection retry attempts. |
|
|
2816
2835
|
|
|
2817
2836
|
<a id="snowflakesourceconfig"></a>
|
|
2818
2837
|
## SnowflakeSourceConfig
|
|
@@ -2822,15 +2841,38 @@ Snowflake source configuration.
|
|
|
2822
2841
|
|-------|------|:--------:|-------------|
|
|
2823
2842
|
| `type` | enum: "snowflake" | | Source type identifier. |
|
|
2824
2843
|
| `account` | str | | Snowflake account identifier (e.g. xy12345.us-east-1). |
|
|
2825
|
-
| `user` | str | | Snowflake user name. |
|
|
2826
2844
|
| `database` | str | | Snowflake database name. |
|
|
2827
|
-
| `warehouse` | str | | Snowflake virtual warehouse name. |
|
|
2828
2845
|
| `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
|
|
2846
|
+
| `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
|
|
2829
2847
|
| `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
|
|
2830
2848
|
| `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
|
|
2849
|
+
| `user` | str | ✓ | Snowflake user name. Omit for token-based authentication when supported. |
|
|
2831
2850
|
| `password` | str | ✓ | Snowflake password. Omit when using OAuth or key-pair auth. |
|
|
2851
|
+
| `warehouse` | str | ✓ | Snowflake virtual warehouse name. |
|
|
2832
2852
|
| `schema` | str | ✓ | Default schema for queries. |
|
|
2833
2853
|
| `role` | str | ✓ | Snowflake role to assume for the session. |
|
|
2854
|
+
| `authenticator` | str | ✓ | Snowflake authenticator name or external-browser mode. |
|
|
2855
|
+
| `private_key` | str | ✓ | PEM private key used for key-pair authentication. |
|
|
2856
|
+
| `private_key_path` | str | ✓ | Path to a PEM private key for key-pair authentication. |
|
|
2857
|
+
| `private_key_passphrase` | str | ✓ | Passphrase for the configured private key. |
|
|
2858
|
+
| `token` | str | ✓ | OAuth access token for token authentication. |
|
|
2859
|
+
| `oauth_client_id` | str | ✓ | OAuth client identifier. |
|
|
2860
|
+
| `oauth_client_secret` | str | ✓ | OAuth client secret. |
|
|
2861
|
+
| `query_tag` | str | ✓ | Snowflake query tag applied to statements. |
|
|
2862
|
+
| `client_session_keep_alive` | bool | ✓ | Whether Snowflake keeps the client session alive. |
|
|
2863
|
+
| `host` | str | ✓ | Snowflake host override. |
|
|
2864
|
+
| `port` | int | ✓ | Snowflake port override. |
|
|
2865
|
+
| `proxy_host` | str | ✓ | HTTP proxy host for Snowflake connections. |
|
|
2866
|
+
| `proxy_port` | int | ✓ | HTTP proxy port for Snowflake connections. |
|
|
2867
|
+
| `protocol` | str | ✓ | Network protocol for the Snowflake connection. |
|
|
2868
|
+
| `connect_retries` | int | ✓ | Number of retries while opening a connection. |
|
|
2869
|
+
| `connect_timeout` | int | ✓ | Connection timeout in seconds. |
|
|
2870
|
+
| `retry_on_database_errors` | bool | ✓ | Whether database errors are retried. |
|
|
2871
|
+
| `retry_all` | bool | ✓ | Whether all connection errors are retried. |
|
|
2872
|
+
| `insecure_mode` | bool | ✓ | Whether TLS certificate verification is disabled. |
|
|
2873
|
+
| `reuse_connections` | bool | ✓ | Whether dbt reuses Snowflake connections. |
|
|
2874
|
+
| `s3_stage_vpce_dns_name` | str | ✓ | Private VPC endpoint DNS name for S3 staging. |
|
|
2875
|
+
| `platform_detection_timeout_seconds` | float | ✓ | Timeout for Snowflake platform detection. |
|
|
2834
2876
|
|
|
2835
2877
|
<a id="bigquerysourceconfig"></a>
|
|
2836
2878
|
## BigQuerySourceConfig
|
|
@@ -2842,12 +2884,37 @@ BigQuery source configuration.
|
|
|
2842
2884
|
| `project` | str | | GCP project ID. |
|
|
2843
2885
|
| `dataset` | str | | BigQuery dataset name (equivalent to schema). |
|
|
2844
2886
|
| `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
|
|
2887
|
+
| `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
|
|
2845
2888
|
| `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
|
|
2846
2889
|
| `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
|
|
2847
2890
|
| `keyfile` | str | ✓ | Path to service account JSON key file. |
|
|
2848
|
-
| `keyfile_json` | dict[str,
|
|
2891
|
+
| `keyfile_json` | dict[str, str \| int \| float \| bool] | ✓ | Inline service account JSON dict. |
|
|
2849
2892
|
| `location` | str | ✓ | Dataset location (e.g. US, EU). |
|
|
2850
|
-
| `method` | enum: "oauth", "service-account", "service-account-json" | ✓ | dbt-bigquery authentication method. Inferred from keyfile/keyfile_json when omitted: 'service-account-json' if keyfile_json set, 'service-account' if keyfile set, 'oauth' (Application Default Credentials) otherwise. |
|
|
2893
|
+
| `method` | enum: "oauth", "oauth-secrets", "service-account", "service-account-json", "external-oauth-wif" | ✓ | dbt-bigquery authentication method. Inferred from keyfile/keyfile_json when omitted: 'service-account-json' if keyfile_json set, 'service-account' if keyfile set, 'oauth' (Application Default Credentials) otherwise. |
|
|
2894
|
+
| `execution_project` | str | ✓ | GCP project billed for BigQuery execution. |
|
|
2895
|
+
| `quota_project` | str | ✓ | GCP project used for quota attribution. |
|
|
2896
|
+
| `api_endpoint` | str | ✓ | BigQuery API endpoint override. |
|
|
2897
|
+
| `priority` | enum: "interactive", "batch" | ✓ | BigQuery job priority. |
|
|
2898
|
+
| `maximum_bytes_billed` | int | ✓ | Maximum bytes a BigQuery job may bill. |
|
|
2899
|
+
| `impersonate_service_account` | str | ✓ | Service account to impersonate for BigQuery jobs. |
|
|
2900
|
+
| `job_retry_deadline_seconds` | int | ✓ | Deadline in seconds for retrying a BigQuery job. |
|
|
2901
|
+
| `job_retries` | int | ✓ | Number of BigQuery job retry attempts (dbt accepts retries as an input alias). |
|
|
2902
|
+
| `job_creation_timeout_seconds` | int | ✓ | Timeout in seconds while creating a BigQuery job. |
|
|
2903
|
+
| `job_execution_timeout_seconds` | int | ✓ | Timeout in seconds while executing a BigQuery job. |
|
|
2904
|
+
| `token` | str | ✓ | OAuth access token. |
|
|
2905
|
+
| `refresh_token` | str | ✓ | OAuth refresh token. |
|
|
2906
|
+
| `client_id` | str | ✓ | OAuth client identifier. |
|
|
2907
|
+
| `client_secret` | str | ✓ | OAuth client secret. |
|
|
2908
|
+
| `token_uri` | str | ✓ | OAuth token endpoint URI. |
|
|
2909
|
+
| `workload_pool_provider_path` | str | ✓ | Workload identity pool provider resource path. |
|
|
2910
|
+
| `service_account_impersonation_url` | str | ✓ | Service-account impersonation endpoint URL. |
|
|
2911
|
+
| `token_endpoint` | dict[str, str] | ✓ | OAuth token endpoint configuration. |
|
|
2912
|
+
| `compute_region` | str | ✓ | Dataproc compute region. |
|
|
2913
|
+
| `dataproc_cluster_name` | str | ✓ | Dataproc cluster name. |
|
|
2914
|
+
| `gcs_bucket` | str | ✓ | Cloud Storage bucket for Dataproc submission. |
|
|
2915
|
+
| `submission_method` | str | ✓ | dbt-bigquery Dataproc submission method. |
|
|
2916
|
+
| `dataproc_batch` | dict[str, str \| int \| float \| bool] | ✓ | Dataproc batch configuration. |
|
|
2917
|
+
| `scopes` | list[str] | ✓ | OAuth scopes requested for BigQuery credentials. |
|
|
2851
2918
|
|
|
2852
2919
|
<a id="redshiftsourceconfig"></a>
|
|
2853
2920
|
## RedshiftSourceConfig
|
|
@@ -2857,14 +2924,43 @@ Redshift source configuration.
|
|
|
2857
2924
|
|-------|------|:--------:|-------------|
|
|
2858
2925
|
| `type` | enum: "redshift" | | Source type identifier. |
|
|
2859
2926
|
| `host` | str | | Redshift cluster host name. |
|
|
2860
|
-
| `dbname` | str | | Redshift database name. |
|
|
2861
|
-
| `user` | str | | Redshift user name. |
|
|
2862
|
-
| `password` | str | | Redshift password. |
|
|
2927
|
+
| `dbname` | str | | Redshift database name (dbt accepts database as an input alias). |
|
|
2863
2928
|
| `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
|
|
2929
|
+
| `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
|
|
2864
2930
|
| `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
|
|
2865
2931
|
| `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
|
|
2866
2932
|
| `port` | int | ✓ | Redshift port number. |
|
|
2867
2933
|
| `schema` | str | ✓ | Default schema for queries. |
|
|
2934
|
+
| `user` | str | ✓ | Redshift user name. Omit for IAM-based authentication when supported. |
|
|
2935
|
+
| `password` | str | ✓ | Redshift password. Omit for IAM-based authentication when supported. |
|
|
2936
|
+
| `method` | str | ✓ | Redshift authentication method. |
|
|
2937
|
+
| `cluster_id` | str | ✓ | Redshift cluster identifier for IAM authentication. |
|
|
2938
|
+
| `iam_profile` | str | ✓ | IAM profile ARN used for Redshift authentication. |
|
|
2939
|
+
| `autocreate` | bool | ✓ | Whether dbt may create the database user. |
|
|
2940
|
+
| `db_groups` | list[str] | ✓ | Redshift database groups assigned to the user. |
|
|
2941
|
+
| `ra3_node` | bool | ✓ | Whether the target uses Redshift RA3 nodes. |
|
|
2942
|
+
| `connect_timeout` | int | ✓ | Connection timeout in seconds. |
|
|
2943
|
+
| `role` | str | ✓ | IAM role ARN used for Redshift operations. |
|
|
2944
|
+
| `sslmode` | str | ✓ | SSL verification mode for the Redshift connection. |
|
|
2945
|
+
| `retries` | int | ✓ | Number of Redshift connection retry attempts. |
|
|
2946
|
+
| `retry_all` | bool | ✓ | Whether all connection errors are retried. |
|
|
2947
|
+
| `region` | str | ✓ | AWS region containing the Redshift target. |
|
|
2948
|
+
| `autocommit` | bool | ✓ | Whether Redshift statements autocommit. |
|
|
2949
|
+
| `access_key_id` | str | ✓ | AWS access key identifier. |
|
|
2950
|
+
| `secret_access_key` | str | ✓ | AWS secret access key. |
|
|
2951
|
+
| `idc_region` | str | ✓ | AWS IAM Identity Center region. |
|
|
2952
|
+
| `issuer_url` | str | ✓ | Identity-provider issuer URL. |
|
|
2953
|
+
| `idp_listen_port` | int | ✓ | Local port used for identity-provider callbacks. |
|
|
2954
|
+
| `idc_client_display_name` | str | ✓ | IAM Identity Center client display name. |
|
|
2955
|
+
| `idp_response_timeout` | int | ✓ | Identity-provider response timeout in seconds. |
|
|
2956
|
+
| `token_endpoint` | dict[str, str] | ✓ | Identity-provider token endpoint configuration. |
|
|
2957
|
+
| `is_serverless` | bool | ✓ | Whether the target is Redshift Serverless. |
|
|
2958
|
+
| `serverless_work_group` | str | ✓ | Redshift Serverless workgroup name. |
|
|
2959
|
+
| `serverless_acct_id` | str | ✓ | AWS account identifier for Redshift Serverless. |
|
|
2960
|
+
| `tcp_keepalive` | bool | ✓ | Whether TCP keepalives are enabled. |
|
|
2961
|
+
| `tcp_keepalive_idle` | int | ✓ | Idle seconds before TCP keepalives begin. |
|
|
2962
|
+
| `tcp_keepalive_interval` | int | ✓ | Seconds between TCP keepalive probes. |
|
|
2963
|
+
| `tcp_keepalive_count` | int | ✓ | Number of TCP keepalive probes before failure. |
|
|
2868
2964
|
|
|
2869
2965
|
<a id="mysqlsourceconfig"></a>
|
|
2870
2966
|
## MySQLSourceConfig
|
|
@@ -2878,6 +2974,7 @@ MySQL source configuration.
|
|
|
2878
2974
|
| `user` | str | | MySQL user name. |
|
|
2879
2975
|
| `password` | str | | MySQL password. |
|
|
2880
2976
|
| `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
|
|
2977
|
+
| `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
|
|
2881
2978
|
| `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
|
|
2882
2979
|
| `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
|
|
2883
2980
|
| `port` | int | ✓ | MySQL port number. |
|
|
@@ -2891,10 +2988,26 @@ DuckDB source configuration.
|
|
|
2891
2988
|
|-------|------|:--------:|-------------|
|
|
2892
2989
|
| `type` | enum: "duckdb" | | Source type identifier. |
|
|
2893
2990
|
| `cache` | [Cache](#cache) | ✓ | Cache policy default for every query against this source, e.g. cache: 1h — queries inherit it and may refine it; cache: false opts them out. |
|
|
2991
|
+
| `max_query_duration_seconds` | int | ✓ | Maximum execution time for one query in seconds. Overrides execution.max_query_duration_seconds for this source. |
|
|
2894
2992
|
| `lookml_path` | str | ✓ | Relative path to the directory of .lkml files backing this source's models. |
|
|
2895
2993
|
| `models` | dict[str, [LookMLModelConfig](#lookmlmodelconfig)] | ✓ | Named LookML model collections nested under this source. |
|
|
2896
2994
|
| `path` | str | ✓ | DuckDB file path or ':memory:' for an in-memory database. |
|
|
2897
2995
|
| `schema` | str | ✓ | Default schema for unqualified table names (sets search_path). |
|
|
2996
|
+
| `duckdb_config` | dict[str, str \| int \| float \| bool] | ✓ | DuckDB connection configuration values, such as enable_external_access. |
|
|
2997
|
+
| `extensions` | list[str \| dict[str, str]] | ✓ | DuckDB extensions to install and load. |
|
|
2998
|
+
| `settings` | dict[str, str \| int \| float \| bool] | ✓ | DuckDB settings and pragma values. |
|
|
2999
|
+
| `secrets` | list[dict[str, str \| int \| float \| bool]] | ✓ | DuckDB secret definitions for external services. |
|
|
3000
|
+
| `external_root` | str | ✓ | Root path for dbt-duckdb external materializations. |
|
|
3001
|
+
| `use_credential_provider` | str | ✓ | Credential-provider chain used for external services. |
|
|
3002
|
+
| `attach` | list[DuckDBAttachmentConfig] | ✓ | Databases to attach to the DuckDB connection. |
|
|
3003
|
+
| `filesystems` | list[dict[str, str \| int \| float \| bool]] | ✓ | fsspec filesystem configurations attached to DuckDB. |
|
|
3004
|
+
| `remote` | DuckDBRemoteConfig | ✓ | Remote DuckDB connection configuration. |
|
|
3005
|
+
| `plugins` | list[DuckDBPluginConfig] | ✓ | dbt-duckdb plugin configurations. |
|
|
3006
|
+
| `disable_transactions` | bool | ✓ | Whether dbt-duckdb disables statement transactions. |
|
|
3007
|
+
| `keep_open` | bool | ✓ | Whether dbt-duckdb keeps its connection open. |
|
|
3008
|
+
| `module_paths` | list[str] | ✓ | Python module paths dbt-duckdb loads. |
|
|
3009
|
+
| `retries` | DuckDBRetriesConfig | ✓ | dbt-duckdb connection and query retry configuration. |
|
|
3010
|
+
| `is_ducklake` | bool | ✓ | Whether this source uses DuckLake. |
|
|
2898
3011
|
|
|
2899
3012
|
<a id="sqlitesourceconfig"></a>
|
|
2900
3013
|
## SQLiteSourceConfig
|
dataface/agent_api/pack.py
CHANGED
|
@@ -24,7 +24,6 @@ from dataface.core.inspect.resolver import LayeredSchemaResolver
|
|
|
24
24
|
from dataface.core.pack.models import PackProposal, ProposedDashboard
|
|
25
25
|
from dataface.core.pack.planner import SourceEntry, plan_pack
|
|
26
26
|
from dataface.core.pack.proposal_store import dump_proposal
|
|
27
|
-
from dataface.core.project import Project
|
|
28
27
|
|
|
29
28
|
if TYPE_CHECKING:
|
|
30
29
|
from dataface.cli.filesystem_project import FilesystemProject
|
|
@@ -413,7 +412,7 @@ def _validate_scaffold_targets(
|
|
|
413
412
|
|
|
414
413
|
def apply_proposal(
|
|
415
414
|
proposal: PackProposal,
|
|
416
|
-
project:
|
|
415
|
+
project: FilesystemProject,
|
|
417
416
|
overwrite: bool = False,
|
|
418
417
|
) -> ScaffoldResult:
|
|
419
418
|
"""Apply an approved PackProposal, writing a sparse ``faces/`` folder tree.
|
|
@@ -64,8 +64,8 @@ class ProjectSession:
|
|
|
64
64
|
Composition roots (CLI, MCP, dft serve, Cloud, A lIe, Playground) construct
|
|
65
65
|
one ProjectSession at their documented boundary and pass it (or its component
|
|
66
66
|
resources) into core. Verb methods on ProjectSession are thin forwarders to
|
|
67
|
-
agent_api functions — they unpack self.project
|
|
68
|
-
|
|
67
|
+
agent_api functions — they unpack self.project so callers don't re-thread
|
|
68
|
+
it at every call site.
|
|
69
69
|
"""
|
|
70
70
|
|
|
71
71
|
project: Project
|
|
@@ -206,15 +206,13 @@ class ProjectSession:
|
|
|
206
206
|
# from_project(adapter_registry=...)) never reach here. But
|
|
207
207
|
# from_project() can also be called WITHOUT an injected registry
|
|
208
208
|
# against a non-filesystem Project (e.g. rendering a query-less face
|
|
209
|
-
# through an in-memory Project in tests) — that's a supported path
|
|
210
|
-
#
|
|
211
|
-
#
|
|
212
|
-
#
|
|
213
|
-
#
|
|
214
|
-
# reaches (a non-filesystem Project has no data files to open on
|
|
215
|
-
# local disk in the first place).
|
|
209
|
+
# through an in-memory Project in tests) — that's a supported path:
|
|
210
|
+
# build_adapter_registry takes a base Project and only special-cases
|
|
211
|
+
# FilesystemProject internally (data_dir / dbt-sibling detection fall
|
|
212
|
+
# back to None for any other host), so no data file is ever
|
|
213
|
+
# materialized via a non-filesystem Project's disk.
|
|
216
214
|
return build_adapter_registry(
|
|
217
|
-
|
|
215
|
+
self.project,
|
|
218
216
|
read_only=self._read_only,
|
|
219
217
|
profile_type=self._dialect,
|
|
220
218
|
duckdb_config=self._duckdb_config,
|
|
@@ -244,7 +242,7 @@ class ProjectSession:
|
|
|
244
242
|
# Cloud-managed sources on every refresh-driven path. Popping the
|
|
245
243
|
# cached keys preserves the instance (and its class) while forcing the
|
|
246
244
|
# next access to re-run each property body.
|
|
247
|
-
for key in ("
|
|
245
|
+
for key in ("sources", "warnings_ignore"):
|
|
248
246
|
vars(self.project).pop(key, None)
|
|
249
247
|
|
|
250
248
|
def close(self) -> None:
|
|
@@ -264,7 +262,11 @@ class ProjectSession:
|
|
|
264
262
|
|
|
265
263
|
@property
|
|
266
264
|
def faces_dir(self) -> Path:
|
|
267
|
-
|
|
265
|
+
# ProjectSession is FS-only-meaningful here: `.open()` always builds a
|
|
266
|
+
# FilesystemProject, and this property's only caller
|
|
267
|
+
# (ai/context.py's resolve_dashboard_path) is a CLI/MCP-only path.
|
|
268
|
+
# Same reasoning as the adapter_registry cast above.
|
|
269
|
+
return cast("FilesystemProject", self.project).faces_dir
|
|
268
270
|
|
|
269
271
|
@cached_property
|
|
270
272
|
def _relationship_context(self) -> RelationshipContext | None:
|
|
@@ -285,14 +287,7 @@ class ProjectSession:
|
|
|
285
287
|
|
|
286
288
|
def validate_paths(self, paths: list[Path] | None) -> list[ValidateResult]:
|
|
287
289
|
results = _validate.validate_paths(paths, project=self.project)
|
|
288
|
-
return _validate.annotate_with_data_lint(results,
|
|
289
|
-
|
|
290
|
-
def _source_names(self) -> frozenset[str]:
|
|
291
|
-
"""Return the configured source names for /data/ alias validation.
|
|
292
|
-
|
|
293
|
-
Reads from the project config file — no adapter registry or DB connection needed.
|
|
294
|
-
"""
|
|
295
|
-
return frozenset(self.sources.sources.keys())
|
|
290
|
+
return _validate.annotate_with_data_lint(results, project=self.project)
|
|
296
291
|
|
|
297
292
|
@overload
|
|
298
293
|
def validate_query(
|
dataface/agent_api/search.py
CHANGED
|
@@ -240,19 +240,16 @@ def _build_index(project: Project, *, under: str) -> list[dict[str, Any]]:
|
|
|
240
240
|
continue
|
|
241
241
|
if not isinstance(content, dict):
|
|
242
242
|
continue
|
|
243
|
-
title = content.get("title",
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
#
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
Path(relpath.removeprefix(prefix))
|
|
250
|
-
if relpath.startswith(prefix)
|
|
251
|
-
else Path(relpath)
|
|
243
|
+
title = content.get("title", pf.stem)
|
|
244
|
+
rel = PurePosixPath(pf.relpath)
|
|
245
|
+
# iter_faces(under=FACES_SUBDIR) guarantees relpath is under "faces/",
|
|
246
|
+
# but the fallback keeps face_path sane if that ever changes.
|
|
247
|
+
face_path = Path(
|
|
248
|
+
rel.relative_to(FACES_SUBDIR) if rel.is_relative_to(FACES_SUBDIR) else rel
|
|
252
249
|
)
|
|
253
250
|
entry = _index_entry_from_content(
|
|
254
251
|
face_path=face_path,
|
|
255
|
-
file_path=Path(relpath),
|
|
252
|
+
file_path=Path(pf.relpath),
|
|
256
253
|
title=title,
|
|
257
254
|
description=content.get("description", ""),
|
|
258
255
|
content=content,
|
|
@@ -49,7 +49,11 @@ class InstallSkillsResult(BaseModel):
|
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
def skills_for_file_install() -> list[Skill]:
|
|
52
|
-
"""Workflow skills exposed on the CLI surface.
|
|
52
|
+
"""Workflow skills exposed on the CLI surface.
|
|
53
|
+
|
|
54
|
+
All file-backed by construction: no ``project``/``extra_skills`` is passed,
|
|
55
|
+
so only wheel built-ins are listed.
|
|
56
|
+
"""
|
|
53
57
|
return sorted(
|
|
54
58
|
(s for s in list_skills(surface="cli").skills if s.kind == "workflow"),
|
|
55
59
|
key=lambda s: s.name,
|
|
@@ -87,6 +91,9 @@ def detect_legacy_skill_dirs(
|
|
|
87
91
|
|
|
88
92
|
|
|
89
93
|
def _rendered_skill_md(skill: Skill) -> str:
|
|
94
|
+
# Narrowing only — skills_for_file_install lists built-ins, which always
|
|
95
|
+
# have a directory; a file-less one would raise on the `/` below anyway.
|
|
96
|
+
assert skill.directory is not None
|
|
90
97
|
raw = (skill.directory / "SKILL.md").read_text(encoding="utf-8")
|
|
91
98
|
if not raw.startswith("---"):
|
|
92
99
|
raise ValueError(f"{skill.directory / 'SKILL.md'}: missing frontmatter")
|