Package restkit :: Module forms
[hide private]
[frames] | no frames]

Source Code for Module restkit.forms

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of restkit released under the MIT license.  
  4  # See the NOTICE for more information. 
  5   
  6   
  7  import mimetypes 
  8  import os 
  9  import re 
 10  import urllib 
 11   
 12   
 13  from restkit.util import to_bytestring, url_quote 
 14   
 15  MIME_BOUNDARY = 'END_OF_PART' 
 16   
17 -def form_encode(obj, charser="utf8"):
18 tmp = [] 19 for key, value in obj.items(): 20 tmp.append("%s=%s" % (url_quote(key), 21 url_quote(value))) 22 return to_bytestring("&".join(tmp))
23 24
25 -class BoundaryItem(object):
26 - def __init__(self, name, value, fname=None, filetype=None, filesize=None):
27 self.name = url_quote(name) 28 if value is not None and not hasattr(value, 'read'): 29 value = url_quote(value) 30 self.size = len(value) 31 self.value = value 32 if fname is not None: 33 if isinstance(fname, unicode): 34 fname = fname.encode("utf-8").encode("string_escape").replace('"', '\\"') 35 else: 36 fname = fname.encode("string_escape").replace('"', '\\"') 37 self.fname = fname 38 if filetype is not None: 39 filetype = to_bytestring(filetype) 40 self.filetype = filetype 41 42 if isinstance(value, file) and filesize is None: 43 try: 44 value.flush() 45 except IOError: 46 pass 47 self.size = int(os.fstat(value.fileno())[6])
48
49 - def encode_hdr(self, boundary):
50 """Returns the header of the encoding of this parameter""" 51 boundary = url_quote(boundary) 52 headers = ["--%s" % boundary] 53 if self.fname: 54 disposition = 'form-data; name="%s"; filename="%s"' % (self.name, 55 self.fname) 56 else: 57 disposition = 'form-data; name="%s"' % self.name 58 headers.append("Content-Disposition: %s" % disposition) 59 if self.filetype: 60 filetype = self.filetype 61 else: 62 filetype = "text/plain; charset=utf-8" 63 headers.append("Content-Type: %s" % filetype) 64 headers.append("Content-Length: %i" % self.size) 65 headers.append("") 66 headers.append("") 67 return "\r\n".join(headers)
68
69 - def encode(self, boundary):
70 """Returns the string encoding of this parameter""" 71 value = self.value 72 if re.search("^--%s$" % re.escape(boundary), value, re.M): 73 raise ValueError("boundary found in encoded string") 74 75 return "%s%s\r\n" % (self.encode_hdr(boundary), value)
76
77 - def iter_encode(self, boundary, blocksize=16384):
78 if not hasattr(self.value, "read"): 79 yield self.encode(boundary) 80 else: 81 yield self.encode_hdr(boundary) 82 while True: 83 block = self.value.read(blocksize) 84 if not block: 85 yield "\r\n" 86 break 87 yield block
88 89
90 -class MultipartForm(object):
91
92 - def __init__(self, params, boundary, headers):
93 self.boundary = boundary 94 self.boundaries = [] 95 self.size = 0 96 97 self.content_length = headers.get('Content-Length') 98 99 if hasattr(params, 'items'): 100 params = params.items() 101 102 for param in params: 103 name, value = param 104 if hasattr(value, "read"): 105 fname = getattr(value, 'name') 106 if fname is not None: 107 filetype = ';'.join(filter(None, mimetypes.guess_type(fname))) 108 else: 109 filetype = None 110 if not isinstance(value, file) and self.content_length is None: 111 value = value.read() 112 113 boundary = BoundaryItem(name, value, fname, filetype) 114 else: 115 boundary = BoundaryItem(name, value) 116 self.boundaries.append(boundary)
117
118 - def get_size(self):
119 if self.content_length is not None: 120 return int(self.content_length) 121 size = 0 122 for boundary in self.boundaries: 123 size = size + boundary.size 124 return size
125
126 - def __iter__(self):
127 for boundary in self.boundaries: 128 for block in boundary.iter_encode(self.boundary): 129 yield block 130 yield "--%s--\r\n" % self.boundary
131 132
133 -def multipart_form_encode(params, headers, boundary):
134 headers = headers or {} 135 boundary = urllib.quote_plus(boundary) 136 body = MultipartForm(params, boundary, headers) 137 headers['Content-Type'] = "multipart/form-data; boundary=%s" % boundary 138 headers['Content-Length'] = str(body.get_size()) 139 return body, headers
140