9
9
from enum import IntEnum
10
10
from io import BytesIO
11
11
from numbers import Number
12
- from typing import Dict , Tuple , Union
12
+ from typing import TYPE_CHECKING
13
13
14
14
from .decoders import Base64Decoder , QuotedPrintableDecoder
15
15
from .exceptions import FileError , FormParserError , MultipartParseError , QuerystringParseError
16
16
17
+ if TYPE_CHECKING : # pragma: no cover
18
+ from typing import Callable , TypedDict
19
+
20
+ class QuerystringCallbacks (TypedDict , total = False ):
21
+ on_field_start : Callable [[], None ]
22
+ on_field_name : Callable [[bytes , int , int ], None ]
23
+ on_field_data : Callable [[bytes , int , int ], None ]
24
+ on_field_end : Callable [[], None ]
25
+ on_end : Callable [[], None ]
26
+
27
+ class OctetStreamCallbacks (TypedDict , total = False ):
28
+ on_start : Callable [[], None ]
29
+ on_data : Callable [[bytes , int , int ], None ]
30
+ on_end : Callable [[], None ]
31
+
32
+ class MultipartCallbacks (TypedDict , total = False ):
33
+ on_part_begin : Callable [[], None ]
34
+ on_part_data : Callable [[bytes , int , int ], None ]
35
+ on_part_end : Callable [[], None ]
36
+ on_headers_begin : Callable [[], None ]
37
+ on_header_field : Callable [[bytes , int , int ], None ]
38
+ on_header_value : Callable [[bytes , int , int ], None ]
39
+ on_header_end : Callable [[], None ]
40
+ on_headers_finished : Callable [[], None ]
41
+ on_end : Callable [[], None ]
42
+
43
+
17
44
# Unique missing object.
18
45
_missing = object ()
19
46
@@ -86,7 +113,7 @@ def join_bytes(b):
86
113
return bytes (list (b ))
87
114
88
115
89
- def parse_options_header (value : Union [ str , bytes ] ) -> Tuple [bytes , Dict [bytes , bytes ]]:
116
+ def parse_options_header (value : str | bytes ) -> tuple [bytes , dict [bytes , bytes ]]:
90
117
"""
91
118
Parses a Content-Type header into a value in the following format:
92
119
(content_type, {parameters})
@@ -148,15 +175,15 @@ class Field:
148
175
:param name: the name of the form field
149
176
"""
150
177
151
- def __init__ (self , name ):
178
+ def __init__ (self , name : str ):
152
179
self ._name = name
153
- self ._value = []
180
+ self ._value : list [ bytes ] = []
154
181
155
182
# We cache the joined version of _value for speed.
156
183
self ._cache = _missing
157
184
158
185
@classmethod
159
- def from_value (klass , name , value ) :
186
+ def from_value (cls , name : str , value : bytes | None ) -> Field :
160
187
"""Create an instance of a :class:`Field`, and set the corresponding
161
188
value - either None or an actual value. This method will also
162
189
finalize the Field itself.
@@ -166,22 +193,22 @@ def from_value(klass, name, value):
166
193
None
167
194
"""
168
195
169
- f = klass (name )
196
+ f = cls (name )
170
197
if value is None :
171
198
f .set_none ()
172
199
else :
173
200
f .write (value )
174
201
f .finalize ()
175
202
return f
176
203
177
- def write (self , data ) :
204
+ def write (self , data : bytes ) -> int :
178
205
"""Write some data into the form field.
179
206
180
207
:param data: a bytestring
181
208
"""
182
209
return self .on_data (data )
183
210
184
- def on_data (self , data ) :
211
+ def on_data (self , data : bytes ) -> int :
185
212
"""This method is a callback that will be called whenever data is
186
213
written to the Field.
187
214
@@ -191,24 +218,24 @@ def on_data(self, data):
191
218
self ._cache = _missing
192
219
return len (data )
193
220
194
- def on_end (self ):
221
+ def on_end (self ) -> None :
195
222
"""This method is called whenever the Field is finalized."""
196
223
if self ._cache is _missing :
197
224
self ._cache = b"" .join (self ._value )
198
225
199
- def finalize (self ):
226
+ def finalize (self ) -> None :
200
227
"""Finalize the form field."""
201
228
self .on_end ()
202
229
203
- def close (self ):
230
+ def close (self ) -> None :
204
231
"""Close the Field object. This will free any underlying cache."""
205
232
# Free our value array.
206
233
if self ._cache is _missing :
207
234
self ._cache = b"" .join (self ._value )
208
235
209
236
del self ._value
210
237
211
- def set_none (self ):
238
+ def set_none (self ) -> None :
212
239
"""Some fields in a querystring can possibly have a value of None - for
213
240
example, the string "foo&bar=&baz=asdf" will have a field with the
214
241
name "foo" and value None, one with name "bar" and value "", and one
@@ -218,7 +245,7 @@ def set_none(self):
218
245
self ._cache = None
219
246
220
247
@property
221
- def field_name (self ):
248
+ def field_name (self ) -> str :
222
249
"""This property returns the name of the field."""
223
250
return self ._name
224
251
@@ -230,13 +257,13 @@ def value(self):
230
257
231
258
return self ._cache
232
259
233
- def __eq__ (self , other ) :
260
+ def __eq__ (self , other : object ) -> bool :
234
261
if isinstance (other , Field ):
235
262
return self .field_name == other .field_name and self .value == other .value
236
263
else :
237
264
return NotImplemented
238
265
239
- def __repr__ (self ):
266
+ def __repr__ (self ) -> str :
240
267
if len (self .value ) > 97 :
241
268
# We get the repr, and then insert three dots before the final
242
269
# quote.
@@ -553,7 +580,7 @@ class BaseParser:
553
580
def __init__ (self ):
554
581
self .logger = logging .getLogger (__name__ )
555
582
556
- def callback (self , name , data = None , start = None , end = None ):
583
+ def callback (self , name : str , data = None , start = None , end = None ):
557
584
"""This function calls a provided callback with some data. If the
558
585
callback is not set, will do nothing.
559
586
@@ -584,7 +611,7 @@ def callback(self, name, data=None, start=None, end=None):
584
611
self .logger .debug ("Calling %s with no data" , name )
585
612
func ()
586
613
587
- def set_callback (self , name , new_func ):
614
+ def set_callback (self , name : str , new_func ):
588
615
"""Update the function for a callback. Removes from the callbacks dict
589
616
if new_func is None.
590
617
@@ -637,7 +664,7 @@ class OctetStreamParser(BaseParser):
637
664
i.e. unbounded.
638
665
"""
639
666
640
- def __init__ (self , callbacks = {}, max_size = float ("inf" )):
667
+ def __init__ (self , callbacks : OctetStreamCallbacks = {}, max_size = float ("inf" )):
641
668
super ().__init__ ()
642
669
self .callbacks = callbacks
643
670
self ._started = False
@@ -647,7 +674,7 @@ def __init__(self, callbacks={}, max_size=float("inf")):
647
674
self .max_size = max_size
648
675
self ._current_size = 0
649
676
650
- def write (self , data ):
677
+ def write (self , data : bytes ):
651
678
"""Write some data to the parser, which will perform size verification,
652
679
and then pass the data to the underlying callback.
653
680
@@ -732,7 +759,9 @@ class QuerystringParser(BaseParser):
732
759
i.e. unbounded.
733
760
"""
734
761
735
- def __init__ (self , callbacks = {}, strict_parsing = False , max_size = float ("inf" )):
762
+ state : QuerystringState
763
+
764
+ def __init__ (self , callbacks : QuerystringCallbacks = {}, strict_parsing = False , max_size = float ("inf" )):
736
765
super ().__init__ ()
737
766
self .state = QuerystringState .BEFORE_FIELD
738
767
self ._found_sep = False
@@ -748,7 +777,7 @@ def __init__(self, callbacks={}, strict_parsing=False, max_size=float("inf")):
748
777
# Should parsing be strict?
749
778
self .strict_parsing = strict_parsing
750
779
751
- def write (self , data ):
780
+ def write (self , data : bytes ):
752
781
"""Write some data to the parser, which will perform size verification,
753
782
parse into either a field name or value, and then pass the
754
783
corresponding data to the underlying callback. If an error is
@@ -780,7 +809,7 @@ def write(self, data):
780
809
781
810
return l
782
811
783
- def _internal_write (self , data , length ):
812
+ def _internal_write (self , data : bytes , length : int ):
784
813
state = self .state
785
814
strict_parsing = self .strict_parsing
786
815
found_sep = self ._found_sep
@@ -989,7 +1018,7 @@ class MultipartParser(BaseParser):
989
1018
i.e. unbounded.
990
1019
"""
991
1020
992
- def __init__ (self , boundary , callbacks = {}, max_size = float ("inf" )):
1021
+ def __init__ (self , boundary , callbacks : MultipartCallbacks = {}, max_size = float ("inf" )):
993
1022
# Initialize parser state.
994
1023
super ().__init__ ()
995
1024
self .state = MultipartState .START
0 commit comments