ronantakizawa/codereview-bench huggingface dataset:
Repository: matplotlib/matplotlib
File: src/ft2font_wrapper.cpp (C++)

Code before:
    FT2Image &im = self->x->get_image();
    py::ssize_t dims[] = {
        static_cast<py::ssize_t>(im.get_height()),
        static_cast<py::ssize_t>(im.get_width())
    };
    return py::array_t<unsigned char>(dims, im.get_buffer());
}

const char *PyFT2Font__get_type1_encoding_vector__doc__ = R"""(
    Return a list mapping CharString indices of a Type 1 font to FreeType glyph indices.

    Returns
    -------
    list[int]
)""";

static std::array<FT_UInt, 256>
PyFT2Font__get_type1_encoding_vector(PyFT2Font *self)
{
    auto face = self->x->get_face();
    auto indices = std::array<FT_UInt, 256>{};
    for (auto i = 0; i < indices.size(); ++i) {
        auto len = FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, nullptr, 0);
        if (len == -1) {
            throw std::runtime_error{
                "FT_Get_PS_Font_Value tried to access a non-existent value"};
        }
        auto buf = std::unique_ptr<char[]>{new char[len]};
        FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, buf.get(), len);
        indices[i] = FT_Get_Name_Index(face, buf.get());
    }
    return indices;
}

static const char *
PyFT2Font_postscript_name(PyFT2Font *self)
{
    const char *ps_name = FT_Get_Postscript_Name(self->x->get_face());
    if (ps_name == nullptr) {
        ps_name = "UNAVAILABLE";
    }

    return ps_name;
}

static FT_Long
PyFT2Font_num_faces(PyFT2Font *self)
{
    return self->x->get_face()->num_faces;
}


Review comment (suggestion):
Is it possible to give more context here, e.g. on which font and index the issue occurs, I could imagine one is quite lost otherwise.

