adding berlios support, including support for patches/features
authorBernd Zeimetz <bernd@bzed.de>
Tue, 16 Oct 2007 17:41:43 +0000 (19:41 +0200)
committerPierre Habouzit <madcoder@debian.org>
Fri, 19 Oct 2007 07:26:40 +0000 (09:26 +0200)
Signed-off-by: Bernd Zeimetz <bernd@bzed.de>
remote/berlios.py [new file with mode: 0644]

diff --git a/remote/berlios.py b/remote/berlios.py
new file mode 100644 (file)
index 0000000..d32d344
--- /dev/null
@@ -0,0 +1,104 @@
+# vim:set encoding=utf-8:
+###############################################################################
+# Copyright:
+#   © 2006 Sanghyeon Seo   <sanxiyn@gmail.com>
+#   © 2006 Pierre Habouzit <madcoder@debian.org>
+#   © 2007 Bernd Zeimetz   <bernd@bzed.de>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+# 
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+###############################################################################
+
+import urllib, urlparse, cgi, re
+
+from BeautifulSoup import BeautifulSoup
+from __init__ import *
+from base import maketoken
+
+#the status page
+MAX_BERLIOS_ID_LEN = 6
+
+def parse_table(soup, key, count):
+    #I have no damn clue why they have Status twice on their pages
+    #while Resolution is only listed once. ARGH!
+    cell  = soup.fetchText(key)[count].findParent('td')
+    return cell.contents[2]
+
+def parse_status_page(soup, id):
+    #propably a weird way to add 0 in front of the number
+    id = (MAX_BERLIOS_ID_LEN - len(id)) * '0' + id
+    cell  = soup.firstText(id).findParent('tr')
+    try:
+        return cell.fetchChildren()[5].string
+    except IndexError:
+        return Null
+
+gid_re = re.compile(r'.*group_id=([0-9]+).*')
+class BerliosData:
+    def __init__(self, uri, id):
+
+        self.id = id or failwith(uri, "Berlios: no id")
+
+        bugtype = uri.split('/')[3]
+        soup = BeautifulSoup(urllib.urlopen(uri))
+        if not bugtype == 'bugs':
+            self.status = parse_table(soup, 'Status:', 1)
+            self.resolution = 'Unknown'
+        else:
+            self.resolution  = parse_table(soup, 'Resolution:', 0)
+            gid = gid_re.findall(uri)[0]
+            offset = 0
+
+            #berlios does not list the status for bugs on the bug's page, MEH!
+            #even worse, not all bugs are listed on the overview page...
+            while True:
+                status_uri = 'http://developer.berlios.de/bugs/index.php?func=browse&group_id=%s&set=custom&_assigned_to=0&_status=100&_category=100&_bug_group=100&offset=%s&order=bug_id' % (gid, str(offset))
+                soup = BeautifulSoup(urllib.urlopen(status_uri))
+                self.status = parse_status_page(soup, str(id))
+                if self.status:
+                    break
+                #we don't want to parse ALL pages with bugs... that could be long...
+                if (not soup.firstText('Next 50 -->')) or offset >= 200:
+                    break
+                offset += 50
+    
+        if self.resolution == 'Duplicate':
+            raise DupeExn(uri)
+
+class RemoteBerlios(RemoteBts):
+    def __init__(self, cnf):
+        bugre  = '^%%(uri)s/\\?func=detail%(bugtype)s&%(bugtype)s_id=([0-9]+)$' % \
+                  {'bugtype' : cnf['bugtype']}
+        urifmt = '%%(uri)s/?func=detail%(bugtype)s&%(bugtype)s_id=%%(id)s' % \
+                  {'bugtype' : cnf['bugtype']}
+        RemoteBts.__init__(self, cnf, bugre, urifmt, BerliosData)
+
+    def isClosing(self, status, resolution):
+        return resolution == 'Fixed' or status == 'Closed'
+
+    def isWontfix(self, status, resolution):
+        return status == 'Wont Fix' or status == 'Deleted' or status == 'Rejected'
+
+RemoteBts.register('berlios', RemoteBerlios)
+