FogBugz » FogBugzPy A Python wrapper for the FogBugz API Read More
Clone URL:  
Pushed to one repository · View In Graph Contained in 0.9.2, 0.9.3, and 0.9.5

I needed this capability so ended up writing it. You're welcome to redistribute it freely - it's fairly straightforward but probably needs a bit of documentation.

Changeset c448c4ca361a

Parent 40b58f990562

by Paul Jimenez

Changes to one file · Browse files at c448c4ca361a Showing diff from parent 40b58f990562 Diff from another changeset...

Change 1 of 3 Show Entire File fogbugz.py Stacked
 
1
2
 
 
3
4
5
 
19
20
21
22
 
23
24
 
25
26
27
 
61
62
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
65
66
67
68
 
 
 
 
 
 
 
 
 
 
69
70
 
 
71
72
73
 
1
2
3
4
5
6
7
 
21
22
23
 
24
25
 
26
27
28
29
 
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 
100
101
102
103
104
105
106
107
108
109
110
 
111
112
113
114
115
@@ -1,5 +1,7 @@
 import urllib  import urllib2 +import mimetools +from StringIO import StringIO    from BeautifulSoup import BeautifulSoup, CData   @@ -19,9 +21,9 @@
  url += '/'     if token: - self._token = token.encode('utf-8') + self._token = token.encode('utf-8')   else: - self_token = None + self._token = None     self._opener = urllib2.build_opener()   try: @@ -61,13 +63,53 @@
  """   self._token = token.encode('utf-8')   + def __encode_multipart_formdata(self, fields, files): + """ + fields is a sequence of (key, value) elements for regular form fields. + files is a sequence of (filename, filehandle) files to be uploaded + returns (content_type, body) + """ + BOUNDARY = mimetools.choose_boundary() + + if len(files) > 0: + fields['nFileCount'] = str(len(files)) + + crlf = '\r\n' + buf = StringIO() + + for k, v in fields.items(): + print("field: %s: %s"% (repr(k), repr(v))) + buf.write(crlf.join([ '--' + BOUNDARY, 'Content-disposition: form-data; name="%s"' % k, '', v, '' ])) + + n = 0 + for f, h in files.items(): + n += 1 + buf.write(crlf.join([ '--' + BOUNDARY, 'Content-disposition: form-data; name="File%d"; filename="%s"' % ( n, f), '' ])) + buf.write(crlf.join([ 'Content-type: application/octet-stream', '', '' ])) + buf.write(h.read()) + buf.write(crlf) + + buf.write('--' + BOUNDARY + '--' + crlf) + content_type = "multipart/form-data; boundary=%s" % BOUNDARY + return content_type, buf.getvalue() +   def __makerequest(self, cmd, **kwargs):   kwargs["cmd"] = cmd   if self._token:   kwargs["token"] = self._token - + + fields = dict([k, v.encode('utf-8') if isinstance(v,basestring) else v] for k, v in kwargs.items()) + files = fields.get('Files', {}) + if 'Files' in fields: + del fields['Files'] + + content_type, body = self.__encode_multipart_formdata(fields, files) + headers = { 'Content-Type': content_type, + 'Content-Length': str(len(body))} +   try: - response = BeautifulSoup(self._opener.open(self._url+urllib.urlencode(dict([k, v.encode('utf-8') if isinstance(v,basestring) else v ] for k, v in kwargs.items())))).response + request = urllib2.Request(self._url, body, headers) + response = BeautifulSoup(self._opener.open(request)).response   except urllib2.URLError, e:   raise FogBugzConnectionError(e)   except UnicodeDecodeError, e: