Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Testing pyplot type hints #30201

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions lib/matplotlib/tests/test_pyplot.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import ast
import difflib
import inspect

import numpy as np
import sys
Expand Down Expand Up @@ -484,3 +486,75 @@

# Smoke test that matshow does not ask for a new figsize on the existing figure
plt.matshow(arr, fignum=fig.number)


def assert_signatures_identical(plt_meth, original_meth, remove_self_param=False):
def get_src(meth):
meth_src = Path(inspect.getfile(meth))
meth_stub = meth_src.with_suffix(".pyi")
return meth_stub if meth_stub.exists() else meth_src

def tree_loop(tree, name, class_):
for item in tree.body:
if class_ and isinstance(item, ast.ClassDef) and item.name == class_:
return tree_loop(item, name, None)

if isinstance(item, ast.FunctionDef) and item.name == name:
return item

raise ValueError(f"Cannot find {class_}.{name} in ast")

Check warning on line 505 in lib/matplotlib/tests/test_pyplot.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_pyplot.py#L505

Added line #L505 was not covered by tests

def get_signature(meth):
qualname = meth.__qualname__
class_ = None if "." not in qualname else qualname.split(".")[-2]
path = get_src(meth)
tree = ast.parse(path.read_text())
node = tree_loop(tree, meth.__name__, class_)

params = dict(inspect.signature(meth).parameters)
args = node.args
allargs = (
*args.posonlyargs,
*args.args,
args.vararg,
*args.kwonlyargs,
args.kwarg
)
for param in allargs:
if param is None:
continue
if param.annotation is None:
continue
annotation = ast.unparse(param.annotation)
params[param.arg] = params[param.arg].replace(annotation=annotation)

if node.returns is not None:
return inspect.Signature(
params.values(),
return_annotation=ast.unparse(node.returns)
)
else:
return inspect.Signature(params.values())

Check warning on line 537 in lib/matplotlib/tests/test_pyplot.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_pyplot.py#L537

Added line #L537 was not covered by tests

plt_sig = get_signature(plt_meth)
original_sig = get_signature(original_meth)

assert plt_sig.return_annotation == original_sig.return_annotation

original_params = original_sig.parameters
if remove_self_param:
if next(iter(original_params)) not in ["self"]:
raise ValueError(f"{original_sig} is not an instance method")

Check warning on line 547 in lib/matplotlib/tests/test_pyplot.py

View check run for this annotation

Codecov / codecov/patch

lib/matplotlib/tests/test_pyplot.py#L547

Added line #L547 was not covered by tests

original_params = original_params.copy()
del original_params["self"]

assert plt_sig.parameters == original_params


def test_setloglevel_signature():
assert_signatures_identical(plt.set_loglevel, mpl.set_loglevel)


def test_polar_signature():
assert_signatures_identical(plt.polar, plt.Axes.plot, True)
Loading