make 'maketoken' public, and translate 'None' into None
authormadcoder <madcoder>
Sat, 6 May 2006 10:40:26 +0000 (10:40 +0000)
committermadcoder <madcoder>
Sat, 6 May 2006 10:40:26 +0000 (10:40 +0000)
import savane backend by Sanghyeon Seo

btslink.cfg
remote/base.py
remote/savane.py [new file with mode: 0644]

index 1d30c13eed5ec851671afc0cea186588da76e3d3..b2cfa9f84bb94c257b063582f9a7c7841e9b8512 100644 (file)
@@ -147,6 +147,22 @@ uri-re   = https?://trac.videolan.org/vlc/ticket/([0-9]*)
 type     = trac
 uri      = http://trac.xiph.org
 
+;*************************************************************************}}}*
+;
+; Savanes
+;
+;*************************************************************************{{{*
+
+[savanah-gnu]
+type     = savane
+uri      = http://savannah.gnu.org/bugs/
+uri-re   = https?://savannah.gnu.org/bugs/(?:index.php|)\?(?:.*&)*item_id=([0-9]+)
+
+[savanah-nongnu]
+type     = savane
+uri      = http://savannah.nongnu.org/bugs/
+uri-re   = https?://savannah.nongnu.org/bugs/(?:index.php|)\?(?:.*&)*item_id=([0-9]+)
+
 ;*************************************************************************}}}*
 
 ;[openoffice.org]
index d71a8d7a728e6d085ac67ad592e70ec4437bb5fb..7f3ab3de3b4ef3ad0c4f54f51cf0fe186dcf614a 100644 (file)
@@ -30,6 +30,8 @@
 
 import sys, re
 
+makeToken_re = re.compile(r"[^a-zA-Z0-9@.+\-]")
+
 class RemoteException(Exception):
     def __init__(self, *args):
         self.args = args
@@ -37,8 +39,11 @@ class RemoteException(Exception):
 def failwith(s):
     raise RemoteException(s)
 
+def maketoken(val):
+    if val and val.lower() == 'none': return None
+    return val and makeToken_re.sub('-', val)
+
 class RemoteReport:
-    _tokenre = re.compile("[^a-zA-Z0-9@.+\-]")
 
     def __init__(self, uri, data, bts):
         self._uri  = uri
@@ -46,15 +51,12 @@ class RemoteReport:
         self.bts   = bts
 
         self.id         = data.id
-        self.status     = self._makeToken(data.status)
-        self.resolution = self._makeToken(data.resolution)
+        self.status     = maketoken(data.status)
+        self.resolution = maketoken(data.resolution)
 
     def uri(self):
         return self.bts.getUri(self.id)
 
-    def _makeToken(self, val):
-        return val and RemoteReport._tokenre.sub('-', val)
-
     def isClosed(self):
         return self.bts.isClosing(self.status, self.resolution)
 
@@ -150,5 +152,5 @@ class RemoteBts:
     def _bugId(self, data):
         return data.id
 
-import bugzilla, trac
+import bugzilla, trac, savane
 
diff --git a/remote/savane.py b/remote/savane.py
new file mode 100644 (file)
index 0000000..50d7266
--- /dev/null
@@ -0,0 +1,71 @@
+# vim:set encoding=utf-8:
+###############################################################################
+# Copyright:
+#   © 2006 Sanghyeon Seo   <sanxiyn@gmail.com>
+#   © 2006 Pierre Habouzit <madcoder@debian.org>
+#
+# 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
+
+from BeautifulSoup import BeautifulSoup
+from base import RemoteBts, failwith, maketoken
+
+def parse_uri(uri, key):
+    qs = urlparse.urlparse(uri)[4]
+    dic = cgi.parse_qs(qs)
+    return dic[key][0]
+
+def parse_table(soup, key):
+    cell  = soup.firstText(key).findParent('td')
+    return maketoken(cell.nextSibling.string)
+
+class SavaneData:
+    def __init__(self, uri):
+        self.id = parse_uri(uri, 'item_id')
+
+        soup = BeautifulSoup(urllib.urlopen(uri))
+
+        self.status     = parse_table(soup, 'Open/Closed:') or failwith("Savanah: no status")
+        self.resolution = parse_table(soup, 'Status:')
+
+        if self.resolution == 'Duplicate':
+            failwith("Savane: don't know how to follow duplicates")
+
+class RemoteSavane(RemoteBts):
+    def __init__(self, cnf):
+        bugre  = r'^%(uri)s/\?func=detailitem&item_id=([0-9]+)$'
+        urifmt = '%(uri)s/?func=detailitem&item_id=%(id)s'
+        RemoteBts.__init__(self, cnf, bugre, urifmt, SavaneData)
+
+    def isClosing(self, status, resolution):
+        return status == 'Closed' and resolution != 'Wont-Fix'
+
+    def isWontfix(self, status, resolution):
+        return resolution == 'Wont-Fix'
+
+RemoteSavane.register('savane', RemoteSavane)
+