Code after:
    np.ndarray[int]

    See Also
    --------
    .get_path
)""";

static py::array
PyFT2Font_get_image(PyFT2Font *self)
{
    FT2Image &im = self->x->get_image();
    py::ssize_t dims[] = {
        static_cast<py::ssize_t>(im.get_height()),
        static_cast<py::ssize_t>(im.get_width())
    };
    return py::array_t<unsigned char>(dims, im.get_buffer());
}

const char *PyFT2Font__get_type1_encoding_vector__doc__ = R"""(
    Return a list mapping CharString indices of a Type 1 font to FreeType glyph indices.

    Returns
    -------
    list[int]
)""";

static std::array<FT_UInt, 256>
PyFT2Font__get_type1_encoding_vector(PyFT2Font *self)
{
    auto face = self->x->get_face();
    auto indices = std::array<FT_UInt, 256>{};
    for (auto i = 0u; i < indices.size(); ++i) {
        auto len = FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, nullptr, 0);
        if (len == -1) {
            // Explicitly ignore missing entries (mapped to glyph 0 = .notdef).
            continue;
        }
        auto buf = std::make_unique<char[]>(len);
        FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, buf.get(), len);
        indices[i] = FT_Get_Name_Index(face, buf.get());
    }
    return indices;
}

static const char *
PyFT2Font_postscript_name(PyFT2Font *self)
{
    const char *ps_name = FT_Get_Postscript_Name(self->x->get_face());
    if (ps_name == nullptr) {
        ps_name = "UNAVAILABLE";
    }
Repository: matplotlib/matplotlib
File: src/ft2font_wrapper.cpp (C++)

Code before:
    };
    return py::array_t<unsigned char>(dims, im.get_buffer());
}

const char *PyFT2Font__get_type1_encoding_vector__doc__ = R"""(
    Return a list mapping CharString indices of a Type 1 font to FreeType glyph indices.

    Returns
    -------
    list[int]
)""";

static std::array<FT_UInt, 256>
PyFT2Font__get_type1_encoding_vector(PyFT2Font *self)
{
    auto face = self->x->get_face();
    auto indices = std::array<FT_UInt, 256>{};
    for (auto i = 0; i < indices.size(); ++i) {
        auto len = FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, nullptr, 0);
        if (len == -1) {
            throw std::runtime_error{
                "FT_Get_PS_Font_Value tried to access non-existent value "
                "PS_DICT_ENCODING_ENTRY #" + std::to_string(i) + " of "
                + PyFT2Font_fname(self).cast<std::string>()};
        }
        auto buf = std::unique_ptr<char[]>{new char[len]};
        FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, buf.get(), len);
        indices[i] = FT_Get_Name_Index(face, buf.get());
    }
    return indices;
}

static const char *
PyFT2Font_postscript_name(PyFT2Font *self)
{
    const char *ps_name = FT_Get_Postscript_Name(self->x->get_face());
    if (ps_name == nullptr) {
        ps_name = "UNAVAILABLE";
    }

    return ps_name;
}

static FT_Long
PyFT2Font_num_faces(PyFT2Font *self)
{
    return self->x->get_face()->num_faces;
}

static const char *
PyFT2Font_family_name(PyFT2Font *self)

Review comment (suggestion):
I think you can shorten this with `std::make_unique`?
```suggestion
        auto buf = std::make_unique<char[]>(len);
```

Code after:
    };
    return py::array_t<unsigned char>(dims, im.get_buffer());
}

const char *PyFT2Font__get_type1_encoding_vector__doc__ = R"""(
    Return a list mapping CharString indices of a Type 1 font to FreeType glyph indices.

    Returns
    -------
    list[int]
)""";

static std::array<FT_UInt, 256>
PyFT2Font__get_type1_encoding_vector(PyFT2Font *self)
{
    auto face = self->x->get_face();
    auto indices = std::array<FT_UInt, 256>{};
    for (auto i = 0u; i < indices.size(); ++i) {
        auto len = FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, nullptr, 0);
        if (len == -1) {
            // Explicitly ignore missing entries (mapped to glyph 0 = .notdef).
            continue;
        }
        auto buf = std::make_unique<char[]>(len);
        FT_Get_PS_Font_Value(face, PS_DICT_ENCODING_ENTRY, i, buf.get(), len);
        indices[i] = FT_Get_Name_Index(face, buf.get());
    }
    return indices;
}

static const char *
PyFT2Font_postscript_name(PyFT2Font *self)
{
    const char *ps_name = FT_Get_Postscript_Name(self->x->get_face());
    if (ps_name == nullptr) {
        ps_name = "UNAVAILABLE";
    }

    return ps_name;
}

static FT_Long
PyFT2Font_num_faces(PyFT2Font *self)
{
    return self->x->get_face()->num_faces;
}

static const char *
PyFT2Font_family_name(PyFT2Font *self)
{
    const char *name = self->x->get_face()->family_name;
Repository: matplotlib/matplotlib
File: src/_macosx.m (Objective-C)

Code before:
FigureManager_dealloc(FigureManager* self)
{
    [self->window close];
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject*
FigureManager__show(FigureManager* self)
{
    [self->window makeKeyAndOrderFront: nil];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager__raise(FigureManager* self)
{
    [self->window orderFrontRegardless];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager_destroy(FigureManager* self)
{
    [self->window close];
    self->window = NULL;
    [super destroy];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager_set_icon(PyObject* null, PyObject* args) {
    PyObject* icon_path;
    if (!PyArg_ParseTuple(args, "O&", &PyUnicode_FSDecoder, &icon_path)) {
        return NULL;
    }
    const char* icon_path_ptr = PyUnicode_AsUTF8(icon_path);
    if (!icon_path_ptr) {
        Py_DECREF(icon_path);
        return NULL;
    }
    @autoreleasepool {
        NSString* ns_icon_path = [NSString stringWithUTF8String: icon_path_ptr];
        Py_DECREF(icon_path);
        if (!ns_icon_path) {
            PyErr_SetString(PyExc_RuntimeError, "Could not convert to NSString*");
            return NULL;
        }
        NSImage* image = [[[NSImage alloc] initByReferencingFile: ns_icon_path] autorelease];
        if (!image) {
            PyErr_SetString(PyExc_RuntimeError, "Could not create NSImage*");
            return NULL;

Review comment (bug):
I could need a bit of help here from someone with more Objective-C / Cpython knowledge. This is missing the equivalent of `super.destroy()`. The change here was a rather wild guess from pattern-matching other similar cases in the module, but is apparently not correct, because this now fails the build with
> ../../src/_macosx.m:689:6: error: use of undeclared identifier 'super'

Code after:

static void
FigureManager_dealloc(FigureManager* self)
{
    [self->window close];
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject*
FigureManager__show(FigureManager* self)
{
    [self->window makeKeyAndOrderFront: nil];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager__raise(FigureManager* self)
{
    [self->window orderFrontRegardless];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager_destroy(FigureManager* self)
{
    [self->window close];
    self->window = NULL;

    // call super(self, FigureManager).destroy() - it seems we need the
    // explicit arguments, and just super() doesn't work in the C API.
    PyObject *super_obj = PyObject_CallFunctionObjArgs(
        (PyObject *)&PySuper_Type,
        (PyObject *)&FigureManagerType,
        self,
        NULL
    );
    if (super_obj == NULL) {
        return NULL; // error
    }
    PyObject *result = PyObject_CallMethod(super_obj, "destroy", NULL);
    Py_DECREF(super_obj);
    if (result == NULL) {
        return NULL; // error
    }
    Py_DECREF(result);

    Py_RETURN_NONE;
}

static PyObject*
FigureManager_set_icon(PyObject* null, PyObject* args) {
Repository: matplotlib/matplotlib
File: src/_macosx.m (Objective-C)

Code before:

static PyObject*
FigureManager__raise(FigureManager* self)
{
    [self->window orderFrontRegardless];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager_destroy(FigureManager* self)
{
    [self->window close];
    self->window = NULL;

    // call super().destroy()
    PyObject *super_obj = PyObject_CallFunctionObjArgs(
        (PyObject *)&PySuper_Type,
        (PyObject *)&FigureManagerType,
        self,
        NULL
    );
    if (super_obj == NULL) {
        return NULL; // error
    }
    PyObject *result = PyObject_CallMethod(super_obj, "destroy", NULL);
    Py_DECREF(super_obj);
    if (result == NULL) {
        return NULL; // error
    }
    Py_DECREF(result);

    Py_RETURN_NONE;
}

static PyObject*
FigureManager_set_icon(PyObject* null, PyObject* args) {
    PyObject* icon_path;
    if (!PyArg_ParseTuple(args, "O&", &PyUnicode_FSDecoder, &icon_path)) {
        return NULL;
    }
    const char* icon_path_ptr = PyUnicode_AsUTF8(icon_path);
    if (!icon_path_ptr) {
        Py_DECREF(icon_path);
        return NULL;
    }
    @autoreleasepool {
        NSString* ns_icon_path = [NSString stringWithUTF8String: icon_path_ptr];
        Py_DECREF(icon_path);
        if (!ns_icon_path) {
            PyErr_SetString(PyExc_RuntimeError, "Could not convert to NSString*");
            return NULL;

Review comment (suggestion):
Can drop the args
```suggestion
    PyObject *result = PyObject_CallMethodNoArgs(super_obj, "destroy");
```

Code after:

static PyObject*
FigureManager__raise(FigureManager* self)
{
    [self->window orderFrontRegardless];
    Py_RETURN_NONE;
}

static PyObject*
FigureManager_destroy(FigureManager* self)
{
    [self->window close];
    self->window = NULL;

    // call super(self, FigureManager).destroy() - it seems we need the
    // explicit arguments, and just super() doesn't work in the C API.
    PyObject *super_obj = PyObject_CallFunctionObjArgs(
        (PyObject *)&PySuper_Type,
        (PyObject *)&FigureManagerType,
        self,
        NULL
    );
    if (super_obj == NULL) {
        return NULL; // error
    }
    PyObject *result = PyObject_CallMethod(super_obj, "destroy", NULL);
    Py_DECREF(super_obj);
    if (result == NULL) {
        return NULL; // error
    }
    Py_DECREF(result);

    Py_RETURN_NONE;
}

static PyObject*
FigureManager_set_icon(PyObject* null, PyObject* args) {
    PyObject* icon_path;
    if (!PyArg_ParseTuple(args, "O&", &PyUnicode_FSDecoder, &icon_path)) {
        return NULL;
    }
    const char* icon_path_ptr = PyUnicode_AsUTF8(icon_path);
    if (!icon_path_ptr) {
        Py_DECREF(icon_path);
        return NULL;
    }
    @autoreleasepool {
        NSString* ns_icon_path = [NSString stringWithUTF8String: icon_path_ptr];
        Py_DECREF(icon_path);
        if (!ns_icon_path) {
            PyErr_SetString(PyExc_RuntimeError, "Could not convert to NSString*");
Repository: matplotlib/matplotlib
File: lib/matplotlib/tests/test_axes.py (Python)

Code before:
        assert mcolors.same_color(bar.get_facecolor(), 'red')

    # case 3: Only 'facecolor'
    bars = ax.bar([21, 22, 23], [4, 5, 6], facecolor='yellow')
    for bar in bars:
        assert mcolors.same_color(bar.get_facecolor(), 'yellow')

    # case 4: 'facecolor' and 'color'
    bars = ax.bar([31, 32, 33], [4, 5, 6], color='red', facecolor='green')
    for bar in bars:
        assert mcolors.same_color(bar.get_facecolor(), 'green')


@check_figures_equal()
def test_axes_set_position_external_bbox_unchanged(fig_test, fig_ref):
    # From #29410: Modifying Axes' position also alters the original Bbox
    # object used for initialization
    bbox = mtransforms.Bbox([[0.0, 0.0], [1.0, 1.0]])
    ax_test = fig_test.add_axes(bbox)
    ax_test.set_position([0.25, 0.25, 0.5, 0.5])
    assert (bbox.x0, bbox.y0, bbox.width, bbox.height) == (0.0, 0.0, 1.0, 1.0)
    ax_ref = fig_ref.add_axes([0.25, 0.25, 0.5, 0.5])


def test_bar_shape_mismatch():
    x = ["foo", "bar"]
    height = [1, 2, 3]
    error_message = (
        r"Mismatch is between 'x' with shape \(2,\) and 'height' with shape \(3,\)"
    )
    with pytest.raises(ValueError, match=error_message):
        plt.bar(x, height)


Review comment (suggestion):
```suggestion
    values = [5, float('nan'), float('inf')]
```
Optional. `df` is typically used as variable name for dataframes, so it's slightly misleading here.

Code after:


@check_figures_equal()
def test_axes_set_position_external_bbox_unchanged(fig_test, fig_ref):
    # From #29410: Modifying Axes' position also alters the original Bbox
    # object used for initialization
    bbox = mtransforms.Bbox([[0.0, 0.0], [1.0, 1.0]])
    ax_test = fig_test.add_axes(bbox)
    ax_test.set_position([0.25, 0.25, 0.5, 0.5])
    assert (bbox.x0, bbox.y0, bbox.width, bbox.height) == (0.0, 0.0, 1.0, 1.0)
    ax_ref = fig_ref.add_axes([0.25, 0.25, 0.5, 0.5])


def test_bar_shape_mismatch():
    x = ["foo", "bar"]
    height = [1, 2, 3]
    error_message = (
        r"Mismatch is between 'x' with shape \(2,\) and 'height' with shape \(3,\)"
    )
    with pytest.raises(ValueError, match=error_message):
        plt.bar(x, height)


def test_pie_non_finite_values():
    fig, ax = plt.subplots()
    df = [5, float('nan'), float('inf')]

    with pytest.raises(ValueError, match='Wedge sizes must be finite numbers'):
        ax.pie(df, labels=['A', 'B', 'C'])
Repository: matplotlib/matplotlib
File: lib/matplotlib/tests/test_axes.py (Python)

Code before:

    # Creates a simple plot with error bars and a specified ecolor
    x = np.linspace(0, 10, 10)
    y = np.sin(x)
    yerr = 0.1
    mpl.rcParams['lines.markeredgecolor'] = 'green'
    ecolor = 'red'

    fig, ax = plt.subplots()
    errorbars = ax.errorbar(x, y, yerr=yerr, ecolor=ecolor, fmt='o', capsize=5)

    # Tests if the caps have the specified color
    for cap in errorbars[2]:
        assert mcolors.same_color(cap.get_edgecolor(), ecolor)


def test_caps_no_ecolor():

    # Creates a simple plot with error bars without specifying ecolor
    x = np.linspace(0, 10, 10)
    y = np.sin(x)
    yerr = 0.1
    mpl.rcParams['lines.markeredgecolor'] = 'green'

    fig, ax = plt.subplots()
    errorbars = ax.errorbar(x, y, yerr=yerr, fmt='o', capsize=5)

    # Tesrts if the caps have the default color (blue)
    for cap in errorbars[2]:
        assert mcolors.same_color(cap.get_edgecolor(), "blue")


def test_pie_non_finite_values():
    fig, ax = plt.subplots()
    df = [5, float('nan'), float('inf')]

    with pytest.raises(ValueError, match='Wedge sizes must be finite numbers'):
        ax.pie(df, labels=['A', 'B', 'C'])


Review comment (suggestion):
As above:

```suggestion
    mpl.rcParams['lines.markeredgecolor'] = 'green'

    fig, ax = plt.subplots()
    errorbars = ax.errorbar(x, np.sin(x), yerr=0.1)
```

Code after:

    # Creates a simple plot with error bars and a specified ecolor
    x = np.linspace(0, 10, 10)
    mpl.rcParams['lines.markeredgecolor'] = 'green'
    ecolor = 'red'

    fig, ax = plt.subplots()
    errorbars = ax.errorbar(x, np.sin(x), yerr=0.1, ecolor=ecolor)

    # Tests if the caps have the specified color
    for cap in errorbars[2]:
        assert mcolors.same_color(cap.get_edgecolor(), ecolor)


def test_caps_no_ecolor():

    # Creates a simple plot with error bars without specifying ecolor
    x = np.linspace(0, 10, 10)
    mpl.rcParams['lines.markeredgecolor'] = 'green'
    fig, ax = plt.subplots()
    errorbars = ax.errorbar(x, np.sin(x), yerr=0.1)

    # Tests if the caps have the default color (blue)
    for cap in errorbars[2]:
        assert mcolors.same_color(cap.get_edgecolor(), "blue")


def test_pie_non_finite_values():
    fig, ax = plt.subplots()
    df = [5, float('nan'), float('inf')]

    with pytest.raises(ValueError, match='Wedge sizes must be finite numbers'):
        ax.pie(df, labels=['A', 'B', 'C'])
Repository: matplotlib/matplotlib
File: lib/matplotlib/scale.py (Python)

Code before:
            return scale_cls(**kwargs)
        raise


if scale_factory.__doc__:
    scale_factory.__doc__ = scale_factory.__doc__ % {
        "names": ", ".join(map(repr, get_scale_names()))}


def register_scale(scale_class):
    """
    Register a new kind of scale.

    Parameters
    ----------
    scale_class : subclass of `ScaleBase`
        The scale to register.
    """
    sig = inspect.signature(scale_class.__init__)
    if 'axis' in sig.parameters:
        warnings.warn(
            f"The scale class {scale_class.__name__} still uses the 'axis' "
            "parameter in its constructor. Consider refactoring it to remove "
            "this dependency.",
            DeprecationWarning
        )
    _scale_mapping[scale_class.name] = scale_class


def _get_scale_docs():
    """
    Helper function for generating docstrings related to scales.
    """
    docs = []
    for name, scale_class in _scale_mapping.items():
        docstring = inspect.getdoc(scale_class.__init__) or ""
        docs.extend([
            f"    {name!r}",
            "",
            textwrap.indent(docstring, " " * 8),
            ""
        ])
    return "\n".join(docs)


_docstring.interpd.register(
    scale_type='{%s}' % ', '.join([repr(x) for x in get_scale_names()]),
    scale_docs=_get_scale_docs().rstrip(),
    )


Review comment (suggestion):
We should not do this yet. For a transition period, we must still silently accept scales with axis parameter. Otherwise, this will surface in user code in the next matplotlib release, but users cannot do anything about the warning because most likely the scales come from a third party library.

Well, we can introduce this as a PendingDeprecationWarning, but even then, this has to be done in concert with us being able to call the class without the parameter, so it should be part of #29358 (or maybe introduced only in a later release). The first step must be to create full compatibility with both call patterns. Only then we can start to (pending) deprecate.

Code after:
if scale_factory.__doc__:
    scale_factory.__doc__ = scale_factory.__doc__ % {
        "names": ", ".join(map(repr, get_scale_names()))}


def register_scale(scale_class):
    """
    Register a new kind of scale.

    Parameters
    ----------
    scale_class : subclass of `ScaleBase`
        The scale to register.
    """
    _scale_mapping[scale_class.name] = scale_class


def _get_scale_docs():
    """
    Helper function for generating docstrings related to scales.
    """
    docs = []
    for name, scale_class in _scale_mapping.items():
        docstring = inspect.getdoc(scale_class.__init__) or ""
        docs.extend([
            f"    {name!r}",
            "",
            textwrap.indent(docstring, " " * 8),
            ""
        ])
    return "\n".join(docs)


_docstring.interpd.register(
    scale_type='{%s}' % ', '.join([repr(x) for x in get_scale_names()]),
    scale_docs=_get_scale_docs().rstrip(),
    )
Repository: matplotlib/matplotlib
File: lib/matplotlib/scale.pyi (Python)

Code before:
        functions: tuple[
            Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike]
        ],
    ) -> None: ...

class LogTransform(Transform):
    input_dims: int
    output_dims: int
    base: float
    def __init__(
        self, base: float, nonpositive: Literal["clip", "mask"] = ...
    ) -> None: ...
    def inverted(self) -> InvertedLogTransform: ...

class InvertedLogTransform(Transform):
    input_dims: int
    output_dims: int
    base: float
    def __init__(self, base: float) -> None: ...
    def inverted(self) -> LogTransform: ...

class LogScale(ScaleBase):
    name: str
    subs: Iterable[int] | None
    def __init__(
        self: LogScale,
        axis: Union[Axis, None] = None,
        *,
        base: float = 10,
        subs: Union[Iterable[int], None] = None,
        nonpositive: Union[Literal['clip'], Literal['mask']] = 'clip'
    ) -> None: ...
    @property
    def base(self) -> float: ...
    def get_transform(self) -> Transform: ...

class FuncScaleLog(LogScale):
    def __init__(
        self,
        axis: Axis | None,
        functions: tuple[
            Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike]
        ],
        base: float = ...,
    ) -> None: ...
    @property
    def base(self) -> float: ...
    def get_transform(self) -> Transform: ...

class SymmetricalLogTransform(Transform):
    input_dims: int

Review comment (suggestion):
You don't type `self`. It's implicitly understood by typecheckers.

Code after:
    def __init__(
        self,
        axis: Axis | None,
        functions: tuple[
            Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike]
        ],
    ) -> None: ...

class LogTransform(Transform):
    input_dims: int
    output_dims: int
    base: float
    def __init__(
        self, base: float, nonpositive: Literal["clip", "mask"] = ...
    ) -> None: ...
    def inverted(self) -> InvertedLogTransform: ...

class InvertedLogTransform(Transform):
    input_dims: int
    output_dims: int
    base: float
    def __init__(self, base: float) -> None: ...
    def inverted(self) -> LogTransform: ...

class LogScale(ScaleBase):
    name: str
    subs: Iterable[int] | None
    def __init__(
        self,
        axis: Axis | None = ...,
        *,
        base: float = ...,
        subs: Iterable[int] | None = ...,
        nonpositive: Literal["clip", "mask"] = ...
    ) -> None: ...
    @property
    def base(self) -> float: ...
    def get_transform(self) -> Transform: ...

class FuncScaleLog(LogScale):
    def __init__(
        self,
        axis: Axis | None,
        functions: tuple[
            Callable[[ArrayLike], ArrayLike], Callable[[ArrayLike], ArrayLike]
        ],
        base: float = ...,
    ) -> None: ...
    @property
    def base(self) -> float: ...
    def get_transform(self) -> Transform: ...