parameters: (self, environ, keep_blank_values, strict_parsing)
docstring: Internal: read a part that is itself multipart.
docstring_summary: Internal: read a part that is itself multipart.
docstring_tokens: Internal : read a part that is itself multipart .
function: def read_multi(self, environ, keep_blank_values, strict_parsing):
          """Internal: read a part that is itself multipart."""
          ib = self.innerboundary
          if not valid_boundary(ib):
              raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
          self.list = []
          if self.qs_on_post:
              query = urllib.parse.parse_qsl(
                  self.qs_on_post, self.keep_blank_values, self.strict_parsing,
                  encoding=self.encoding, errors=self.errors,
                  max_num_fields=self.max_num_fields, separator=self.separator)
              self.list.extend(MiniFieldStorage(key, value) for key, value in query)
  
          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 inner boundary
          while (first_line.strip() != (b"--" + self.innerboundary) and
                  first_line):
              first_line = self.fp.readline()
              self.bytes_read += len(first_line)
  
          # Propagate max_num_fields into the sub class appropriately
          max_num_fields = self.max_num_fields
          if max_num_fields is not None:
              max_num_fields -= len(self.list)
  
          while True:
              parser = FeedParser()
              hdr_text = b""
              while True:
                  data = self.fp.readline()
                  hdr_text += data
                  if not data.strip():
                      break
              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:
                  del headers['content-length']
  
              limit = None if self.limit is None \
                  else self.limit - self.bytes_read
              part = klass(self.fp, headers, ib, environ, keep_blank_values,
                           strict_parsing, limit,
                           self.encoding, self.errors, max_num_fields, self.separator)
  
              if max_num_fields is not None:
                  max_num_fields -= 1
                  if part.list:
                      max_num_fields -= len(part.list)
                  if max_num_fields < 0:
                      raise ValueError('Max number of fields exceeded')
  
              self.bytes_read += part.bytes_read
              self.list.append(part)
              if part.done or self.bytes_read >= self.length > 0:
                  break
          self.skip_lines()
function_tokens: def read_multi ( self , environ , keep_blank_values , strict_parsing ) : ib = self . innerboundary if not valid_boundary ( ib ) : raise ValueError ( 'Invalid boundary in multipart form: %r' % ( ib , ) ) self . list = [ ] if self . qs_on_post : query = urllib . parse . parse_qsl ( self . qs_on_post , self . keep_blank_values , self . strict_parsing , encoding = self . encoding , errors = self . errors , max_num_fields = self . max_num_fields , separator = self . separator ) self . list . extend ( MiniFieldStorage ( key , value ) for key , value in query ) 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 inner boundary while ( first_line . strip ( ) != ( b"--" + self . innerboundary ) and first_line ) : first_line = self . fp . readline ( ) self . bytes_read += len ( first_line ) # Propagate max_num_fields into the sub class appropriately max_num_fields = self . max_num_fields if max_num_fields is not None : max_num_fields -= len ( self . list ) while True : parser = FeedParser ( ) hdr_text = b"" while True : data = self . fp . readline ( ) hdr_text += data if not data . strip ( ) : break 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 : del headers [ 'content-length' ] limit = None if self . limit is None else self . limit - self . bytes_read part = klass ( self . fp , headers , ib , environ , keep_blank_values , strict_parsing , limit , self . encoding , self . errors , max_num_fields , self . separator ) if max_num_fields is not None : max_num_fields -= 1 if part . list : max_num_fields -= len ( part . list ) if max_num_fields < 0 : raise ValueError ( 'Max number of fields exceeded' ) self . bytes_read += part . bytes_read self . list . append ( part ) if part . done or self . bytes_read >= self . length > 0 : break self . skip_lines ( )