return super().dispatch(request, *args, **kwargs)      def get_success_url(self):        url = self.get_redirect_url()        return url or resolve_url(settings.LOGIN_REDIRECT_URL)        return self.get_redirect_url() or self.get_default_redirect_url()      def get_redirect_url(self):         """Return the user-originating redirect URL if it's safe."""


)         return redirect_to if url_is_safe else '' <ins>    def get_default_redirect_url(self):        """Return the default redirect URL."""        return resolve_url(self.next_page or settings.LOGIN_REDIRECT_URL)</ins>     def get_form_class(self):         return self.authentication_form or self.form_class


def __init__(self, argv=None):         self.argv = argv or sys.argv[:]         self.prog_name = os.path.basename(self.argv[0])<ins>        if self.prog_name == '__main__.py':            self.prog_name = 'python -m django'</ins>         self.settings_exception = None      def main_help_text(self, commands_only=False):


# types they are. The key is the alias of the joined table (possibly         # the table name) and the value is a Join-like object (see         # sql.datastructures.Join for more information).        self.alias_map = {}        self.alias_map = OrderedDict()         # Sometimes the query contains references to aliases in outer queries (as         # a result of split_exclude). Correct alias quoting needs to know these         # aliases too.


self.orphans = int(orphans)         self.allow_empty_first_page = allow_empty_first_page <ins>    def __iter__(self):        for page_number in self.page_range:            yield self.page(page_number)</ins>     def validate_number(self, number):         """Validate the given 1-based page number."""         try:


import pkgutil import sys from collections import OrderedDict, defaultdict<ins>from difflib import get_close_matches</ins> from importlib import import_module  import django


settings.INSTALLED_APPS             else:                 sys.stderr.write("No Django settings specified.\n")            sys.stderr.write(                "Unknown command: %r\nType '%s help' for usage.\n"                % (subcommand, self.prog_name)            )            possible_matches = get_close_matches(subcommand, commands)            sys.stderr.write('Unknown command: %r' % subcommand)            if possible_matches:                sys.stderr.write('. Did you mean %s?' % possible_matches[0])            sys.stderr.write("\nType '%s help' for usage.\n" % self.prog_name)             sys.exit(1)         if isinstance(app_name, BaseCommand):             # If the command is already loaded, use it directly.


self, prog="%s %s" % (os.path.basename(prog_name), subcommand),             description=self.help or None,         )<ins>        # Add command-specific arguments first so that they appear in the        # --help output before arguments common to all commands.        self.add_arguments(parser)</ins>         parser.add_argument('--version', action='version', version=self.get_version())         parser.add_argument(             '-v', '--verbosity', action='store', dest='verbosity', default=1,


'--no-color', action='store_true', dest='no_color',             help="Don't colorize the command output.",         )<del>        self.add_arguments(parser)</del>         return parser      def add_arguments(self, parser):


if frameon is None:             frameon = rcParams['figure.frameon']         if not np.isfinite(figsize).all():            raise ValueError('figure size must be finite not '                             '{}'.format(figsize))        if not np.isfinite(figsize).all() or (np.array(figsize) <= 0).any():            raise ValueError('figure size must be positive finite not '                             f'{figsize}')         self.bbox_inches = Bbox.from_bounds(0, 0, *figsize)          self.dpi_scale_trans = Affine2D().scale(dpi, dpi)


# argument, so unpack them         if h is None:             w, h = w        if not all(np.isfinite(_) for _ in (w, h)):            raise ValueError('figure size must be finite not '                             '({}, {})'.format(w, h))        size = w, h        if not np.isfinite(size).all() or (np.array(size) <= 0).any():            raise ValueError(f'figure size must be positive finite not {size}')         self.bbox_inches.p1 = w, h          if forward:


`.Axis.contains`.         """         martist.Artist.__init__(self)<ins>        self._remove_overlapping_locs = True</ins>         self.set_figure(axes.figure)          self.isDefault_label = True


majorTicks = _LazyTickList(major=True)     minorTicks = _LazyTickList(major=False) <ins>    def get_remove_overlapping_locs(self):        return self._remove_overlapping_locs    def set_remove_overlapping_locs(self, val):        self._remove_overlapping_locs = bool(val)    remove_overlapping_locs = property(        get_remove_overlapping_locs, set_remove_overlapping_locs,        doc=('If minor ticker locations that overlap with major '             'ticker locations should be trimmed.'))</ins>     def set_label_coords(self, x, y, transform=None):         """         Set the coordinates of the label.


Update ticks (position and labels) using the current data interval of         the axes.  Return the list of ticks that will be drawn.         """        major_locs = self.major.locator()        major_ticks = self.get_major_ticks(len(major_locs))        major_locs = self.get_majorticklocs()         major_labels = self.major.formatter.format_ticks(major_locs)        major_ticks = self.get_major_ticks(len(major_locs))        self.major.formatter.set_locs(major_locs)         for tick, loc, label in zip(major_ticks, major_locs, major_labels):             tick.update_position(loc)             tick.set_label1(label)             tick.set_label2(label)        minor_locs = self.minor.locator()        minor_ticks = self.get_minor_ticks(len(minor_locs))        minor_locs = self.get_minorticklocs()         minor_labels = self.minor.formatter.format_ticks(minor_locs)        minor_ticks = self.get_minor_ticks(len(minor_locs))        self.minor.formatter.set_locs(minor_locs)         for tick, loc, label in zip(minor_ticks, minor_locs, minor_labels):             tick.update_position(loc)             tick.set_label1(label)             tick.set_label2(label)         ticks = [*major_ticks, *minor_ticks]         # mark the ticks that we will not be using as not visible        for t in (self.minorTicks[len(minor_locs):] +                  self.majorTicks[len(major_locs):]):            t.set_visible(False)         view_low, view_high = self.get_view_interval()         if view_low > view_high:             view_low, view_high = view_high, view_low


# Use the transformed view limits as scale.  1e-5 is the default rtol         # for np.isclose.         tol = (hi - lo) * 1e-5        minor_locs = [            loc for loc, tr_loc in zip(minor_locs, tr_minor_locs)            if not np.isclose(tr_loc, tr_major_locs, atol=tol, rtol=0).any()]        if self.remove_overlapping_locs:            minor_locs = [                loc for loc, tr_loc in zip(minor_locs, tr_minor_locs)                if ~np.isclose(tr_loc, tr_major_locs, atol=tol, rtol=0).any()]         return minor_locs      def get_ticklocs(self, minor=False):


def get_major_ticks(self, numticks=None):         'Get the tick instances; grow as necessary.'         if numticks is None:            numticks = len(self.get_major_locator()())            numticks = len(self.get_majorticklocs())          while len(self.majorTicks) < numticks:             # Update the new tick label properties from the old.


def get_minor_ticks(self, numticks=None):         'Get the minor tick instances; grow as necessary.'         if numticks is None:            numticks = len(self.get_minor_locator()())            numticks = len(self.get_minorticklocs())          while len(self.minorTicks) < numticks:             # Update the new tick label properties from the old.


return tuple(color)         # string gray.         try:            return (float(c),) * 3 + (alpha if alpha is not None else 1.,)            c = float(c)         except ValueError:             pass        raise ValueError("Invalid RGBA argument: {!r}".format(orig_c))        else:            if not (0 <= c <= 1):                raise ValueError(                    f"Invalid string grayscale value {orig_c!r}. "                    f"Value must be within 0-1 range")            return c, c, c, alpha if alpha is not None else 1.        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")     # tuple color.     c = np.array(c)     if not np.can_cast(c.dtype, float, "same_kind") or c.ndim != 1:         # Test the dtype explicitly as `map(float, ...)`, `np.array(...,         # float)` and `np.array(...).astype(float)` all convert "0.5" to 0.5.         # Test dimensionality to reject single floats.        raise ValueError("Invalid RGBA argument: {!r}".format(orig_c))        raise ValueError(f"Invalid RGBA argument: {orig_c!r}")     # Return a tuple to prevent the cached value from being modified.     c = tuple(c.astype(float))     if len(c) not in [3, 4]:


(self._xmargin and scalex and self._autoscaleXon) or                 (self._ymargin and scaley and self._autoscaleYon)):             stickies = [artist.sticky_edges for artist in self.get_children()]            x_stickies = np.array([x for sticky in stickies for x in sticky.x])            y_stickies = np.array([y for sticky in stickies for y in sticky.y])            if self.get_xscale().lower() == 'log':                x_stickies = x_stickies[x_stickies > 0]            if self.get_yscale().lower() == 'log':                y_stickies = y_stickies[y_stickies > 0]         else:  # Small optimization.            x_stickies, y_stickies = [], []            stickies = []        x_stickies = np.sort([x for sticky in stickies for x in sticky.x])        y_stickies = np.sort([y for sticky in stickies for y in sticky.y])        if self.get_xscale().lower() == 'log':            x_stickies = x_stickies[x_stickies > 0]        if self.get_yscale().lower() == 'log':            y_stickies = y_stickies[y_stickies > 0]          def handle_single_axis(scale, autoscaleon, shared_axes, interval,                                minpos, axis, margin, stickies, set_bound):


locator = axis.get_major_locator()             x0, x1 = locator.nonsingular(x0, x1)             # Prevent margin addition from crossing a sticky value.  Small            # tolerances (whose values come from isclose()) must be used due to            # floating point issues with streamplot.            def tol(x): return 1e-5 * abs(x) + 1e-8            # Index of largest element < x0 + tol, if any.            i0 = stickies.searchsorted(x0 + tol(x0)) - 1            x0bound = stickies[i0] if i0 != -1 else None            # Index of smallest element > x1 - tol, if any.            i1 = stickies.searchsorted(x1 - tol(x1))            x1bound = stickies[i1] if i1 != len(stickies) else None             # Add the margin in figure space and then transform back, to handle             # non-linear scales.             minpos = getattr(bb, minpos)             transform = axis.get_transform()             inverse_trans = transform.inverted()            # We cannot use exact equality due to floating point issues e.g.            # with streamplot.            do_lower_margin = not np.any(np.isclose(x0, stickies))            do_upper_margin = not np.any(np.isclose(x1, stickies))             x0, x1 = axis._scale.limit_range_for_scale(x0, x1, minpos)             x0t, x1t = transform.transform([x0, x1])            if np.isfinite(x1t) and np.isfinite(x0t):                delta = (x1t - x0t) * margin            else:                # If at least one bound isn't finite, set margin to zero                delta = 0            if do_lower_margin:                x0t -= delta            if do_upper_margin:                x1t += delta            x0, x1 = inverse_trans.transform([x0t, x1t])            delta = (x1t - x0t) * margin            if not np.isfinite(delta):                delta = 0  # If a bound isn't finite, set margin to zero.            x0, x1 = inverse_trans.transform([x0t - delta, x1t + delta])            # Apply sticky bounds.            if x0bound is not None:                x0 = max(x0, x0bound)            if x1bound is not None:                x1 = min(x1, x1bound)              if not self._tight:                 x0, x1 = locator.view_limits(x0, x1)


"""         if not isinstance(formatter, mticker.Formatter):             raise TypeError("formatter argument should be instance of "                    "matplotlib.ticker.Formatter")                            "matplotlib.ticker.Formatter")         self.isDefault_majfmt = False         self.major.formatter = formatter         formatter.set_axis(self)diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py-- a/lib/matplotlib/figure.py++ b/lib/matplotlib/figure.py


