11import json
2- from _typeshed .wsgi import WSGIApplication
3- from collections .abc import Mapping , Sequence
2+ from _typeshed import SupportsItems , SupportsKeysAndGetItem
3+ from _typeshed .wsgi import WSGIApplication , WSGIEnvironment
4+ from collections .abc import Iterable , Sequence
45from http .cookiejar import CookieJar , DefaultCookiePolicy
56from typing import Any , Generic , Literal , TypeVar
67from typing_extensions import TypeAlias
78
89from webob .request import BaseRequest
10+ from webtest .forms import File , Upload
911from webtest .response import TestResponse
1012
13+ # NOTE: While it is possible to pass different kinds of values depending on
14+ # the exact configuration of the request, it seems more robust to
15+ # restrict them to the types that are supported by all code paths.
16+ # I don't expect anyone to try to pass different kinds of values
17+ # in a non-JSON request.
18+ _ParamValue : TypeAlias = File | Upload | int | bytes | str
19+ _Params : TypeAlias = SupportsItems [str | bytes , _ParamValue ] | Sequence [tuple [str | bytes , _ParamValue ]]
20+ # NOTE: Using `Collection` rather than `Iterable` would probably be slightly
21+ # safer since WebTest will check this parameter for truthyness. But since
22+ # objects are truthy by default, this should only lead to issues in truly
23+ # exotic cases.
24+ _ExtraEnviron : TypeAlias = SupportsKeysAndGetItem [str , Any ] | Iterable [tuple [str , Any ]]
1125_Files : TypeAlias = Sequence [tuple [str , str ] | tuple [str , str , bytes ]]
1226_AppT = TypeVar ("_AppT" , bound = WSGIApplication , default = WSGIApplication )
1327
@@ -27,15 +41,19 @@ class TestApp(Generic[_AppT]):
2741 app : _AppT
2842 lint : bool
2943 relative_to : str | None
30- extra_environ : dict [ str , Any ]
44+ extra_environ : WSGIEnvironment
3145 use_unicode : bool
3246 cookiejar : CookieJar
3347 JSONEncoder : json .JSONEncoder
3448 __test__ : Literal [False ]
3549 def __init__ (
3650 self ,
3751 app : _AppT ,
38- extra_environ : dict [str , Any ] | None = None ,
52+ # NOTE: this extra_environ is different from the others and needs to
53+ # support __delitem__, it seems easiest to just treat this like
54+ # a regular WSGIEnvironment. The docs also say that this should
55+ # be a dictionary.
56+ extra_environ : WSGIEnvironment | None = None ,
3957 relative_to : str | None = None ,
4058 use_unicode : bool = True ,
4159 cookiejar : CookieJar | None = None ,
@@ -57,19 +75,19 @@ class TestApp(Generic[_AppT]):
5775 def get (
5876 self ,
5977 url : str ,
60- params : Mapping [ str , str ] | str | None = None ,
61- headers : Mapping [str , str ] | None = None ,
62- extra_environ : Mapping [ str , Any ] | None = None ,
78+ params : _Params | str | None = None ,
79+ headers : dict [str , str ] | None = None ,
80+ extra_environ : _ExtraEnviron | None = None ,
6381 status : int | str | None = None ,
6482 expect_errors : bool = False ,
6583 xhr : bool = False ,
6684 ) -> TestResponse : ...
6785 def post (
6886 self ,
6987 url : str ,
70- params : Mapping [ str , str ] | str = "" ,
71- headers : Mapping [str , str ] | None = None ,
72- extra_environ : Mapping [ str , Any ] | None = None ,
88+ params : _Params | str = "" ,
89+ headers : dict [str , str ] | None = None ,
90+ extra_environ : _ExtraEnviron | None = None ,
7391 status : int | str | None = None ,
7492 upload_files : _Files | None = None ,
7593 expect_errors : bool = False ,
@@ -79,9 +97,9 @@ class TestApp(Generic[_AppT]):
7997 def put (
8098 self ,
8199 url : str ,
82- params : Mapping [ str , str ] | str = "" ,
83- headers : Mapping [str , str ] | None = None ,
84- extra_environ : Mapping [ str , Any ] | None = None ,
100+ params : _Params | str = "" ,
101+ headers : dict [str , str ] | None = None ,
102+ extra_environ : _ExtraEnviron | None = None ,
85103 status : int | str | None = None ,
86104 upload_files : _Files | None = None ,
87105 expect_errors : bool = False ,
@@ -91,9 +109,9 @@ class TestApp(Generic[_AppT]):
91109 def patch (
92110 self ,
93111 url : str ,
94- params : Mapping [ str , str ] | str = "" ,
95- headers : Mapping [str , str ] | None = None ,
96- extra_environ : Mapping [ str , Any ] | None = None ,
112+ params : _Params | str = "" ,
113+ headers : dict [str , str ] | None = None ,
114+ extra_environ : _ExtraEnviron | None = None ,
97115 status : int | str | None = None ,
98116 upload_files : _Files | None = None ,
99117 expect_errors : bool = False ,
@@ -103,9 +121,9 @@ class TestApp(Generic[_AppT]):
103121 def delete (
104122 self ,
105123 url : str ,
106- params : Mapping [ str , str ] | str = "" ,
107- headers : Mapping [str , str ] | None = None ,
108- extra_environ : Mapping [ str , Any ] | None = None ,
124+ params : _Params | str = "" ,
125+ headers : dict [str , str ] | None = None ,
126+ extra_environ : _ExtraEnviron | None = None ,
109127 status : int | str | None = None ,
110128 expect_errors : bool = False ,
111129 content_type : str | None = None ,
@@ -114,18 +132,18 @@ class TestApp(Generic[_AppT]):
114132 def options (
115133 self ,
116134 url : str ,
117- headers : Mapping [str , str ] | None = None ,
118- extra_environ : Mapping [ str , Any ] | None = None ,
135+ headers : dict [str , str ] | None = None ,
136+ extra_environ : _ExtraEnviron | None = None ,
119137 status : int | str | None = None ,
120138 expect_errors : bool = False ,
121139 xhr : bool = False ,
122140 ) -> TestResponse : ...
123141 def head (
124142 self ,
125143 url : str ,
126- params : Mapping [ str , str ] | str | None = None ,
127- headers : Mapping [str , str ] | None = None ,
128- extra_environ : Mapping [ str , Any ] | None = None ,
144+ params : _Params | str | None = None ,
145+ headers : dict [str , str ] | None = None ,
146+ extra_environ : _ExtraEnviron | None = None ,
129147 status : int | str | None = None ,
130148 expect_errors : bool = False ,
131149 xhr : bool = False ,
@@ -135,8 +153,8 @@ class TestApp(Generic[_AppT]):
135153 url : str ,
136154 params : Any = ...,
137155 * ,
138- headers : Mapping [str , str ] | None = None ,
139- extra_environ : Mapping [ str , Any ] | None = None ,
156+ headers : dict [str , str ] | None = None ,
157+ extra_environ : _ExtraEnviron | None = None ,
140158 status : int | str | None = None ,
141159 expect_errors : bool = False ,
142160 content_type : str | None = None ,
@@ -147,8 +165,8 @@ class TestApp(Generic[_AppT]):
147165 url : str ,
148166 params : Any = ...,
149167 * ,
150- headers : Mapping [str , str ] | None = None ,
151- extra_environ : Mapping [ str , Any ] | None = None ,
168+ headers : dict [str , str ] | None = None ,
169+ extra_environ : _ExtraEnviron | None = None ,
152170 status : int | str | None = None ,
153171 expect_errors : bool = False ,
154172 content_type : str | None = None ,
@@ -159,8 +177,8 @@ class TestApp(Generic[_AppT]):
159177 url : str ,
160178 params : Any = ...,
161179 * ,
162- headers : Mapping [str , str ] | None = None ,
163- extra_environ : Mapping [ str , Any ] | None = None ,
180+ headers : dict [str , str ] | None = None ,
181+ extra_environ : _ExtraEnviron | None = None ,
164182 status : int | str | None = None ,
165183 expect_errors : bool = False ,
166184 content_type : str | None = None ,
@@ -171,14 +189,14 @@ class TestApp(Generic[_AppT]):
171189 url : str ,
172190 params : Any = ...,
173191 * ,
174- headers : Mapping [str , str ] | None = None ,
175- extra_environ : Mapping [ str , Any ] | None = None ,
192+ headers : dict [str , str ] | None = None ,
193+ extra_environ : _ExtraEnviron | None = None ,
176194 status : int | str | None = None ,
177195 expect_errors : bool = False ,
178196 content_type : str | None = None ,
179197 xhr : bool = False ,
180198 ) -> TestResponse : ...
181- def encode_multipart (self , params : Sequence [tuple [str , str ]], files : _Files ) -> tuple [str , bytes ]: ...
199+ def encode_multipart (self , params : Iterable [tuple [str | bytes , _ParamValue ]], files : _Files ) -> tuple [str , bytes ]: ...
182200 def request (
183201 self , url_or_req : str | TestRequest , status : int | str | None = None , expect_errors : bool = False , ** req_params : Any
184202 ) -> TestResponse : ...
0 commit comments