Skip to content

Commit

Permalink
Cleanup compat code for obsolete versions of dependencies (#3607)
Browse files Browse the repository at this point in the history
  • Loading branch information
hamdanal authored Dec 30, 2023
1 parent 45a098f commit 785708f
Show file tree
Hide file tree
Showing 12 changed files with 44 additions and 115 deletions.
6 changes: 1 addition & 5 deletions seaborn/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1160,11 +1160,7 @@ def _attach(
# For categorical y, we want the "first" level to be at the top of the axis
if self.var_types.get("y", None) == "categorical":
for ax in ax_list:
try:
ax.yaxis.set_inverted(True)
except AttributeError: # mpl < 3.1
if not ax.yaxis_inverted():
ax.invert_yaxis()
ax.yaxis.set_inverted(True)

# TODO -- Add axes labels

Expand Down
16 changes: 0 additions & 16 deletions seaborn/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,6 @@
from seaborn.utils import _version_predates


def MarkerStyle(marker=None, fillstyle=None):
"""
Allow MarkerStyle to accept a MarkerStyle object as parameter.
Supports matplotlib < 3.3.0
https://github.com/matplotlib/matplotlib/pull/16692
"""
if isinstance(marker, mpl.markers.MarkerStyle):
if fillstyle is None:
return marker
else:
marker = marker.get_marker()
return mpl.markers.MarkerStyle(marker, fillstyle)


def norm_from_scale(scale, norm):
"""Produce a Normalize object given a Scale and min/max domain limits."""
# This is an internal maplotlib function that simplifies things to access
Expand Down
10 changes: 2 additions & 8 deletions seaborn/_core/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ def layout(

# TODO def legend (ugh)

def theme(self, *args: dict[str, Any]) -> Plot:
def theme(self, config: dict[str, Any], /) -> Plot:
"""
Control the appearance of elements in the plot.
Expand All @@ -880,13 +880,7 @@ def theme(self, *args: dict[str, Any]) -> Plot:
"""
new = self._clone()

# We can skip this whole block on Python 3.8+ with positional-only syntax
nargs = len(args)
if nargs != 1:
err = f"theme() takes 1 positional argument, but {nargs} were given"
raise TypeError(err)

rc = mpl.RcParams(args[0])
rc = mpl.RcParams(config)
new._theme.update(rc)

return new
Expand Down
9 changes: 2 additions & 7 deletions seaborn/_core/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,20 @@
import warnings

import numpy as np
from numpy.typing import ArrayLike
from pandas import Series
import matplotlib as mpl
from matplotlib.colors import to_rgb, to_rgba, to_rgba_array
from matplotlib.markers import MarkerStyle
from matplotlib.path import Path

from seaborn._core.scales import Scale, Boolean, Continuous, Nominal, Temporal
from seaborn._core.rules import categorical_order, variable_type
from seaborn._compat import MarkerStyle
from seaborn.palettes import QUAL_PALETTES, color_palette, blend_palette
from seaborn.utils import get_color_cycle

from typing import Any, Callable, Tuple, List, Union, Optional

try:
from numpy.typing import ArrayLike
except ImportError:
# numpy<1.20.0 (Jan 2021)
ArrayLike = Any

RGBTuple = Tuple[float, float, float]
RGBATuple = Tuple[float, float, float, float]
ColorSpec = Union[RGBTuple, RGBATuple, str]
Expand Down
6 changes: 4 additions & 2 deletions seaborn/_statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class instantiation.
"""
from numbers import Number
from statistics import NormalDist
import numpy as np
import pandas as pd
try:
Expand All @@ -35,7 +36,7 @@ class instantiation.
_no_scipy = True

from .algorithms import bootstrap
from .utils import _check_argument, _normal_quantile_func
from .utils import _check_argument


class KDE:
Expand Down Expand Up @@ -627,7 +628,8 @@ def _compute_k(self, n):
elif self.k_depth == "proportion":
k = int(np.log2(n)) - int(np.log2(n * self.outlier_prop)) + 1
elif self.k_depth == "trustworthy":
point_conf = 2 * _normal_quantile_func(1 - self.trust_alpha / 2) ** 2
normal_quantile_func = np.vectorize(NormalDist().inv_cdf)
point_conf = 2 * normal_quantile_func(1 - self.trust_alpha / 2) ** 2
k = int(np.log2(n / point_conf)) + 1
else:
# Allow having k directly specified as input
Expand Down
20 changes: 10 additions & 10 deletions seaborn/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import pandas as pd

import matplotlib as mpl
from matplotlib.cbook import normalize_kwargs
from matplotlib.collections import PatchCollection
from matplotlib.markers import MarkerStyle
from matplotlib.patches import Rectangle
import matplotlib.pyplot as plt

Expand All @@ -23,11 +25,9 @@
_default_color,
_get_patch_legend_artist,
_get_transform_functions,
_normalize_kwargs,
_scatter_legend_artist,
_version_predates,
)
from seaborn._compat import MarkerStyle
from seaborn._statistics import (
EstimateAggregator,
LetterValues,
Expand Down Expand Up @@ -605,7 +605,7 @@ def plot_boxes(
value_var = {"x": "y", "y": "x"}[self.orient]

def get_props(element, artist=mpl.lines.Line2D):
return _normalize_kwargs(plot_kws.pop(f"{element}props", {}), artist)
return normalize_kwargs(plot_kws.pop(f"{element}props", {}), artist)

if not fill and linewidth is None:
linewidth = mpl.rcParams["lines.linewidth"]
Expand Down Expand Up @@ -1175,7 +1175,7 @@ def plot_points(
agg_var = {"x": "y", "y": "x"}[self.orient]
iter_vars = ["hue"]

plot_kws = _normalize_kwargs(plot_kws, mpl.lines.Line2D)
plot_kws = normalize_kwargs(plot_kws, mpl.lines.Line2D)
plot_kws.setdefault("linewidth", mpl.rcParams["lines.linewidth"] * 1.8)
plot_kws.setdefault("markeredgewidth", plot_kws["linewidth"] * 0.75)
plot_kws.setdefault("markersize", plot_kws["linewidth"] * np.sqrt(2 * np.pi))
Expand Down Expand Up @@ -2371,7 +2371,7 @@ def barplot(

agg_cls = WeightedAggregator if "weight" in p.plot_data else EstimateAggregator
aggregator = agg_cls(estimator, errorbar, n_boot=n_boot, seed=seed)
err_kws = {} if err_kws is None else _normalize_kwargs(err_kws, mpl.lines.Line2D)
err_kws = {} if err_kws is None else normalize_kwargs(err_kws, mpl.lines.Line2D)

# Deprecations to remove in v0.15.0.
err_kws, capsize = p._err_kws_backcompat(err_kws, errcolor, errwidth, capsize)
Expand Down Expand Up @@ -2506,7 +2506,7 @@ def pointplot(

agg_cls = WeightedAggregator if "weight" in p.plot_data else EstimateAggregator
aggregator = agg_cls(estimator, errorbar, n_boot=n_boot, seed=seed)
err_kws = {} if err_kws is None else _normalize_kwargs(err_kws, mpl.lines.Line2D)
err_kws = {} if err_kws is None else normalize_kwargs(err_kws, mpl.lines.Line2D)

# Deprecations to remove in v0.15.0.
p._point_kwargs_backcompat(scale, join, kwargs)
Expand Down Expand Up @@ -2848,7 +2848,7 @@ def catplot(
color = desaturate(color, saturation)

if kind in ["strip", "swarm"]:
kwargs = _normalize_kwargs(kwargs, mpl.collections.PathCollection)
kwargs = normalize_kwargs(kwargs, mpl.collections.PathCollection)
kwargs["edgecolor"] = p._complement_color(
kwargs.pop("edgecolor", default), color, p._hue_map
)
Expand Down Expand Up @@ -3023,14 +3023,14 @@ def catplot(
# Deprecations to remove in v0.15.0.
# TODO Uncomment when removing deprecation backcompat
# capsize = kwargs.pop("capsize", 0)
# err_kws = _normalize_kwargs(kwargs.pop("err_kws", {}), mpl.lines.Line2D)
# err_kws = normalize_kwargs(kwargs.pop("err_kws", {}), mpl.lines.Line2D)
p._point_kwargs_backcompat(
kwargs.pop("scale", deprecated),
kwargs.pop("join", deprecated),
kwargs
)
err_kws, capsize = p._err_kws_backcompat(
_normalize_kwargs(kwargs.pop("err_kws", {}), mpl.lines.Line2D),
normalize_kwargs(kwargs.pop("err_kws", {}), mpl.lines.Line2D),
None,
errwidth=kwargs.pop("errwidth", deprecated),
capsize=kwargs.pop("capsize", 0),
Expand All @@ -3052,7 +3052,7 @@ def catplot(
aggregator = agg_cls(estimator, errorbar, n_boot=n_boot, seed=seed)

err_kws, capsize = p._err_kws_backcompat(
_normalize_kwargs(kwargs.pop("err_kws", {}), mpl.lines.Line2D),
normalize_kwargs(kwargs.pop("err_kws", {}), mpl.lines.Line2D),
errcolor=kwargs.pop("errcolor", deprecated),
errwidth=kwargs.pop("errwidth", deprecated),
capsize=kwargs.pop("capsize", 0),
Expand Down
6 changes: 3 additions & 3 deletions seaborn/distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.transforms as tx
from matplotlib.cbook import normalize_kwargs
from matplotlib.colors import to_rgba
from matplotlib.collections import LineCollection

Expand All @@ -28,7 +29,6 @@
remove_na,
_get_transform_functions,
_kde_support,
_normalize_kwargs,
_check_argument,
_assign_default_kwargs,
_default_color,
Expand Down Expand Up @@ -171,7 +171,7 @@ def _artist_kws(self, kws, fill, element, multiple, color, alpha):
"""Handle differences between artists in filled/unfilled plots."""
kws = kws.copy()
if fill:
kws = _normalize_kwargs(kws, mpl.collections.PolyCollection)
kws = normalize_kwargs(kws, mpl.collections.PolyCollection)
kws.setdefault("facecolor", to_rgba(color, alpha))

if element == "bars":
Expand Down Expand Up @@ -916,7 +916,7 @@ def plot_univariate_density(
artist = mpl.collections.PolyCollection
else:
artist = mpl.lines.Line2D
plot_kws = _normalize_kwargs(plot_kws, artist)
plot_kws = normalize_kwargs(plot_kws, artist)

# Input checking
_check_argument("multiple", ["layer", "stack", "fill"], multiple)
Expand Down
6 changes: 3 additions & 3 deletions seaborn/relational.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.cbook import normalize_kwargs

from ._base import (
VectorPlotter,
Expand All @@ -14,7 +15,6 @@
_default_color,
_deprecate_ci,
_get_transform_functions,
_normalize_kwargs,
_scatter_legend_artist,
)
from ._statistics import EstimateAggregator, WeightedAggregator
Expand Down Expand Up @@ -237,7 +237,7 @@ def plot(self, ax, kws):
# gotten from the corresponding matplotlib function, and calling the
# function will advance the axes property cycle.

kws = _normalize_kwargs(kws, mpl.lines.Line2D)
kws = normalize_kwargs(kws, mpl.lines.Line2D)
kws.setdefault("markeredgewidth", 0.75)
kws.setdefault("markeredgecolor", "w")

Expand Down Expand Up @@ -400,7 +400,7 @@ def plot(self, ax, kws):
if data.empty:
return

kws = _normalize_kwargs(kws, mpl.collections.PathCollection)
kws = normalize_kwargs(kws, mpl.collections.PathCollection)

# Define the vectors of x and y positions
empty = np.full(len(data), np.nan)
Expand Down
55 changes: 4 additions & 51 deletions seaborn/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,6 @@ def ci_to_errsize(cis, heights):
return errsize


def _normal_quantile_func(q):
"""
Compute the quantile function of the standard normal distribution.
This wrapper exists because we are dropping scipy as a mandatory dependency
but statistics.NormalDist was added to the standard library in 3.8.
"""
try:
from statistics import NormalDist
qf = np.vectorize(NormalDist().inv_cdf)
except ImportError:
try:
from scipy.stats import norm
qf = norm.ppf
except ImportError:
msg = (
"Standard normal quantile functions require either Python>=3.8 or scipy"
)
raise RuntimeError(msg)
return qf(q)


def _draw_figure(fig):
"""Force draw of a matplotlib figure, accounting for back-compat."""
# See https://github.com/matplotlib/matplotlib/issues/19197 for context
Expand Down Expand Up @@ -110,7 +87,7 @@ def _default_color(method, hue, color, kws, saturation=1):

elif method.__name__ == "plot":

color = _normalize_kwargs(kws, mpl.lines.Line2D).get("color")
color = normalize_kwargs(kws, mpl.lines.Line2D).get("color")
scout, = method([], [], scalex=False, scaley=False, color=color)
color = scout.get_color()
scout.remove()
Expand Down Expand Up @@ -155,7 +132,7 @@ def _default_color(method, hue, color, kws, saturation=1):

elif method.__name__ == "fill_between":

kws = _normalize_kwargs(kws, mpl.collections.PolyCollection)
kws = normalize_kwargs(kws, mpl.collections.PolyCollection)
scout = method([], [], **kws)
facecolor = scout.get_facecolor()
color = to_rgb(facecolor[0])
Expand Down Expand Up @@ -714,11 +691,7 @@ def get_view_interval(self):
formatter.set_scientific(False)
formatter.axis = dummy_axis()

# TODO: The following two lines should be replaced
# once pinned matplotlib>=3.1.0 with:
# formatted_levels = formatter.format_ticks(raw_levels)
formatter.set_locs(raw_levels)
formatted_levels = [formatter(x) for x in raw_levels]
formatted_levels = formatter.format_ticks(raw_levels)

return raw_levels, formatted_levels

Expand Down Expand Up @@ -774,26 +747,6 @@ def to_utf8(obj):
return str(obj)


def _normalize_kwargs(kws, artist):
"""Wrapper for mpl.cbook.normalize_kwargs that supports <= 3.2.1."""
_alias_map = {
'color': ['c'],
'linewidth': ['lw'],
'linestyle': ['ls'],
'facecolor': ['fc'],
'edgecolor': ['ec'],
'markerfacecolor': ['mfc'],
'markeredgecolor': ['mec'],
'markeredgewidth': ['mew'],
'markersize': ['ms']
}
try:
kws = normalize_kwargs(kws, artist)
except AttributeError:
kws = normalize_kwargs(kws, _alias_map)
return kws


def _check_argument(param, options, value, prefix=False):
"""Raise if value for param is not in options."""
if prefix and value is not None:
Expand Down Expand Up @@ -905,7 +858,7 @@ def _version_predates(lib: ModuleType, version: str) -> bool:

def _scatter_legend_artist(**kws):

kws = _normalize_kwargs(kws, mpl.collections.PathCollection)
kws = normalize_kwargs(kws, mpl.collections.PathCollection)

edgecolor = kws.pop("edgecolor", None)
rc = mpl.rcParams
Expand Down
2 changes: 1 addition & 1 deletion tests/_core/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,7 @@ def test_theme_params(self):
def test_theme_error(self):

p = Plot()
with pytest.raises(TypeError, match=r"theme\(\) takes 1 positional"):
with pytest.raises(TypeError, match=r"theme\(\) takes 2 positional"):
p.theme("arg1", "arg2")

def test_theme_validation(self):
Expand Down
Loading

0 comments on commit 785708f

Please sign in to comment.