Skip to content

Commit 77928e8

Browse files
committed
add more e2e type check tests
1 parent d82aa44 commit 77928e8

File tree

8 files changed

+111
-24
lines changed

8 files changed

+111
-24
lines changed

e2e_projects/type_checking/pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,21 @@ build-backend = "uv_build"
1414
[dependency-groups]
1515
dev = [
1616
"pyrefly>=0.52.0",
17+
"pyright>=1.1.408",
1718
"pytest>=8.2.0",
1819
]
1920

2021
[tool.mutmut]
2122
debug = true
2223
# TODO: pyrefly ignores mutants/ dir if it is in .gitignore
23-
type_check_command = ["pyrefly", "check", "--output-format=json", "--use-ignore-files=false"]
24+
# type_check_command = ["pyrefly", "check", "--output-format=json", "--use-ignore-files=false"]
25+
type_check_command = ["pyright", "--outputjson"]
2426

2527
[tool.pyrefly]
2628
project-includes = [
2729
"**/*.py*",
2830
"**/*.ipynb",
2931
]
32+
33+
[tool.pyright]
34+
typeCheckingMode = "strict"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
11
def hello() -> str:
22
greeting: str = "Hello from type-checking!"
33
return greeting
4+
5+
def a_hello_wrapper() -> str:
6+
# verify that hello() keeps the return type str
7+
# (if not, this will type error and not be mutated)
8+
return hello() + "2"
9+
10+
class Person:
11+
def set_name(self, name: str):
12+
self.name = name
13+
14+
def get_name(self):
15+
# return type should be inferred as "str"
16+
return self.name
17+
18+
def mutate_me():
19+
p = Person()
20+
p.set_name('charlie')
21+
# Verify that p.get_name keeps the return type str
22+
name: str = p.get_name()
23+
return name
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
from type_checking import hello
1+
from type_checking import *
22

33
def test_hello():
4-
assert hello() == "Hello from type-checking!"
4+
assert hello() == "Hello from type-checking!"
5+
6+
def test_a_hello_wrapper():
7+
assert isinstance(a_hello_wrapper(), str)
8+
9+
def test_mutate_me():
10+
assert mutate_me() == "charlie"

e2e_projects/type_checking/uv.lock

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ source-include = ["HISTORY.rst"]
5555
dev = [
5656
"inline-snapshot>=0.32.0",
5757
"pyrefly>=0.52.0",
58+
"pyright>=1.1.408",
5859
"pytest-asyncio>=1.0.0",
5960
"ruff>=0.15.1",
6061
]

src/mutmut/trampoline_templates.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,32 @@ def mangle_function_name(*, name, class_name):
2525
from typing import Callable
2626
from typing import ClassVar
2727
28-
MutantDict = Annotated[dict[str, Callable], "Mutant"]
28+
MutantDict = Annotated[dict[str, Callable], "Mutant"] # type: ignore
2929
3030
31-
def _mutmut_trampoline(orig, mutants, call_args, call_kwargs, self_arg = None):
31+
def _mutmut_trampoline(orig, mutants, call_args, call_kwargs, self_arg = None): # type: ignore
3232
\"""Forward call to original or mutated function, depending on the environment\"""
33-
import os
34-
mutant_under_test = os.environ['MUTANT_UNDER_TEST']
35-
if mutant_under_test == 'fail':
36-
from mutmut.__main__ import MutmutProgrammaticFailException
37-
raise MutmutProgrammaticFailException('Failed programmatically')
38-
elif mutant_under_test == 'stats':
39-
from mutmut.__main__ import record_trampoline_hit
40-
record_trampoline_hit(orig.__module__ + '.' + orig.__name__)
33+
import os # type: ignore
34+
mutant_under_test = os.environ['MUTANT_UNDER_TEST'] # type: ignore
35+
if mutant_under_test == 'fail': # type: ignore
36+
from mutmut.__main__ import MutmutProgrammaticFailException # type: ignore
37+
raise MutmutProgrammaticFailException('Failed programmatically') # type: ignore
38+
elif mutant_under_test == 'stats': # type: ignore
39+
from mutmut.__main__ import record_trampoline_hit # type: ignore
40+
record_trampoline_hit(orig.__module__ + '.' + orig.__name__) # type: ignore
4141
# (for class methods, orig is bound and thus does not need the explicit self argument)
42-
result = orig(*call_args, **call_kwargs)
43-
return result
44-
prefix = orig.__module__ + '.' + orig.__name__ + '__mutmut_'
45-
if not mutant_under_test.startswith(prefix):
46-
result = orig(*call_args, **call_kwargs)
47-
return result
48-
mutant_name = mutant_under_test.rpartition('.')[-1]
49-
if self_arg is not None:
42+
result = orig(*call_args, **call_kwargs) # type: ignore
43+
return result # type: ignore
44+
prefix = orig.__module__ + '.' + orig.__name__ + '__mutmut_' # type: ignore
45+
if not mutant_under_test.startswith(prefix): # type: ignore
46+
result = orig(*call_args, **call_kwargs) # type: ignore
47+
return result # type: ignore
48+
mutant_name = mutant_under_test.rpartition('.')[-1] # type: ignore
49+
if self_arg is not None: # type: ignore
5050
# call to a class method where self is not bound
51-
result = mutants[mutant_name](self_arg, *call_args, **call_kwargs)
51+
result = mutants[mutant_name](self_arg, *call_args, **call_kwargs) # type: ignore
5252
else:
53-
result = mutants[mutant_name](*call_args, **call_kwargs)
54-
return result
53+
result = mutants[mutant_name](*call_args, **call_kwargs) # type: ignore
54+
return result # type: ignore
5555
5656
"""

tests/e2e/test_e2e_type_checking.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ def test_type_checking_result_snapshot():
1111
"type_checking.x_hello__mutmut_2": 1,
1212
"type_checking.x_hello__mutmut_3": 1,
1313
"type_checking.x_hello__mutmut_4": 1,
14+
"type_checking.x_a_hello_wrapper__mutmut_1": 6,
15+
"type_checking.x_a_hello_wrapper__mutmut_2": 0,
16+
"type_checking.x_mutate_me__mutmut_1": 6,
17+
"type_checking.x_mutate_me__mutmut_2": 6,
18+
"type_checking.x_mutate_me__mutmut_3": 1,
19+
"type_checking.x_mutate_me__mutmut_4": 1,
20+
"type_checking.x_mutate_me__mutmut_5": 6,
1421
}
1522
}
1623
)

uv.lock

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)