11"""Helpers for WebOb requests and responses."""
2+ from __future__ import annotations
3+
24from collections .abc import MutableMapping
35from itertools import chain , repeat
46from lazy import lazy
7+ import typing as t
58
69import webob
7- from django .http import HttpResponse
8- from webob .multidict import MultiDict , NestedMultiDict , NoVars
10+ import webob .multidict
11+ import django .core .files .uploadedfile
12+ import django .http
13+ import django .utils .datastructures
914
1015
11- def webob_to_django_response (webob_response ) :
16+ def webob_to_django_response (webob_response : webob . Response ) -> django . http . HttpResponse :
1217 """Returns a django response to the `webob_response`"""
13- django_response = HttpResponse (
18+ django_response = django . http . HttpResponse (
1419 webob_response .app_iter ,
1520 content_type = webob_response .content_type ,
1621 status = webob_response .status_code ,
@@ -28,11 +33,11 @@ class HeaderDict(MutableMapping):
2833 """
2934 UNPREFIXED_HEADERS = ('CONTENT_TYPE' , 'CONTENT_LENGTH' )
3035
31- def __init__ (self , meta ):
36+ def __init__ (self , meta : dict [ str , str ] ):
3237 super ().__init__ ()
3338 self ._meta = meta
3439
35- def _meta_name (self , name ) :
40+ def _meta_name (self , name : str ) -> str :
3641 """
3742 Translate HTTP header names to the format used by Django request objects.
3843
@@ -43,41 +48,43 @@ def _meta_name(self, name):
4348 name = 'HTTP_' + name
4449 return name
4550
46- def _un_meta_name (self , name ) :
51+ def _un_meta_name (self , name : str ) -> str :
4752 """
4853 Reverse of _meta_name
4954 """
5055 if name .startswith ('HTTP_' ):
5156 name = name [5 :]
5257 return name .replace ('_' , '-' ).title ()
5358
54- def __getitem__ (self , name ):
59+ def __getitem__ (self , name : str ):
5560 return self ._meta [self ._meta_name (name )]
5661
57- def __setitem__ (self , name , value ):
62+ def __setitem__ (self , name : str , value : str ):
5863 self ._meta [self ._meta_name (name )] = value
5964
60- def __delitem__ (self , name ):
65+ def __delitem__ (self , name : str ):
6166 del self ._meta [self ._meta_name (name )]
6267
63- def __iter__ (self ):
68+ def __iter__ (self ) -> t . Iterator [ str ] :
6469 for key in self ._meta :
6570 if key in self .UNPREFIXED_HEADERS or key .startswith ('HTTP_' ):
6671 yield self ._un_meta_name (key )
6772
68- def __len__ (self ):
73+ def __len__ (self ) -> int :
6974 return len (list (self ))
7075
7176
72- def querydict_to_multidict (query_dict , wrap = None ):
77+ def querydict_to_multidict (
78+ query_dict : django .utils .datastructures .MultiValueDict ,
79+ wrap : t .Callable [[t .Any ], t .Any ] | None = None
80+ ) -> webob .multidict .MultiDict :
7381 """
7482 Returns a new `webob.MultiDict` from a `django.http.QueryDict`.
7583
7684 If `wrap` is provided, it's used to wrap the values.
77-
7885 """
7986 wrap = wrap or (lambda val : val )
80- return MultiDict (chain .from_iterable (
87+ return webob . multidict . MultiDict (chain .from_iterable (
8188 zip (repeat (key ), (wrap (v ) for v in vals ))
8289 for key , vals in query_dict .lists ()
8390 ))
@@ -87,32 +94,35 @@ class DjangoUploadedFile:
8794 """
8895 Looks like a cgi.FieldStorage, but wraps a Django UploadedFile.
8996 """
90- def __init__ (self , uploaded ):
97+ def __init__ (self , uploaded : django . core . files . uploadedfile . UploadedFile ):
9198 # FieldStorage needs a file attribute.
92- self .file = uploaded
99+ self .file : t . Any = uploaded
93100
94101 @property
95- def name (self ):
102+ def name (self ) -> str :
96103 """The name of the input element used to upload the file."""
97104 return self .file .field_name
98105
99106 @property
100- def filename (self ):
107+ def filename (self ) -> str :
101108 """The name of the uploaded file."""
102109 return self .file .name
103110
104111
105112class DjangoWebobRequest (webob .Request ):
106113 """
107- An implementation of the webob request api, backed
108- by a django request
114+ An implementation of the webob request api, backed by a django request
109115 """
110- def __init__ (self , request ):
116+ # Note:
117+ # This implementation is close enough to webob.Request for it to work OK, but it does
118+ # make mypy complain that the type signatures are different, hence the 'type: ignore' pragmas.
119+
120+ def __init__ (self , request : django .http .HttpRequest ):
111121 self ._request = request
112122 super ().__init__ (self .environ )
113123
114124 @lazy
115- def environ (self ):
125+ def environ (self ) -> dict [ str , str ]: # type: ignore[override]
116126 """
117127 Add path_info to the request's META dictionary.
118128 """
@@ -123,40 +133,40 @@ def environ(self):
123133 return environ
124134
125135 @property
126- def GET (self ):
136+ def GET (self ) -> webob . multidict . MultiDict : # type: ignore[override]
127137 """
128138 Returns a new `webob.MultiDict` from the request's GET query.
129139 """
130140 return querydict_to_multidict (self ._request .GET )
131141
132142 @property
133- def POST (self ):
143+ def POST (self ) -> webob . multidict . MultiDict | webob . multidict . NoVars : # type: ignore[override]
134144 if self .method not in ('POST' , 'PUT' , 'PATCH' ):
135- return NoVars ('Not a form request' )
145+ return webob . multidict . NoVars ('Not a form request' )
136146
137147 # Webob puts uploaded files into the POST dictionary, so here we
138148 # combine the Django POST data and uploaded FILES data into a single
139149 # dict.
140- return NestedMultiDict (
150+ return webob . multidict . NestedMultiDict (
141151 querydict_to_multidict (self ._request .POST ),
142152 querydict_to_multidict (self ._request .FILES , wrap = DjangoUploadedFile ),
143153 )
144154
145155 @property
146- def body (self ):
156+ def body (self ) -> bytes : # type: ignore[override]
147157 """
148158 Return the content of the request body.
149159 """
150160 return self ._request .body
151161
152- @property
153- def body_file (self ):
162+ @property # type: ignore[misc]
163+ def body_file (self ) -> django . http . HttpRequest : # type: ignore[override]
154164 """
155165 Input stream of the request
156166 """
157167 return self ._request
158168
159169
160- def django_to_webob_request (django_request ) :
170+ def django_to_webob_request (django_request : django . http . HttpRequest ) -> webob . Request :
161171 """Returns a WebOb request to the `django_request`"""
162172 return DjangoWebobRequest (django_request )
0 commit comments