1
2
3 '''Module for encoding data as form-data/multipart'''
4
5 import os
6 import base64
7
8
10
11 '''A single part of the multipart data.
12
13 >>> Part({'name': 'headline'}, 'Nice Photo')
14 ... # doctest: +ELLIPSIS
15 <flickrapi.multipart.Part object at 0x...>
16
17 >>> image = open('tests/photo.jpg')
18 >>> Part({'name': 'photo', 'filename': image}, image.read(), 'image/jpeg')
19 ... # doctest: +ELLIPSIS
20 <flickrapi.multipart.Part object at 0x...>
21 '''
22
23 - def __init__(self, parameters, payload, content_type=None):
24 self.content_type = content_type
25 self.parameters = parameters
26 self.payload = payload
27
29 '''Renders this part -> List of Strings'''
30
31 parameters = ['%s="%s"' % (k, v)
32 for k, v in self.parameters.iteritems()]
33
34 lines = ['Content-Disposition: form-data; %s' % '; '.join(parameters)]
35
36 if self.content_type:
37 lines.append("Content-Type: %s" % self.content_type)
38
39 lines.append('')
40
41 if isinstance(self.payload, unicode):
42 lines.append(self.payload.encode('utf-8'))
43 else:
44 lines.append(self.payload)
45
46 return lines
47
48
50 '''A single part with a file as the payload
51
52 This example has the same semantics as the second Part example:
53
54 >>> FilePart({'name': 'photo'}, 'tests/photo.jpg', 'image/jpeg')
55 ... #doctest: +ELLIPSIS
56 <flickrapi.multipart.FilePart object at 0x...>
57 '''
58
59 - def __init__(self, parameters, filename, content_type):
60 parameters['filename'] = filename
61
62 imagefile = open(filename, 'rb')
63 payload = imagefile.read()
64 imagefile.close()
65
66 Part.__init__(self, parameters, payload, content_type)
67
68
70 """Generate a random boundary, a bit like Python 2.5's uuid module."""
71
72 bytes = os.urandom(16)
73 return base64.b64encode(bytes, 'ab').strip('=')
74
75
77 '''Container for multipart data'''
78
80 '''Creates a new Multipart.'''
81
82 self.parts = []
83 self.content_type = 'form-data/multipart'
84 self.boundary = boundary()
85
87 '''Attaches a part'''
88
89 self.parts.append(part)
90
92 '''Renders the Multipart'''
93
94 lines = []
95 for part in self.parts:
96 lines += ['--' + self.boundary]
97 lines += part.render()
98 lines += ['--' + self.boundary + "--"]
99
100 return '\r\n'.join(lines)
101
103 '''Returns the top-level HTTP header of this multipart'''
104
105 return ("Content-Type",
106 "multipart/form-data; boundary=%s" % self.boundary)
107