Skip to content
Open
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ jobs:
- name: Run pyrefly on 'tests' (using the local stubs) and on the local stubs
run: poetry run poe pyrefly

- name: Run pyrefly's type coverage check on 'tests'
run: poetry run poe pyrefly_coverage

- name: Run pyright on 'tests' (using the local stubs) and on the local stubs
run: poetry run poe pyright

Expand Down
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ help = "Run all tests"
script = "scripts.test:run_tests(src=True, dist=True)"

[tool.poe.tasks.test]
help = "Run local tests (includes 'mypy', 'pyright', 'pyrefly', 'ty', 'pytest', and 'style')"
help = "Run local tests (includes 'mypy', 'pyright', 'pyrefly', 'pyrefly_coverage', 'ty', 'pytest', and 'style')"
script = "scripts.test:run_tests(src=True)"

[tool.poe.tasks.test_dist]
Expand Down Expand Up @@ -131,6 +131,10 @@ script = "scripts.test.run:pyrefly_src_strict"
help = "Run pyrefly on 'tests' (using the local stubs) and on the local stubs with preset 'all'"
script = "scripts.test.run:pyrefly_src_all"

[tool.poe.tasks.pyrefly_coverage]
help = "Run pyrefly's type coverage check on 'tests'"
script = "scripts.test.run:pyrefly_coverage"

[tool.poe.tasks.pyright]
help = "Run pyright on 'tests' (using the local stubs) and on the local stubs"
script = "scripts.test.run:pyright_src"
Expand Down
1 change: 1 addition & 0 deletions scripts/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
_SRC_STEPS = [
_step.ty_src,
_step.pyrefly_src,
_step.pyrefly_coverage,
_step.mypy_src,
_step.pyright_src,
_step.pytest,
Expand Down
4 changes: 4 additions & 0 deletions scripts/test/_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
name="Run pyrefly on 'tests' (using the local stubs) and on the local stubs with preset 'all'",
run=run.pyrefly_src_all,
)
pyrefly_coverage = Step(
name="Run pyrefly coverage check on 'tests'",
run=run.pyrefly_coverage,
)
pyright_src = Step(
name="Run pyright on 'tests' (using the local stubs) and on the local stubs",
run=run.pyright_src,
Expand Down
12 changes: 12 additions & 0 deletions scripts/test/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,18 @@ def pyrefly_src_all() -> None:
subprocess.run(cmd, check=True)


def pyrefly_coverage() -> None:
cmd = [
"pyrefly",
"coverage",
"check",
"tests",
"--python-version",
_PYTHON_VERSION,
]
subprocess.run(cmd, check=True)


def type_completeness() -> None:
cmd = ["python", "-m", "scripts.type_completeness"]
subprocess.run(cmd, check=True)
80 changes: 59 additions & 21 deletions tests/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
datetime,
timedelta,
)
from typing import (
Any,
Literal,
)

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -62,15 +66,23 @@
VoidDtypeArg,
)

PYTHON_BOOL_ARGS = dict.fromkeys((bool, "bool"), np.bool_)
PANDAS_BOOL_ARGS = dict.fromkeys((pd.BooleanDtype(), "boolean"), np.bool_)
NUMPY_BOOL_ARGS = dict.fromkeys((np.bool_, "?", "b1", "bool_"), np.bool_)
PYARROW_BOOL_ARGS = dict.fromkeys(("bool[pyarrow]", "boolean[pyarrow]"), bool)
PYTHON_BOOL_ARGS: dict[str | type[bool], type[np.bool_]] = dict.fromkeys(
(bool, "bool"), np.bool_
)
PANDAS_BOOL_ARGS: dict[str | pd.BooleanDtype, type[np.bool_]] = dict.fromkeys(
(pd.BooleanDtype(), "boolean"), np.bool_
)
NUMPY_BOOL_ARGS: dict[str | type[np.bool_], type[np.bool_]] = dict.fromkeys(
(np.bool_, "?", "b1", "bool_"), np.bool_
)
PYARROW_BOOL_ARGS: dict[str, type[bool]] = dict.fromkeys(
("bool[pyarrow]", "boolean[pyarrow]"), bool
)
ASTYPE_BOOL_ARGS = (
PYTHON_BOOL_ARGS | PANDAS_BOOL_ARGS | NUMPY_BOOL_ARGS | PYARROW_BOOL_ARGS
)

