Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup compat code for obsolete versions of dependencies #3607

Merged
merged 1 commit into from
Dec 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading