# Buggy code
def add_legend_data(self, ax):
    """Add labeled artists to represent the different plot semantics."""
    verbosity = self.legend
    if verbosity not in ["brief", "full"]:
        err = "`legend` must be 'brief', 'full', or False"
        raise ValueError(err)

    legend_kwargs = {}
    keys = []

    title_kws = dict(color="w", s=0, linewidth=0, marker="", dashes="")

    def update(var_name, val_name, **kws):
        key = var_name, val_name
        if key in legend_kwargs:
            legend_kwargs[key].update(**kws)
        else:
            keys.append(key)

            legend_kwargs[key] = dict(**kws)

    # -- Add a legend for hue semantics
    if verbosity == "brief" and self._hue_map.map_type == "numeric":
        if isinstance(self._hue_map.norm, mpl.colors.LogNorm):
            locator = mpl.ticker.LogLocator(numticks=3)
        else:
            locator = mpl.ticker.MaxNLocator(nbins=3)
        limits = min(self._hue_map.levels), max(self._hue_map.levels)
        hue_levels, hue_formatted_levels = locator_to_legend_entries(
            locator, limits, self.plot_data["hue"].dtype
        )
    elif self._hue_map.levels is None:
        hue_levels = hue_formatted_levels = []
    else:
        hue_levels = hue_formatted_levels = self._hue_map.levels

    # Add the hue semantic subtitle
    if "hue" in self.variables and self.variables["hue"] is not None:
        update((self.variables["hue"], "title"), self.variables["hue"], **title_kws)

    # Add the hue semantic labels
    for level, formatted_level in zip(hue_levels, hue_formatted_levels):
        if level is not None:
            color = self._hue_map(level)
            update(self.variables["hue"], formatted_level, color=color)

    # -- Add a legend for size semantics

    if verbosity == "brief" and self._size_map.map_type == "numeric":
        # Define how ticks will interpolate between the min/max data values
        if isinstance(self._size_map.norm, mpl.colors.LogNorm):
            locator = mpl.ticker.LogLocator(numticks=3)
        else:
            locator = mpl.ticker.MaxNLocator(nbins=3)
        # Define the min/max data values
        limits = min(self._size_map.levels), max(self._size_map.levels)
        size_levels, size_formatted_levels = locator_to_legend_entries(
            locator, limits, self.plot_data["size"].dtype
        )
    elif self._size_map.levels is None:
        size_levels = size_formatted_levels = []
    else:
        size_levels = size_formatted_levels = self._size_map.levels

    # Add the size semantic subtitle
    if "size" in self.variables and self.variables["size"] is not None:
        update((self.variables["size"], "title"), self.variables["size"], **title_kws)

    # Add the size semantic labels
    for level, formatted_level in zip(size_levels, size_formatted_levels):
        if level is not None:
            size = self._size_map(level)
            update(
                self.variables["size"],
                formatted_level,
                linewidth=size,
                s=size,
            )

    # -- Add a legend for style semantics

    # Add the style semantic title
    if "style" in self.variables and self.variables["style"] is not None:
        update((self.variables["style"], "title"), self.variables["style"], **title_kws)

    # Add the style semantic labels
    if self._style_map.levels is not None:
        for level in self._style_map.levels:
            if level is not None:
                attrs = self._style_map(level)
                update(
                    self.variables["style"],
                    level,
                    marker=attrs.get("marker", ""),
                    dashes=attrs.get("dashes", ""),
                )

    func = getattr(ax, self._legend_func)

    legend_data = {}
    legend_order = []

    for key in keys:
        _, label = key
        kws = legend_kwargs[key]
        kws.setdefault("color", ".2")
        use_kws = {}
        for attr in self._legend_attributes + ["visible"]:
            if attr in kws:
                use_kws[attr] = kws[attr]
        artist = func([], [], label=label, **use_kws)
        if self._legend_func == "plot":
            artist = artist[0]
        legend_data[key] = artist
        legend_order.append(key)

    self.legend_data = legend_data
    self.legend_order = legend_order


# Traceback (AttributeError)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
AttributeError: 'float' object has no attribute 'rint'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
60     try:
---> 61         return bound(*args, **kwds)
62     except TypeError:

TypeError: loop of ufunc does not support argument 0 of type float which has no callable rint method

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
AttributeError: 'float' object has no attribute 'rint'

The above exception was the direct cause of the following exception:

TypeError                                 Traceback (most recent call last)
<ipython-input-76-61b464cca20e> in <module>
----> 1 sns.lineplot(x=[0, 1, 0, 1], y=[0, 1, 0, 2], hue=pd.Series([1, 1, 3, 3], dtype=object))

~/code/seaborn/seaborn/_decorators.py in inner_f(*args, **kwargs)
44             )
45         kwargs.update({k: arg for k, arg in zip(sig.parameters, args)})
---> 46         return f(**kwargs)
47     return inner_f
48

~/code/seaborn/seaborn/relational.py in lineplot(x, y, hue, size, style, data, palette, hue_order, hue_norm, sizes, size_order, size_norm, dashes, markers, style_order, units, estimator, ci, n_boot, seed, sort, err_style, err_kws, legend, ax, **kwargs)
642         ax = plt.gca()
643
--> 644     p.plot(ax, kwargs)
645     return ax
646

~/code/seaborn/seaborn/relational.py in plot(self, ax, kws)
362         self.label_axes(ax)
363         if self.legend:
--> 364             self.add_legend_data(ax)
365             handles, _ = ax.get_legend_handles_labels()
366             if handles:

~/code/seaborn/seaborn/relational.py in add_legend_data(self, ax)
70                 locator = mpl.ticker.MaxNLocator(nbins=3)
71             limits = min(self._hue_map.levels), max(self._hue_map.levels)
---> 72             hue_levels, hue_formatted_levels = locator_to_legend_entries(
73                 locator, limits, self.plot_data["hue"].dtype
74             )

~/code/seaborn/seaborn/utils.py in locator_to_legend_entries(locator, limits, dtype)
564     # once pinned matplotlib>=3.1.0 with:
565     # formatted_levels = formatter.format_ticks(raw_levels)
--> 566     formatter.set_locs(raw_levels)
567     formatted_levels = [formatter(x) for x in raw_levels]
568

~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/matplotlib/ticker.py in set_locs(self, locs)
687                 self._compute_offset()
688             self._set_order_of_magnitude()
--> 689             self._set_format()
690
691     def _compute_offset(self):

~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/matplotlib/ticker.py in _set_format(self)
789         thresh = 1e-3 * 10 ** loc_range_oom
790         while sigfigs >= 0:
--> 791             if np.abs(locs - np.round(locs, decimals=sigfigs)).max() < thresh:
792                 sigfigs -= 1
793             else:

<__array_function__ internals> in round_(*args, **kwargs)

~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/numpy/core/fromnumeric.py in round_(a, decimals, out)
3597     around : equivalent function; see for details.
3598     """
-> 3599     return around(a, decimals=decimals, out=out)
3600
3601

<__array_function__ internals> in around(*args, **kwargs)

~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/numpy/core/fromnumeric.py in around(a, decimals, out)
3222
3223     """
-> 3224     return _wrapfunc(a, 'round', decimals=decimals, out=out)
3225
3226

~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
68         # Call _wrapit from within the except clause to ensure a potential
69         # exception has a traceback chain.
---> 70         return _wrapit(obj, method, *args, **kwds)
71
72

~/miniconda3/envs/seaborn-refactor/lib/python3.8/site-packages/numpy/core/fromnumeric.py in _wrapit(obj, method, *args, **kwds)
45     except AttributeError:
46         wrap = None
---> 47     result = getattr(asarray(obj), method)(*args, **kwds)
48     if wrap:
49         if not isinstance(result, mu.ndarray):

TypeError: loop of ufunc does not support argument 0 of type float which has no callable rint method

# Fixed code
def add_legend_data(self, ax):
    """Add labeled artists to represent the different plot semantics."""
    verbosity = self.legend
    if verbosity not in ["brief", "full"]:
        err = "`legend` must be 'brief', 'full', or False"
        raise ValueError(err)

    legend_kwargs = {}
    keys = []

    title_kws = dict(color="w", s=0, linewidth=0, marker="", dashes="")

    def update(var_name, val_name, **kws):
        key = var_name, val_name
        if key in legend_kwargs:
            legend_kwargs[key].update(**kws)
        else:
            keys.append(key)

            legend_kwargs[key] = dict(**kws)

    # -- Add a legend for hue semantics
    if verbosity == "brief" and self._hue_map.map_type == "numeric":
        if isinstance(self._hue_map.norm, mpl.colors.LogNorm):
            locator = mpl.ticker.LogLocator(numticks=3)
        else:
            locator = mpl.ticker.MaxNLocator(nbins=3)
        limits = min(self._hue_map.levels), max(self._hue_map.levels)
        hue_levels, hue_formatted_levels = locator_to_legend_entries(
            locator, limits, self.plot_data["hue"].infer_objects().dtype
        )
    elif self._hue_map.levels is None:
        hue_levels = hue_formatted_levels = []
    else:
        hue_levels = hue_formatted_levels = self._hue_map.levels

    # Add the hue semantic subtitle
    if "hue" in self.variables and self.variables["hue"] is not None:
        update((self.variables["hue"], "title"), self.variables["hue"], **title_kws)

    # Add the hue semantic labels
    for level, formatted_level in zip(hue_levels, hue_formatted_levels):
        if level is not None:
            color = self._hue_map(level)
            update(self.variables["hue"], formatted_level, color=color)

    # -- Add a legend for size semantics

    if verbosity == "brief" and self._size_map.map_type == "numeric":
        # Define how ticks will interpolate between the min/max data values
        if isinstance(self._size_map.norm, mpl.colors.LogNorm):
            locator = mpl.ticker.LogLocator(numticks=3)
        else:
            locator = mpl.ticker.MaxNLocator(nbins=3)
        # Define the min/max data values
        limits = min(self._size_map.levels), max(self._size_map.levels)
        size_levels, size_formatted_levels = locator_to_legend_entries(
            locator, limits, self.plot_data["size"].infer_objects().dtype
        )
    elif self._size_map.levels is None:
        size_levels = size_formatted_levels = []
    else:
        size_levels = size_formatted_levels = self._size_map.levels

    # Add the size semantic subtitle
    if "size" in self.variables and self.variables["size"] is not None:
        update((self.variables["size"], "title"), self.variables["size"], **title_kws)

    # Add the size semantic labels
    for level, formatted_level in zip(size_levels, size_formatted_levels):
        if level is not None:
            size = self._size_map(level)
            update(
                self.variables["size"],
                formatted_level,
                linewidth=size,
                s=size,
            )

    # -- Add a legend for style semantics

    # Add the style semantic title
    if "style" in self.variables and self.variables["style"] is not None:
        update((self.variables["style"], "title"), self.variables["style"], **title_kws)

    # Add the style semantic labels
    if self._style_map.levels is not None:
        for level in self._style_map.levels:
            if level is not None:
                attrs = self._style_map(level)
                update(
                    self.variables["style"],
                    level,
                    marker=attrs.get("marker", ""),
                    dashes=attrs.get("dashes", ""),
                )

    func = getattr(ax, self._legend_func)

    legend_data = {}
    legend_order = []

    for key in keys:
        _, label = key
        kws = legend_kwargs[key]
        kws.setdefault("color", ".2")
        use_kws = {}
        for attr in self._legend_attributes + ["visible"]:
            if attr in kws:
                use_kws[attr] = kws[attr]
        artist = func([], [], label=label, **use_kws)
        if self._legend_func == "plot":
            artist = artist[0]
        legend_data[key] = artist
        legend_order.append(key)

    self.legend_data = legend_data
    self.legend_order = legend_order