annotate bzconsole/api.py @ 41:5d09b4e9a21b

cleanup
author Jeff Hammel <jhammel@mozilla.com>
date Sun, 16 Dec 2012 20:04:03 -0800
parents 99cdb343273f
children 678b82fedb40
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
1 """
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
2 console API to bugzilla
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
3 """
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
4
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
5 import base64
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
6 import httplib
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
7 import json
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
8 import os
38
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
9 import patch
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
10 import subprocess
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
11 import sys
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
12 import urllib
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
13 import urllib2
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
14
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
15 from StringIO import StringIO
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
16
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
17 from utils import tmpbuffer
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
18
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
19
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
20 class BZapi(object):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
21 """
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
22 console API to bugzilla
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
23 """
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
24
35
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
25 # currently there is only one cache for configuration
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
26 config_cache = '.bzconfiguration'
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
27
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
28 def __init__(self,
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
29 server='https://api-dev.bugzilla.mozilla.org/latest',
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
30 refresh=False,
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
31 print_request=None,
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
32 username=None,
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
33 password=None):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
34 """
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
35 - refresh : refresh the (cached) configuration
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
36 - print_request : log any request information to a file
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
37 """
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
38 self.server = server
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
39 self.refresh = refresh
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
40 self.print_request = print_request
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
41 self.username = username
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
42 self.password = password
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
43
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
44 def products(self, classification=None):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
45 """list bugzilla products"""
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
46 configuration = self.configuration()
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
47 if classification:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
48 products = [i for i in configuration['product'] if configuration['product'][i]['classification'] == 'Components']
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
49 return sorted(products)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
50 else:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
51 return sorted(configuration['product'].keys())
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
52
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
53 def components(self, product):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
54 """list bugzilla components for a particular product"""
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
55 configuration = self.configuration()
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
56 assert product in configuration['product'], 'Product %s not found' % product
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
57 return sorted(configuration['product'][product]['component'].keys())
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
58
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
59 def _unique_components(self):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
60 """returns a dict of unique component, product"""
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
61 retval = {}
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
62 dupe = set()
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
63 for product in self.products():
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
64 for component in self.components(product):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
65 if component in retval:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
66 dupe.add(component)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
67 else:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
68 retval[component] = product
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
69 for d in dupe:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
70 del retval[d]
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
71 return retval, dupe
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
72
26
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
73 def users(self, match):
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
74 """returns users matching a search string"""
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
75 assert self.username and self.password, "Must be authenticated"
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
76 return self._request('/user?match=%s' % match)
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
77
27
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
78 def bug(self, number):
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
79 """display a bug"""
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
80 number = int(number)
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
81 return self._request('/bug/%d' % number)
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
82
21
e04729acf5be allow bzconsole to implicitly get the product from the component for new bugs, if the component is unique
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
83 def new(self, component, title, product=None,
32
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
84 version=None, description=None, whiteboard=(), cc=(),
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
85 blocks=(), depends_on=()):
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
86 """file a new bug. username and password must be set"""
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
87
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
88 # sanity check
21
e04729acf5be allow bzconsole to implicitly get the product from the component for new bugs, if the component is unique
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
89 if product:
28
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
90 assert product in self.products(), "Product not found"
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
91 assert component in self.components(product), "Component not found"
21
e04729acf5be allow bzconsole to implicitly get the product from the component for new bugs, if the component is unique
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
92 else:
28
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
93 unique, dupe = self._unique_components()
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
94 assert component in unique, 'Unique component not found: %s' % component
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
95 product = unique[component]
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
96 assert title, 'Must provide a bug summary'
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
97 assert self.username and self.password, "Must be authenticated"
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
98
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
99 # infer version if not given
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
100 if version is None:
28
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
101 versions = self._configuration['product'][product]['version']
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
102 if len(versions) == 1:
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
103 version = versions[0]
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
104 else:
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
105 default_versions = ('unspecified', 'Trunk')
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
106 for ver in default_versions:
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
107 version = ver
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
108 if version in self._configuration['product'][product]['version']:
a46a76a7990d fix single version products and bump version
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
109 break
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
110 assert version in self._configuration['product'][product]['version'], 'Version not found'
21
e04729acf5be allow bzconsole to implicitly get the product from the component for new bugs, if the component is unique
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
111
26
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
112 # create the needed data structure
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
113 request = dict(product=product, component=component,
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
114 summary=title, version=version,
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
115 op_sys='All', platform='All',)
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
116
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
117 # add CC, if given
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
118 if cc:
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
119 if isinstance(cc, basestring):
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
120 cc=[cc]
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
121 users = []
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
122 for match in cc:
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
123 user = self.users(match)['users']
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
124 assert len(user) == 1, 'Non-unique user: %s' % match
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
125 users.append(user[0])
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
126 request['cc'] = users
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
127
31
f6513032ad28 add a blocks field
Jeff Hammel <jhammel@mozilla.com>
parents: 30
diff changeset
128 # add blocks, if given:
f6513032ad28 add a blocks field
Jeff Hammel <jhammel@mozilla.com>
parents: 30
diff changeset
129 if blocks:
f6513032ad28 add a blocks field
Jeff Hammel <jhammel@mozilla.com>
parents: 30
diff changeset
130 blocks = [int(i) for i in blocks]
f6513032ad28 add a blocks field
Jeff Hammel <jhammel@mozilla.com>
parents: 30
diff changeset
131 request['blocks'] = blocks
f6513032ad28 add a blocks field
Jeff Hammel <jhammel@mozilla.com>
parents: 30
diff changeset
132
32
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
133 # add depends_on, if given
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
134 if depends_on:
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
135 depends_on = [int(i) for i in depends_on]
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
136 request['depends_on'] = depends_on
e843b7f1f400 fix up depends_on
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
137
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
138 # get the bug description
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
139 if not description:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
140 description = tmpbuffer()
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
141 assert description, "Must provide a non-empty description"
26
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
142 request['comments'] = [self._comment(description)]
27
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
143
23
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
144 # add whiteboard, if given
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
145 if whiteboard:
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
146 if isinstance(whiteboard, basestring):
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
147 whiteboard=[whiteboard]
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
148 whiteboard = ''.join(['[%s]' % i for i in whiteboard])
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
149 request['whiteboard'] = whiteboard
2eaf17cb07f6 add whiteboard to new entry
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
150
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
151 # POST the request
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
152 try:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
153 results = self._request('/bug', request)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
154 except Exception, e:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
155 raise
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
156
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
157 # return the URL
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
158 return results['ref']
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
159
35
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
160 def attach(self, bug, attachment, description=None, reviewer=None, comment=None):
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
161 """
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
162 add an attachment to a bug
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
163
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
164 - bug: bug number to attach to
35
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
165 - attachment: file or URL of attachment
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
166 - reviewer: flag for review (r?)
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
167 - comment: add this comment to the bug
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
168 """
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
169
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
170 if not description:
36
619e27c447b8 correct variable name + comment
Jeff Hammel <jhammel@mozilla.com>
parents: 35
diff changeset
171 # fairly hacky :/
619e27c447b8 correct variable name + comment
Jeff Hammel <jhammel@mozilla.com>
parents: 35
diff changeset
172 description = attachment
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
173
35
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
174 # read contents
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
175 if '://' in attachment:
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
176 # URL
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
177 basename = attachment.rstrip('/').rsplit('/', 1)[-1]
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
178 contents = urllib2.urlopen(attachment).read()
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
179 else:
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
180 # file path
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
181 basename = os.path.basename(attachment)
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
182 contents = file(attachment).read()
94b0b7b4f190 attachment filename for bzapi
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
183
38
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
184 is_patch = bool(patch.fromstring(contents))
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
185 if is_patch:
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
186 content_type = 'text/plain'
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
187 else:
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
188 # TODO: better content_type
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
189 content_type = 'text/plain'
38
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
190
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
191 # patch flags
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
192 flags = []
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
193 if reviewer:
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
194 # from
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
195 # https://github.com/toolness/pybugzilla/blob/master/bzpatch.py#L177
39
15c264451c3d more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
196 flags.append({'name': 'review',
15c264451c3d more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
197 'requestee': {'name': reviewer},
15c264451c3d more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
198 'status': '?',
15c264451c3d more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
199 'type_id': 4 # yay for magic numbers! :/
15c264451c3d more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
200 })
38
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
201
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
202 # create attachment data structure
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
203 # https://wiki.mozilla.org/Bugzilla:REST_API:Objects#Attachment
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
204 contents = contents.encode('base64')
41
5d09b4e9a21b cleanup
Jeff Hammel <jhammel@mozilla.com>
parents: 40
diff changeset
205 attachment= {'content_type': content_type,
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
206 'data': contents,
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
207 'description': description,
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
208 'encoding': 'base64',
38
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
209 'file_name': basename,
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
210 'flags': flags,
0a3c7d8eec72 utilize patch to determine if a patch or not
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
211 'is_patch': is_patch,
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
212 'is_private': False,
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
213 'size': len(contents)
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
214 }
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
215
40
99cdb343273f can now attach things
Jeff Hammel <jhammel@mozilla.com>
parents: 39
diff changeset
216 return self._request('/bug/%s/attachment' % bug, attachment)
34
1ce13b2b54a4 stubbing adding attachment; incomplete
Jeff Hammel <jhammel@mozilla.com>
parents: 32
diff changeset
217
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
218 def configuration(self):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
219 """bugzilla configuration"""
27
d5e88dadde69 add a bug command thingy
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
220
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
221 if not hasattr(self, '_configuration'):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
222 config_cache = os.path.join(os.environ['HOME'], self.config_cache)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
223 if not self.refresh:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
224 try:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
225 self._configuration = json.loads(file(config_cache).read())
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
226 except:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
227 pass
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
228 if not getattr(self, '_configuration', None):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
229 self._configuration = self._request('/configuration')
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
230 if not self.print_request:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
231 f = file(config_cache, 'w')
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
232 print >> f, json.dumps(self._configuration)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
233 self.refresh = False
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
234 return self._configuration
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
235
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
236 ### internal methods
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
237
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
238 def _comment(self, text):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
239 retval = {'is_private': False, 'text': text}
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
240 return retval
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
241
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
242 def _request(self, path, data=None):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
243 url = self.server + path
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
244 query = {}
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
245 if self.username:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
246 query['username'] = self.username
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
247 if self.password:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
248 query['password'] = self.password
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
249 if query:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
250 query = urllib.urlencode(query)
26
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
251 joiner = '?' in url and '&' or '?'
85357b075211 add ability to CC and use multiple whiteboard
Jeff Hammel <jhammel@mozilla.com>
parents: 25
diff changeset
252 url += joiner + query
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
253 headers = {'Accept': 'application/json',
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
254 'Content-Type': 'application/json'}
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
255 if data:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
256 data = json.dumps(data)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
257 req = urllib2.Request(url, data, headers)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
258
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
259 # print out the request
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
260 # from http://stackoverflow.com/questions/603856/how-do-you-get-default-headers-in-a-urllib2-request
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
261 if self.print_request:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
262
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
263 f = file(self.print_request, 'a')
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
264 class MyHTTPConnection(httplib.HTTPConnection):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
265 def send(self, s):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
266 print >> f, s # or save them, or whatever!
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
267 httplib.HTTPConnection.send(self, s)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
268
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
269 class MyHTTPSConnection(httplib.HTTPSConnection):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
270 def send(self, s):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
271 print >> f, s
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
272 httplib.HTTPSConnection.send(self, s)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
273
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
274 class MyHTTPHandler(urllib2.HTTPHandler):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
275 def http_open(self, req):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
276 return self.do_open(MyHTTPConnection, req)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
277 class MyHTTPSHandler(urllib2.HTTPSHandler):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
278 def https_open(self, req):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
279 return self.do_open(MyHTTPSConnection, req)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
280
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
281 if self.server.startswith('https://'):
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
282 opener = urllib2.build_opener(MyHTTPSHandler)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
283 else:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
284 opener = urllib2.build_opener(MyHTTPHandler)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
285 opener.open(req)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
286 return
30
07dc3f9de6bc print the damn thing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
287
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
288 try:
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
289 response = urllib2.urlopen(req)
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
290 except Exception, e:
30
07dc3f9de6bc print the damn thing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
291 print e
07dc3f9de6bc print the damn thing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
292 if data:
07dc3f9de6bc print the damn thing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
293 print data
20
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
294 import pdb; pdb.set_trace()
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
295 the_page = response.read()
c819c8388ad1 * separate api class
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
296 return json.loads(the_page)