Skip to content

Commit

Permalink
refactor: Remove channels parameter in infer_encoding_types (#3564)
Browse files Browse the repository at this point in the history
* test: Monkeypatch channels global

Removes the dependency in `test_infer_encoding_types`

* refactor: Remove `channels` parameter in `infer_encoding_types`

Was kept, but only needed for tests since #3444.
As `infer_encoding_types` is not public API - this is a safe remove, no need for deprecation
  • Loading branch information
dangotbanned authored Sep 4, 2024
1 parent db97a0b commit 5207768
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 33 deletions.
29 changes: 2 additions & 27 deletions altair/utils/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

if TYPE_CHECKING:
import typing as t
from types import ModuleType

import pandas as pd
from narwhals.typing import IntoExpr
Expand Down Expand Up @@ -812,22 +811,6 @@ class _ChannelCache:
channel_to_name: dict[type[SchemaBase], str]
name_to_channel: dict[str, dict[_ChannelType, type[SchemaBase]]]

@classmethod
def from_channels(cls, channels: ModuleType, /) -> _ChannelCache:
# - This branch is only kept for tests that depend on mocking `channels`.
# - No longer needs to pass around `channels` reference and rebuild every call.
c_to_n = {
c: c._encoding_name
for c in channels.__dict__.values()
if isinstance(c, type)
and issubclass(c, SchemaBase)
and hasattr(c, "_encoding_name")
}
self = cls.__new__(cls)
self.channel_to_name = c_to_n
self.name_to_channel = _invert_group_channels(c_to_n)
return self

@classmethod
def from_cache(cls) -> _ChannelCache:
global _CHANNEL_CACHE
Expand Down Expand Up @@ -925,9 +908,7 @@ def _reduce(it: Iterator[tuple[type[Any], str]]) -> Any:
return {k: _reduce(chans) for k, chans in grouper}


def infer_encoding_types(
args: tuple[Any, ...], kwargs: dict[str, Any], channels: ModuleType | None = None
):
def infer_encoding_types(args: tuple[Any, ...], kwargs: dict[str, Any]):
"""
Infer typed keyword arguments for args and kwargs.
Expand All @@ -937,20 +918,14 @@ def infer_encoding_types(
Sequence of function args
kwargs : MutableMapping
Dict of function kwargs
channels : ModuleType
The module containing all altair encoding channel classes.
Returns
-------
kwargs : dict
All args and kwargs in a single dict, with keys and types
based on the channels mapping.
"""
cache = (
_ChannelCache.from_channels(channels)
if channels
else _ChannelCache.from_cache()
)
cache = _ChannelCache.from_cache()
# First use the mapping to convert args to kwargs based on their types.
for arg in args:
el = next(iter(arg), None) if isinstance(arg, (list, tuple)) else arg
Expand Down
35 changes: 29 additions & 6 deletions tests/utils/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pandas.api.types import infer_dtype

import altair as alt
from altair.utils import core
from altair.utils.core import infer_encoding_types, parse_shorthand, update_nested
from tests import skip_requires_pyarrow

Expand Down Expand Up @@ -267,18 +268,40 @@ def test_update_nested():


@pytest.fixture
def channels():
def channels() -> types.ModuleType:
channels = types.ModuleType("channels")
exec(FAKE_CHANNELS_MODULE, channels.__dict__)
return channels


@pytest.fixture
def channels_cached(channels) -> core._ChannelCache:
"""Previously ``_ChannelCache.from_channels``."""
cached = core._ChannelCache.__new__(core._ChannelCache)
cached.channel_to_name = {
c: c._encoding_name
for c in channels.__dict__.values()
if isinstance(c, type)
and issubclass(c, alt.SchemaBase)
and hasattr(c, "_encoding_name")
}
cached.name_to_channel = core._invert_group_channels(cached.channel_to_name)
return cached


def _getargs(*args, **kwargs):
return args, kwargs


# NOTE: Dependent on a no longer needed implementation detail
def test_infer_encoding_types(channels):
def test_infer_encoding_types(
monkeypatch: pytest.MonkeyPatch, channels, channels_cached
):
# Indirectly initialize `_CHANNEL_CACHE`
infer_encoding_types((), {})
# Replace with contents of `FAKE_CHANNELS_MODULE`
# Scoped to only this test
monkeypatch.setattr(core, "_CHANNEL_CACHE", channels_cached)

expected = {
"x": channels.X("xval"),
"y": channels.YValue("yval"),
Expand All @@ -289,17 +312,17 @@ def test_infer_encoding_types(channels):
args, kwds = _getargs(
channels.X("xval"), channels.YValue("yval"), channels.StrokeWidthValue(4)
)
assert infer_encoding_types(args, kwds, channels) == expected
assert infer_encoding_types(args, kwds) == expected

# All keyword args
args, kwds = _getargs(x="xval", y=alt.value("yval"), strokeWidth=alt.value(4))
assert infer_encoding_types(args, kwds, channels) == expected
assert infer_encoding_types(args, kwds) == expected

# Mixed positional & keyword
args, kwds = _getargs(
channels.X("xval"), channels.YValue("yval"), strokeWidth=alt.value(4)
)
assert infer_encoding_types(args, kwds, channels) == expected
assert infer_encoding_types(args, kwds) == expected


def test_infer_encoding_types_with_condition():
Expand Down

0 comments on commit 5207768

Please sign in to comment.