def _remove_ax(self, ax):         def _reset_loc_form(axis):            axis.set_major_formatter(axis.get_major_formatter())            axis.set_major_locator(axis.get_major_locator())            axis.set_minor_formatter(axis.get_minor_formatter())            axis.set_minor_locator(axis.get_minor_locator())            # Set the formatters and locators to be associated with axis            # (where previously they may have been associated with another            # Axis isntance)            majfmt = axis.get_major_formatter()            if not majfmt.axis.isDefault_majfmt:                axis.set_major_formatter(majfmt)            majloc = axis.get_major_locator()            if not majloc.axis.isDefault_majloc:                axis.set_major_locator(majloc)            minfmt = axis.get_minor_formatter()            if not minfmt.axis.isDefault_minfmt:                axis.set_minor_formatter(minfmt)            minloc = axis.get_minor_locator()            if not minfmt.axis.isDefault_minloc:                axis.set_minor_locator(minloc)          def _break_share_link(ax, grouper):             siblings = grouper.get_siblings(ax)


'ha': 'center'},                  'tick': {'inward_factor': 0.2,                           'outward_factor': 0.1,                          'linewidth': rcParams['lines.linewidth'],                          'color': 'k'},                          'linewidth': rcParams['lines.linewidth']},                  'axisline': {'linewidth': 0.75,                               'color': (0, 0, 0, 1)},                  'grid': {'color': (0.9, 0.9, 0.9, 1),


'outward_factor': 0.1,                           'linewidth': rcParams.get(                               adir + 'tick.major.width',                              rcParams['xtick.major.width']),                          'color': rcParams.get(                              adir + 'tick.color',                              rcParams['xtick.color'])},                              rcParams['xtick.major.width'])},                  'axisline': {'linewidth': rcParams['axes.linewidth'],                               'color': rcParams['axes.edgecolor']},                  'grid': {'color': rcParams['grid.color'],


dx, dy = (self.axes.transAxes.transform([peparray[0:2, 1]]) -                   self.axes.transAxes.transform([peparray[0:2, 0]]))[0]         lxyz = 0.5*(edgep1 + edgep2)        lxyz = 0.5 * (edgep1 + edgep2)          # A rough estimate; points are ambiguous since 3D plots rotate         ax_scale = self.axes.bbox.size / self.figure.bbox.size


ticksign = -1          for tick in ticks:<del></del>             # Get tick line positions             pos = copy.copy(edgep1)             pos[index] = tick.get_loc()


tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))             tick.tick1line.set_linewidth(info['tick']['linewidth'])<del>            tick.tick1line.set_color(info['tick']['color'])</del>             tick.draw(renderer)          renderer.close_group('axis3d')


density = bool(density) or bool(normed)         if density and not stacked:            hist_kwargs = dict(density=density)            hist_kwargs['density'] = density          # List to store all the top coordinates of the histograms         tops = []


xerr = kwargs.pop('xerr', None)         yerr = kwargs.pop('yerr', None)         error_kw = kwargs.pop('error_kw', {})<ins>        ezorder = error_kw.pop('zorder', None)        if ezorder is None:            ezorder = kwargs.get('zorder', None)            if ezorder is not None:                # If using the bar zorder, increment slightly to make sure                # errorbars are drawn on top of bars                ezorder += 0.01        error_kw.setdefault('zorder', ezorder)</ins>         ecolor = kwargs.pop('ecolor', 'k')         capsize = kwargs.pop('capsize', rcParams["errorbar.capsize"])         error_kw.setdefault('ecolor', ecolor)


"""     Select the backend used for rendering and GUI integration. <ins>    If pyplot is already imported, `~matplotlib.pyplot.switch_backend` is used    and if the new backend is different than the current backend, all Figures    will be closed.</ins>     Parameters     ----------     backend : str


--------     :ref:`backends`     matplotlib.get_backend    matplotlib.pyplot.switch_backend     """     name = validate_backend(backend)     # don't (prematurely) resolve the "auto" backend settingdiff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py-- a/lib/matplotlib/pyplot.py++ b/lib/matplotlib/pyplot.py


def switch_backend(newbackend):     """    Close all open figures and set the Matplotlib backend.    Set the pyplot backend.     The argument is case-insensitive.  Switching to an interactive backend is    possible only if no event loop for another interactive backend has started.    Switching to and from non-interactive backends is always possible.    Switching to an interactive backend is possible only if no event loop for    another interactive backend has started.  Switching to and from    non-interactive backends is always possible.    If the new backend is different than the current backend then all open    Figures will be closed via ``plt.close('all')``.      Parameters     ----------     newbackend : str        The name of the backend to use.        The case-insensitive name of the backend to use.     """     global _backend_mod     # make sure the init is pulled up so we can assign to it later     import matplotlib.backends    close("all")      if newbackend is rcsetup._auto_backend_sentinel:         current_framework = cbook._get_running_interactive_framework()


switch_backend("agg")             rcParamsOrig["backend"] = "agg"             return<ins>    # have to escape the switch on access logic    old_backend = dict.__getitem__(rcParams, 'backend')</ins>      backend_mod = importlib.import_module(         cbook._backend_module_name(newbackend))


# Need to keep a global reference to the backend for compatibility reasons.     # See https://github.com/matplotlib/matplotlib/issues/6092     matplotlib.backends.backend = newbackend<ins>    if not cbook._str_equal(old_backend, newbackend):        close("all")</ins>      # make sure the repl display hook is installed in case we become     # interactive


cbook._warn_external(                 f"Attempting to set identical left == right == {left} results "                 f"in singular transformations; automatically expanding.")        swapped = left > right         left, right = self.xaxis.get_major_locator().nonsingular(left, right)         left, right = self.xaxis.limit_range_for_scale(left, right)        if swapped:            left, right = right, left          self.viewLim.intervalx = (left, right)         if auto is not None:


f"Attempting to set identical bottom == top == {bottom} "                 f"results in singular transformations; automatically "                 f"expanding.")        swapped = bottom > top         bottom, top = self.yaxis.get_major_locator().nonsingular(bottom, top)         bottom, top = self.yaxis.limit_range_for_scale(bottom, top)        if swapped:            bottom, top = top, bottom          self.viewLim.intervaly = (bottom, top)         if auto is not None:diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py-- a/lib/matplotlib/ticker.py++ b/lib/matplotlib/ticker.py


return locs      def nonsingular(self, v0, v1):        """Modify the endpoints of a range as needed to avoid singularities."""        return mtransforms.nonsingular(v0, v1, increasing=False, expander=.05)        """Expand a range as needed to avoid singularities."""        return mtransforms.nonsingular(v0, v1, expander=.05)      def view_limits(self, vmin, vmax):         """diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py-- a/lib/mpl_toolkits/mplot3d/axes3d.py++ b/lib/mpl_toolkits/mplot3d/axes3d.py


cbook._warn_external(                 f"Attempting to set identical left == right == {left} results "                 f"in singular transformations; automatically expanding.")        swapped = left > right         left, right = self.xaxis.get_major_locator().nonsingular(left, right)         left, right = self.xaxis.limit_range_for_scale(left, right)        if swapped:            left, right = right, left         self.xy_viewLim.intervalx = (left, right)          if auto is not None:


f"Attempting to set identical bottom == top == {bottom} "                 f"results in singular transformations; automatically "                 f"expanding.")        swapped = bottom > top         bottom, top = self.yaxis.get_major_locator().nonsingular(bottom, top)         bottom, top = self.yaxis.limit_range_for_scale(bottom, top)        if swapped:            bottom, top = top, bottom         self.xy_viewLim.intervaly = (bottom, top)          if auto is not None:


f"Attempting to set identical bottom == top == {bottom} "                 f"results in singular transformations; automatically "                 f"expanding.")        swapped = bottom > top         bottom, top = self.zaxis.get_major_locator().nonsingular(bottom, top)         bottom, top = self.zaxis.limit_range_for_scale(bottom, top)        if swapped:            bottom, top = top, bottom         self.zz_viewLim.intervalx = (bottom, top)          if auto is not None:


# For blitting, the init_func should return a sequence of modified         # artists.         if self._init_func is None:            self._draw_frame(next(self.new_frame_seq()))            try:                frame_data = next(self.new_frame_seq())            except StopIteration:                # we can't start the iteration, it may have already been                # exhausted by a previous save or just be 0 length.                # warn and bail.                warnings.warn(                    "Can not start iterating the frames for the initial draw. "                    "This can be caused by passing in a 0 length sequence "                    "for *frames*.\n\n"                    "If you passed *frames* as a generator "                    "it may be exhausted due to a previous display or save."                )                return            self._draw_frame(frame_data)         else:             self._drawn_artists = self._init_func()             if self._blit:


year      = 2007 }""" # modelled after sys.version_info_VersionInfo = namedtuple('_VersionInfo',                          'major, minor, micro, releaselevel, serial') def __getattr__(name):    if name == "__version__":def _parse_to_version_info(version_str):    """    Parse a version string to a namedtuple analogous to sys.version_info.    See:    https://packaging.pypa.io/en/latest/version.html#packaging.version.parse    https://docs.python.org/3/library/sys.html#sys.version_info    """    v = parse_version(version_str)    if v.pre is None and v.post is None and v.dev is None:        return _VersionInfo(v.major, v.minor, v.micro, 'final', 0)    elif v.dev is not None:        return _VersionInfo(v.major, v.minor, v.micro, 'alpha', v.dev)    elif v.pre is not None:        releaselevel = {            'a': 'alpha',            'b': 'beta',            'rc': 'candidate'}.get(v.pre[0], 'alpha')        return _VersionInfo(v.major, v.minor, v.micro, releaselevel, v.pre[1])    else:        # fallback for v.post: guess-next-dev scheme from setuptools_scm        return _VersionInfo(v.major, v.minor, v.micro + 1, 'alpha', v.post)def _get_version():    """Return the version string used for __version__."""    # Only shell out to a git subprocess if really needed, and not on a    # shallow clone, such as those used by CI, as the latter would trigger    # a warning from setuptools_scm.    root = Path(__file__).resolve().parents[2]    if (root / ".git").exists() and not (root / ".git/shallow").exists():         import setuptools_scm        return setuptools_scm.get_version(            root=root,            version_scheme="post-release",            local_scheme="node-and-date",            fallback_version=_version.version,        )    else:  # Get the version from the _version.py setuptools_scm file.        return _version.versiondef __getattr__(name):    if name in ("__version__", "__version_info__"):         global __version__  # cache it.        # Only shell out to a git subprocess if really needed, and not on a        # shallow clone, such as those used by CI, as the latter would trigger        # a warning from setuptools_scm.        root = Path(__file__).resolve().parents[2]        if (root / ".git").exists() and not (root / ".git/shallow").exists():            __version__ = setuptools_scm.get_version(                root=root,                version_scheme="post-release",                local_scheme="node-and-date",                fallback_version=_version.version,            )        else:  # Get the version from the _version.py setuptools_scm file.            __version__ = _version.version        return __version__        __version__ = _get_version()        global __version__info__  # cache it.        __version_info__ = _parse_to_version_info(__version__)        return __version__ if name == "__version__" else __version_info__     raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


**lineprops):         super().__init__(ax)         self.connect_event('motion_notify_event', self.onmove)        self.connect_event('draw_event', self.clear)        self.connect_event('motion_notify_event', self._onmove)        self.connect_event('draw_event', self._clear)          self.visible = True         self.horizOn = horizOn


self.background = None         self.needclear = False     @_api.deprecated('3.5')     def clear(self, event):         """Internal event handler to clear the cursor."""        self._clear(event)         if self.ignore(event):             return        if self.useblit:            self.background = self.canvas.copy_from_bbox(self.ax.bbox)         self.linev.set_visible(False)         self.lineh.set_visible(False)     def onmove(self, event):    def _clear(self, event):        """Internal event handler to clear the cursor."""        if self.ignore(event):            return        if self.useblit:            self.background = self.canvas.copy_from_bbox(self.ax.bbox)    onmove = _api.deprecate_privatize_attribute('3.5')    def _onmove(self, event):         """Internal event handler to draw the cursor when the mouse moves."""         if self.ignore(event):             return


self.needclear = False             return         self.needclear = True        if not self.visible:            return         self.linev.set_xdata((event.xdata, event.xdata))        self.linev.set_visible(self.visible and self.vertOn)          self.lineh.set_ydata((event.ydata, event.ydata))        self.linev.set_visible(self.visible and self.vertOn)         self.lineh.set_visible(self.visible and self.horizOn)         self._update()        if self.visible and (self.vertOn or self.horizOn):            self._update()      def _update(self):         if self.useblit:


"""Connect events."""         for canvas, info in self._canvas_infos.items():             info["cids"] = [                canvas.mpl_connect('motion_notify_event', self.onmove),                canvas.mpl_connect('draw_event', self.clear),                canvas.mpl_connect('motion_notify_event', self._onmove),                canvas.mpl_connect('draw_event', self._clear),             ]      def disconnect(self):


canvas.mpl_disconnect(cid)             info["cids"].clear()     @_api.deprecated('3.5')     def clear(self, event):        """Clear the cursor."""        if self.ignore(event):            return        self._clear(event)        for line in self.vlines + self.hlines:            line.set_visible(False)    def _clear(self, event):         """Clear the cursor."""         if self.ignore(event):             return         if self.useblit:             for canvas, info in self._canvas_infos.items():                 info["background"] = canvas.copy_from_bbox(canvas.figure.bbox)        for line in self.vlines + self.hlines:            line.set_visible(False)     def onmove(self, event):    onmove = _api.deprecate_privatize_attribute('3.5')    def _onmove(self, event):         if (self.ignore(event)                 or event.inaxes not in self.axes                 or not event.canvas.widgetlock.available(self)):             return         self.needclear = True        if not self.visible:            return         if self.vertOn:             for line in self.vlines:                 line.set_xdata((event.xdata, event.xdata))


for line in self.hlines:                 line.set_ydata((event.ydata, event.ydata))                 line.set_visible(self.visible)        self._update()        if self.visible and (self.vertOn or self.horizOn):            self._update()      def _update(self):         if self.useblit:


return [self.filename(fmt) for fmt in self.formats]  def out_of_date(original, derived):def out_of_date(original, derived, includes=None):     """    Return whether *derived* is out-of-date relative to *original*, both of    which are full file paths.    Return whether *derived* is out-of-date relative to *original* or any of    the RST files included in it using the RST include directive (*includes*).    *derived* and *original* are full paths, and *includes* is optionally a    list of full paths which may have been included in the *original*.     """    return (not os.path.exists(derived) or            (os.path.exists(original) and             os.stat(derived).st_mtime < os.stat(original).st_mtime))    if not os.path.exists(derived):        return True    if includes is None:        includes = []    files_to_check = [original, *includes]    def out_of_date_one(original, derived_mtime):        return (os.path.exists(original) and                derived_mtime < os.stat(original).st_mtime)    derived_mtime = os.stat(derived).st_mtime    return any(out_of_date_one(f, derived_mtime) for f in files_to_check)   class PlotError(RuntimeError):


def render_figures(code, code_path, output_dir, output_base, context,                    function_name, config, context_reset=False,                   close_figs=False):                   close_figs=False,                   code_includes=None):     """     Run a pyplot script and save the images in *output_dir*.


all_exists = True     img = ImageFile(output_base, output_dir)     for format, dpi in formats:        if out_of_date(code_path, img.filename(format)):        if context or out_of_date(code_path, img.filename(format),                                  includes=code_includes):             all_exists = False             break         img.formats.append(format)


else:                 img = ImageFile('%s_%02d' % (output_base, j), output_dir)             for fmt, dpi in formats:                if out_of_date(code_path, img.filename(fmt)):                if context or out_of_date(code_path, img.filename(fmt),                                          includes=code_includes):                     all_exists = False                     break                 img.formats.append(fmt)


build_dir_link = build_dir     source_link = dest_dir_link + '/' + output_base + source_ext <ins>    # get list of included rst files so that the output is updated when any    # plots in the included files change. These attributes are modified by the    # include directive (see the docutils.parsers.rst.directives.misc module).    try:        source_file_includes = [os.path.join(os.getcwd(), t[0])                                for t in state.document.include_log]    except AttributeError:        # the document.include_log attribute only exists in docutils >=0.17,        # before that we need to inspect the state machine        possible_sources = {os.path.join(setup.confdir, t[0])                            for t in state_machine.input_lines.items}        source_file_includes = [f for f in possible_sources                                if os.path.isfile(f)]    # remove the source file itself from the includes    try:        source_file_includes.remove(source_file_name)    except ValueError:        pass</ins>     # make figures     try:         results = render_figures(code,


function_name,                                  config,                                  context_reset=context_opt == 'reset',                                 close_figs=context_opt == 'close-figs')                                 close_figs=context_opt == 'close-figs',                                 code_includes=source_file_includes)         errors = []     except PlotError as err:         reporter = state.memo.reporter


from matplotlib.collections import (     Collection, CircleCollection, LineCollection, PathCollection,     PolyCollection, RegularPolyCollection)<ins>from matplotlib.text import Text</ins> from matplotlib.transforms import Bbox, BboxBase, TransformedBbox from matplotlib.transforms import BboxTransformTo, BboxTransformFrom from matplotlib.offsetbox import (


handler = self.get_legend_handler(legend_handler_map, orig_handle)             if handler is None:                 _api.warn_external(                    "Legend does not support {!r} instances.\nA proxy artist "                    "may be used instead.\nSee: "                    "https://matplotlib.org/users/legend_guide.html"                    "#creating-artists-specifically-for-adding-to-the-legend-"                    "aka-proxy-artists".format(orig_handle))                             "Legend does not support handles for {0} "                             "instances.\nA proxy artist may be used "                             "instead.\nSee: https://matplotlib.org/"                             "stable/tutorials/intermediate/legend_guide.html"                             "#controlling-the-legend-entries".format(                                 type(orig_handle).__name__))                 # No handle for this artist, so we just defer to None.                 handle_list.append(None)             else:


for ax in axs:         handles_original += [             *(a for a in ax._children              if isinstance(a, (Line2D, Patch, Collection))),              if isinstance(a, (Line2D, Patch, Collection, Text))),             *ax.containers]         # support parasite axes:         if hasattr(ax, 'parasites'):             for axx in ax.parasites:                 handles_original += [                     *(a for a in axx._children                      if isinstance(a, (Line2D, Patch, Collection))),                      if isinstance(a, (Line2D, Patch, Collection, Text))),                     *axx.containers]      handler_map = {**Legend.get_default_handler_map(),


label = handle.get_label()         if label != '_nolegend_' and has_handler(handler_map, handle):             yield handle        elif (label not in ['_nolegend_', ''] and                not has_handler(handler_map, handle)):            _api.warn_external(                             "Legend does not support handles for {0} "                             "instances.\nSee: https://matplotlib.org/stable/"                             "tutorials/intermediate/legend_guide.html"                             "#implementing-a-custom-legend-handler".format(                                 type(handle).__name__))            continue   def _get_legend_handles_labels(axs, legend_handler_map=None):diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py-- a/lib/matplotlib/text.py++ b/lib/matplotlib/text.py


"""         Create a `.Text` instance at *x*, *y* with string *text*. <ins>        While Text accepts the 'label' keyword argument, by default it is not        added to the handles of a legend.</ins>         Valid keyword arguments are:          %(Text:kwdoc)s


# we have re-set the vmin/vmax to account for small errors                 # that may have moved input values in/out of range                 s_vmin, s_vmax = vrange                if isinstance(self.norm, mcolors.LogNorm):                    if s_vmin < 0:                        s_vmin = max(s_vmin, np.finfo(scaled_dtype).eps)                if isinstance(self.norm, mcolors.LogNorm) and s_vmin <= 0:                    # Don't give 0 or negative values to LogNorm                    s_vmin = np.finfo(scaled_dtype).eps                 with cbook._setattr_cm(self.norm,                                        vmin=s_vmin,                                        vmax=s_vmax,


The scale factor by which the length is shrunken or             expanded (default 16.0)             The PGF backend uses this argument as an RNG seed and not as            described above. Using the same seed yields the same random shape.             .. ACCEPTS: (scale: float, length: float, randomness: float)         """         if scale is None:diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py-- a/lib/matplotlib/backends/backend_pgf.py++ b/lib/matplotlib/backends/backend_pgf.py


r"{\pgfqpoint{%fin}{%fin}}"                         % coords) <ins>        # apply pgf decorators        sketch_params = gc.get_sketch_params() if gc else None        if sketch_params is not None:            # Only "length" directly maps to "segment length" in PGF's API.            # PGF uses "amplitude" to pass the combined deviation in both x-            # and y-direction, while matplotlib only varies the length of the            # wiggle along the line ("randomness" and "length" parameters)            # and has a separate "scale" argument for the amplitude.            # -> Use "randomness" as PRNG seed to allow the user to force the            # same shape on multiple sketched lines            scale, length, randomness = sketch_params            if scale is not None:                # make matplotlib and PGF rendering visually similar                length *= 0.5                scale *= 2                # PGF guarantees that repeated loading is a no-op                writeln(self.fh, r"\usepgfmodule{decorations}")                writeln(self.fh, r"\usepgflibrary{decorations.pathmorphing}")                writeln(self.fh, r"\pgfkeys{/pgf/decoration/.cd, "                        f"segment length = {(length * f):f}in, "                        f"amplitude = {(scale * f):f}in}}")                writeln(self.fh, f"\\pgfmathsetseed{{{int(randomness)}}}")                writeln(self.fh, r"\pgfdecoratecurrentpath{random steps}")</ins>     def _pgf_path_draw(self, stroke=True, fill=False):         actions = []         if stroke:


segments = []          for path in self._paths:            vertices = [vertex for vertex, _ in path.iter_segments()]            vertices = [                vertex                for vertex, _                # Never simplify here, we want to get the data-space values                # back and there in no way to know the "right" simplification                # threshold so never try.                in path.iter_segments(simplify=False)            ]             vertices = np.asarray(vertices)             segments.append(vertices)


self.artists.append(self._rect)      def _setup_edge_handle(self, props):        self._edge_handles = ToolLineHandles(self.ax, self.extents,        # Define initial position using the axis bounds to keep the same bounds        if self.direction == 'horizontal':            positions = self.ax.get_xbound()        else:            positions = self.ax.get_ybound()        self._edge_handles = ToolLineHandles(self.ax, positions,                                              direction=self.direction,                                              line_props=props,                                              useblit=self.useblit)


x = kwargs.pop('x', None)         y = kwargs.pop('y', None)        autopos = x is None and y is None        if info['name'] in ['_supxlabel', '_suptitle']:            autopos = y is None        elif info['name'] == '_supylabel':            autopos = x is None         if x is None:             x = info['x0']         if y is None:


extend = norm.extend             else:                 extend = 'neither'        self.alpha = alpha        self.alpha = None        # Call set_alpha to handle array-like alphas properly        self.set_alpha(alpha)         self.cmap = cmap         self.norm = norm         self.values = values


self.stale = True      def set_alpha(self, alpha):        """Set the transparency between 0 (transparent) and 1 (opaque)."""        self.alpha = alpha        """        Set the transparency between 0 (transparent) and 1 (opaque).        If an array is provided, *alpha* will be set to None to use the        transparency values associated with the colormap.        """        self.alpha = None if isinstance(alpha, np.ndarray) else alpha      def _set_scale(self, scale, **kwargs):         """


GRIDLINE_INTERPOLATION_STEPS         self.label1 = mtext.Text(             np.nan, np.nan,            fontsize=labelsize, color=labelcolor, visible=label1On)            fontsize=labelsize, color=labelcolor, visible=label1On,            rotation=self._labelrotation[1])         self.label2 = mtext.Text(             np.nan, np.nan,            fontsize=labelsize, color=labelcolor, visible=label2On)            fontsize=labelsize, color=labelcolor, visible=label2On,            rotation=self._labelrotation[1])          self._apply_tickdir(tickdir)


class CallbackRegistry:     """    Handle registering and disconnecting for a set of signals and callbacks:    Handle registering, processing, blocking, and disconnecting    for a set of signals and callbacks:          >>> def oneat(x):         ...    print('eat', x)


>>> callbacks.process('eat', 456)         eat 456         >>> callbacks.process('be merry', 456) # nothing will be called         >>> callbacks.disconnect(id_eat)         >>> callbacks.process('eat', 456)      # nothing will be called         >>> with callbacks.blocked(signal='drink'):        ...     callbacks.process('drink', 123) # nothing will be called        >>> callbacks.process('drink', 123)        drink 123     In practice, one should always disconnect all callbacks when they are     no longer needed to avoid dangling references (and thus memory leaks).     However, real code in Matplotlib rarely does so, and due to its design,


else:                         raise <ins>    @contextlib.contextmanager    def blocked(self, *, signal=None):        """        Block callback signals from being processed.        A context manager to temporarily block/disable callback signals        from being processed by the registered listeners.        Parameters        ----------        signal : str, optional            The callback signal to block. The default is to block all signals.        """        orig = self.callbacks        try:            if signal is None:                # Empty out the callbacks                self.callbacks = {}            else:                # Only remove the specific signal                self.callbacks = {k: orig[k] for k in orig if k != signal}            yield        finally:            self.callbacks = orig</ins>  class silent_list(list):     """


# Clear the callback registry for this axis, or it may "leak"         self.callbacks = cbook.CallbackRegistry()         self._reset_major_tick_kw()        self._reset_minor_tick_kw()        # whether the grids are on        self._major_tick_kw['gridOn'] = (                mpl.rcParams['axes.grid'] and                mpl.rcParams['axes.grid.which'] in ('both', 'major'))        self._minor_tick_kw['gridOn'] = (                mpl.rcParams['axes.grid'] and                mpl.rcParams['axes.grid.which'] in ('both', 'minor'))         self.reset_ticks()          self.converter = None


"""         # local import only to avoid circularity         from matplotlib.axes import Axes        from matplotlib.figure import Figure        from matplotlib.figure import FigureBase          super().__init__()


self.isaxes = True             self.axes = parent             self.set_figure(parent.figure)        elif isinstance(parent, Figure):        elif isinstance(parent, FigureBase):             self.isaxes = False             self.set_figure(parent)         else:            raise TypeError("Legend needs either Axes or Figure as parent")            raise TypeError(                "Legend needs either Axes or FigureBase as parent"            )         self.parent = parent          self._loc_used_default = loc is None


if pattern_re.search(key))      def copy(self):        return {k: dict.__getitem__(self, k) for k in self}        rccopy = RcParams()        for k in self:  # Skip deprecations and revalidation.            dict.__setitem__(rccopy, k, dict.__getitem__(self, k))        return rccopy   def rc_params(fail_on_error=False):


rcParams = RcParams()  # The global instance. dict.update(rcParams, dict.items(rcParamsDefault)) dict.update(rcParams, _rc_params_in_file(matplotlib_fname()))rcParamsOrig = rcParams.copy() with _api.suppress_matplotlib_deprecation_warning():    rcParamsOrig = RcParams(rcParams.copy())     # This also checks that all rcParams are indeed listed in the template.     # Assigning to rcsetup.defaultParams is left only for backcompat.     defaultParams = rcsetup.defaultParams = {


shared_x = self in self._shared_axes["x"]         shared_y = self in self._shared_axes["y"]        # Not sure whether we need this check:         if shared_x and shared_y:            raise RuntimeError("adjustable='datalim' is not allowed when both "                               "axes are shared")            raise RuntimeError("set_aspect(..., adjustable='datalim') or "                               "axis('equal') are not allowed when both axes "                               "are shared.  Try set_aspect(..., "                               "adjustable='box').")          # If y is shared, then we are only allowed to change x, etc.         if shared_y:


self.set_autoscale_on(True)                 self.set_aspect('auto')                 self.autoscale_view(tight=False)<del>                # self.apply_aspect()</del>                 if s == 'equal':                     self.set_aspect('equal', adjustable='datalim')                 elif s == 'scaled':


plt.axes((left, bottom, width, height), facecolor='w')     """     fig = gcf()    pos = kwargs.pop('position', None)     if arg is None:        return fig.add_subplot(**kwargs)        if pos is None:            return fig.add_subplot(**kwargs)        else:            return fig.add_axes(pos, **kwargs)     else:         return fig.add_axes(arg, **kwargs)


self.solver.addConstraint(c | 'required')      def add_child(self, child, i=0, j=0):        self.children[i, j] = child        # np.ix_ returns the cross product of i and j indices        self.children[np.ix_(np.atleast_1d(i), np.atleast_1d(j))] = child      def parent_constraints(self):         # constraints that are due to the parent...


self.unit = unit         self.proxy_target = self.value     def __copy__(self):        return TaggedValue(self.value, self.unit)     def __getattribute__(self, name):         if name.startswith('__'):             return object.__getattribute__(self, name)diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py-- a/lib/matplotlib/lines.py++ b/lib/matplotlib/lines.py


2D lines with support for a variety of line styles, markers, colors, etc. """ <ins>import copy</ins> from numbers import Integral, Number, Real import logging


----------         x : 1D array         """        self._xorig = x        self._xorig = copy.copy(x)         self._invalidx = True         self.stale = True


----------         y : 1D array         """        self._yorig = y        self._yorig = copy.copy(y)         self._invalidy = True         self.stale = True


ticks : `~matplotlib.ticker.Locator` or array-like of float      format : str or `~matplotlib.ticker.Formatter`<ins>        If string, it supports '%' operator and `str.format` formats:        e.g. ``"%4.2e"`` or ``"{x:.2e}"``.</ins>      drawedges : bool


self.locator = ticks    # Handle default in _ticker()          if isinstance(format, str):            self.formatter = ticker.FormatStrFormatter(format)            # Check format between FormatStrFormatter and StrMethodFormatter            try:                self.formatter = ticker.FormatStrFormatter(format)                _ = self.formatter(0)            except TypeError:                self.formatter = ticker.StrMethodFormatter(format)         else:             self.formatter = format  # Assume it is a Formatter or None         self.draw_all()


if offsets.shape == (2,):                 offsets = offsets[None, :]             self._offsets = offsets<ins>        elif transOffset is not None:            _api.warn_deprecated(                '3.5',                removal='3.6',                message='Passing *transOffset* without *offsets* has no '                        'effect. This behavior is deprecated since %(since)s '                        'and %(removal)s, *transOffset* will begin having an '                        'effect regardless of *offsets*. In the meantime, if '                        'you wish to set *transOffset*, call '                        'collection.set_offset_transform(transOffset) '                        'explicitly.')            transOffset = None</ins>          self._transOffset = transOffset


--------         .. plot:: gallery/lines_bars_and_markers/eventplot_demo.py         """        # We do the conversion first since not all unitized data is uniform        positions, lineoffsets, linelengths = self._process_unit_info(            [("x", positions), ("y", lineoffsets), ("y", linelengths)], kwargs)         lineoffsets, linelengths = self._process_unit_info(                [("y", lineoffsets), ("y", linelengths)], kwargs)        # fix positions, noting that it can be a list of lists:         if not np.iterable(positions):             positions = [positions]         elif any(np.iterable(position) for position in positions):


if len(positions) == 0:             return [] <ins>        poss = []        for position in positions:            poss += self._process_unit_info([("x", position)], kwargs)        positions = poss</ins>         # prevent 'singular' keys from **kwargs dict from overriding the effect         # of 'plural' keyword arguments (e.g. 'color' overriding 'colors')         colors = cbook._local_over_kwdict(colors, kwargs, 'color')


"""         # Process **kwargs to handle aliases, conflicts with explicit kwargs:         x, y = self._process_unit_info([("x", x), ("y", y)], kwargs)         # np.ma.ravel yields an ndarray, not a masked array,         # unless its argument is a masked array.         x = np.ma.ravel(x)


p = r'([a-zA-Z]+)'     ret_text = re.sub(p, r'}$\1$\\mathdefault{', text)     # Braces ensure dashes are not spaced like binary operators.    ret_text = '$\\mathdefault{'+ret_text.replace('-', '{-}')+'}$'    # Braces ensure symbols are not spaced like binary operators.    ret_text = ret_text.replace('-', '{-}').replace(':', '{:}')    # To not concatenate space between numbers.    ret_text = ret_text.replace(' ', r'\;')    ret_text = '$\\mathdefault{' + ret_text + '}$'     ret_text = ret_text.replace('$\\mathdefault{}$', '')     return ret_text


try:             return self._dict[name]         except KeyError:            raise ValueError(            raise AttributeError(                 f"'Spines' object does not contain a '{name}' spine")      def __getitem__(self, key):


key = (path, id(trf))             custom_clip_cmd = self._clip_paths.get(key)             if custom_clip_cmd is None:                custom_clip_cmd = "c%x" % len(self._clip_paths)                custom_clip_cmd = "c%d" % len(self._clip_paths)                 self._pswriter.write(f"""\ /{custom_clip_cmd} {{ {self._convert_path(path, trf, simplify=False)}


path_codes = []         for i, (path, transform) in enumerate(self._iter_collection_raw_paths(                 master_transform, paths, all_transforms)):            name = 'p%x_%x' % (self._path_collection_id, i)            name = 'p%d_%d' % (self._path_collection_id, i)             path_bytes = self._convert_path(path, transform, simplify=False)             self._pswriter.write(f"""\ /{name} {{


val = self._max_in_bounds(pos)             self.set_max(val)         if self._active_handle:            self._active_handle.set_xdata([val])            if self.orientation == "vertical":                self._active_handle.set_ydata([val])            else:                self._active_handle.set_xdata([val])      def _update(self, event):         """Update the slider position."""


return          # determine which handle was grabbed        handle = self._handles[            np.argmin(        if self.orientation == "vertical":            handle_index = np.argmin(                np.abs([h.get_ydata()[0] - event.ydata for h in self._handles])            )        else:            handle_index = np.argmin(                 np.abs([h.get_xdata()[0] - event.xdata for h in self._handles])             )        ]        handle = self._handles[handle_index]         # these checks ensure smooth behavior if the handles swap which one         # has a higher value. i.e. if one is dragged over and past the other.         if handle is not self._active_handle:


xy[2] = .75, val[1]             xy[3] = .75, val[0]             xy[4] = .25, val[0]            self._handles[0].set_ydata([val[0]])            self._handles[1].set_ydata([val[1]])         else:             xy[0] = val[0], .25             xy[1] = val[0], .75             xy[2] = val[1], .75             xy[3] = val[1], .25             xy[4] = val[0], .25            self._handles[0].set_xdata([val[0]])            self._handles[1].set_xdata([val[1]])         self.poly.xy = xy         self.valtext.set_text(self._format(val))         if self.drawon:             self.ax.figure.canvas.draw_idle()         self.val = val


is_numlike = all(units.ConversionInterface.is_numlike(v)                              and not isinstance(v, (str, bytes))                              for v in values)        if is_numlike:        if values.size and is_numlike:             _api.warn_deprecated(                 "3.5", message="Support for passing numbers through unit "                 "converters is deprecated since %(since)s and support will be "


convertible = self._str_is_convertible(val)             if val not in self._mapping:                 self._mapping[val] = next(self._counter)        if convertible:        if data.size and convertible:             _log.info('Using categorical units to plot a list of strings '                       'that are all parsable as floats or dates. If these '                       'strings should be plotted as numbers, cast to the '


if 'antialiaseds' not in kwargs and ec.lower() == "none":         kwargs['antialiaseds'] = False     _api.check_isinstance((Normalize, None), norm=norm)     if shading == 'gouraud':         if facecolors is not None:             raise ValueError(                 "shading='gouraud' can only be used when the colors "                 "are specified at the points, not at the faces.")        collection = TriMesh(tri, **kwargs)        colors = point_colors        collection = TriMesh(tri, alpha=alpha, array=point_colors,                             cmap=cmap, norm=norm, **kwargs)     else:         # Vertices of triangles.         maskedTris = tri.get_masked_triangles()


colors = facecolors[~tri.mask]         else:             colors = facecolors        collection = PolyCollection(verts, alpha=alpha, array=colors,                                    cmap=cmap, norm=norm, **kwargs)         collection = PolyCollection(verts, **kwargs)    collection.set_alpha(alpha)    collection.set_array(colors)    _api.check_isinstance((Normalize, None), norm=norm)    collection.set_cmap(cmap)    collection.set_norm(norm)     collection._scale_norm(norm, vmin, vmax)     ax.grid(False)


"""         Find the point in the contour plot that is closest to ``(x, y)``. <ins>        This method does not support filled contours.</ins>         Parameters         ----------         x, y : float


# sufficiently well that the time is not noticeable.         # Nonetheless, improvements could probably be made.         if self.filled:            raise ValueError("Method does not support filled contours.")         if indices is None:            indices = range(len(self.levels))            indices = range(len(self.collections))          d2min = np.inf         conmin = None


from collections.abc import Sized, Sequence import copy import functools<ins>import importlib</ins> import inspect import io import itertools


class Norm(base_norm_cls):         def __reduce__(self):            cls = type(self)            # If the class is toplevel-accessible, it is possible to directly            # pickle it "by name".  This is required to support norm classes            # defined at a module's toplevel, as the inner base_norm_cls is            # otherwise unpicklable (as it gets shadowed by the generated norm            # class).  If either import or attribute access fails, fall back to            # the general path.            try:                if cls is getattr(importlib.import_module(cls.__module__),                                  cls.__qualname__):                    return (_create_empty_object_of_class, (cls,), vars(self))            except (ImportError, AttributeError):                pass             return (_picklable_norm_constructor,                     (scale_cls, base_norm_cls, bound_init_signature),                    self.__dict__)                    vars(self))          def __init__(self, *args, **kwargs):             ba = bound_init_signature.bind(*args, **kwargs)


return Norm  def _picklable_norm_constructor(*args):    cls = _make_norm_from_scale(*args)def _create_empty_object_of_class(cls):     return cls.__new__(cls)  def _picklable_norm_constructor(*args):    return _create_empty_object_of_class(_make_norm_from_scale(*args)) @make_norm_from_scale(     scale.FuncScale,     init=lambda functions, vmin=None, vmax=None, clip=False: None)


import matplotlib as mpl from . import _api, cbook<ins>from .colors import BoundaryNorm</ins> from .cm import ScalarMappable from .path import Path from .transforms import (Bbox, IdentityTransform, Transform, TransformedBbox,


return "[]"             normed = self.norm(data)             if np.isfinite(normed):                # Midpoints of neighboring color intervals.                neighbors = self.norm.inverse(                    (int(self.norm(data) * n) + np.array([0, 1])) / n)                delta = abs(neighbors - data).max()                if isinstance(self.norm, BoundaryNorm):                    # not an invertible normalization mapping                    cur_idx = np.argmin(np.abs(self.norm.boundaries - data))                    neigh_idx = max(0, cur_idx - 1)                    # use max diff to prevent delta == 0                    delta = np.diff(                        self.norm.boundaries[neigh_idx:cur_idx + 2]                    ).max()                else:                    # Midpoints of neighboring color intervals.                    neighbors = self.norm.inverse(                        (int(normed * n) + np.array([0, 1])) / n)                    delta = abs(neighbors - data).max()                 g_sig_digits = cbook._g_sig_digits(data, delta)             else:                 g_sig_digits = 3  # Consistent with default below.


if not self.drawedges:                 if len(self._y) >= self.n_rasterize:                     self.solids.set_rasterized(True)        self.dividers.set_segments(            np.dstack([X, Y])[1:-1] if self.drawedges else [])        if self.drawedges:            start_idx = 0 if self._extend_lower() else 1            end_idx = len(X) if self._extend_upper() else -1            self.dividers.set_segments(np.dstack([X, Y])[start_idx:end_idx])        else:            self.dividers.set_segments([])      def _add_solids_patches(self, X, Y, C, mappable):         hatches = mappable.hatches * len(C)  # Have enough hatches.


# mostly 0: years,  1: months,  2: days,         # 3: hours, 4: minutes, 5: seconds, 6: microseconds         for level in range(5, -1, -1):            if len(np.unique(tickdate[:, level])) > 1:                if level < 2:            unique = np.unique(tickdate[:, level])            if len(unique) > 1:                # if 1 is included in unique, the year is shown in ticks                if level < 2 and np.any(unique == 1):                     show_offset = False                 break             elif level == 0:


else:         # Color from positional parameter C         if not args:            raise ValueError(                "Missing color parameter. Please pass C positionally or "                "facecolors via keyword")            raise TypeError(                "tripcolor() missing 1 required positional argument: 'C'; or "                "1 required keyword-only argument: 'facecolors'")         elif len(args) > 1:            _api.warn_external(                "Additional positional parameters {args[1:]!r} are ignored")            _api.warn_deprecated(                "3.6", message=f"Additional positional parameters "                f"{args[1:]!r} are ignored; support for them is deprecated "                f"since %(since)s and will be removed %(removal)s")         C = np.asarray(args[0])         if len(C) == len(tri.x):             # having this before the len(tri.triangles) comparison gives


from . import (_api, _docstring, backend_tools, cbook, colors, ticker,                transforms) from .lines import Line2Dfrom .patches import Circle, Rectangle, Ellipsefrom .patches import Circle, Rectangle, Ellipse, Polygon from .transforms import TransformedPatchPath, Affine2D


facecolor=track_color             )             ax.add_patch(self.track)            self.poly = ax.axhspan(valinit[0], valinit[1], 0, 1, **kwargs)            poly_transform = self.ax.get_yaxis_transform(which="grid")             handleXY_1 = [.5, valinit[0]]             handleXY_2 = [.5, valinit[1]]         else:


facecolor=track_color             )             ax.add_patch(self.track)            self.poly = ax.axvspan(valinit[0], valinit[1], 0, 1, **kwargs)            poly_transform = self.ax.get_xaxis_transform(which="grid")             handleXY_1 = [valinit[0], .5]             handleXY_2 = [valinit[1], .5]        self.poly = Polygon(np.zeros([5, 2]), **kwargs)        self._update_selection_poly(*valinit)        self.poly.set_transform(poly_transform)        self.poly.get_path()._interpolation_steps = 100        self.ax.add_patch(self.poly)        self.ax._request_autoscale_view()         self._handles = [             ax.plot(                 *handleXY_1,


self._active_handle = None         self.set_val(valinit) <ins>    def _update_selection_poly(self, vmin, vmax):        """        Update the vertices of the *self.poly* slider in-place        to cover the data range *vmin*, *vmax*.        """        # The vertices are positioned        #  1 ------ 2        #  |        |        # 0, 4 ---- 3        verts = self.poly.xy        if self.orientation == "vertical":            verts[0] = verts[4] = .25, vmin            verts[1] = .25, vmax            verts[2] = .75, vmax            verts[3] = .75, vmin        else:            verts[0] = verts[4] = vmin, .25            verts[1] = vmin, .75            verts[2] = vmax, .75            verts[3] = vmax, .25</ins>     def _min_in_bounds(self, min):         """Ensure the new min value is between valmin and self.val[1]."""         if min <= self.valmin:


"""         val = np.sort(val)         _api.check_shape((2,), val=val)        val[0] = self._min_in_bounds(val[0])        val[1] = self._max_in_bounds(val[1])        xy = self.poly.xy        vmin, vmax = val        vmin = self._min_in_bounds(vmin)        vmax = self._max_in_bounds(vmax)        self._update_selection_poly(vmin, vmax)         if self.orientation == "vertical":            xy[0] = .25, val[0]            xy[1] = .25, val[1]            xy[2] = .75, val[1]            xy[3] = .75, val[0]            xy[4] = .25, val[0]            self._handles[0].set_ydata([val[0]])            self._handles[1].set_ydata([val[1]])            self._handles[0].set_ydata([vmin])            self._handles[1].set_ydata([vmax])         else:            xy[0] = val[0], .25            xy[1] = val[0], .75            xy[2] = val[1], .75            xy[3] = val[1], .25            xy[4] = val[0], .25            self._handles[0].set_xdata([vmin])            self._handles[1].set_xdata([vmax])             self._handles[0].set_xdata([val[0]])            self._handles[1].set_xdata([val[1]])        self.poly.xy = xy        self.valtext.set_text(self._format(val))        self.valtext.set_text(self._format((vmin, vmax)))          if self.drawon:             self.ax.figure.canvas.draw_idle()        self.val = val        self.val = (vmin, vmax)         if self.eventson:            self._observers.process("changed", val)            self._observers.process("changed", (vmin, vmax))      def on_changed(self, func):         """


lines._internal_update(kwargs)          if len(y) > 0:            minx = min(xmin.min(), xmax.min())            maxx = max(xmin.max(), xmax.max())            miny = y.min()            maxy = y.max()            minx = min(np.nanmin(xmin), np.nanmin(xmax))            maxx = max(np.nanmax(xmin), np.nanmax(xmax))            miny = np.nanmin(y)            maxy = np.nanmax(y)              corners = (minx, miny), (maxx, maxy)


lines._internal_update(kwargs)          if len(x) > 0:            minx = x.min()            maxx = x.max()            miny = min(ymin.min(), ymax.min())            maxy = max(ymin.max(), ymax.max())            minx = np.nanmin(x)            maxx = np.nanmax(x)            miny = min(np.nanmin(ymin), np.nanmin(ymax))            maxy = max(np.nanmax(ymin), np.nanmax(ymax))              corners = (minx, miny), (maxx, maxy)             self.update_datalim(corners)


extrema = max(x0, x1) if dat >= 0 else min(x0, x1)                 length = abs(x0 - x1)             if err is None:            if err is None or np.size(err) == 0:                 endpt = extrema             elif orientation == "vertical":                 endpt = err[:, 1].max() if dat >= 0 else err[:, 1].min()


f"'{dep_axis}err' (shape: {np.shape(err)}) must be a "                     f"scalar or a 1D or (2, n) array-like whose shape matches "                     f"'{dep_axis}' (shape: {np.shape(dep)})") from None            if np.any(err < -err):  # like err<0, but also works for timedelta.            res = np.zeros_like(err, dtype=bool)  # Default in case of nan            if np.any(np.less(err, -err, out=res, where=(err == err))):                # like err<0, but also works for timedelta and nan.                 raise ValueError(                     f"'{dep_axis}err' must not contain negative values")             # This is like


if np.any(dl < 0.0):                 raise ValueError(                     "All values in the dash list must be non-negative")            if not np.any(dl > 0.0):            if dl.size and not np.any(dl > 0.0):                 raise ValueError(                     'At least one value in the dash list must be positive')         self._dashes = dash_offset, dash_list


# default to zeros         self._offsets = np.zeros((1, 2))        self._has_offsets = offsets is not None         if offsets is not None:        if self._has_offsets:             offsets = np.asanyarray(offsets, float)             # Broadcast (2,) -> (1, 2) but nothing else.             if offsets.shape == (2,):


offsets = offsets.filled(np.nan)             # get_path_collection_extents handles nan but not masked arrays         if len(paths) and len(offsets):        if len(paths):             if any(transform.contains_branch_seperately(transData)):                 # collections that are just in data units (like quiver)                 # can properly have the axes limits set by their shape +


offset_trf.transform_non_affine(offsets),                     offset_trf.get_affine().frozen())             # this is for collections that have their paths (shapes)            # in physical, axes-relative, or figure-relative units            # (i.e. like scatter). We can't uniquely set limits based on            # those shapes, so we just set the limits based on their            # location.            offsets = (offset_trf - transData).transform(offsets)            # note A-B means A B^{-1}            offsets = np.ma.masked_invalid(offsets)            if not offsets.mask.all():                bbox = transforms.Bbox.null()                bbox.update_from_data_xy(offsets)                return bbox            if self._has_offsets:                # this is for collections that have their paths (shapes)                # in physical, axes-relative, or figure-relative units                # (i.e. like scatter). We can't uniquely set limits based on                # those shapes, so we just set the limits based on their                # location.                offsets = (offset_trf - transData).transform(offsets)                # note A-B means A B^{-1}                offsets = np.ma.masked_invalid(offsets)                if not offsets.mask.all():                    bbox = transforms.Bbox.null()                    bbox.update_from_data_xy(offsets)                    return bbox         return transforms.Bbox.null()      def get_window_extent(self, renderer):


from matplotlib import cbook from matplotlib import _docstring from matplotlib.backend_bases import FigureCanvasBase, MouseButtonfrom matplotlib.figure import Figure, figaspectfrom matplotlib.figure import Figure, FigureBase, figaspect from matplotlib.gridspec import GridSpec, SubplotSpec from matplotlib import rcParams, rcParamsDefault, get_backend, rcParamsOrig from matplotlib.rcsetup import interactive_bk as _interactive_bk


Parameters     ----------    num : int or str or `.Figure`, optional    num : int or str or `.Figure` or `.SubFigure`, optional         A unique identifier for the figure.          If a figure with that identifier already exists, this figure is made


will be used for the ``Figure.number`` attribute, otherwise, an         auto-generated integer value is used (starting at 1 and incremented         for each new figure). If *num* is a string, the figure label and the        window title is set to this value.        window title is set to this value.  If num is a ``SubFigure``, its        parent ``Figure`` is activated.      figsize : (float, float), default: :rc:`figure.figsize`         Width, height in inches.


`~matplotlib.rcParams` defines the default values, which can be modified     in the matplotlibrc file.     """    if isinstance(num, Figure):    if isinstance(num, FigureBase):         if num.canvas.manager is None:             raise ValueError("The passed figure is not managed by pyplot")         _pylab_helpers.Gcf.set_active(num.canvas.manager)        return num        return num.figure      allnums = get_fignums()     next_num = max(allnums) + 1 if allnums else 1


yield (line.decode('utf-8') for line in f)     else:         fname = os.path.expanduser(fname)        encoding = locale.getpreferredencoding(do_setlocale=False)        if encoding is None:            encoding = "utf-8"        with open(fname, encoding=encoding) as f:        with open(fname, encoding='utf-8') as f:             yield f


fname, line_no, line.rstrip('\n'))                 rc_temp[key] = (val, line, line_no)         except UnicodeDecodeError:            _log.warning('Cannot decode configuration file %s with encoding '                         '%s, check LANG and LC_* variables.',                         fname,                         locale.getpreferredencoding(do_setlocale=False)                         or 'utf-8 (default)')            _log.warning('Cannot decode configuration file %r as utf-8.',                         fname)             raise      config = RcParams()diff --git a/setup.py b/setup.py-- a/setup.py++ b/setup.py


# line.  Otherwise, use the default `##backend: Agg` which has no effect     # even after decommenting, which allows _auto_backend_sentinel to be filled     # in at import time.    template_lines = path.read_text().splitlines(True)    template_lines = path.read_text(encoding="utf-8").splitlines(True)     backend_line_idx, = [  # Also asserts that there is a single such line.         idx for idx, line in enumerate(template_lines)         if "#backend:" in line]


"#backend: {}\n".format(setupext.options["backend"])         if setupext.options["backend"]         else "##backend: Agg\n")    path.write_text("".join(template_lines))    path.write_text("".join(template_lines), encoding="utf-8")   class BuildPy(setuptools.command.build_py.build_py):


m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)             tops.append(m)         tops = np.array(tops, float)  # causes problems later if it's an int<ins>        bins = np.array(bins, float)  # causes problems if float16</ins>         if stacked:             tops = tops.cumsum(axis=0)             # If a stacked density plot, normalize so the area of all the


return ret  def xticks(ticks=None, labels=None, **kwargs):def xticks(ticks=None, labels=None, *, minor=False, **kwargs):     """     Get or set the current tick locations and labels of the x-axis.


labels : array-like, optional         The labels to place at the given *ticks* locations.  This argument can         only be passed if *ticks* is passed as well.<ins>    minor : bool, default: False        If ``False``, get/set the major ticks/labels; if ``True``, the minor        ticks/labels.</ins>     **kwargs         `.Text` properties can be used to control the appearance of the labels.


ax = gca()      if ticks is None:        locs = ax.get_xticks()        locs = ax.get_xticks(minor=minor)         if labels is not None:             raise TypeError("xticks(): Parameter 'labels' can't be set "                             "without setting 'ticks'")     else:        locs = ax.set_xticks(ticks)        locs = ax.set_xticks(ticks, minor=minor)      if labels is None:        labels = ax.get_xticklabels()        labels = ax.get_xticklabels(minor=minor)         for l in labels:             l._internal_update(kwargs)     else:        labels = ax.set_xticklabels(labels, **kwargs)        labels = ax.set_xticklabels(labels, minor=minor, **kwargs)      return locs, labels  def yticks(ticks=None, labels=None, **kwargs):def yticks(ticks=None, labels=None, *, minor=False, **kwargs):     """     Get or set the current tick locations and labels of the y-axis.


ax = gca()      if ticks is None:        locs = ax.get_yticks()        locs = ax.get_yticks(minor=minor)         if labels is not None:             raise TypeError("yticks(): Parameter 'labels' can't be set "                             "without setting 'ticks'")     else:        locs = ax.set_yticks(ticks)        locs = ax.set_yticks(ticks, minor=minor)      if labels is None:        labels = ax.get_yticklabels()        labels = ax.get_yticklabels(minor=minor)         for l in labels:             l._internal_update(kwargs)     else:        labels = ax.set_yticklabels(labels, **kwargs)        labels = ax.set_yticklabels(labels, minor=minor, **kwargs)      return locs, labels


# will (re)import pyplot and then call switch_backend if we need to         # resolve the auto sentinel)         switch_backend(dict.__getitem__(rcParams, "backend"))<del>        # Just to be safe.  Interactive mode can be turned on without calling        # `plt.ion()` so register it again here.  This is safe because multiple        # calls to `install_repl_displayhook` are no-ops and the registered        # function respects `mpl.is_interactive()` to determine if it should        # trigger a draw.        install_repl_displayhook()</del>     return _backend_mod


# See https://github.com/matplotlib/matplotlib/issues/6092     matplotlib.backends.backend = newbackend <ins>    # make sure the repl display hook is installed in case we become    # interactive    install_repl_displayhook()</ins>  def _warn_if_gui_out_of_main_thread():     if (_get_required_interactive_framework(_get_backend_mod())


self._transform - ax.figure.transSubfigure)  def _process_plot_format(fmt):def _process_plot_format(fmt, *, ambiguous_fmt_datakey=False):     """     Convert a MATLAB style color/line style format string to a (*linestyle*,     *marker*, *color*) tuple.


except ValueError:         pass  # No, not just a color.     errfmt = ("{!r} is neither a data key nor a valid format string ({})"              if ambiguous_fmt_datakey else              "{!r} is not a valid format string ({})")     i = 0     while i < len(fmt):         c = fmt[i]         if fmt[i:i+2] in mlines.lineStyles:  # First, the two-char styles.             if linestyle is not None:                raise ValueError(                    f'Illegal format string {fmt!r}; two linestyle symbols')                raise ValueError(errfmt.format(fmt, "two linestyle symbols"))             linestyle = fmt[i:i+2]             i += 2         elif c in mlines.lineStyles:             if linestyle is not None:                raise ValueError(                    f'Illegal format string {fmt!r}; two linestyle symbols')                raise ValueError(errfmt.format(fmt, "two linestyle symbols"))             linestyle = c             i += 1         elif c in mlines.lineMarkers:             if marker is not None:                raise ValueError(                    f'Illegal format string {fmt!r}; two marker symbols')                raise ValueError(errfmt.format(fmt, "two marker symbols"))             marker = c             i += 1         elif c in mcolors.get_named_colors_mapping():             if color is not None:                raise ValueError(                    f'Illegal format string {fmt!r}; two color symbols')                raise ValueError(errfmt.format(fmt, "two color symbols"))             color = c             i += 1         elif c == 'C' and i < len(fmt) - 1:


i += 2         else:             raise ValueError(                f'Unrecognized character {c} in format string {fmt!r}')                errfmt.format(fmt, f"unrecognized character {c!r}"))      if linestyle is None and marker is None:         linestyle = mpl.rcParams['lines.linestyle']


kwargs["label"] = mpl._label_from_arg(                     replaced[label_namer_idx], args[label_namer_idx])             args = replaced<ins>        ambiguous_fmt_datakey = data is not None and len(args) == 2</ins>          if len(args) >= 4 and not cbook.is_scalar_or_string(                 kwargs.get("label")):


if args and isinstance(args[0], str):                 this += args[0],                 args = args[1:]            yield from self._plot_args(this, kwargs)            yield from self._plot_args(                this, kwargs, ambiguous_fmt_datakey=ambiguous_fmt_datakey)      def get_next_color(self):         """Return the next color in the cycle."""


seg.set(**kwargs)         return seg, kwargs     def _plot_args(self, tup, kwargs, return_kwargs=False):    def _plot_args(self, tup, kwargs, *,                   return_kwargs=False, ambiguous_fmt_datakey=False):         """         Process the arguments of ``plot([x], y, [fmt], **kwargs)`` calls.


The keyword arguments passed to ``plot()``.          return_kwargs : bool            If true, return the effective keyword arguments after label            Whether to also return the effective keyword arguments after label             unpacking as well.         ambiguous_fmt_datakey : bool            Whether the format string in *tup* could also have been a            misspelled data key.         Returns         -------         result


if len(tup) > 1 and isinstance(tup[-1], str):             # xy is tup with fmt stripped (could still be (y,) only)             *xy, fmt = tup            linestyle, marker, color = _process_plot_format(fmt)            linestyle, marker, color = _process_plot_format(                fmt, ambiguous_fmt_datakey=ambiguous_fmt_datakey)         elif len(tup) == 3:             raise ValueError('third arg must be a format string')         else:


if delta == 0:         # delta = 0 may occur when trying to format values over a tiny range;         # in that case, replace it by the distance to the closest float.        delta = np.spacing(value)        delta = abs(np.spacing(value))     # If e.g. value = 45.67 and delta = 0.02, then we want to round to 2 digits     # after the decimal point (floor(log10(0.02)) = -2); 45.67 contributes 2     # digits before the decimal point (floor(log10(45.67)) + 1 = 2): the total


to set the fontsize alongside other font properties, use the *size*     parameter in *title_fontproperties*. <ins>alignment : {'center', 'left', 'right'}, default: 'center'    The alignment of the legend title and the box of entries. The entries    are aligned as a single block, so that markers always lined up.</ins> borderpad : float, default: :rc:`legend.borderpad`     The fractional whitespace inside the legend border, in font-size units.


frameon=None,         # draw frame         handler_map=None,         title_fontproperties=None,  # properties for the legend title<ins>        alignment="center",       # control the alignment within the legend box</ins>         *,         ncol=1  # synonym for ncols (backward compatibility)     ):


)         self._set_artist_props(self.legendPatch) <ins>        _api.check_in_list(["center", "left", "right"], alignment=alignment)        self._alignment = alignment</ins>         # init with null renderer         self._init_legend_box(handles, labels, markerfirst)


self._legend_title_box = TextArea("")         self._legend_box = VPacker(pad=self.borderpad * fontsize,                                    sep=self.labelspacing * fontsize,                                   align="center",                                   align=self._alignment,                                    children=[self._legend_title_box,                                              self._legend_handle_box])         self._legend_box.set_figure(self.figure)


r"""Return the list of `~.text.Text`\s in the legend."""         return silent_list('Text', self.texts)     def set_alignment(self, alignment):        """        Set the alignment of the legend title and the box of entries.        The entries are aligned as a single block, so that markers always        lined up.        Parameters        ----------        alignment : {'center', 'left', 'right'}.        """        _api.check_in_list(["center", "left", "right"], alignment=alignment)        self._alignment = alignment        self._legend_box.align = alignment    def get_alignment(self):        """Get the alignment value of the legend box"""        return self._legend_box.align     def set_title(self, title, prop=None):         """        Set the legend title. Fontproperties can be optionally set        with *prop* parameter.        Set legend title and title style.        Parameters        ----------        title : str            The legend title.        prop : `.font_manager.FontProperties` or `str` or `pathlib.Path`            The font properties of the legend title.            If a `str`, it is interpreted as a fontconfig pattern parsed by            `.FontProperties`.  If a `pathlib.Path`, it is interpreted as the            absolute path to a font file.         """         self._legend_title_box._text.set_text(title)         if title:


def dpi(self, value):         self._parent.dpi = value <ins>    @property    def _cachedRenderer(self):        return self._parent._cachedRenderer    @_cachedRenderer.setter    def _cachedRenderer(self, renderer):        self._parent._cachedRenderer = renderer</ins>     def _redo_transform_rel_fig(self, bbox=None):         """         Make the transSubfigure bbox relative to Figure transform.


if it is too close to being singular (i.e. a range of ~0).         """         if not np.isfinite(vmin) or not np.isfinite(vmax):            # Except if there is no data, then use 2000-2010 as default.            return (date2num(datetime.date(2000, 1, 1)),                    date2num(datetime.date(2010, 1, 1)))            # Except if there is no data, then use 1970 as default.            return (date2num(datetime.date(1970, 1, 1)),                    date2num(datetime.date(1970, 1, 2)))         if vmax < vmin:             vmin, vmax = vmax, vmin         unit = self._get_unit()


# whatever is thrown at us, we can scale the unit.         # But default nonsingular date plots at an ~4 year period.         if not np.isfinite(vmin) or not np.isfinite(vmax):            # Except if there is no data, then use 2000-2010 as default.            return (date2num(datetime.date(2000, 1, 1)),                    date2num(datetime.date(2010, 1, 1)))            # Except if there is no data, then use 1970 as default.            return (date2num(datetime.date(1970, 1, 1)),                    date2num(datetime.date(1970, 1, 2)))         if vmax < vmin:             vmin, vmax = vmax, vmin         if vmin == vmax:


majloc = AutoDateLocator(tz=tz,                                  interval_multiples=self._interval_multiples)         majfmt = AutoDateFormatter(majloc, tz=tz)        datemin = datetime.date(2000, 1, 1)        datemax = datetime.date(2010, 1, 1)        datemin = datetime.date(1970, 1, 1)        datemax = datetime.date(1970, 1, 2)          return units.AxisInfo(majloc=majloc, majfmt=majfmt, label='',                               default_limits=(datemin, datemax))


zero_formats=self._zero_formats,                                       offset_formats=self._offset_formats,                                       show_offset=self._show_offset)        datemin = datetime.date(2000, 1, 1)        datemax = datetime.date(2010, 1, 1)        datemin = datetime.date(1970, 1, 1)        datemax = datetime.date(1970, 1, 2)         return units.AxisInfo(majloc=majloc, majfmt=majfmt, label='',                               default_limits=(datemin, datemax))


# re-generate legend, if checkbox is checked         if generate_legend:             draggable = None            ncol = 1            ncols = 1             if axes.legend_ is not None:                 old_legend = axes.get_legend()                 draggable = old_legend._draggable is not None                ncol = old_legend._ncol            new_legend = axes.legend(ncol=ncol)                ncols = old_legend._ncols            new_legend = axes.legend(ncols=ncols)             if new_legend:                 new_legend.set_draggable(draggable) diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py-- a/lib/matplotlib/legend.py++ b/lib/matplotlib/legend.py


loc='upper right', bbox_to_anchor=(0.5, 0.5) ncol : int, default: 1ncols : int, default: 1     The number of columns that the legend has.     For backward compatibility, the spelling *ncol* is also supported    but it is discouraged. If both are given, *ncols* takes precedence. prop : None or `matplotlib.font_manager.FontProperties` or dict     The font properties of the legend. If None (default), the current     :data:`matplotlib.rcParams` will be used.


borderaxespad=None,  # pad between the axes and legend border         columnspacing=None,  # spacing between columns         ncol=1,     # number of columns        ncols=1,     # number of columns         mode=None,  # horizontal distribution of columns: None or "expand"          fancybox=None,  # True: fancy box, False: rounded box, None: rcParam


frameon=None,         # draw frame         handler_map=None,         title_fontproperties=None,  # properties for the legend title<ins>        *,        ncol=1  # synonym for ncols (backward compatibility)</ins>     ):         """         Parameters


handles = list(handles)         if len(handles) < 2:            ncol = 1        self._ncol = ncol            ncols = 1        self._ncols = ncols if ncols != 1 else ncol          if self.numpoints <= 0:             raise ValueError("numpoints must be > 0; it was %d" % numpoints)


self.stale = True         self._legend_box.set_offset(self._findoffset) <ins>    def set_ncols(self, ncols):        """Set the number of columns."""        self._ncols = ncols</ins>     def _get_loc(self):         return self._loc_real


handles_and_labels.append((handlebox, textbox))          columnbox = []        # array_split splits n handles_and_labels into ncol columns, with the        # first n%ncol columns having an extra entry.  filter(len, ...) handles        # the case where n < ncol: the last ncol-n columns are empty and get        # filtered out.        for handles_and_labels_column \                in filter(len, np.array_split(handles_and_labels, self._ncol)):        # array_split splits n handles_and_labels into ncols columns, with the        # first n%ncols columns having an extra entry.  filter(len, ...)        # handles the case where n < ncols: the last ncols-n columns are empty        # and get filtered out.        for handles_and_labels_column in filter(                len, np.array_split(handles_and_labels, self._ncols)):             # pack handlebox and labelbox into itembox             itemboxes = [HPacker(pad=0,                                  sep=self.handletextpad * fontsize,


aspect = 1 / aspect      parent.set_subplotspec(ss_main)    parent.set_anchor(loc_settings["panchor"])    if panchor is not False:        parent.set_anchor(panchor)      fig = parent.get_figure()     cax = fig.add_subplot(ss_cb, label="<colorbar>")


hatches=(None,), alpha=None, origin=None, extent=None,                  cmap=None, colors=None, norm=None, vmin=None, vmax=None,                  extend='neither', antialiased=None, nchunk=0, locator=None,                 transform=None,                 transform=None, negative_linestyles=None,                  **kwargs):         """         Draw contour lines or filled regions, depending on


self._transform = transform <ins>        self.negative_linestyles = negative_linestyles        # If negative_linestyles was not defined as a kwarg,        # define negative_linestyles with rcParams        if self.negative_linestyles is None:            self.negative_linestyles = \                mpl.rcParams['contour.negative_linestyle']</ins>         kwargs = self._process_args(*args, **kwargs)         self._process_levels()


if linestyles is None:             tlinestyles = ['solid'] * Nlev             if self.monochrome:                neg_ls = mpl.rcParams['contour.negative_linestyle']                 eps = - (self.zmax - self.zmin) * 1e-15                 for i, lev in enumerate(self.levels):                     if lev < eps:                        tlinestyles[i] = neg_ls                        tlinestyles[i] = self.negative_linestyles         else:             if isinstance(linestyles, str):                 tlinestyles = [linestyles] * Nlev


iterable is shorter than the number of contour levels     it will be repeated as necessary. <ins>negative_linestyles : {*None*, 'solid', 'dashed', 'dashdot', 'dotted'}, \                       optional    *Only applies to* `.contour`.    If *negative_linestyles* is None, the default is 'dashed' for    negative contours.    *negative_linestyles* can also be an iterable of the above    strings specifying a set of linestyles to be used. If this    iterable is shorter than the number of contour levels    it will be repeated as necessary.</ins> hatches : list[str], optional     *Only applies to* `.contourf`.


alpha : float         The colorbar transparency between 0 (transparent) and 1 (opaque).     orientation : {'vertical', 'horizontal'}    orientation : None or {'vertical', 'horizontal'}        If None, use the value determined by *location*. If both        *orientation* and *location* are None then defaults to 'vertical'.      ticklocation : {'auto', 'left', 'right', 'top', 'bottom'}        The location of the colorbar ticks. The *ticklocation* must match        *orientation*. For example, a horizontal colorbar can only have ticks        at the top or the bottom. If 'auto', the ticks will be the same as        *location*, so a colorbar to the left will have ticks to the left. If        *location* is None, the ticks will be at the bottom for a horizontal        colorbar and at the right for a vertical.      drawedges : bool        Whether to draw lines at color boundaries.      filled : bool     %(_colormap_kw_doc)s    location : None or {'left', 'right', 'top', 'bottom'}        Set the *orientation* and *ticklocation* of the colorbar using a        single argument. Colorbars on the left and right are vertical,        colorbars at the top and bottom are horizontal. The *ticklocation* is        the same as *location*, so if *location* is 'top', the ticks are on        the top. *orientation* and/or *ticklocation* can be provided as well        and overrides the value set by *location*, but there will be an error        for incompatible combinations.        .. versionadded:: 3.7     """      n_rasterize = 50  # rasterize solids if number of colors >= n_rasterize


