From 72a80e35c8a6b52d75c4c7b5b66b321fe960455b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Wed, 15 Nov 2023 16:38:02 -0500 Subject: [PATCH] TYP: towards matplotlib 3.8 (#55253) * TYP: towards matplotlib 3.8 * test 3.8 * ignore pyright errors * merging error * Conditional on import * Disable parallel build to see docbuild error * Some unnecessary ignores * Add typing in test_sql * type ignores * Multiple ignores * Uncomment --------- Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> --- ci/deps/actions-310.yaml | 2 +- ci/deps/actions-311-downstream_compat.yaml | 2 +- ci/deps/actions-311.yaml | 2 +- ci/deps/actions-39.yaml | 2 +- ci/deps/circle-310-arm64.yaml | 2 +- environment.yml | 2 +- pandas/plotting/_matplotlib/converter.py | 28 ++++++-- pandas/plotting/_matplotlib/core.py | 82 +++++++++++++++------- pandas/plotting/_matplotlib/hist.py | 26 +++++-- pandas/plotting/_matplotlib/style.py | 4 +- pandas/plotting/_matplotlib/timeseries.py | 26 ++++--- pandas/plotting/_matplotlib/tools.py | 18 +++-- pandas/tests/io/test_sql.py | 4 +- pandas/tests/plotting/common.py | 6 +- pyright_reportGeneralTypeIssues.json | 3 + requirements-dev.txt | 2 +- 16 files changed, 149 insertions(+), 62 deletions(-) diff --git a/ci/deps/actions-310.yaml b/ci/deps/actions-310.yaml index b22f8cb34c8147..94652e8586d774 100644 --- a/ci/deps/actions-310.yaml +++ b/ci/deps/actions-310.yaml @@ -33,7 +33,7 @@ dependencies: - gcsfs>=2022.11.0 - jinja2>=3.1.2 - lxml>=4.9.2 - - matplotlib>=3.6.3, <3.8 + - matplotlib>=3.6.3 - numba>=0.56.4 - numexpr>=2.8.4 - odfpy>=1.4.1 diff --git a/ci/deps/actions-311-downstream_compat.yaml b/ci/deps/actions-311-downstream_compat.yaml index ceea734352fca9..bf47bfe3a83ec5 100644 --- a/ci/deps/actions-311-downstream_compat.yaml +++ b/ci/deps/actions-311-downstream_compat.yaml @@ -34,7 +34,7 @@ dependencies: - gcsfs>=2022.11.0 - jinja2>=3.1.2 - lxml>=4.9.2 - - matplotlib>=3.6.3, <3.8 + - matplotlib>=3.6.3 - numba>=0.56.4 - numexpr>=2.8.4 - odfpy>=1.4.1 diff --git a/ci/deps/actions-311.yaml b/ci/deps/actions-311.yaml index 1c9f349c2eb28b..bd9e2059ef4775 100644 --- a/ci/deps/actions-311.yaml +++ b/ci/deps/actions-311.yaml @@ -33,7 +33,7 @@ dependencies: - gcsfs>=2022.11.0 - jinja2>=3.1.2 - lxml>=4.9.2 - - matplotlib>=3.6.3, <3.8 + - matplotlib>=3.6.3 - numba>=0.56.4 - numexpr>=2.8.4 - odfpy>=1.4.1 diff --git a/ci/deps/actions-39.yaml b/ci/deps/actions-39.yaml index 92b88a34094d2a..cf4087a3e46703 100644 --- a/ci/deps/actions-39.yaml +++ b/ci/deps/actions-39.yaml @@ -33,7 +33,7 @@ dependencies: - gcsfs>=2022.11.0 - jinja2>=3.1.2 - lxml>=4.9.2 - - matplotlib>=3.6.3, <3.8 + - matplotlib>=3.6.3 - numba>=0.56.4 - numexpr>=2.8.4 - odfpy>=1.4.1 diff --git a/ci/deps/circle-310-arm64.yaml b/ci/deps/circle-310-arm64.yaml index f81b91fcbae3b9..abe6145d077ed8 100644 --- a/ci/deps/circle-310-arm64.yaml +++ b/ci/deps/circle-310-arm64.yaml @@ -33,7 +33,7 @@ dependencies: - gcsfs>=2022.11.0 - jinja2>=3.1.2 - lxml>=4.9.2 - - matplotlib>=3.6.3, <3.8 + - matplotlib>=3.6.3 - numba>=0.56.4 - numexpr>=2.8.4 - odfpy>=1.4.1 diff --git a/environment.yml b/environment.yml index e41389c7f262a8..aea71efd72f2c0 100644 --- a/environment.yml +++ b/environment.yml @@ -35,7 +35,7 @@ dependencies: - ipython - jinja2>=3.1.2 - lxml>=4.9.2 - - matplotlib>=3.6.3, <3.8 + - matplotlib>=3.6.3 - numba>=0.56.4 - numexpr>=2.8.4 - openpyxl>=3.1.0 diff --git a/pandas/plotting/_matplotlib/converter.py b/pandas/plotting/_matplotlib/converter.py index 5a7ceabbf554ea..848fb77c942fbe 100644 --- a/pandas/plotting/_matplotlib/converter.py +++ b/pandas/plotting/_matplotlib/converter.py @@ -64,6 +64,8 @@ if TYPE_CHECKING: from collections.abc import Generator + from matplotlib.axis import Axis + from pandas._libs.tslibs.offsets import BaseOffset @@ -187,7 +189,7 @@ class TimeFormatter(Formatter): def __init__(self, locs) -> None: self.locs = locs - def __call__(self, x, pos: int = 0) -> str: + def __call__(self, x, pos: int | None = 0) -> str: """ Return the time of day as a formatted string. @@ -364,8 +366,14 @@ def get_locator(self, dmin, dmax): locator = MilliSecondLocator(self.tz) locator.set_axis(self.axis) - locator.axis.set_view_interval(*self.axis.get_view_interval()) - locator.axis.set_data_interval(*self.axis.get_data_interval()) + # error: Item "None" of "Axis | _DummyAxis | _AxisWrapper | None" + # has no attribute "get_data_interval" + locator.axis.set_view_interval( # type: ignore[union-attr] + *self.axis.get_view_interval() # type: ignore[union-attr] + ) + locator.axis.set_data_interval( # type: ignore[union-attr] + *self.axis.get_data_interval() # type: ignore[union-attr] + ) return locator return mdates.AutoDateLocator.get_locator(self, dmin, dmax) @@ -950,6 +958,8 @@ class TimeSeries_DateLocator(Locator): day : {int}, optional """ + axis: Axis + def __init__( self, freq: BaseOffset, @@ -999,7 +1009,9 @@ def __call__(self): base = self.base (d, m) = divmod(vmin, base) vmin = (d + 1) * base - locs = list(range(vmin, vmax + 1, base)) + # error: No overload variant of "range" matches argument types "float", + # "float", "int" + locs = list(range(vmin, vmax + 1, base)) # type: ignore[call-overload] return locs def autoscale(self): @@ -1038,6 +1050,8 @@ class TimeSeries_DateFormatter(Formatter): Whether the formatter works in dynamic mode or not. """ + axis: Axis + def __init__( self, freq: BaseOffset, @@ -1084,7 +1098,7 @@ def set_locs(self, locs) -> None: (vmin, vmax) = (vmax, vmin) self._set_default_format(vmin, vmax) - def __call__(self, x, pos: int = 0) -> str: + def __call__(self, x, pos: int | None = 0) -> str: if self.formatdict is None: return "" else: @@ -1107,6 +1121,8 @@ class TimeSeries_TimedeltaFormatter(Formatter): Formats the ticks along an axis controlled by a :class:`TimedeltaIndex`. """ + axis: Axis + @staticmethod def format_timedelta_ticks(x, pos, n_decimals: int) -> str: """ @@ -1124,7 +1140,7 @@ def format_timedelta_ticks(x, pos, n_decimals: int) -> str: s = f"{int(d):d} days {s}" return s - def __call__(self, x, pos: int = 0) -> str: + def __call__(self, x, pos: int | None = 0) -> str: (vmin, vmax) = tuple(self.axis.get_view_interval()) n_decimals = min(int(np.ceil(np.log10(100 * 10**9 / abs(vmax - vmin)))), 9) return self.format_timedelta_ticks(x, pos, n_decimals) diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py index 76b68c6b03dd2d..6be8284d2a0be7 100644 --- a/pandas/plotting/_matplotlib/core.py +++ b/pandas/plotting/_matplotlib/core.py @@ -529,9 +529,16 @@ def _maybe_right_yaxis(self, ax: Axes, axes_num: int) -> Axes: # otherwise, create twin axes orig_ax, new_ax = ax, ax.twinx() # TODO: use Matplotlib public API when available - new_ax._get_lines = orig_ax._get_lines - new_ax._get_patches_for_fill = orig_ax._get_patches_for_fill - orig_ax.right_ax, new_ax.left_ax = new_ax, orig_ax + new_ax._get_lines = orig_ax._get_lines # type: ignore[attr-defined] + # TODO #54485 + new_ax._get_patches_for_fill = ( # type: ignore[attr-defined] + orig_ax._get_patches_for_fill # type: ignore[attr-defined] + ) + # TODO #54485 + orig_ax.right_ax, new_ax.left_ax = ( # type: ignore[attr-defined] + new_ax, + orig_ax, + ) if not self._has_plotted_object(orig_ax): # no data on left y orig_ax.get_yaxis().set_visible(False) @@ -540,7 +547,7 @@ def _maybe_right_yaxis(self, ax: Axes, axes_num: int) -> Axes: new_ax.set_yscale("log") elif self.logy == "sym" or self.loglog == "sym": new_ax.set_yscale("symlog") - return new_ax + return new_ax # type: ignore[return-value] @final @cache_readonly @@ -1206,12 +1213,15 @@ def _get_errorbars( @final def _get_subplots(self, fig: Figure): - from matplotlib.axes import Subplot + if Version(mpl.__version__) < Version("3.8"): + from matplotlib.axes import Subplot as Klass + else: + from matplotlib.axes import Axes as Klass return [ ax for ax in fig.get_axes() - if (isinstance(ax, Subplot) and ax.get_subplotspec() is not None) + if (isinstance(ax, Klass) and ax.get_subplotspec() is not None) ] @final @@ -1255,8 +1265,10 @@ def _post_plot_logic(self, ax: Axes, data) -> None: x, y = self.x, self.y xlabel = self.xlabel if self.xlabel is not None else pprint_thing(x) ylabel = self.ylabel if self.ylabel is not None else pprint_thing(y) - ax.set_xlabel(xlabel) - ax.set_ylabel(ylabel) + # error: Argument 1 to "set_xlabel" of "_AxesBase" has incompatible + # type "Hashable"; expected "str" + ax.set_xlabel(xlabel) # type: ignore[arg-type] + ax.set_ylabel(ylabel) # type: ignore[arg-type] @final def _plot_colorbar(self, ax: Axes, *, fig: Figure, **kwds): @@ -1393,7 +1405,7 @@ def _get_norm_and_cmap(self, c_values, color_by_categorical: bool): else: cmap = None - if color_by_categorical: + if color_by_categorical and cmap is not None: from matplotlib import colors n_cats = len(self.data[c].cat.categories) @@ -1584,13 +1596,13 @@ def _ts_plot(self, ax: Axes, x, data: Series, style=None, **kwds): decorate_axes(ax.left_ax, freq, kwds) if hasattr(ax, "right_ax"): decorate_axes(ax.right_ax, freq, kwds) - ax._plot_data.append((data, self._kind, kwds)) + # TODO #54485 + ax._plot_data.append((data, self._kind, kwds)) # type: ignore[attr-defined] lines = self._plot(ax, data.index, np.asarray(data.values), style=style, **kwds) # set date formatter, locators and rescale limits - # error: Argument 3 to "format_dateaxis" has incompatible type "Index"; - # expected "DatetimeIndex | PeriodIndex" - format_dateaxis(ax, ax.freq, data.index) # type: ignore[arg-type] + # TODO #54485 + format_dateaxis(ax, ax.freq, data.index) # type: ignore[arg-type, attr-defined] return lines @final @@ -1606,11 +1618,15 @@ def _initialize_stacker(cls, ax: Axes, stacking_id, n: int) -> None: if stacking_id is None: return if not hasattr(ax, "_stacker_pos_prior"): - ax._stacker_pos_prior = {} + # TODO #54485 + ax._stacker_pos_prior = {} # type: ignore[attr-defined] if not hasattr(ax, "_stacker_neg_prior"): - ax._stacker_neg_prior = {} - ax._stacker_pos_prior[stacking_id] = np.zeros(n) - ax._stacker_neg_prior[stacking_id] = np.zeros(n) + # TODO #54485 + ax._stacker_neg_prior = {} # type: ignore[attr-defined] + # TODO #54485 + ax._stacker_pos_prior[stacking_id] = np.zeros(n) # type: ignore[attr-defined] + # TODO #54485 + ax._stacker_neg_prior[stacking_id] = np.zeros(n) # type: ignore[attr-defined] @final @classmethod @@ -1624,9 +1640,17 @@ def _get_stacked_values( cls._initialize_stacker(ax, stacking_id, len(values)) if (values >= 0).all(): - return ax._stacker_pos_prior[stacking_id] + values + # TODO #54485 + return ( + ax._stacker_pos_prior[stacking_id] # type: ignore[attr-defined] + + values + ) elif (values <= 0).all(): - return ax._stacker_neg_prior[stacking_id] + values + # TODO #54485 + return ( + ax._stacker_neg_prior[stacking_id] # type: ignore[attr-defined] + + values + ) raise ValueError( "When stacked is True, each column must be either " @@ -1640,9 +1664,11 @@ def _update_stacker(cls, ax: Axes, stacking_id: int | None, values) -> None: if stacking_id is None: return if (values >= 0).all(): - ax._stacker_pos_prior[stacking_id] += values + # TODO #54485 + ax._stacker_pos_prior[stacking_id] += values # type: ignore[attr-defined] elif (values <= 0).all(): - ax._stacker_neg_prior[stacking_id] += values + # TODO #54485 + ax._stacker_neg_prior[stacking_id] += values # type: ignore[attr-defined] def _post_plot_logic(self, ax: Axes, data) -> None: from matplotlib.ticker import FixedLocator @@ -1658,7 +1684,9 @@ def get_label(i): if self._need_to_set_index: xticks = ax.get_xticks() xticklabels = [get_label(x) for x in xticks] - ax.xaxis.set_major_locator(FixedLocator(xticks)) + # error: Argument 1 to "FixedLocator" has incompatible type "ndarray[Any, + # Any]"; expected "Sequence[float]" + ax.xaxis.set_major_locator(FixedLocator(xticks)) # type: ignore[arg-type] ax.set_xticklabels(xticklabels) # If the index is an irregular time series, then by default @@ -1737,9 +1765,11 @@ def _plot( # type: ignore[override] if stacking_id is None: start = np.zeros(len(y)) elif (y >= 0).all(): - start = ax._stacker_pos_prior[stacking_id] + # TODO #54485 + start = ax._stacker_pos_prior[stacking_id] # type: ignore[attr-defined] elif (y <= 0).all(): - start = ax._stacker_neg_prior[stacking_id] + # TODO #54485 + start = ax._stacker_neg_prior[stacking_id] # type: ignore[attr-defined] else: start = np.zeros(len(y)) @@ -2005,7 +2035,9 @@ def _decorate_ticks( ax.set_yticklabels(ticklabels) if name is not None and self.use_index: ax.set_ylabel(name) - ax.set_xlabel(self.xlabel) + # error: Argument 1 to "set_xlabel" of "_AxesBase" has incompatible type + # "Hashable | None"; expected "str" + ax.set_xlabel(self.xlabel) # type: ignore[arg-type] class PiePlot(MPLPlot): diff --git a/pandas/plotting/_matplotlib/hist.py b/pandas/plotting/_matplotlib/hist.py index f5b415f12f37d7..de4fd91541a9d8 100644 --- a/pandas/plotting/_matplotlib/hist.py +++ b/pandas/plotting/_matplotlib/hist.py @@ -199,11 +199,21 @@ def _get_column_weights(weights, i: int, y): def _post_plot_logic(self, ax: Axes, data) -> None: if self.orientation == "horizontal": - ax.set_xlabel("Frequency" if self.xlabel is None else self.xlabel) - ax.set_ylabel(self.ylabel) + # error: Argument 1 to "set_xlabel" of "_AxesBase" has incompatible + # type "Hashable"; expected "str" + ax.set_xlabel( + "Frequency" + if self.xlabel is None + else self.xlabel # type: ignore[arg-type] + ) + ax.set_ylabel(self.ylabel) # type: ignore[arg-type] else: - ax.set_xlabel(self.xlabel) - ax.set_ylabel("Frequency" if self.ylabel is None else self.ylabel) + ax.set_xlabel(self.xlabel) # type: ignore[arg-type] + ax.set_ylabel( + "Frequency" + if self.ylabel is None + else self.ylabel # type: ignore[arg-type] + ) @property def orientation(self) -> PlottingOrientation: @@ -447,8 +457,14 @@ def hist_series( ax.grid(grid) axes = np.array([ax]) + # error: Argument 1 to "set_ticks_props" has incompatible type "ndarray[Any, + # dtype[Any]]"; expected "Axes | Sequence[Axes]" set_ticks_props( - axes, xlabelsize=xlabelsize, xrot=xrot, ylabelsize=ylabelsize, yrot=yrot + axes, # type: ignore[arg-type] + xlabelsize=xlabelsize, + xrot=xrot, + ylabelsize=ylabelsize, + yrot=yrot, ) else: diff --git a/pandas/plotting/_matplotlib/style.py b/pandas/plotting/_matplotlib/style.py index a5f34e9434cb74..bf4e4be3bfd82e 100644 --- a/pandas/plotting/_matplotlib/style.py +++ b/pandas/plotting/_matplotlib/style.py @@ -269,7 +269,9 @@ def _is_single_string_color(color: Color) -> bool: """ conv = matplotlib.colors.ColorConverter() try: - conv.to_rgba(color) + # error: Argument 1 to "to_rgba" of "ColorConverter" has incompatible type + # "str | Sequence[float]"; expected "tuple[float, float, float] | ..." + conv.to_rgba(color) # type: ignore[arg-type] except ValueError: return False else: diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index 5471305b03bafc..f0b68e5dde4501 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -126,7 +126,7 @@ def _upsample_others(ax: Axes, freq: BaseOffset, kwargs: dict[str, Any]) -> None labels.extend(rlabels) if legend is not None and kwargs.get("legend", True) and len(lines) > 0: - title = legend.get_title().get_text() + title: str | None = legend.get_title().get_text() if title == "None": title = None ax.legend(lines, labels, loc="best", title=title) @@ -136,7 +136,8 @@ def _replot_ax(ax: Axes, freq: BaseOffset, kwargs: dict[str, Any]): data = getattr(ax, "_plot_data", None) # clear current axes and data - ax._plot_data = [] + # TODO #54485 + ax._plot_data = [] # type: ignore[attr-defined] ax.clear() decorate_axes(ax, freq, kwargs) @@ -148,7 +149,8 @@ def _replot_ax(ax: Axes, freq: BaseOffset, kwargs: dict[str, Any]): series = series.copy() idx = series.index.asfreq(freq, how="S") series.index = idx - ax._plot_data.append((series, plotf, kwds)) + # TODO #54485 + ax._plot_data.append((series, plotf, kwds)) # type: ignore[attr-defined] # for tsplot if isinstance(plotf, str): @@ -165,17 +167,23 @@ def _replot_ax(ax: Axes, freq: BaseOffset, kwargs: dict[str, Any]): def decorate_axes(ax: Axes, freq: BaseOffset, kwargs: dict[str, Any]) -> None: """Initialize axes for time-series plotting""" if not hasattr(ax, "_plot_data"): - ax._plot_data = [] + # TODO #54485 + ax._plot_data = [] # type: ignore[attr-defined] - ax.freq = freq + # TODO #54485 + ax.freq = freq # type: ignore[attr-defined] xaxis = ax.get_xaxis() - xaxis.freq = freq + # TODO #54485 + xaxis.freq = freq # type: ignore[attr-defined] if not hasattr(ax, "legendlabels"): - ax.legendlabels = [kwargs.get("label", None)] + # TODO #54485 + ax.legendlabels = [kwargs.get("label", None)] # type: ignore[attr-defined] else: ax.legendlabels.append(kwargs.get("label", None)) - ax.view_interval = None - ax.date_axis_info = None + # TODO #54485 + ax.view_interval = None # type: ignore[attr-defined] + # TODO #54485 + ax.date_axis_info = None # type: ignore[attr-defined] def _get_ax_freq(ax: Axes): diff --git a/pandas/plotting/_matplotlib/tools.py b/pandas/plotting/_matplotlib/tools.py index 8c0e401f991a62..898b5b25e7b017 100644 --- a/pandas/plotting/_matplotlib/tools.py +++ b/pandas/plotting/_matplotlib/tools.py @@ -52,10 +52,12 @@ def maybe_adjust_figure(fig: Figure, *args, **kwargs) -> None: def format_date_labels(ax: Axes, rot) -> None: # mini version of autofmt_xdate for label in ax.get_xticklabels(): - label.set_ha("right") + label.set_horizontalalignment("right") label.set_rotation(rot) fig = ax.get_figure() - maybe_adjust_figure(fig, bottom=0.2) + if fig is not None: + # should always be a Figure but can technically be None + maybe_adjust_figure(fig, bottom=0.2) def table( @@ -76,8 +78,14 @@ def table( cellText = data.values + # error: Argument "cellText" to "table" has incompatible type "ndarray[Any, + # Any]"; expected "Sequence[Sequence[str]] | None" return matplotlib.table.table( - ax, cellText=cellText, rowLabels=rowLabels, colLabels=colLabels, **kwargs + ax, + cellText=cellText, # type: ignore[arg-type] + rowLabels=rowLabels, + colLabels=colLabels, + **kwargs, ) @@ -369,12 +377,12 @@ def _has_externally_shared_axis(ax1: Axes, compare_axis: str) -> bool: "_has_externally_shared_axis() needs 'x' or 'y' as a second parameter" ) - axes = axes.get_siblings(ax1) + axes_siblings = axes.get_siblings(ax1) # Retain ax1 and any of its siblings which aren't in the same position as it ax1_points = ax1.get_position().get_points() - for ax2 in axes: + for ax2 in axes_siblings: if not np.array_equal(ax1_points, ax2.get_position().get_points()): return True diff --git a/pandas/tests/io/test_sql.py b/pandas/tests/io/test_sql.py index b274866b7c9a82..9ac20774b8c932 100644 --- a/pandas/tests/io/test_sql.py +++ b/pandas/tests/io/test_sql.py @@ -3179,7 +3179,9 @@ def dtype_backend_data() -> DataFrame: @pytest.fixture def dtype_backend_expected(): - def func(storage, dtype_backend, conn_name): + def func(storage, dtype_backend, conn_name) -> DataFrame: + string_array: StringArray | ArrowStringArray + string_array_na: StringArray | ArrowStringArray if storage == "python": string_array = StringArray(np.array(["a", "b", "c"], dtype=np.object_)) string_array_na = StringArray(np.array(["a", "b", pd.NA], dtype=np.object_)) diff --git a/pandas/tests/plotting/common.py b/pandas/tests/plotting/common.py index fd5a66049bd24b..69120160699c24 100644 --- a/pandas/tests/plotting/common.py +++ b/pandas/tests/plotting/common.py @@ -328,7 +328,7 @@ def _check_axes_shape(axes, axes_num=None, layout=None, figsize=None): ) -def _flatten_visible(axes): +def _flatten_visible(axes: Axes | Sequence[Axes]) -> Sequence[Axes]: """ Flatten axes, and filter only visible @@ -339,8 +339,8 @@ def _flatten_visible(axes): """ from pandas.plotting._matplotlib.tools import flatten_axes - axes = flatten_axes(axes) - axes = [ax for ax in axes if ax.get_visible()] + axes_ndarray = flatten_axes(axes) + axes = [ax for ax in axes_ndarray if ax.get_visible()] return axes diff --git a/pyright_reportGeneralTypeIssues.json b/pyright_reportGeneralTypeIssues.json index c059b9c589ecd8..e155b340530693 100644 --- a/pyright_reportGeneralTypeIssues.json +++ b/pyright_reportGeneralTypeIssues.json @@ -99,6 +99,9 @@ "pandas/io/sql.py", "pandas/io/stata.py", "pandas/plotting/_matplotlib/boxplot.py", + "pandas/plotting/_matplotlib/core.py", + "pandas/plotting/_matplotlib/timeseries.py", + "pandas/plotting/_matplotlib/tools.py", "pandas/tseries/frequencies.py", "pandas/tseries/holiday.py", ], diff --git a/requirements-dev.txt b/requirements-dev.txt index 490e1702990302..faf915f4b9716a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,7 +24,7 @@ gcsfs>=2022.11.0 ipython jinja2>=3.1.2 lxml>=4.9.2 -matplotlib>=3.6.3, <3.8 +matplotlib>=3.6.3 numba>=0.56.4 numexpr>=2.8.4 openpyxl>=3.1.0