PYTHON_INT_ARGS = dict.fromkeys((int, "int"), np.integer)
PYTHON_INT_ARGS: dict[str | type[int], Any] = dict.fromkeys((int, "int"), np.integer)
PANDAS_INT_ARGS = {
**dict.fromkeys((pd.Int8Dtype(), "Int8"), np.int8), # pandas Int8
**dict.fromkeys((pd.Int16Dtype(), "Int16"), np.int16), # pandas Int16
Expand All @@ -97,7 +109,9 @@
# numpy signed pointer (platform dependent one of int[8,16,32,64])
**dict.fromkeys((np.intp, "intp", "p"), np.intp),
}
PYARROW_INT_ARGS = dict.fromkeys([f"int{b}[pyarrow]" for b in (8, 16, 32, 64)], int)
PYARROW_INT_ARGS: dict[str, type[int]] = dict.fromkeys(
[f"int{b}[pyarrow]" for b in (8, 16, 32, 64)], int
)
ASTYPE_INT_ARGS = PYTHON_INT_ARGS | PANDAS_INT_ARGS | NUMPY_INT_ARGS | PYARROW_INT_ARGS

PANDAS_UINT_ARGS = {
Expand Down Expand Up @@ -126,10 +140,14 @@
# numpy unsigned pointer (platform dependent one of uint[8,16,32,64])
**dict.fromkeys((np.uintp, "uintp", "P"), np.uintp),
}
PYARROW_UINT_ARGS = dict.fromkeys([f"uint{b}[pyarrow]" for b in (8, 16, 32, 64)], int)
PYARROW_UINT_ARGS: dict[str, type[int]] = dict.fromkeys(
[f"uint{b}[pyarrow]" for b in (8, 16, 32, 64)], int
)
ASTYPE_UINT_ARGS = PANDAS_UINT_ARGS | NUMPY_UINT_ARGS | PYARROW_UINT_ARGS

PYTHON_FLOAT_ARGS = dict.fromkeys((float, "float"), np.floating)
PYTHON_FLOAT_ARGS: dict[str | type[float], type[np.floating]] = dict.fromkeys(
(float, "float"), np.floating
)
PANDAS_FLOAT_ARGS = {
**dict.fromkeys((pd.Float32Dtype(), "Float32"), np.float32), # pandas Float32
**dict.fromkeys((pd.Float64Dtype(), "Float64"), np.float64), # pandas Float64
Expand Down Expand Up @@ -164,7 +182,9 @@
| PYARROW_FLOAT_ARGS
)

