Permalink
Browse files

Let's not rest on hopes, cgi.FieldStorage needs patching on Py3

  • Loading branch information...
1 parent 0d77204 commit 1ac5148d680a020f3a05138ef0c1a5f529c49ed5 @bertjwregeer bertjwregeer committed Dec 22, 2016
Showing with 69 additions and 76 deletions.
  1. +69 −76 webob/compat.py
View
@@ -139,85 +139,78 @@ def parse_qsl_text(qs, encoding='utf-8'):
from cgi import FieldStorage as _cgi_FieldStorage
# Various different FieldStorage work-arounds required on Python 3.x
-
- if sys.version_info[:3] < (3, 7, 0): # pragma no cover
- # Assume that this will be fixed in Python 3.7
-
- class cgi_FieldStorage(_cgi_FieldStorage):
-
- # Work around https://bugs.python.org/issue27777
- def make_file(self):
- if self._binary_file or self.length >= 0:
- return tempfile.TemporaryFile("wb+")
- else:
- return tempfile.TemporaryFile(
- "w+",
- encoding=self.encoding, newline='\n'
- )
-
- # Work around http://bugs.python.org/issue23801
- # This is taken exactly from Python 3.5's cgi.py module
- def read_multi(self, environ, keep_blank_values, strict_parsing):
- """Internal: read a part that is itself multipart."""
- ib = self.innerboundary
- if not cgi.valid_boundary(ib):
- raise ValueError(
- 'Invalid boundary in multipart form: %r' % (ib,))
- self.list = []
- if self.qs_on_post:
- query = cgi.urllib.parse.parse_qsl(
- self.qs_on_post, self.keep_blank_values,
- self.strict_parsing,
- encoding=self.encoding, errors=self.errors)
- for key, value in query:
- self.list.append(cgi.MiniFieldStorage(key, value))
-
- klass = self.FieldStorageClass or self.__class__
- first_line = self.fp.readline() # bytes
- if not isinstance(first_line, bytes):
- raise ValueError("%s should return bytes, got %s"
- % (self.fp, type(first_line).__name__))
+ class cgi_FieldStorage(_cgi_FieldStorage): # pragma: no cover
+
+ # Work around https://bugs.python.org/issue27777
+ def make_file(self):
+ if self._binary_file or self.length >= 0:
+ return tempfile.TemporaryFile("wb+")
+ else:
+ return tempfile.TemporaryFile(
+ "w+",
+ encoding=self.encoding, newline='\n'
+ )
+
+ # Work around http://bugs.python.org/issue23801
+ # This is taken exactly from Python 3.5's cgi.py module
+ def read_multi(self, environ, keep_blank_values, strict_parsing):
+ """Internal: read a part that is itself multipart."""
+ ib = self.innerboundary
+ if not cgi.valid_boundary(ib):
+ raise ValueError(
+ 'Invalid boundary in multipart form: %r' % (ib,))
+ self.list = []
+ if self.qs_on_post:
+ query = cgi.urllib.parse.parse_qsl(
+ self.qs_on_post, self.keep_blank_values,
+ self.strict_parsing,
+ encoding=self.encoding, errors=self.errors)
+ for key, value in query:
+ self.list.append(cgi.MiniFieldStorage(key, value))
+
+ klass = self.FieldStorageClass or self.__class__
+ first_line = self.fp.readline() # bytes
+ if not isinstance(first_line, bytes):
+ raise ValueError("%s should return bytes, got %s"
+ % (self.fp, type(first_line).__name__))
+ self.bytes_read += len(first_line)
+
+ # Ensure that we consume the file until we've hit our innerboundary
+ while (first_line.strip() != (b"--" + self.innerboundary) and
+ first_line):
+ first_line = self.fp.readline()
self.bytes_read += len(first_line)
- # Ensure that we consume the file until we've hit our innerboundary
- while (first_line.strip() != (b"--" + self.innerboundary) and
- first_line):
- first_line = self.fp.readline()
- self.bytes_read += len(first_line)
-
+ while True:
+ parser = cgi.FeedParser()
+ hdr_text = b""
while True:
- parser = cgi.FeedParser()
- hdr_text = b""
- while True:
- data = self.fp.readline()
- hdr_text += data
- if not data.strip():
- break
- if not hdr_text:
+ data = self.fp.readline()
+ hdr_text += data
+ if not data.strip():
break
- # parser takes strings, not bytes
- self.bytes_read += len(hdr_text)
- parser.feed(hdr_text.decode(self.encoding, self.errors))
- headers = parser.close()
- # Some clients add Content-Length for part headers, ignore them
- if 'content-length' in headers:
- filename = None
- if 'content-disposition' in self.headers:
- cdisp, pdict = parse_header(self.headers['content-disposition'])
- if 'filename' in pdict:
- filename = pdict['filename']
- if filename is None:
- del headers['content-length']
- part = klass(self.fp, headers, ib, environ, keep_blank_values,
- strict_parsing, self.limit-self.bytes_read,
- self.encoding, self.errors)
- self.bytes_read += part.bytes_read
- self.list.append(part)
- if part.done or self.bytes_read >= self.length > 0:
- break
- self.skip_lines()
- else: # pragma no cover
- cgi_FieldStorage = _cgi_FieldStorage
-
+ if not hdr_text:
+ break
+ # parser takes strings, not bytes
+ self.bytes_read += len(hdr_text)
+ parser.feed(hdr_text.decode(self.encoding, self.errors))
+ headers = parser.close()
+ # Some clients add Content-Length for part headers, ignore them
+ if 'content-length' in headers:
+ filename = None
+ if 'content-disposition' in self.headers:
+ cdisp, pdict = parse_header(self.headers['content-disposition'])
+ if 'filename' in pdict:
+ filename = pdict['filename']
+ if filename is None:
+ del headers['content-length']
+ part = klass(self.fp, headers, ib, environ, keep_blank_values,
+ strict_parsing, self.limit-self.bytes_read,
+ self.encoding, self.errors)
+ self.bytes_read += part.bytes_read
+ self.list.append(part)
+ if part.done or self.bytes_read >= self.length > 0:
+ break
+ self.skip_lines()
else:
from cgi import FieldStorage as cgi_FieldStorage

0 comments on commit 1ac5148

Please sign in to comment.