Skip to content

Commit

Permalink
feat: Parse [project.optional-dependencies] for vegafusion, `vl-c…
Browse files Browse the repository at this point in the history
…onvert-python`

Reduces duplication, noted in #3720 (comment)
  • Loading branch information
dangotbanned committed Jan 2, 2025
1 parent 88ad05a commit 0c3c220
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 4 deletions.
2 changes: 1 addition & 1 deletion altair/utils/schemapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -1656,7 +1656,7 @@ def with_property_setters(cls: type[TSchemaBase]) -> type[TSchemaBase]:
"vega-datasets": "v2.11.0",
"vega-embed": "6",
"vega-lite": "v5.20.1",
"vegafusion": "1.5.0",
"vegafusion": "1.6.6",
"vl-convert-python": "1.7.0",
}
"""
Expand Down
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ doc = [
vega-datasets = "v2.11.0" # https://github.com/vega/vega-datasets
vega-embed = "6" # https://github.com/vega/vega-embed
vega-lite = "v5.20.1" # https://github.com/vega/vega-lite
vegafusion = "1.5.0" # https://github.com/vega/vegafusion
vl-convert-python = "1.7.0" # https://github.com/vega/vl-convert

[tool.hatch.version]
path = "altair/__init__.py"
Expand Down
48 changes: 47 additions & 1 deletion tools/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import sys
from collections import deque
from itertools import chain
from pathlib import Path
from typing import TYPE_CHECKING, Any, ClassVar, Literal

Expand All @@ -32,6 +33,7 @@
else:
# NOTE: See https://github.com/hukkin/tomli?tab=readme-ov-file#building-a-tomlitomllib-compatibility-layer
import tomli as tomllib # type: ignore
from packaging.requirements import Requirement
from packaging.version import parse as parse_version

import vl_convert as vlc
Expand Down Expand Up @@ -61,7 +63,9 @@
_REPO_ROOT: Path = Path(__file__).parent.parent
_JUPYTER_INDEX = "altair/jupyter/js/index.js"
_PYPROJECT: Literal["pyproject.toml"] = "pyproject.toml"
_LOWER_BOUNDS = frozenset((">=", "==", "~=", "==="))

VegaProjectPy: TypeAlias = Literal["vegafusion", "vl-convert-python"]
VegaProject: TypeAlias = Literal[
"vega-datasets", "vega-embed", "vega-lite", "vegafusion", "vl-convert-python"
]
Expand Down Expand Up @@ -90,14 +94,25 @@ class _Versions:
[tool.altair.vega] -> "tool", "altair", "vega"
"""
_PY_DEPS_PATH: ClassVar[Sequence[LiteralString]] = (
"project",
"optional-dependencies",
)
_PY_DEPS: ClassVar[frozenset[VegaProjectPy]] = frozenset(
("vl-convert-python", "vegafusion")
)

_CONST_NAME: ClassVar[Literal["VERSIONS"]] = "VERSIONS"
"""Variable name for the exported literal."""

_mapping: Mapping[VegaProject, str]

def __init__(self) -> None:
self._mapping = _keypath(_read_pyproject_toml(), self._TABLE_PATH)
pyproject = _read_pyproject_toml()
py_deps = _keypath(pyproject, self._PY_DEPS_PATH)
js_deps = _keypath(pyproject, self._TABLE_PATH)
all_deps = chain(js_deps.items(), self._iter_py_deps_versions(py_deps))
self._mapping = dict(sorted(all_deps))

def __getitem__(self, key: VegaProject) -> str:
return self._mapping[key]
Expand Down Expand Up @@ -211,6 +226,37 @@ def update_vega_embed(self) -> None:
with fp.open("w", encoding="utf-8", newline="\n") as f:
f.writelines(lines)

def _iter_py_deps_versions(
self, dep_groups: dict[str, Sequence[str]], /
) -> Iterator[tuple[VegaProjectPy, str]]:
"""
Extract the name and lower version bound for all Vega python packages.
Parameters
----------
dep_groups
Mapping of dependency/extra groups to requirement strings.
.. note::
It is expected that this is **either** `project.optional-dependencies`_ or `dependency-groups`_.
.. _project.optional-dependencies:
https://packaging.python.org/en/latest/specifications/pyproject-toml/#dependencies-optional-dependencies
.. _dependency-groups:
https://peps.python.org/pep-0735/
"""
for deps in dep_groups.values():
for req_string in deps:
req = Requirement(req_string)
if req.name in self._PY_DEPS:
it = (
parse_version(sp.version)
for sp in req.specifier
if sp.operator in _LOWER_BOUNDS
)
version = str(min(it))
yield req.name, version


def __getattr__(name: str) -> _Versions:
if name == "VERSIONS":
Expand Down

0 comments on commit 0c3c220

Please sign in to comment.