1515from typing import Dict
1616from typing import Iterable
1717from typing import List
18+ from typing import Mapping
1819from typing import Optional
1920from typing import Set
2021from typing import Tuple
4445from _pytest .compat import STRING_TYPES
4546from _pytest .config import Config
4647from _pytest .config import ExitCode
48+ from _pytest .compat import TYPE_CHECKING
4749from _pytest .config import hookimpl
4850from _pytest .config .argparsing import Parser
4951from _pytest .deprecated import FUNCARGNAMES
5355from _pytest .mark import ParameterSet
5456from _pytest .mark .structures import get_unpacked_marks
5557from _pytest .mark .structures import Mark
58+ from _pytest .mark .structures import MarkDecorator
5659from _pytest .mark .structures import normalize_mark_list
5760from _pytest .outcomes import fail
5861from _pytest .outcomes import skip
5962from _pytest .pathlib import parts
6063from _pytest .warning_types import PytestCollectionWarning
6164from _pytest .warning_types import PytestUnhandledCoroutineWarning
6265
66+ if TYPE_CHECKING :
67+ from typing_extensions import Literal
68+
6369
6470def pyobj_property (name ):
6571 def get (self ):
@@ -798,16 +804,17 @@ def hasnew(obj):
798804
799805
800806class 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