Internal: read a part that is itself multipart.
(self, environ, keep_blank_values, strict_parsing)
| 612 | FieldStorageClass = None |
| 613 | |
| 614 | def read_multi(self, environ, keep_blank_values, strict_parsing): |
| 615 | """Internal: read a part that is itself multipart.""" |
| 616 | ib = self.innerboundary |
| 617 | if not valid_boundary(ib): |
| 618 | raise ValueError('Invalid boundary in multipart form: %r' % (ib,)) |
| 619 | self.list = [] |
| 620 | if self.qs_on_post: |
| 621 | query = urllib.parse.parse_qsl( |
| 622 | self.qs_on_post, self.keep_blank_values, self.strict_parsing, |
| 623 | encoding=self.encoding, errors=self.errors, |
| 624 | max_num_fields=self.max_num_fields, separator=self.separator) |
| 625 | self.list.extend(MiniFieldStorage(key, value) for key, value in query) |
| 626 | |
| 627 | klass = self.FieldStorageClass or self.__class__ |
| 628 | first_line = self.fp.readline() # bytes |
| 629 | if not isinstance(first_line, bytes): |
| 630 | raise ValueError("%s should return bytes, got %s" \ |
| 631 | % (self.fp, type(first_line).__name__)) |
| 632 | self.bytes_read += len(first_line) |
| 633 | |
| 634 | # Ensure that we consume the file until we've hit our inner boundary |
| 635 | while (first_line.strip() != (b"--" + self.innerboundary) and |
| 636 | first_line): |
| 637 | first_line = self.fp.readline() |
| 638 | self.bytes_read += len(first_line) |
| 639 | |
| 640 | # Propagate max_num_fields into the sub class appropriately |
| 641 | max_num_fields = self.max_num_fields |
| 642 | if max_num_fields is not None: |
| 643 | max_num_fields -= len(self.list) |
| 644 | |
| 645 | while True: |
| 646 | parser = FeedParser() |
| 647 | hdr_text = b"" |
| 648 | while True: |
| 649 | data = self.fp.readline() |
| 650 | hdr_text += data |
| 651 | if not data.strip(): |
| 652 | break |
| 653 | if not hdr_text: |
| 654 | break |
| 655 | # parser takes strings, not bytes |
| 656 | self.bytes_read += len(hdr_text) |
| 657 | parser.feed(hdr_text.decode(self.encoding, self.errors)) |
| 658 | headers = parser.close() |
| 659 | |
| 660 | # Some clients add Content-Length for part headers, ignore them |
| 661 | if 'content-length' in headers: |
| 662 | del headers['content-length'] |
| 663 | |
| 664 | limit = None if self.limit is None \ |
| 665 | else self.limit - self.bytes_read |
| 666 | part = klass(self.fp, headers, ib, environ, keep_blank_values, |
| 667 | strict_parsing, limit, |
| 668 | self.encoding, self.errors, max_num_fields, self.separator) |
| 669 | |
| 670 | if max_num_fields is not None: |
| 671 | max_num_fields -= 1 |
no test coverage detected