-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtest_signatures.py
135 lines (112 loc) · 4.91 KB
/
test_signatures.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from inspect import Parameter, getmembers, isfunction, signature
from types import FunctionType
from typing import Callable # See https://github.com/python/mypy/issues/6864
import pytest
from hypothesis import given, settings
from hypothesis import strategies as st
from .api import *
from .wrappers import LibraryInfo
VAR_KINDS = (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD)
KIND_TO_STR = {
Parameter.POSITIONAL_OR_KEYWORD: "pos or kw argument",
Parameter.POSITIONAL_ONLY: "pos-only argument",
Parameter.KEYWORD_ONLY: "keyword-only argument",
Parameter.VAR_POSITIONAL: "star-args (i.e. *args) argument",
Parameter.VAR_KEYWORD: "star-kwargs (i.e. **kwargs) argument",
}
def _test_signature(func, stub):
try:
sig = signature(func)
except ValueError:
pytest.skip("Signature not inspectable")
stub_sig = signature(stub)
params = list(sig.parameters.values())
df_stub_params = list(stub_sig.parameters.values())
# sanity checks
if len(params) > 0:
assert params[0].name != "self"
assert df_stub_params[0].name == "self"
del df_stub_params[0]
non_kwonly_stub_params = [
p for p in df_stub_params if p.kind != Parameter.KEYWORD_ONLY
]
# sanity check
assert non_kwonly_stub_params == df_stub_params[: len(non_kwonly_stub_params)]
# We're not interested if the array module has additional arguments, so we
# only iterate through the arguments listed in the spec.
for i, stub_param in enumerate(non_kwonly_stub_params):
assert (
len(params) >= i + 1
), f"Argument '{stub_param.name}' missing from signature"
param = params[i]
# We're not interested in the name if it isn't actually used
if stub_param.kind not in [Parameter.POSITIONAL_ONLY, *VAR_KINDS]:
assert (
param.name == stub_param.name
), f"Expected argument '{param.name}' to be named '{stub_param.name}'"
if stub_param.kind in [Parameter.POSITIONAL_OR_KEYWORD, *VAR_KINDS]:
f_stub_kind = KIND_TO_STR[stub_param.kind]
assert param.kind == stub_param.kind, (
f"{param.name} is a {KIND_TO_STR[param.kind]}, "
f"but should be a {f_stub_kind}"
)
kwonly_stub_params = df_stub_params[len(non_kwonly_stub_params) :]
for stub_param in kwonly_stub_params:
assert (
stub_param.name in sig.parameters.keys()
), f"Argument '{stub_param.name}' missing from signature"
param = next(p for p in params if p.name == stub_param.name)
f_stub_kind = KIND_TO_STR[stub_param.kind]
assert param.kind in [stub_param.kind, Parameter.POSITIONAL_OR_KEYWORD], (
f"{param.name} is a {KIND_TO_STR[param.kind]}, "
f"but should be a {f_stub_kind} "
f"(or at least a {KIND_TO_STR[Parameter.POSITIONAL_OR_KEYWORD]})"
)
@given(data=st.data())
@settings(max_examples=1)
def test_toplevel_dataframe_dunder_dataframe(libinfo: LibraryInfo, data: st.DataObject):
df = data.draw(libinfo.toplevel_dataframes(), label="df")
assert hasattr(df, "__dataframe__")
assert isinstance(df.__dataframe__, Callable) # type: ignore
_test_signature(df.__dataframe__, DataFrame.__dataframe__)
df_stub_params = []
for _, stub in getmembers(DataFrame, predicate=isfunction):
p = pytest.param(stub, id=stub.__name__)
df_stub_params.append(p)
@pytest.mark.parametrize("stub", df_stub_params)
@given(data=st.data())
@settings(max_examples=1)
def test_dataframe_method(
libinfo: LibraryInfo, stub: FunctionType, data: st.DataObject
):
df = data.draw(libinfo.interchange_dataframes(), label="df")
assert hasattr(df, stub.__name__)
method = getattr(df, stub.__name__)
assert isinstance(method, Callable) # type: ignore
_test_signature(method, stub)
col_stub_params = []
for _, stub in getmembers(Column, predicate=isfunction):
p = pytest.param(stub, id=stub.__name__)
col_stub_params.append(p)
@pytest.mark.parametrize("stub", col_stub_params)
@given(data=st.data())
@settings(max_examples=1)
def test_column_method(libinfo: LibraryInfo, stub: FunctionType, data: st.DataObject):
col = data.draw(libinfo.columns(), label="col")
assert hasattr(col, stub.__name__)
method = getattr(col, stub.__name__)
assert isinstance(method, Callable) # type: ignore
_test_signature(method, stub)
buf_stub_params = []
for _, stub in getmembers(Buffer, predicate=isfunction):
p = pytest.param(stub, id=stub.__name__)
buf_stub_params.append(p)
@pytest.mark.parametrize("stub", buf_stub_params)
@given(data=st.data())
@settings(max_examples=1)
def test_buffer_method(libinfo: LibraryInfo, stub: FunctionType, data: st.DataObject):
buf = data.draw(libinfo.buffers(), label="buf")
assert hasattr(buf, stub.__name__)
method = getattr(buf, stub.__name__)
assert isinstance(method, Callable) # type: ignore
_test_signature(method, stub)