dataface 0.3.2.dev22__py3-none-any.whl → 0.3.2.dev111__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/__init__.py +70 -23
- dataface/agent_api/__init__.py +162 -68
- dataface/agent_api/_paths.py +9 -3
- dataface/agent_api/docs/yaml-reference.md +240 -106
- dataface/agent_api/init.py +1 -1
- dataface/agent_api/project_session.py +2 -1
- dataface/agent_api/serve.py +115 -0
- dataface/ai/agent.py +28 -2
- dataface/cli/_project.py +100 -1
- dataface/cli/commands/board_artifact.py +5 -2
- dataface/cli/commands/describe.py +7 -3
- dataface/cli/commands/docs.py +12 -3
- dataface/cli/commands/init.py +7 -14
- dataface/cli/commands/inspect.py +6 -1
- dataface/cli/commands/mcp_init.py +23 -43
- dataface/cli/commands/migrate.py +8 -3
- dataface/cli/commands/query.py +11 -8
- dataface/cli/commands/render.py +20 -9
- dataface/cli/commands/search.py +8 -2
- dataface/cli/commands/serve.py +26 -76
- dataface/cli/commands/skills_init.py +2 -19
- dataface/cli/commands/validate.py +7 -2
- dataface/cli/filesystem_project.py +5 -4
- dataface/cli/main.py +2 -19
- dataface/core/__init__.py +73 -28
- dataface/core/{compile/colors.py → colors.py} +20 -5
- dataface/core/compile/compiler.py +97 -34
- dataface/core/compile/data_table.py +7 -2
- dataface/core/compile/enrich.py +18 -44
- dataface/core/compile/face_warnings.py +46 -8
- dataface/core/compile/format.py +47 -1
- dataface/core/compile/inherit_graph.py +3 -3
- dataface/core/compile/inherit_registry.yaml +1 -1
- dataface/core/compile/migrations.py +112 -9
- dataface/core/compile/models/chart/normalized/kpi.py +0 -4
- dataface/core/compile/models/chart/resolved/_base.py +28 -10
- dataface/core/compile/models/chart/resolved/callout.py +2 -3
- dataface/core/compile/models/chart/resolved/kpi.py +7 -3
- dataface/core/compile/models/chart/resolved/table.py +16 -2
- dataface/core/compile/models/markers.py +1 -1
- dataface/core/compile/models/primitives.py +175 -2
- dataface/core/compile/models/source.py +5 -5
- dataface/core/compile/models/style/authored/__init__.py +32 -8
- dataface/core/compile/models/style/authored/_base.py +126 -69
- dataface/core/compile/models/style/authored/table.py +61 -3
- dataface/core/compile/models/style/resolved/__init__.py +12 -2
- dataface/core/compile/models/style/resolved/_base.py +142 -57
- dataface/core/compile/models/style/resolved/_cartesian.py +6 -11
- dataface/core/compile/models/style/resolved/_cascade.py +141 -54
- dataface/core/compile/models/style/resolved/area.py +1 -1
- dataface/core/compile/models/style/resolved/bar.py +1 -1
- dataface/core/compile/models/style/resolved/line.py +1 -1
- dataface/core/compile/models/style/resolved/scatter.py +3 -2
- dataface/core/compile/models/style/theme/__init__.py +36 -14
- dataface/core/compile/models/style/theme/_chart_base.py +17 -9
- dataface/core/compile/models/style/theme/axis.py +432 -312
- dataface/core/compile/models/style/theme/charts.py +10 -6
- dataface/core/compile/models/style/theme/kpi.py +2 -1
- dataface/core/compile/models/style/theme/page.py +5 -2
- dataface/core/compile/models/style/theme/table.py +2 -2
- dataface/core/compile/models/vega_lite/config.py +1 -1
- dataface/core/compile/normalize_charts.py +6 -2
- dataface/core/compile/normalize_queries.py +21 -7
- dataface/core/compile/resolve/__init__.py +2 -0
- dataface/core/compile/resolve/_axes.py +147 -44
- dataface/core/compile/resolve/_channels.py +1 -1
- dataface/core/compile/resolve/_dispatch.py +1 -1
- dataface/core/compile/resolve/_domain.py +49 -32
- dataface/core/compile/resolve/_kwargs.py +39 -12
- dataface/core/compile/resolve/_marks.py +8 -3
- dataface/core/compile/resolve/_palette.py +7 -3
- dataface/core/compile/resolve/_table.py +124 -33
- dataface/core/compile/resolve/area.py +48 -18
- dataface/core/compile/resolve/bar.py +245 -64
- dataface/core/compile/resolve/geo.py +10 -3
- dataface/core/compile/resolve/heatmap.py +16 -8
- dataface/core/compile/resolve/line.py +35 -12
- dataface/core/compile/resolve/pie.py +4 -1
- dataface/core/compile/resolve/pie_attachment.py +1 -1
- dataface/core/compile/resolve/scatter.py +25 -13
- dataface/core/compile/resolve/simple.py +25 -2
- dataface/core/compile/schema_renderers/prompt.py +1 -1
- dataface/core/compile/schema_renderers/textmate_grammar.py +8 -1
- dataface/core/compile/source_map.py +211 -28
- dataface/core/compile/style_cascade.py +126 -55
- dataface/core/compile/yaml_error_formatter.py +1 -1
- dataface/core/connections.py +10 -3
- dataface/core/dashboard.py +24 -18
- dataface/core/defaults/themes/_base.yaml +49 -39
- dataface/core/defaults/themes/cream.yaml +4 -4
- dataface/core/defaults/themes/diagnostics-title-baseline.yaml +1 -1
- dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +1 -1
- dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +1 -1
- dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +1 -1
- dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +1 -1
- dataface/core/defaults/themes/editorial.yaml +6 -6
- dataface/core/defaults/themes/neon.yaml +15 -8
- dataface/core/defaults/themes/plain.yaml +6 -4
- dataface/core/defaults/themes/stark.yaml +16 -7
- dataface/core/defaults/themes/vivid.yaml +15 -8
- dataface/core/diagnostics/__init__.py +2 -2
- dataface/core/diagnostics/codes_compile.py +13 -31
- dataface/core/diagnostics/codes_execute.py +79 -0
- dataface/core/diagnostics/codes_render.py +87 -28
- dataface/core/diagnostics/diagnostic.py +30 -0
- dataface/core/diagnostics/hints.py +19 -0
- dataface/core/dialects/base.py +17 -0
- dataface/core/dialects/postgres.py +14 -0
- dataface/core/dialects/redshift.py +5 -0
- dataface/core/execute/__init__.py +59 -14
- dataface/core/execute/adapters/dbt_adapter.py +4 -1
- dataface/core/execute/adapters/dbt_adapter_factory.py +19 -0
- dataface/core/execute/adapters/dbt_utils.py +84 -20
- dataface/core/execute/adapters/postgres_connection_manager.py +48 -0
- dataface/core/execute/adapters/sql_adapter.py +72 -4
- dataface/core/execute/dbt_jinja.py +65 -10
- dataface/core/execute/executor.py +69 -16
- dataface/core/font_measure.py +28 -0
- dataface/core/fonts.py +8 -5
- dataface/core/inspect/__init__.py +46 -6
- dataface/core/project.py +13 -1
- dataface/core/render/chart/data_table_attachment.py +14 -12
- dataface/core/render/chart/emitters/_cartesian.py +21 -18
- dataface/core/render/chart/emitters/_channels.py +56 -8
- dataface/core/render/chart/emitters/_label_overlap.py +18 -15
- dataface/core/render/chart/emitters/_measured_label_padding.py +4 -4
- dataface/core/render/chart/emitters/area.py +3 -3
- dataface/core/render/chart/emitters/bar.py +60 -35
- dataface/core/render/chart/emitters/geo.py +8 -13
- dataface/core/render/chart/emitters/heatmap.py +20 -26
- dataface/core/render/chart/emitters/line.py +2 -2
- dataface/core/render/chart/emitters/scatter.py +7 -30
- dataface/core/render/chart/features/baseline.py +22 -9
- dataface/core/render/chart/features/endpoint_labels.py +55 -32
- dataface/core/render/chart/features/mirror_axis.py +12 -9
- dataface/core/render/chart/features/value_labels.py +1 -1
- dataface/core/render/chart/kpi.py +11 -90
- dataface/core/render/chart/presentation.py +6 -8
- dataface/core/render/chart/rendering.py +3 -12
- dataface/core/render/chart/session.py +10 -0
- dataface/core/render/chart/spec.py +3 -0
- dataface/core/render/chart/spec_builders.py +18 -18
- dataface/core/render/chart/table.py +81 -36
- dataface/core/render/chart/table_support.py +2 -53
- dataface/core/render/chart/time_unit_detect.py +3 -2
- dataface/core/render/chart/translate.py +82 -44
- dataface/core/render/chart/type_inference.py +45 -25
- dataface/core/render/chart/validation.py +91 -0
- dataface/core/render/chart/vega_lite.py +30 -11
- dataface/core/render/chart/vl_field_maps.py +111 -76
- dataface/core/render/converters/chart.py +16 -6
- dataface/core/render/faces.py +3 -2
- dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.woff2 +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.woff2 +0 -0
- dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -93
- dataface/core/render/fonts/_font_face.css +10 -0
- dataface/core/render/layout_sizing.py +267 -238
- dataface/core/render/numeral_expr.py +80 -0
- dataface/core/render/warnings/bar_band_width_too_narrow.py +64 -6
- dataface/core/render/warnings/layered_chart_shared_y_axis_scale_mismatch.py +25 -3
- dataface/core/render/warnings/likely_currency_or_percent_missing_formatter.py +12 -6
- dataface/core/render/warnings/palette_unsupported.py +6 -0
- dataface/core/render/warnings/pie_dominant_segment.py +1 -0
- dataface/core/render/warnings/pie_too_many_segments.py +1 -0
- dataface/core/render/warnings/point_map_out_of_projection.py +1 -0
- dataface/core/render/warnings/query_returned_zero_rows.py +1 -0
- dataface/core/render/warnings/redundant_encoding.py +20 -1
- dataface/core/render/warnings/registry.py +7 -3
- dataface/core/render/warnings/temporal_single_point.py +1 -0
- dataface/core/render/warnings/too_many_color_categories.py +1 -0
- dataface/core/render/warnings/too_many_x_categories.py +18 -2
- dataface/core/render/warnings/value_labels_crowd_width.py +9 -0
- dataface/core/render/warnings/y_encoding_mostly_null.py +1 -0
- dataface/core/render_format.py +18 -0
- dataface/core/text/format_d3.py +56 -0
- dataface/core/text/numeral_scale.py +218 -0
- dataface/core/utils.py +103 -10
- dataface/data/schemas/board-resolved/board-resolved.schema.json +9487 -7978
- dataface/data/schemas/yaml/0.3.2.json +1 -0
- dataface/data/schemas/yaml/manifest.json +7 -0
- {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/METADATA +1 -1
- {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/RECORD +185 -177
- {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/WHEEL +0 -0
- {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/entry_points.txt +0 -0
- {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,12 +4,13 @@ Includes the top-level ``StylePatch`` (the all-encompassing authored overlay)
|
|
|
4
4
|
and the cross-cutting axis/scale/title/padding/tooltip/legend/mark patches
|
|
5
5
|
that chart-family patch files import.
|
|
6
6
|
|
|
7
|
-
Some patches here (``
|
|
8
|
-
``
|
|
9
|
-
built early and injected
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
so injection is the only
|
|
7
|
+
Some patches here (``BaseAxisStylePatch``, ``AxisXStylePatch``,
|
|
8
|
+
``AxisYStylePatch``, ``DataTableStylePatch``, ``PaddingStylePatch``,
|
|
9
|
+
``TooltipStylePatch``, ``TableChartStylePatch``) are built early and injected
|
|
10
|
+
back into ``style.theme``'s module globals so that Pydantic can resolve forward
|
|
11
|
+
references in theme chart-style classes — see the injection block below.
|
|
12
|
+
``theme.py`` must not import from this package, so injection is the only
|
|
13
|
+
DAG-safe path.
|
|
13
14
|
"""
|
|
14
15
|
|
|
15
16
|
from __future__ import annotations
|
|
@@ -34,16 +35,23 @@ from dataface.core.compile.models.style.theme import (
|
|
|
34
35
|
AreaChartStyle,
|
|
35
36
|
AreaLayerStyle,
|
|
36
37
|
AreaMarkStyle,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
AxisGridStyle,
|
|
40
|
-
AxisStyle,
|
|
38
|
+
AxisLabelStyle,
|
|
39
|
+
AxisLineStyle,
|
|
41
40
|
AxisTicksStyle,
|
|
41
|
+
AxisTitleStyle,
|
|
42
|
+
AxisXStyle,
|
|
43
|
+
AxisYStyle,
|
|
44
|
+
BandAxisStyle,
|
|
42
45
|
BarChartStyle,
|
|
43
46
|
BarLayerStyle,
|
|
44
47
|
BarMarkStyle,
|
|
48
|
+
BaseAxisGridStyle,
|
|
49
|
+
BaseAxisStyle,
|
|
50
|
+
BaseScaleStyle,
|
|
45
51
|
ChartsStyle,
|
|
46
52
|
DataTableStyle as DataTableStyle,
|
|
53
|
+
DimensionLabelStyle,
|
|
54
|
+
DimensionTicksStyle,
|
|
47
55
|
GeoshapeChartStyle,
|
|
48
56
|
GlobalMarksStyle,
|
|
49
57
|
HeatmapChartStyle,
|
|
@@ -53,11 +61,13 @@ from dataface.core.compile.models.style.theme import (
|
|
|
53
61
|
LineChartStyle,
|
|
54
62
|
LineLayerStyle,
|
|
55
63
|
LineMarkStyle,
|
|
64
|
+
MeasureGridStyle,
|
|
56
65
|
PaddingStyle,
|
|
57
66
|
PieChartStyle,
|
|
58
67
|
PointMapChartStyle,
|
|
59
68
|
PointMarkStyle,
|
|
60
|
-
|
|
69
|
+
QuantitativeAxisStyle,
|
|
70
|
+
ScaleContinuousStyle,
|
|
61
71
|
ScatterChartStyle,
|
|
62
72
|
ScatterLayerStyle,
|
|
63
73
|
Style,
|
|
@@ -65,73 +75,104 @@ from dataface.core.compile.models.style.theme import (
|
|
|
65
75
|
TitleStyle,
|
|
66
76
|
TooltipStyle,
|
|
67
77
|
TotalStyle,
|
|
78
|
+
XScaleStyle,
|
|
68
79
|
_CartesianChartStyle,
|
|
69
80
|
_GeoChartStyle,
|
|
70
81
|
_RadialChartStyle,
|
|
71
82
|
coerce_gap,
|
|
72
83
|
)
|
|
73
84
|
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
# on
|
|
85
|
+
# ── Scale group patches ───────────────────────────────────────────────────────
|
|
86
|
+
# Generated first (continuous is embedded in BaseScaleStyle, which is
|
|
87
|
+
# embedded in BaseAxisStyle). Order: leaf group → BaseScaleStyle → XScaleStyle.
|
|
88
|
+
|
|
89
|
+
# ScaleContinuousStylePatch carries ScaleDomainValidationMixin (domain shape
|
|
90
|
+
# check) via build_patch_model_ext, but NOT _validate_log_pow_symlog_params —
|
|
91
|
+
# that validator is defined directly on ScaleContinuousStyle (not on a mixin),
|
|
92
|
+
# so build_patch_model_ext naturally excludes it from the patch. A theme layer
|
|
93
|
+
# can set type:log and a chart-local patch can set only log.base; the
|
|
94
|
+
# cross-field check fires once, on the fully-merged result via
|
|
95
|
+
# ScaleContinuousStyle.model_validate.
|
|
81
96
|
if TYPE_CHECKING:
|
|
82
97
|
|
|
83
|
-
class
|
|
98
|
+
class ScaleContinuousStylePatch(ScaleContinuousStyle):
|
|
84
99
|
pass
|
|
85
100
|
|
|
86
101
|
else:
|
|
87
102
|
from dataface.core.compile.models.style.theme import ScaleDomainValidationMixin
|
|
88
103
|
|
|
89
|
-
class
|
|
90
|
-
"""Base for
|
|
91
|
-
authored scale.domain validation from ScaleDomainValidationMixin."""
|
|
104
|
+
class _ScaleContinuousStylePatchBase(_PatchBase, ScaleDomainValidationMixin):
|
|
105
|
+
"""Base for ScaleContinuousStylePatch: extra="forbid" from _PatchBase
|
|
106
|
+
plus the authored scale.domain validation from ScaleDomainValidationMixin."""
|
|
92
107
|
|
|
93
|
-
|
|
94
|
-
build_patch_model_ext(
|
|
108
|
+
ScaleContinuousStylePatch = register_patch(ScaleContinuousStyle)(
|
|
109
|
+
build_patch_model_ext(
|
|
110
|
+
ScaleContinuousStyle, base_cls=_ScaleContinuousStylePatchBase
|
|
111
|
+
)
|
|
95
112
|
)
|
|
96
113
|
|
|
114
|
+
BaseScaleStylePatch = build_patch_model(BaseScaleStyle)
|
|
115
|
+
XScaleStylePatch = build_patch_model(XScaleStyle)
|
|
116
|
+
|
|
117
|
+
# ── Axis ticks patches ─────────────────────────────────────────────────────────
|
|
118
|
+
# Generated (and registered) BEFORE axis variant patches so the recursive
|
|
119
|
+
# axis-variant build reuses these exact classes for their ``ticks`` field.
|
|
120
|
+
# Neither patch carries the step/time_unit cadence validator — same
|
|
121
|
+
# ScaleContinuousStyle convention above: the check is defined directly on
|
|
122
|
+
# DimensionTicksStyle (mode="after"), not a mixin, and build_patch_model_ext
|
|
123
|
+
# only carries over validators living on the patch's own base_cls, so it does
|
|
124
|
+
# NOT leak into either generated patch. It fires once, on the fully-merged
|
|
125
|
+
# theme-tier result, since a theme may set time_unit and a chart-local patch
|
|
126
|
+
# layer may set only step.
|
|
127
|
+
AxisTicksStylePatch = build_patch_model(AxisTicksStyle)
|
|
128
|
+
DimensionTicksStylePatch = build_patch_model(DimensionTicksStyle)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# ── Axis leaf patches ─────────────────────────────────────────────────────────
|
|
132
|
+
# Generated before axis variant patches so the recursive variant builds reuse
|
|
133
|
+
# these exact classes for their sub-object fields.
|
|
134
|
+
AxisGridZeroStylePatch: type # declared for forward reference clarity
|
|
135
|
+
from dataface.core.compile.models.style.theme.axis import (
|
|
136
|
+
AxisGridZeroStyle, # noqa: PLC0415, E402
|
|
137
|
+
)
|
|
97
138
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if TYPE_CHECKING:
|
|
139
|
+
AxisGridZeroStylePatch = build_patch_model(AxisGridZeroStyle)
|
|
140
|
+
BaseAxisGridStylePatch = build_patch_model(BaseAxisGridStyle)
|
|
141
|
+
MeasureGridStylePatch = build_patch_model(MeasureGridStyle)
|
|
142
|
+
AxisLineStylePatch = build_patch_model(AxisLineStyle)
|
|
143
|
+
AxisTitleStylePatch = build_patch_model(AxisTitleStyle)
|
|
144
|
+
AxisLabelStylePatch = build_patch_model(AxisLabelStyle)
|
|
145
|
+
DimensionLabelStylePatch = build_patch_model(DimensionLabelStyle)
|
|
106
146
|
|
|
107
|
-
class AxisTicksStylePatch(AxisTicksStyle):
|
|
108
|
-
pass
|
|
109
147
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
148
|
+
# ── Axis variant patches ──────────────────────────────────────────────────────
|
|
149
|
+
# Five axis-variant patches, each typed to the matching authored slot so extra
|
|
150
|
+
# fields on the wrong variant raise at validation time.
|
|
151
|
+
# TYPE_CHECKING stubs give mypy proper class definitions — at runtime
|
|
152
|
+
# build_patch_model generates the actual Pydantic model.
|
|
153
|
+
if TYPE_CHECKING:
|
|
114
154
|
|
|
115
|
-
class
|
|
116
|
-
|
|
117
|
-
the step/interval/count cadence validation from
|
|
118
|
-
AxisTicksCadenceValidationMixin."""
|
|
155
|
+
class BaseAxisStylePatch(BaseAxisStyle):
|
|
156
|
+
pass
|
|
119
157
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
158
|
+
class AxisXStylePatch(AxisXStyle):
|
|
159
|
+
pass
|
|
123
160
|
|
|
161
|
+
class AxisYStylePatch(AxisYStyle):
|
|
162
|
+
pass
|
|
124
163
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if TYPE_CHECKING:
|
|
164
|
+
class QuantitativeAxisStylePatch(QuantitativeAxisStyle):
|
|
165
|
+
pass
|
|
128
166
|
|
|
129
|
-
class
|
|
167
|
+
class BandAxisStylePatch(BandAxisStyle):
|
|
130
168
|
pass
|
|
131
169
|
|
|
132
170
|
else:
|
|
133
|
-
|
|
134
|
-
|
|
171
|
+
BaseAxisStylePatch = build_patch_model(BaseAxisStyle)
|
|
172
|
+
AxisXStylePatch = build_patch_model(AxisXStyle)
|
|
173
|
+
AxisYStylePatch = build_patch_model(AxisYStyle)
|
|
174
|
+
QuantitativeAxisStylePatch = build_patch_model(QuantitativeAxisStyle)
|
|
175
|
+
BandAxisStylePatch = build_patch_model(BandAxisStyle)
|
|
135
176
|
|
|
136
177
|
if TYPE_CHECKING:
|
|
137
178
|
|
|
@@ -200,19 +241,29 @@ class EndpointLabelsConfig(BaseModel):
|
|
|
200
241
|
# can resolve forward references in _CartesianChartStyle, BarChartStyle, etc.
|
|
201
242
|
# when build_patch_model(Style) triggers schema building for those classes.
|
|
202
243
|
# theme.py must not import from authored/, so injection is the only DAG-safe path.
|
|
244
|
+
# setattr avoids type: ignore[attr-defined] on a dynamically-typed module object.
|
|
203
245
|
import sys as _sys
|
|
204
246
|
|
|
205
247
|
_theme_mod = _sys.modules["dataface.core.compile.models.style.theme"]
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
248
|
+
for _name, _obj in (
|
|
249
|
+
("BaseAxisStylePatch", BaseAxisStylePatch),
|
|
250
|
+
("AxisXStylePatch", AxisXStylePatch),
|
|
251
|
+
("AxisYStylePatch", AxisYStylePatch),
|
|
252
|
+
("QuantitativeAxisStylePatch", QuantitativeAxisStylePatch),
|
|
253
|
+
("BandAxisStylePatch", BandAxisStylePatch),
|
|
254
|
+
("BaseScaleStylePatch", BaseScaleStylePatch),
|
|
255
|
+
("XScaleStylePatch", XScaleStylePatch),
|
|
256
|
+
("DataTableStylePatch", DataTableStylePatch),
|
|
257
|
+
("PaddingStylePatch", PaddingStylePatch),
|
|
258
|
+
("TableChartStylePatch", TableChartStylePatch),
|
|
259
|
+
("TooltipStylePatch", TooltipStylePatch),
|
|
260
|
+
("EndpointLabelsConfig", EndpointLabelsConfig),
|
|
261
|
+
("PaginationConfig", PaginationConfig),
|
|
262
|
+
("TableColumnDefaultsConfig", TableColumnDefaultsConfig),
|
|
263
|
+
("TableColumnConfig", TableColumnConfig),
|
|
264
|
+
):
|
|
265
|
+
setattr(_theme_mod, _name, _obj)
|
|
266
|
+
del _theme_mod, _name, _obj
|
|
216
267
|
|
|
217
268
|
# Rebuild theme chart classes that forward-ref authored types.
|
|
218
269
|
# Must run BEFORE build_patch_model(BarChartStyle) etc. so that model_fields
|
|
@@ -220,7 +271,13 @@ del _theme_mod
|
|
|
220
271
|
# ForwardRefs. The patch factory uses field annotations to determine recursive
|
|
221
272
|
# types; a ForwardRef for EndpointLabelsConfig produces the wrong patch.
|
|
222
273
|
_authored_ns: dict[str, object] = {
|
|
223
|
-
"
|
|
274
|
+
"BaseAxisStylePatch": BaseAxisStylePatch,
|
|
275
|
+
"AxisXStylePatch": AxisXStylePatch,
|
|
276
|
+
"AxisYStylePatch": AxisYStylePatch,
|
|
277
|
+
"QuantitativeAxisStylePatch": QuantitativeAxisStylePatch,
|
|
278
|
+
"BandAxisStylePatch": BandAxisStylePatch,
|
|
279
|
+
"BaseScaleStylePatch": BaseScaleStylePatch,
|
|
280
|
+
"XScaleStylePatch": XScaleStylePatch,
|
|
224
281
|
"DataTableStylePatch": DataTableStylePatch,
|
|
225
282
|
"PaddingStylePatch": PaddingStylePatch,
|
|
226
283
|
"TableChartStylePatch": TableChartStylePatch,
|
|
@@ -270,11 +327,11 @@ class StylePatch(_StylePatchBase): # type: ignore[misc,valid-type]
|
|
|
270
327
|
return coerce_gap(v)
|
|
271
328
|
|
|
272
329
|
|
|
273
|
-
AxisGridStylePatch
|
|
274
|
-
|
|
330
|
+
# AxisGridStylePatch / AxisDomainStylePatch / AxisElementStylePatch are built
|
|
331
|
+
# earlier (before the axis variant patches); they are not rebuilt here.
|
|
275
332
|
# AxisTicksStylePatch is built explicitly above (with the cadence validator
|
|
276
333
|
# base_cls) — not rebuilt here.
|
|
277
|
-
|
|
334
|
+
AxisGridStylePatch = BaseAxisGridStylePatch # backwards-compat alias
|
|
278
335
|
if TYPE_CHECKING:
|
|
279
336
|
|
|
280
337
|
class PointMarkStylePatch(PointMarkStyle):
|
|
@@ -286,9 +343,9 @@ else:
|
|
|
286
343
|
TotalStylePatch = build_patch_model(TotalStyle)
|
|
287
344
|
GlobalMarksStylePatch = build_patch_model(GlobalMarksStyle)
|
|
288
345
|
|
|
289
|
-
# TYPE_CHECKING stub mirrors the
|
|
290
|
-
# class (with accurate field names from LegendStyle) while the runtime
|
|
291
|
-
# the dynamically created patch model from build_patch_model().
|
|
346
|
+
# TYPE_CHECKING stub mirrors the variant-axis-patch pattern — gives mypy a
|
|
347
|
+
# proper class (with accurate field names from LegendStyle) while the runtime
|
|
348
|
+
# uses the dynamically created patch model from build_patch_model().
|
|
292
349
|
if TYPE_CHECKING:
|
|
293
350
|
|
|
294
351
|
class LegendStylePatch(LegendStyle):
|
|
@@ -322,7 +379,7 @@ else:
|
|
|
322
379
|
# Per-family layer style patches — generated from thin required wrappers in style/theme/.
|
|
323
380
|
# build_patch_model recurses: LineLayerStyle{marks: LineChartMarksStyle} →
|
|
324
381
|
# LineLayerStylePatch{marks: LineChartMarksStylePatch | None}.
|
|
325
|
-
# TYPE_CHECKING stubs mirror the
|
|
382
|
+
# TYPE_CHECKING stubs mirror the axis-variant-patch / LegendStylePatch pattern so
|
|
326
383
|
# mypy sees a valid class while the runtime uses the dynamically-created model.
|
|
327
384
|
if TYPE_CHECKING:
|
|
328
385
|
|
|
@@ -322,9 +322,16 @@ class TableColumnConfig(BaseModel):
|
|
|
322
322
|
|
|
323
323
|
@field_validator("spark", mode="before")
|
|
324
324
|
@classmethod
|
|
325
|
-
def
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
def _normalize_spark_shorthand(cls, value: Any) -> Any:
|
|
326
|
+
"""Normalize ``spark: <type>`` string shorthand to ``{"type": <type>}``.
|
|
327
|
+
|
|
328
|
+
Runs before union validation so ``.spark`` is always ``SparkConfig | None``
|
|
329
|
+
after construction — resolve and render never branch on the raw string form.
|
|
330
|
+
"""
|
|
331
|
+
if isinstance(value, str):
|
|
332
|
+
if value in _SPARK_RENAMED_AWAY:
|
|
333
|
+
raise ValueError(_SPARK_RENAMED_AWAY[value])
|
|
334
|
+
return {"type": value}
|
|
328
335
|
return value
|
|
329
336
|
|
|
330
337
|
@model_validator(mode="after")
|
|
@@ -351,6 +358,57 @@ class TableColumnConfig(BaseModel):
|
|
|
351
358
|
)
|
|
352
359
|
|
|
353
360
|
|
|
361
|
+
_SIZING_FIELDS = frozenset({"width", "max_width"})
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def fill_table_column_defaults(
|
|
365
|
+
source: TableColumnConfig | None,
|
|
366
|
+
defaults: TableColumnDefaultsConfig | None,
|
|
367
|
+
*,
|
|
368
|
+
fallback_label: str | None = None,
|
|
369
|
+
link_override: str | None = None,
|
|
370
|
+
) -> TableColumnConfig:
|
|
371
|
+
"""Build one final ``TableColumnConfig`` from an optional explicit source
|
|
372
|
+
and table-level ``column_defaults``, constructed once (never
|
|
373
|
+
``model_copy(update=...)``).
|
|
374
|
+
|
|
375
|
+
Precedence per field: ``source``'s own value > ``defaults`` (fills only
|
|
376
|
+
``None`` fields) > ``fallback_label`` for ``label`` / ``link_override``
|
|
377
|
+
for ``link``, each used only when neither of the above set one.
|
|
378
|
+
``width``/``max_width`` are one sizing slot — a source that claims either
|
|
379
|
+
is never filled from the other by ``defaults``.
|
|
380
|
+
|
|
381
|
+
The single constructor this repo uses both for a resolved chart's own
|
|
382
|
+
columns (``compile/resolve/_table.py``) and for a table renderer's two
|
|
383
|
+
render-native column key spaces — pivot leaf columns and transpose's
|
|
384
|
+
``__metric__``/``__value__`` pair — whose key space doesn't exist until
|
|
385
|
+
a render-time data transform runs, so ``column_defaults`` reaches them
|
|
386
|
+
here instead of at resolve.
|
|
387
|
+
"""
|
|
388
|
+
sizing_claimed = source is not None and (
|
|
389
|
+
source.width is not None or source.max_width is not None
|
|
390
|
+
)
|
|
391
|
+
defaults_fields = (
|
|
392
|
+
frozenset(type(defaults).model_fields) if defaults is not None else frozenset()
|
|
393
|
+
)
|
|
394
|
+
fields: dict[str, Any] = {}
|
|
395
|
+
for name in TableColumnConfig.model_fields:
|
|
396
|
+
value = getattr(source, name) if source is not None else None
|
|
397
|
+
if (
|
|
398
|
+
defaults is not None
|
|
399
|
+
and value is None
|
|
400
|
+
and name in defaults_fields
|
|
401
|
+
and not (name in _SIZING_FIELDS and sizing_claimed)
|
|
402
|
+
):
|
|
403
|
+
value = getattr(defaults, name)
|
|
404
|
+
fields[name] = value
|
|
405
|
+
if fields["label"] is None and fallback_label is not None:
|
|
406
|
+
fields["label"] = fallback_label
|
|
407
|
+
if fields["link"] is None and link_override is not None:
|
|
408
|
+
fields["link"] = link_override
|
|
409
|
+
return TableColumnConfig(**fields)
|
|
410
|
+
|
|
411
|
+
|
|
354
412
|
if TYPE_CHECKING:
|
|
355
413
|
|
|
356
414
|
class SparkStylePatch(SparkStyle):
|
|
@@ -35,16 +35,21 @@ logic, not a model definition — it lives at
|
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
37
|
from dataface.core.compile.models.style.resolved._base import (
|
|
38
|
-
ResolvedAxisDomainStyle,
|
|
39
38
|
ResolvedAxisElementStyle,
|
|
40
39
|
ResolvedAxisGridStyle,
|
|
41
40
|
ResolvedAxisGridZeroStyle,
|
|
42
41
|
ResolvedAxisLabelOverlapConfig,
|
|
42
|
+
ResolvedAxisLineStyle,
|
|
43
43
|
ResolvedAxisStyle,
|
|
44
44
|
ResolvedAxisTicksStyle,
|
|
45
45
|
ResolvedChartsStyle,
|
|
46
46
|
ResolvedLegendElementStyle,
|
|
47
47
|
ResolvedLegendStyle,
|
|
48
|
+
ResolvedScaleContinuousStyle,
|
|
49
|
+
ResolvedScaleLogStyle,
|
|
50
|
+
ResolvedScalePowStyle,
|
|
51
|
+
ResolvedScaleStyle,
|
|
52
|
+
ResolvedScaleSymlogStyle,
|
|
48
53
|
ResolvedStyle,
|
|
49
54
|
_VLConfig,
|
|
50
55
|
effective_padding,
|
|
@@ -95,11 +100,11 @@ from dataface.core.compile.models.style.resolved.table import ResolvedTableStyle
|
|
|
95
100
|
|
|
96
101
|
__all__ = [
|
|
97
102
|
# _base
|
|
98
|
-
"ResolvedAxisDomainStyle",
|
|
99
103
|
"ResolvedAxisElementStyle",
|
|
100
104
|
"ResolvedAxisGridStyle",
|
|
101
105
|
"ResolvedAxisGridZeroStyle",
|
|
102
106
|
"ResolvedAxisLabelOverlapConfig",
|
|
107
|
+
"ResolvedAxisLineStyle",
|
|
103
108
|
"ResolvedAxisStyle",
|
|
104
109
|
"ResolvedAxisTicksStyle",
|
|
105
110
|
"ResolvedCalloutElementStyle",
|
|
@@ -107,6 +112,11 @@ __all__ = [
|
|
|
107
112
|
"ResolvedChartsStyle",
|
|
108
113
|
"ResolvedLegendElementStyle",
|
|
109
114
|
"ResolvedLegendStyle",
|
|
115
|
+
"ResolvedScaleContinuousStyle",
|
|
116
|
+
"ResolvedScaleLogStyle",
|
|
117
|
+
"ResolvedScalePowStyle",
|
|
118
|
+
"ResolvedScaleStyle",
|
|
119
|
+
"ResolvedScaleSymlogStyle",
|
|
110
120
|
"ResolvedStyle",
|
|
111
121
|
"_VLConfig",
|
|
112
122
|
# _base (public function)
|