root/protocols/protocol_launchpadweb.py

Revision 80, 8.4 kB (checked in by ploum@…, 3 months ago)

gros commit tout pourri

Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3import gtk
4import gobject
5import urllib
6from bug import *
7from mechanize import Browser
8from BeautifulSoup import BeautifulSoup
9# You have to change this if you have another storage
10#from auth_dummy import user
11
12baseurl = "https://staging.launchpad.net/"
13#baseurl = "https://launchpad.net/"
14
15class protocol:
16
17# LAUNCHPAD protocol using the web : suboptimal
18
19# Available informations for authentification are :
20# -  user.login()  -> string that contains the login
21# -  user.password() -> string that contains the password
22
23        def __init__(self,manager) :
24                self.user = manager
25
26### Launchpad only functions ####
27
28        def htmlify(self, string) :
29                s1 = string.strip().replace(" "," ")
30                s2 = s1.strip().replace(">",">")
31                s3 = s2.strip().replace("&lt;","<")
32                return s3
33       
34################INFORMATION ABOUT THE BTS ################################
35
36        # Send back the name of the protocol as a simple string
37
38        @staticmethod
39        def Name():
40                return "launchpadweb"
41
42        # send the name of the bts this protocol will talk too.
43        # this is intended for future multi-protocol support
44        # and will enable bookmarks sharing between differents protocols
45        # that speaks to the same bts
46        def btsName(self):
47                return "launchpad"
48
49################BUG RETRIEVING IN THE BTS #################################
50       
51        # Functions related to bugs in your BTS
52        # Functions return an object "bug" (see bug.py)
53        #
54        # You have to implement the following functions :
55        # - retrieveBug(int)
56        # - getBugUrl(int)
57
58        # Retrieve bug take an int, the bug number, and construct a bug object
59        # this bug object is then returned
60        def retrieveBug(self,nbr):
61                zebug = bug(nbr)
62                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63                # this is what you want to modify to support your own protocol
64                zeurl="%sbugs/%s" %(baseurl,str(nbr))
65                f= urllib.urlopen(zeurl)
66                # ici on a le corps principal
67                # faudrait faire un extract pour soulager la mémoire
68                soup1 = BeautifulSoup(f).body.contents[5]
69                # no bug of this number here
70                if soup1.div.h1.contents[0] == "Page not found" :
71                        # a negative number means that the bug doesn't exist
72                        zebug.setNbr(-1)
73                else :
74                        soup = soup1.div.div
75                        title = soup.h1.contents[0]
76                        tbody = soup.findAll('tbody')[0].findAll('td')
77                        product = tbody[0].a.contents[0]
78                        status = tbody[1].contents[0]
79                        importance = tbody[2].contents[0]
80                        string_tmp = tbody[3].a
81                        # Here we look if the bug is assigned to someone or not
82                        if string_tmp != None :
83                                assigned = string_tmp.contents[2].strip()
84                        else :
85                                #Assigned to nobody
86                                assigned = "Nobody yet"
87                        #need to prettify content
88                        content=''
89                        p = soup.findAll('div', recursive=0)[1].div.findAll('p', recursive=0)
90                        for i in p:
91                                for j in i.contents:
92                                        jj = j.string
93                                        # we get rid of <br /> tags
94                                        if jj != None and jj != "<br />" :
95                                                # here we remove manually all &nbsp
96                                                newj = self.htmlify(jj)
97                                                #newj = jj.strip().replace("&nbsp;"," ")
98                                                content = "%s\n%s"%(content,newj)
99                                content = "%s\n"%content
100
101                        zebug.setTitle(title)
102                        zebug.setStatus(status)
103                        zebug.setPackage(product)
104                        zebug.setImportance(importance)
105                        zebug.setDescription(content)
106                        zebug.setAssignee(assigned)
107
108                        array_com = soup.findAll('div', recursive=0)[1].findAll('div','boardComment')
109                        j = 0
110                        com_counter = 0
111                        for i in array_com :
112                                details = i.contents[1].findAll('a')
113                                title = details[0].strong.contents[0]
114                                poster = details[1].contents[0]
115                                body = i.contents[3].findAll('p')
116                                com_counter += 1
117                                content=""
118                                for z in body :
119                                        phrase = ''
120                                        for ligne in z.contents :
121                                                if ligne.string != None :
122                                                        phrase += ligne.string.strip()
123                                        content += self.htmlify(phrase)
124                                        content += "\n\n"
125                                newcom = comment(com_counter,content,poster,title,"00/00/00")
126                                zebug.addComment(newcom)
127
128                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129                return zebug   
130
131        # getBugUrl takes a int, the bug number, and return the URL of
132        # the bug in order to open it in a browser
133        def getBugUrl(self,nbr) :
134                bugnbr = str(nbr)
135                return "%sbugs/%s" %(baseurl,bugnbr)
136
137
138
139################SEARCH IN THE BTS #################################
140
141        # The functions Search will perform a search
142        # in the BTS
143        # All results matching the search are added to a
144        # gtk.ListStore with attributes in the following orders :
145        # gobject.TYPE_INT : number of the bug
146        # gobject.TYPE_STRING : package
147        # gobject.TYPE_STRING : title of the bug
148        # gobject.TYPE_STRING : importance
149        # gobject.TYPE_STRING : status
150        #
151        # You have to implement the following search methods for your BTS :
152        # - genericSearch(string)
153        # - packageSearch(string,string)
154        # - advancedSearch
155        # - packageExist(string) (return a boolean, not a listStore)
156
157
158        #private function to create a new result gtk.ListStore
159        def __newResult(self) :
160                return gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
161       
162        # content is an array of bug numbers
163        def __populateResult(self, results, content, typeofsearch, arg_package):
164                parse = content.body.findAll('tbody')
165                # if no results
166                if len(parse) == 0 :
167                        return results
168                else :
169                        table = parse[1].findAll('tr')
170                        for tr in table :
171                                row = tr.findAll('td')
172                                nbr = int(row[1].contents[0])
173                                title = row[2].a.contents[0]
174                                if typeofsearch == 2 :
175                                        package = row[3].contents[0]
176                                        importance = row[4].contents[0]
177                                        status = row[5].contents[0]
178                                elif typeofsearch == 3 :
179                                        package = arg_package
180                                        importance = row[3].contents[0]
181                                        status = row[4].contents[0]
182                                else :
183                                        package = ''
184                                        importance = ''
185                                        status = ''
186                                results.insert_before(None, [nbr, package, title, importance, status ])
187                        return results
188
189
190        # genericSearch on a given string search_str.
191        def genericSearch(self, search_str) :
192                #creating an empty result first
193                results= self.__newResult()
194                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195                # this is what you want to modify to support your own protocol
196                #inserting dummies bugs
197                plus = search_str.replace(" ","+")
198                zeurl="%sdistros/ubuntu/+bugs?field.searchtext=%s" %(baseurl,plus)
199                f= urllib.urlopen(zeurl)
200                content=BeautifulSoup(f)
201                return self.__populateResult(results, content, 2, None)
202       
203               
204                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205                #returning the results
206                #return results
207
208        # search on a given string search_str but only in bugs of
209        # a given package
210        def packageSearch(self, package, search_str):
211                #creating an empty result first
212                results= self.__newResult()
213                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214                # this is what you want to modify to support your own protocol
215                #inserting dummies bugs
216                # your package search must support a Null search_str
217                if search_str != None :
218                        plus = search_str.replace(" ","+")
219                        zeurl="%sdistros/ubuntu/+source/%s/+bugs?field.searchtext=%s" %(baseurl,package,plus)
220                else :
221                        zeurl="%sdistros/ubuntu/+source/%s/+bugs" %(baseurl,package)
222                f= urllib.urlopen(zeurl)
223                content=BeautifulSoup(f)
224                return self.__populateResult(results, content, 3, package)
225               
226                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227                #returning the results
228                #return results
229
230       
231        # Return true is the package exist in the BTS, false if not             
232        def packageExist(self, package):
233                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234                # this is what you want to modify to support your own protocol
235                zeurl="%sproducts/%s" %(baseurl,package)
236                f= urllib.urlopen(zeurl)
237                #ugly launchpad hack !
238                title=BeautifulSoup(f).html.head.title.contents[0]
239                return title != "Error: Page not found"
240                #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%         
241       
242################MODIFYING A BUG #################################
243
244        # The functions that will allow us to modify a bug
245        #
246        # You have to implement the following search modify for your BTS :
247        # - postComment(string,string,string)
248
249        #private function that log the user into Launchpad
250        # return a mechanize Browser object
251        def __login(self):
252                urllog="%s+login" %baseurl
253                br = Browser()
254                br.set_handle_robots(False)
255                br.open(urllog)
256                br.select_form(name="login")
257                br["loginpage_email"]=self.user.login
258                br["loginpage_password"]=self.user.password
259                response = br.submit()
260                return br
261
262        def postComment(self,bugnbr,title,comment) :
263                urlcom="%sbugs/%s" %(baseurl,bugnbr)
264                br = self.__login()
265                br.open(urlcom)
266                br.select_form(nr=2)
267                # TODO : set the title
268                br["field.comment"]= comment
269                br.submit()
270               
271
272
273       
274
275                       
Note: See TracBrowser for help on using the browser.