alpha=None,                  values=None,                  boundaries=None,                 orientation='vertical',                 orientation=None,                  ticklocation='auto',                  extend=None,                  spacing='uniform',  # uniform or proportional


extendfrac=None,                  extendrect=False,                  label='',<ins>                 location=None,</ins>                  ):          if mappable is None:


mappable.colorbar_cid = mappable.callbacks.connect(             'changed', self.update_normal)         location_orientation = _get_orientation_from_location(location)         _api.check_in_list(            ['vertical', 'horizontal'], orientation=orientation)            [None, 'vertical', 'horizontal'], orientation=orientation)         _api.check_in_list(             ['auto', 'left', 'right', 'top', 'bottom'],             ticklocation=ticklocation)         _api.check_in_list(             ['uniform', 'proportional'], spacing=spacing)         if location_orientation is not None and orientation is not None:            if location_orientation != orientation:                raise TypeError(                    "location and orientation are mutually exclusive")        else:            orientation = orientation or location_orientation or "vertical"         self.ax = ax         self.ax._axes_locator = _ColorbarAxesLocator(self)


self.__scale = None  # linear, log10 for now.  Hopefully more?          if ticklocation == 'auto':            ticklocation = 'bottom' if orientation == 'horizontal' else 'right'            ticklocation = _get_ticklocation_from_orientation(                orientation) if location is None else location         self.ticklocation = ticklocation          self.set_label(label)


