Skip to content

Commit 3fd1ea0

Browse files
committed
Type annotate CallSpec2
1 parent e67b3d1 commit 3fd1ea0

File tree

1 file changed

+39
-16
lines changed

1 file changed

+39
-16
lines changed

src/_pytest/python.py

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from typing import Dict
1616
from typing import Iterable
1717
from typing import List
18+
from typing import Mapping
1819
from typing import Optional
1920
from typing import Set
2021
from typing import Tuple
@@ -44,6 +45,7 @@
4445
from _pytest.compat import STRING_TYPES
4546
from _pytest.config import Config
4647
from _pytest.config import ExitCode
48+
from _pytest.compat import TYPE_CHECKING
4749
from _pytest.config import hookimpl
4850
from _pytest.config.argparsing import Parser
4951
from _pytest.deprecated import FUNCARGNAMES
@@ -53,13 +55,17 @@
5355
from _pytest.mark import ParameterSet
5456
from _pytest.mark.structures import get_unpacked_marks
5557
from _pytest.mark.structures import Mark
58+
from _pytest.mark.structures import MarkDecorator
5659
from _pytest.mark.structures import normalize_mark_list
5760
from _pytest.outcomes import fail
5861
from _pytest.outcomes import skip
5962
from _pytest.pathlib import parts
6063
from _pytest.warning_types import PytestCollectionWarning
6164
from _pytest.warning_types import PytestUnhandledCoroutineWarning
6265

66+
if TYPE_CHECKING:
67+
from typing_extensions import Literal
68+
6369

6470
def pyobj_property(name):
6571
def get(self):
@@ -798,16 +804,17 @@ def hasnew(obj):
798804

799805

800806
class CallSpec2:
801-
def __init__(self, metafunc):
807+
def __init__(self, metafunc: "Metafunc") -> None:
802808
self.metafunc = metafunc
803-
self.funcargs = {}
804-
self._idlist = []
805-
self.params = {}
806-
self._arg2scopenum = {} # used for sorting parametrized resources
807-
self.marks = []
808-
self.indices = {}
809-
810-
def copy(self):
809+
self.funcargs = {} # type: Dict[str, object]
810+
self._idlist = [] # type: List[str]
811+
self.params = {} # type: Dict[str, object]
812+
# Used for sorting parametrized resources.
813+
self._arg2scopenum = {} # type: Dict[str, int]
814+
self.marks = [] # type: List[Mark]
815+
self.indices = {} # type: Dict[str, int]
816+
817+
def copy(self) -> "CallSpec2":
811818
cs = CallSpec2(self.metafunc)
812819
cs.funcargs.update(self.funcargs)
813820
cs.params.update(self.params)
@@ -817,25 +824,39 @@ def copy(self):
817824
cs._idlist = list(self._idlist)
818825
return cs
819826

820-
def _checkargnotcontained(self, arg):
827+
def _checkargnotcontained(self, arg: str) -> None:
821828
if arg in self.params or arg in self.funcargs:
822829
raise ValueError("duplicate {!r}".format(arg))
823830

824-
def getparam(self, name):
831+
def getparam(self, name: str) -> object:
825832
try:
826833
return self.params[name]
827834
except KeyError:
828835
raise ValueError(name)
829836

830837
@property
831-
def id(self):
838+
def id(self) -> str:
832839
return "-".join(map(str, self._idlist))
833840

834-
def setmulti2(self, valtypes, argnames, valset, id, marks, scopenum, param_index):
841+
def setmulti2(
842+
self,
843+
valtypes: "Mapping[str, Literal['params', 'funcargs']]",
844+
argnames: typing.Sequence[str],
845+
valset: Iterable[object],
846+
id: str,
847+
marks: Iterable[Union[Mark, MarkDecorator]],
848+
scopenum: int,
849+
param_index: int,
850+
) -> None:
835851
for arg, val in zip(argnames, valset):
836852
self._checkargnotcontained(arg)
837853
valtype_for_arg = valtypes[arg]
838-
getattr(self, valtype_for_arg)[arg] = val
854+
if valtype_for_arg == "params":
855+
self.params[arg] = val
856+
elif valtype_for_arg == "funcargs":
857+
self.funcargs[arg] = val
858+
else: # pragma: no cover
859+
assert False, "Unhandled valtype for arg: {}".format(valtype_for_arg)
839860
self.indices[arg] = param_index
840861
self._arg2scopenum[arg] = scopenum
841862
self._idlist.append(id)
@@ -1077,7 +1098,7 @@ def _resolve_arg_value_types(
10771098
self,
10781099
argnames: typing.Sequence[str],
10791100
indirect: Union[bool, typing.Sequence[str]],
1080-
) -> Dict[str, str]:
1101+
) -> Dict[str, "Literal['params', 'funcargs']"]:
10811102
"""Resolves if each parametrized argument must be considered a parameter to a fixture or a "funcarg"
10821103
to the function, based on the ``indirect`` parameter of the parametrized() call.
10831104
@@ -1089,7 +1110,9 @@ def _resolve_arg_value_types(
10891110
* "funcargs" if the argname should be a parameter to the parametrized test function.
10901111
"""
10911112
if isinstance(indirect, bool):
1092-
valtypes = dict.fromkeys(argnames, "params" if indirect else "funcargs")
1113+
valtypes = dict.fromkeys(
1114+
argnames, "params" if indirect else "funcargs"
1115+
) # type: Dict[str, Literal["params", "funcargs"]]
10931116
elif isinstance(indirect, Sequence):
10941117
valtypes = dict.fromkeys(argnames, "funcargs")
10951118
for arg in indirect:

0 commit comments

Comments
 (0)