PYTHON_COMPLEX_ARGS = dict.fromkeys((complex, "complex"), np.complexfloating)
PYTHON_COMPLEX_ARGS: dict[str | type[complex], type[np.complexfloating]] = (
dict.fromkeys((complex, "complex"), np.complexfloating)
)
NUMPY_COMPLEX_ARGS: dict[str | type[np.complexfloating], type[np.complexfloating]] = {
# numpy complex64
**dict.fromkeys((np.csingle, "csingle", "F"), np.csingle),
Expand All @@ -191,7 +211,7 @@
**dict.fromkeys([f"<M8[{u}]" for u in NUMPY_UNITS], datetime),
np.dtype("datetime64[ms]"): datetime,
}
PANDAS_TIMESTAMP_ARGS = dict.fromkeys(
PANDAS_TIMESTAMP_ARGS: dict[str, type[datetime]] = dict.fromkeys(
[f"datetime64[{u}, UTC]" for u in NUMPY_UNITS], datetime
)
PANDAS_ASTYPE_TIMESTAMP_ARGS = {
Expand Down Expand Up @@ -231,17 +251,25 @@
**dict.fromkeys([f"<m8[{u}]" for u in PANDAS_UNITS], timedelta),
}
# pyarrow duration
PYARROW_TIMEDELTA_ARGS = dict.fromkeys(
PYARROW_TIMEDELTA_ARGS: dict[str, type[timedelta]] = dict.fromkeys(
[f"duration[{u}][pyarrow]" for u in NUMPY_UNITS], timedelta
)
TYPE_TIMEDELTA_ARGS = NUMPY_TIMEDELTA_ARGS | PYARROW_TIMEDELTA_ARGS
ASTYPE_TIMEDELTA_ARGS = TYPE_TIMEDELTA_ARGS | PANDAS_ASTYPE_TIMEDELTA_ARGS

PYTHON_STRING_ARGS = dict.fromkeys((str, "str"), str)
PANDAS_BASE_STRING_ARGS = dict.fromkeys((pd.StringDtype(), "string"), str)
PANDAS_STRING_ARGS = dict.fromkeys((pd.StringDtype("python"), "string[python]"), str)
NUMPY_STRING_ARGS = dict.fromkeys((np.str_, "str_", "unicode", "U"), str)
PYARROW_STRING_ARGS = dict.fromkeys((pd.StringDtype("pyarrow"), "string[pyarrow]"), str)
PYTHON_STRING_ARGS: dict[str | type[str], type[str]] = dict.fromkeys((str, "str"), str)
PANDAS_BASE_STRING_ARGS: dict[str | pd.StringDtype, type[str]] = dict.fromkeys(
(pd.StringDtype(), "string"), str
)
PANDAS_STRING_ARGS: 'dict[str | pd.StringDtype[Literal["python"]], type[str]]' = (
dict.fromkeys((pd.StringDtype("python"), "string[python]"), str)
)
NUMPY_STRING_ARGS: dict[str | type[np.str_], type[str]] = dict.fromkeys(
(np.str_, "str_", "unicode", "U"), str
)
PYARROW_STRING_ARGS: 'dict[str | pd.StringDtype[Literal["pyarrow"]], type[str]]' = (
dict.fromkeys((pd.StringDtype("pyarrow"), "string[pyarrow]"), str)
)
ASTYPE_STRING_ARGS = (
PYTHON_STRING_ARGS
| PANDAS_BASE_STRING_ARGS
Expand All @@ -251,8 +279,12 @@
| PYARROW_STRING_ARGS
)

PYTHON_BYTES_ARGS = dict.fromkeys((bytes, "bytes"), bytes)
NUMPY_BYTES_ARGS = dict.fromkeys((np.bytes_, "S", "bytes_"), np.bytes_)
PYTHON_BYTES_ARGS: dict[str | type[bytes], type[bytes]] = dict.fromkeys(
(bytes, "bytes"), bytes
)
NUMPY_BYTES_ARGS: dict[str | type[np.bytes_], type[np.bytes_]] = dict.fromkeys(
(np.bytes_, "S", "bytes_"), np.bytes_
)
PYARROW_BYTES_ARGS = {"binary[pyarrow]": bytes}
ASTYPE_BYTES_ARGS = PYTHON_BYTES_ARGS | NUMPY_BYTES_ARGS | PYARROW_BYTES_ARGS

Expand All @@ -263,11 +295,17 @@
# ("dictionary[pyarrow]", "pd.Series[category]", Categorical),
}

PYTHON_OBJECT_ARGS = dict.fromkeys((object, "object"), object)
NUMPY_OBJECT_ARGS = dict.fromkeys((np.object_, "object_", "O"), object)
PYTHON_OBJECT_ARGS: dict[str | type[object], type[object]] = dict.fromkeys(
(object, "object"), object
)
NUMPY_OBJECT_ARGS: dict[str | type[np.object_], type[object]] = dict.fromkeys(
(np.object_, "object_", "O"), object
)
ASTYPE_OBJECT_ARGS = PYTHON_OBJECT_ARGS | NUMPY_OBJECT_ARGS

NUMPY_VOID_ARGS = dict.fromkeys((np.void, "void", "V"), np.void)
NUMPY_VOID_ARGS: dict[str | type[np.void], type[np.void]] = dict.fromkeys(
(np.void, "void", "V"), np.void
)
ASTYPE_VOID_ARGS = NUMPY_VOID_ARGS

PYTHON_NOT_STR_OBJ_DTYPE_ARGS = (
Expand Down
5 changes: 3 additions & 2 deletions tests/extension/decimal/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def na_value(self) -> decimal.Decimal:

def __init__(self, context: decimal.Context | None = None) -> None:
super().__init__()
self.context = context or decimal.getcontext()
self.context: decimal.Context = context or decimal.getcontext()

def __repr__(self) -> str:
return f"DecimalDtype(context={self.context})"
Expand Down Expand Up @@ -122,7 +122,8 @@ def __init__(
self._data = values_np
# Some aliases for common attribute names to ensure pandas supports
# these
self._items = self.data = self._data
self._items = self._data
self.data: np_ndarray = self._data
# those aliases are currently not working due to assumptions
# in internal code (GH-20735)
# self._values = self.values = self.data
Expand Down
4 changes: 3 additions & 1 deletion tests/frame/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -3556,7 +3556,9 @@ def where_cond2(x: pd.DataFrame) -> pd.DataFrame:
return x > 1


where_cond3 = pd.DataFrame({"a": [True, True, False], "b": [False, False, False]})
where_cond3: pd.DataFrame = pd.DataFrame(
{"a": [True, True, False], "b": [False, False, False]}
)


@pytest.mark.parametrize("cond", [where_cond1, where_cond2, where_cond3])
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/bool/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)

# left operand
left = pd.Index([True, True, False])
left: "pd.Index[bool]" = pd.Index([True, True, False])


def test_add_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/bool/test_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
)
from tests._typing import np_ndarray_int64

left = pd.Index([True, True, False]) # left operand
left: "pd.Index[bool]" = pd.Index([True, True, False]) # left operand


def test_sub_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/complex/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)

