-
Notifications
You must be signed in to change notification settings - Fork 794
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7b3d479
commit 255f736
Showing
21 changed files
with
2,268 additions
and
311 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,321 @@ | ||
"""Customizing chart configuration defaults.""" | ||
|
||
from __future__ import annotations | ||
|
||
from functools import wraps as _wraps | ||
from typing import TYPE_CHECKING, Any | ||
from typing import overload as _overload | ||
|
||
from altair.vegalite.v5.schema._config import ( | ||
AreaConfigKwds, | ||
AutoSizeParamsKwds, | ||
AxisConfigKwds, | ||
AxisResolveMapKwds, | ||
BarConfigKwds, | ||
BindCheckboxKwds, | ||
BindDirectKwds, | ||
BindInputKwds, | ||
BindRadioSelectKwds, | ||
BindRangeKwds, | ||
BoxPlotConfigKwds, | ||
BrushConfigKwds, | ||
CompositionConfigKwds, | ||
ConfigKwds, | ||
DateTimeKwds, | ||
DerivedStreamKwds, | ||
ErrorBandConfigKwds, | ||
ErrorBarConfigKwds, | ||
FeatureGeometryGeoJsonPropertiesKwds, | ||
FormatConfigKwds, | ||
GeoJsonFeatureCollectionKwds, | ||
GeoJsonFeatureKwds, | ||
GeometryCollectionKwds, | ||
GradientStopKwds, | ||
HeaderConfigKwds, | ||
IntervalSelectionConfigKwds, | ||
IntervalSelectionConfigWithoutTypeKwds, | ||
LegendConfigKwds, | ||
LegendResolveMapKwds, | ||
LegendStreamBindingKwds, | ||
LinearGradientKwds, | ||
LineConfigKwds, | ||
LineStringKwds, | ||
LocaleKwds, | ||
MarkConfigKwds, | ||
MergedStreamKwds, | ||
MultiLineStringKwds, | ||
MultiPointKwds, | ||
MultiPolygonKwds, | ||
NumberLocaleKwds, | ||
OverlayMarkDefKwds, | ||
PaddingKwds, | ||
PointKwds, | ||
PointSelectionConfigKwds, | ||
PointSelectionConfigWithoutTypeKwds, | ||
PolygonKwds, | ||
ProjectionConfigKwds, | ||
ProjectionKwds, | ||
RadialGradientKwds, | ||
RangeConfigKwds, | ||
RectConfigKwds, | ||
ResolveKwds, | ||
RowColKwds, | ||
ScaleConfigKwds, | ||
ScaleInvalidDataConfigKwds, | ||
ScaleResolveMapKwds, | ||
SelectionConfigKwds, | ||
StepKwds, | ||
StyleConfigIndexKwds, | ||
ThemeConfig, | ||
TickConfigKwds, | ||
TimeIntervalStepKwds, | ||
TimeLocaleKwds, | ||
TitleConfigKwds, | ||
TitleParamsKwds, | ||
TooltipContentKwds, | ||
TopLevelSelectionParameterKwds, | ||
VariableParameterKwds, | ||
ViewBackgroundKwds, | ||
ViewConfigKwds, | ||
) | ||
from altair.vegalite.v5.theme import themes as _themes | ||
|
||
if TYPE_CHECKING: | ||
import sys | ||
from typing import Any, Callable, Literal | ||
|
||
if sys.version_info >= (3, 11): | ||
from typing import LiteralString | ||
else: | ||
from typing_extensions import LiteralString | ||
if sys.version_info >= (3, 10): | ||
from typing import ParamSpec | ||
else: | ||
from typing_extensions import ParamSpec | ||
|
||
from altair.utils.plugin_registry import Plugin | ||
|
||
P = ParamSpec("P") | ||
|
||
__all__ = [ | ||
"AreaConfigKwds", | ||
"AutoSizeParamsKwds", | ||
"AxisConfigKwds", | ||
"AxisResolveMapKwds", | ||
"BarConfigKwds", | ||
"BindCheckboxKwds", | ||
"BindDirectKwds", | ||
"BindInputKwds", | ||
"BindRadioSelectKwds", | ||
"BindRangeKwds", | ||
"BoxPlotConfigKwds", | ||
"BrushConfigKwds", | ||
"CompositionConfigKwds", | ||
"ConfigKwds", | ||
"DateTimeKwds", | ||
"DerivedStreamKwds", | ||
"ErrorBandConfigKwds", | ||
"ErrorBarConfigKwds", | ||
"FeatureGeometryGeoJsonPropertiesKwds", | ||
"FormatConfigKwds", | ||
"GeoJsonFeatureCollectionKwds", | ||
"GeoJsonFeatureKwds", | ||
"GeometryCollectionKwds", | ||
"GradientStopKwds", | ||
"HeaderConfigKwds", | ||
"IntervalSelectionConfigKwds", | ||
"IntervalSelectionConfigWithoutTypeKwds", | ||
"LegendConfigKwds", | ||
"LegendResolveMapKwds", | ||
"LegendStreamBindingKwds", | ||
"LineConfigKwds", | ||
"LineStringKwds", | ||
"LinearGradientKwds", | ||
"LocaleKwds", | ||
"MarkConfigKwds", | ||
"MergedStreamKwds", | ||
"MultiLineStringKwds", | ||
"MultiPointKwds", | ||
"MultiPolygonKwds", | ||
"NumberLocaleKwds", | ||
"OverlayMarkDefKwds", | ||
"PaddingKwds", | ||
"PointKwds", | ||
"PointSelectionConfigKwds", | ||
"PointSelectionConfigWithoutTypeKwds", | ||
"PolygonKwds", | ||
"ProjectionConfigKwds", | ||
"ProjectionKwds", | ||
"RadialGradientKwds", | ||
"RangeConfigKwds", | ||
"RectConfigKwds", | ||
"ResolveKwds", | ||
"RowColKwds", | ||
"ScaleConfigKwds", | ||
"ScaleInvalidDataConfigKwds", | ||
"ScaleResolveMapKwds", | ||
"SelectionConfigKwds", | ||
"StepKwds", | ||
"StyleConfigIndexKwds", | ||
"ThemeConfig", | ||
"TickConfigKwds", | ||
"TimeIntervalStepKwds", | ||
"TimeLocaleKwds", | ||
"TitleConfigKwds", | ||
"TitleParamsKwds", | ||
"TooltipContentKwds", | ||
"TopLevelSelectionParameterKwds", | ||
"VariableParameterKwds", | ||
"ViewBackgroundKwds", | ||
"ViewConfigKwds", | ||
"active", | ||
"enable", | ||
"get", | ||
"names", | ||
"options", | ||
"register", | ||
"unregister", | ||
] | ||
|
||
|
||
def register( | ||
name: LiteralString, *, enable: bool | ||
) -> Callable[[Plugin[ThemeConfig]], Plugin[ThemeConfig]]: | ||
""" | ||
Decorator for registering a theme function. | ||
Parameters | ||
---------- | ||
name | ||
Unique name assigned in registry. | ||
enable | ||
Auto-enable the wrapped theme. | ||
Examples | ||
-------- | ||
Register and enable a theme:: | ||
import altair as alt | ||
from altair import theme | ||
@theme.register("param_font_size", enable=True) | ||
def custom_theme() -> theme.ThemeConfig: | ||
sizes = 12, 14, 16, 18, 20 | ||
return { | ||
"autosize": {"contains": "content", "resize": True}, | ||
"background": "#F3F2F1", | ||
"config": { | ||
"axisX": {"labelFontSize": sizes[1], "titleFontSize": sizes[1]}, | ||
"axisY": {"labelFontSize": sizes[1], "titleFontSize": sizes[1]}, | ||
"font": "'Lato', 'Segoe UI', Tahoma, Verdana, sans-serif", | ||
"headerColumn": {"labelFontSize": sizes[1]}, | ||
"headerFacet": {"labelFontSize": sizes[1]}, | ||
"headerRow": {"labelFontSize": sizes[1]}, | ||
"legend": {"labelFontSize": sizes[0], "titleFontSize": sizes[1]}, | ||
"text": {"fontSize": sizes[0]}, | ||
"title": {"fontSize": sizes[-1]}, | ||
}, | ||
"height": {"step": 28}, | ||
"width": 350, | ||
} | ||
We can then see the ``name`` parameter displayed when checking:: | ||
theme.active | ||
"param_font_size" | ||
Until another theme has been enabled, all charts will use defaults set in ``custom_theme()``:: | ||
from vega_datasets import data | ||
source = data.stocks() | ||
lines = ( | ||
alt.Chart(source, title=alt.Title("Stocks")) | ||
.mark_line() | ||
.encode(x="date:T", y="price:Q", color="symbol:N") | ||
) | ||
lines.interactive(bind_y=False) | ||
""" | ||
|
||
# HACK: See for `LiteralString` requirement in `name` | ||
# https://github.com/vega/altair/pull/3526#discussion_r1743350127 | ||
def decorate(func: Plugin[ThemeConfig], /) -> Plugin[ThemeConfig]: | ||
_register(name, func) | ||
if enable: | ||
_themes.enable(name) | ||
|
||
@_wraps(func) | ||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> ThemeConfig: | ||
return func(*args, **kwargs) | ||
|
||
return wrapper | ||
|
||
return decorate | ||
|
||
|
||
def unregister(name: LiteralString) -> Plugin[ThemeConfig]: | ||
""" | ||
Remove and return a previously registered theme. | ||
Parameters | ||
---------- | ||
name | ||
Unique name assigned during ``alt.theme.register``. | ||
Raises | ||
------ | ||
TypeError | ||
When ``name`` has not been registered. | ||
""" | ||
plugin = _register(name, None) | ||
if plugin is None: | ||
msg = ( | ||
f"Found no theme named {name!r} in registry.\n" | ||
f"Registered themes:\n" | ||
f"{names()!r}" | ||
) | ||
raise TypeError(msg) | ||
else: | ||
return plugin | ||
|
||
|
||
enable = _themes.enable | ||
get = _themes.get | ||
names = _themes.names | ||
active: str | ||
"""Return the name of the currently active theme.""" | ||
options: dict[str, Any] | ||
"""Return the current themes options dictionary.""" | ||
|
||
|
||
def __dir__() -> list[str]: | ||
return __all__ | ||
|
||
|
||
@_overload | ||
def __getattr__(name: Literal["active"]) -> str: ... # type: ignore[misc] | ||
@_overload | ||
def __getattr__(name: Literal["options"]) -> dict[str, Any]: ... # type: ignore[misc] | ||
def __getattr__(name: str) -> Any: | ||
if name == "active": | ||
return _themes.active | ||
elif name == "options": | ||
return _themes.options | ||
else: | ||
msg = f"module {__name__!r} has no attribute {name!r}" | ||
raise AttributeError(msg) | ||
|
||
|
||
def _register( | ||
name: LiteralString, fn: Plugin[ThemeConfig] | None, / | ||
) -> Plugin[ThemeConfig] | None: | ||
if fn is None: | ||
return _themes._plugins.pop(name, None) | ||
elif _themes.plugin_type(fn): | ||
_themes._plugins[name] = fn | ||
return fn | ||
else: | ||
msg = f"{type(fn).__name__!r} is not a callable theme\n\n{fn!r}" | ||
raise TypeError(msg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.