Skip to content

Commit

Permalink
feat: Adds @register_theme decorator
Browse files Browse the repository at this point in the history
Resolves one item in vega#3519
  • Loading branch information
dangotbanned committed Aug 7, 2024
1 parent 95f654f commit 756b37f
Showing 1 changed file with 89 additions and 3 deletions.
92 changes: 89 additions & 3 deletions altair/vegalite/v5/theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Final, Literal
import sys
from functools import wraps
from typing import TYPE_CHECKING, Any, Callable, Dict, Final, Literal, TypeVar

if sys.version_info >= (3, 10):
from typing import ParamSpec
else:
from typing_extensions import ParamSpec


from altair.utils.theme import ThemeRegistry

if TYPE_CHECKING:
import sys

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 TypeAlias
else:
Expand Down Expand Up @@ -53,6 +63,10 @@
]


P = ParamSpec("P")
R = TypeVar("R", bound=Dict[str, Any])


class VegaTheme:
"""Implementation of a builtin vega theme."""

Expand Down Expand Up @@ -94,3 +108,75 @@ def __repr__(self) -> str:
themes.register(theme, VegaTheme(theme))

themes.enable("default")


def register_theme(
name: LiteralString, *, enable: bool
) -> Callable[[Callable[P, R]], Callable[P, R]]:
"""
Decorator for registering a theme function.
Parameters
----------
name
Unique name assigned in ``alt.themes``.
enable
Auto-enable the wrapped theme.
Examples
--------
Register and enable a theme::
from __future__ import annotations
from typing import Any
import altair as alt
@alt.register_theme("param_font_size", enable=True)
def custom_theme() -> dict[str, Any]:
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,
}
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)
"""

def decorate(func: Callable[P, R], /) -> Callable[P, R]:
themes.register(name, func)
if enable:
themes.enable(name)

@wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
return func(*args, **kwargs)

return wrapper

return decorate

0 comments on commit 756b37f

Please sign in to comment.