Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# code stolen from "six" 

2 

3import sys 

4import types 

5from cgi import parse_header 

6 

7# True if we are running on Python 3. 

8PY3 = sys.version_info[0] == 3 

9PY2 = sys.version_info[0] == 2 

10 

11if PY3: 

12 string_types = str, 

13 integer_types = int, 

14 class_types = type, 

15 text_type = str 

16 long = int 

17else: 

18 string_types = basestring, 

19 integer_types = (int, long) 

20 class_types = (type, types.ClassType) 

21 text_type = unicode 

22 long = long 

23 

24# TODO check if errors is ever used 

25 

26def text_(s, encoding='latin-1', errors='strict'): 

27 if isinstance(s, bytes): 

28 return s.decode(encoding, errors) 

29 return s 

30 

31def bytes_(s, encoding='latin-1', errors='strict'): 

32 if isinstance(s, text_type): 

33 return s.encode(encoding, errors) 

34 return s 

35 

36if PY3: 

37 def native_(s, encoding='latin-1', errors='strict'): 

38 if isinstance(s, text_type): 

39 return s 

40 return str(s, encoding, errors) 

41else: 

42 def native_(s, encoding='latin-1', errors='strict'): 

43 if isinstance(s, text_type): 

44 return s.encode(encoding, errors) 

45 return str(s) 

46 

47try: 

48 from queue import Queue, Empty 

49except ImportError: 

50 from Queue import Queue, Empty 

51 

52try: 

53 from collections.abc import MutableMapping 

54 from collections.abc import Iterable 

55except ImportError: 

56 from collections import MutableMapping 

57 from collections import Iterable 

58 

59if PY3: 

60 from urllib import parse 

61 urlparse = parse 

62 from urllib.parse import quote as url_quote 

63 from urllib.parse import urlencode as url_encode, quote_plus 

64 from urllib.request import urlopen as url_open 

65else: 

66 import urlparse 

67 from urllib import quote_plus 

68 from urllib import quote as url_quote 

69 from urllib import unquote as url_unquote 

70 from urllib import urlencode as url_encode 

71 from urllib2 import urlopen as url_open 

72 

73if PY3: # pragma: no cover 

74 def reraise(exc_info): 

75 etype, exc, tb = exc_info 

76 if exc.__traceback__ is not tb: 

77 raise exc.with_traceback(tb) 

78 raise exc 

79else: 

80 exec("def reraise(exc): raise exc[0], exc[1], exc[2]") 

81 

82 

83if PY3: 

84 def iteritems_(d): 

85 return d.items() 

86 def itervalues_(d): 

87 return d.values() 

88else: 

89 def iteritems_(d): 

90 return d.iteritems() 

91 def itervalues_(d): 

92 return d.itervalues() 

93 

94 

95if PY3: # pragma: no cover 

96 def unquote(string): 

97 if not string: 

98 return b'' 

99 res = string.split(b'%') 

100 if len(res) != 1: 

101 string = res[0] 

102 for item in res[1:]: 

103 try: 

104 string += bytes([int(item[:2], 16)]) + item[2:] 

105 except ValueError: 

106 string += b'%' + item 

107 return string 

108 

109 def url_unquote(s): 

110 return unquote(s.encode('ascii')).decode('latin-1') 

111 

112 def parse_qsl_text(qs, encoding='utf-8'): 

113 qs = qs.encode('latin-1') 

114 qs = qs.replace(b'+', b' ') 

115 pairs = [s2 for s1 in qs.split(b'&') for s2 in s1.split(b';') if s2] 

116 for name_value in pairs: 

117 nv = name_value.split(b'=', 1) 

118 if len(nv) != 2: 

119 nv.append('') 

120 name = unquote(nv[0]) 

121 value = unquote(nv[1]) 

122 yield (name.decode(encoding), value.decode(encoding)) 

123 

124else: 

125 from urlparse import parse_qsl 

126 

127 def parse_qsl_text(qs, encoding='utf-8'): 

128 qsl = parse_qsl( 

129 qs, 

130 keep_blank_values=True, 

131 strict_parsing=False 

132 ) 

133 for (x, y) in qsl: 

134 yield (x.decode(encoding), y.decode(encoding)) 

135 

136 

137if PY3: 

138 from html import escape 

139else: 

140 from cgi import escape 

141 

142 

143if PY3: 

144 import cgi 

145 import tempfile 

146 from cgi import FieldStorage as _cgi_FieldStorage 

147 

148 # Various different FieldStorage work-arounds required on Python 3.x 

149 class cgi_FieldStorage(_cgi_FieldStorage): # pragma: no cover 

150 

151 # Work around https://bugs.python.org/issue27777 

152 def make_file(self): 

153 if self._binary_file or self.length >= 0: 

154 return tempfile.TemporaryFile("wb+") 

155 else: 

156 return tempfile.TemporaryFile( 

157 "w+", 

158 encoding=self.encoding, newline='\n' 

159 ) 

160 

161 # Work around http://bugs.python.org/issue23801 

162 # This is taken exactly from Python 3.5's cgi.py module 

163 def read_multi(self, environ, keep_blank_values, strict_parsing): 

164 """Internal: read a part that is itself multipart.""" 

165 ib = self.innerboundary 

166 if not cgi.valid_boundary(ib): 

167 raise ValueError( 

168 'Invalid boundary in multipart form: %r' % (ib,)) 

169 self.list = [] 

170 if self.qs_on_post: 

171 query = cgi.urllib.parse.parse_qsl( 

172 self.qs_on_post, self.keep_blank_values, 

173 self.strict_parsing, 

174 encoding=self.encoding, errors=self.errors) 

175 for key, value in query: 

176 self.list.append(cgi.MiniFieldStorage(key, value)) 

177 

178 klass = self.FieldStorageClass or self.__class__ 

179 first_line = self.fp.readline() # bytes 

180 if not isinstance(first_line, bytes): 

181 raise ValueError("%s should return bytes, got %s" 

182 % (self.fp, type(first_line).__name__)) 

183 self.bytes_read += len(first_line) 

184 

185 # Ensure that we consume the file until we've hit our innerboundary 

186 while (first_line.strip() != (b"--" + self.innerboundary) and 

187 first_line): 

188 first_line = self.fp.readline() 

189 self.bytes_read += len(first_line) 

190 

191 while True: 

192 parser = cgi.FeedParser() 

193 hdr_text = b"" 

194 while True: 

195 data = self.fp.readline() 

196 hdr_text += data 

197 if not data.strip(): 

198 break 

199 if not hdr_text: 

200 break 

201 # parser takes strings, not bytes 

202 self.bytes_read += len(hdr_text) 

203 parser.feed(hdr_text.decode(self.encoding, self.errors)) 

204 headers = parser.close() 

205 # Some clients add Content-Length for part headers, ignore them 

206 if 'content-length' in headers: 

207 filename = None 

208 if 'content-disposition' in self.headers: 

209 cdisp, pdict = parse_header(self.headers['content-disposition']) 

210 if 'filename' in pdict: 

211 filename = pdict['filename'] 

212 if filename is None: 

213 del headers['content-length'] 

214 part = klass(self.fp, headers, ib, environ, keep_blank_values, 

215 strict_parsing, self.limit-self.bytes_read, 

216 self.encoding, self.errors) 

217 self.bytes_read += part.bytes_read 

218 self.list.append(part) 

219 if part.done or self.bytes_read >= self.length > 0: 

220 break 

221 self.skip_lines() 

222else: 

223 from cgi import FieldStorage as cgi_FieldStorage