# left operand
left = pd.Index([1j, 2j, 3j])
left: "pd.Index[complex]" = pd.Index([1j, 2j, 3j])


def test_add_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/complex/test_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tests._typing import np_ndarray_int64

# left operand
left = pd.Index([1j, 2j, 3j])
left: "pd.Index[complex]" = pd.Index([1j, 2j, 3j])


def test_sub_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/float/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)

# left operand
left = pd.Index([1.0, 2.0, 3.0])
left: "pd.Index[float]" = pd.Index([1.0, 2.0, 3.0])


def test_add_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/float/test_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tests._typing import np_ndarray_int64

# left operand
left = pd.Index([1.0, 2.0, 3.0])
left: "pd.Index[float]" = pd.Index([1.0, 2.0, 3.0])


def test_sub_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/int/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)

# left operand
left = pd.Index([1, 2, 3])
left: "pd.Index[int]" = pd.Index([1, 2, 3])


def test_add_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/int/test_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from tests._typing import np_ndarray_int64

# left operand
left = pd.Index([1, 2, 3])
left: "pd.Index[int]" = pd.Index([1, 2, 3])


def test_sub_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/indexes/str/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
np_ndarray_str,
)

left = pd.Index(["1", "23", "456"]) # left operand
left: "pd.Index[str]" = pd.Index(["1", "23", "456"]) # left operand


def test_add_py_scalar() -> None:
Expand Down
6 changes: 4 additions & 2 deletions tests/indexes/test_indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -887,8 +887,10 @@ def test_interval_index_tuples() -> None:
)


dt_l, dt_r = dt.datetime(2025, 12, 14), dt.datetime(2025, 12, 15)
td_l, td_r = dt.timedelta(seconds=1), dt.timedelta(seconds=2)
dt_l: dt.datetime = dt.datetime(2025, 12, 14)
dt_r: dt.datetime = dt.datetime(2025, 12, 15)
td_l: dt.timedelta = dt.timedelta(seconds=1)
td_r: dt.timedelta = dt.timedelta(seconds=2)


@pytest.mark.parametrize(
Expand Down
2 changes: 1 addition & 1 deletion tests/series/bool/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
np_ndarray_int64,
)

left = pd.Series([True, True, False]) # left operand
left: "pd.Series[bool]" = pd.Series([True, True, False]) # left operand


def test_add_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/series/bool/test_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
)
from tests._typing import np_ndarray_int64

left = pd.Series([True, True, False]) # left operand
left: "pd.Series[bool]" = pd.Series([True, True, False]) # left operand


def test_sub_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/series/complex/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
np_ndarray_int64,
)

left = pd.Series([1j, 2j, 3j]) # left operand
left: "pd.Series[complex]" = pd.Series([1j, 2j, 3j]) # left operand


def test_add_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/series/complex/test_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from tests import check
from tests._typing import np_ndarray_int64

left = pd.Series([1j, 2j, 3j]) # left operand
left: "pd.Series[complex]" = pd.Series([1j, 2j, 3j]) # left operand


def test_sub_py_scalar() -> None:
Expand Down
2 changes: 1 addition & 1 deletion tests/series/float/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
np_ndarray_int64,
)

left = pd.Series([1.0, 2.0, 3.0]) # left operand
left: "pd.Series[float]" = pd.Series([1.0, 2.0, 3.0]) # left operand


def test_add_py_scalar() -> None:
Expand Down
Loading
Loading