def _normalize_location_orientation(location, orientation):     if location is None:        location = _api.check_getitem(            {None: "right", "vertical": "right", "horizontal": "bottom"},            orientation=orientation)        location = _get_ticklocation_from_orientation(orientation)     loc_settings = _api.check_getitem({        "left":   {"location": "left", "orientation": "vertical",                   "anchor": (1.0, 0.5), "panchor": (0.0, 0.5), "pad": 0.10},        "right":  {"location": "right", "orientation": "vertical",                   "anchor": (0.0, 0.5), "panchor": (1.0, 0.5), "pad": 0.05},        "top":    {"location": "top", "orientation": "horizontal",                   "anchor": (0.5, 0.0), "panchor": (0.5, 1.0), "pad": 0.05},        "bottom": {"location": "bottom", "orientation": "horizontal",                   "anchor": (0.5, 1.0), "panchor": (0.5, 0.0), "pad": 0.15},        "left":   {"location": "left", "anchor": (1.0, 0.5),                   "panchor": (0.0, 0.5), "pad": 0.10},        "right":  {"location": "right", "anchor": (0.0, 0.5),                   "panchor": (1.0, 0.5), "pad": 0.05},        "top":    {"location": "top", "anchor": (0.5, 0.0),                   "panchor": (0.5, 1.0), "pad": 0.05},        "bottom": {"location": "bottom", "anchor": (0.5, 1.0),                   "panchor": (0.5, 0.0), "pad": 0.15},     }, location=location)    loc_settings["orientation"] = _get_orientation_from_location(location)     if orientation is not None and orientation != loc_settings["orientation"]:         # Allow the user to pass both if they are consistent.         raise TypeError("location and orientation are mutually exclusive")     return loc_settings  def _get_orientation_from_location(location):    return _api.check_getitem(        {None: None, "left": "vertical", "right": "vertical",         "top": "horizontal", "bottom": "horizontal"}, location=location)def _get_ticklocation_from_orientation(orientation):    return _api.check_getitem(        {None: "right", "vertical": "right", "horizontal": "bottom"},        orientation=orientation) @_docstring.interpd def make_axes(parents, location=None, orientation=None, fraction=0.15,               shrink=1.0, aspect=20, **kwargs):