diff options
author | 2007-07-22 03:17:07 +0000 | |
---|---|---|
committer | 2007-07-22 03:17:07 +0000 | |
commit | 2ca856e8709a691c528ad74a8fe4f78e051075f3 (patch) | |
tree | 573ca536f3b44d227ab1aeabdac89cadb0cfe239 | |
download | misc-2ca856e8709a691c528ad74a8fe4f78e051075f3.tar.gz misc-2ca856e8709a691c528ad74a8fe4f78e051075f3.tar.bz2 misc-2ca856e8709a691c528ad74a8fe4f78e051075f3.zip |
Fever as sent by Michal
svn path=/fever/; revision=4
-rw-r--r-- | fever/commons.py | 85 | ||||
-rw-r--r-- | fever/fev.py | 47 | ||||
-rw-r--r-- | fever/fever.py | 113 |
3 files changed, 245 insertions, 0 deletions
diff --git a/fever/commons.py b/fever/commons.py new file mode 100644 index 0000000..c44fcc2 --- /dev/null +++ b/fever/commons.py @@ -0,0 +1,85 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +# fever - by Michał Bentkowski 2007 +# licensed under GPL + +# this file contains a few functions not direct related with fever, +# but fever can't work without them. + +# I decided to split it because the main file would be too inlegible + +import re +import tempfile +import sys +import urllib + +def unit(number): + """Changes bytes unit to more legible one""" + mp=1024 + prefixes="","k","M","G","T" # probably we don't need more ones :-) + for (p, i) in zip(prefixes, map(lambda x: mp**x, xrange(len(prefixes)))): + x=float(number)/i + if x < mp: + return "%0.2f %sB" % (x,p) + +def download(url,verbose=False): + """Downloads specified URL. Returns its content""" + block_size=10240 + temp=tempfile.TemporaryFile() + file=urllib.urlopen(url) + try: + filesize=" of "+unit(long(file.headers["content-length"])) + except KeyError: + filesize="" + block=file.read(block_size) + bytes=0 + while block != "": + bytes+=len(block) + temp.write(block) + if verbose: + sys.stdout.write("\rDownloading %s... %s%s" % (file.url[:40], unit(bytes), filesize)) + sys.stdout.flush() + block=file.read(block_size) + if verbose: print "\nDownloaded!" + temp.seek(0) + return temp.read() + +def rpmvercmp(a, b): + """ Comparing algorithm based on original rpmvercmp """ + a,b=map(re.split,("[\W_]+|(\d+)",)*2,(str(a),str(b))) # split versions strings according to rpm version + # comparing algorithm + a,b=map(lambda x: [elem for elem in x if elem not in (None, "")],[a,b]) # and remove empty + # elements + for elem_a, elem_b in zip(a,b): + try: + elem_a=int(elem_a) + except ValueError: + pass + try: + elem_b=int(elem_b) + except ValueError: + pass + elem_a_type,elem_b_type=map(type,(elem_a,elem_b)) + if elem_a_type != elem_b_type: + if elem_a_type == int: + return 1 + else: + return -1 + elif (elem_a_type, elem_b_type) == (int,)*2: + compare=cmp(int(elem_a),int(elem_b)) + if compare != 0: + return compare + else: + compare=cmp(elem_a, elem_b) + if compare != 0: + return compare + return cmp(len(a),len(b)) +def vercmpsort(List): + """Sorting based on an rpmvercmp algorithm""" + for indexes in range(len(List)-1, 0, -1): + for index in range(indexes): + if rpmvercmp(List[index],List[index+1]) == 1: + List[index],List[index+1]=List[index+1],List[index] + List.reverse() + return List
\ No newline at end of file diff --git a/fever/fev.py b/fever/fev.py new file mode 100644 index 0000000..94b79a0 --- /dev/null +++ b/fever/fev.py @@ -0,0 +1,47 @@ +import fever +import xmlrpclib + +statuses=['NEW', 'VERIFIED', 'ASSIGNED', 'REOPENED', 'CLOSED', 'NEEDINFO', 'MODIFIED', 'ON_DEV', 'UNCONFIRMED', 'ON_QA', 'FAILS_QA', 'NEEDINFO_REPORTER', 'RELEASE_PENDING', 'POST'] + +username="a@b.pl" +password="adf" + +Summary="""%s-%s is available""" +Comment="""%s-%s is already available. Repo version is %s. +Please update the package. + +If you have any questions or suggestions related to Fever, +feel free to write them in this bug or have a look at +http://fedoraproject.org/wiki/PackageMaintainers/FEver + +Don't send any messages to fevapp at o2.pl please. + +""" + +url='http://bugzilla.redhat.com/bugzilla/xmlrpc.cgi' + +fev=fever.Fever(2) +fev.checkAllPackages() +x=fev.listNotUpToDate() +notuptodate=[] +for elem in x: + elem=elem.items() + notuptodate.append( (elem[0][0],False,elem[0][1]['sitever'],elem[0][1]['kojiver'])) + +print notuptodate + +server=xmlrpclib.Server(url) +fevbugs=server.bugzilla.runQuery({'emailreporter2': 1, 'email2': username, 'bug_status': statuses}) +descriptions=[elem['short_short_desc'] for elem in fevbugs['bugs']] +for (name, uptodate, aversion, rversion) in notuptodate: + summary=Summary % (name,aversion) + if summary in descriptions: + print "New version of %s has been already submitted" % name + continue + comment=Comment % (name, aversion, rversion) + res = server.bugzilla.createBug({"comment": comment, "short_desc": summary, + 'product': 'Fedora', 'component': name, + 'rep_platform':'All', 'bug_severity': "medium", + 'version': 'devel','op_sys':'Linux', + 'priority': 'normal', 'bug_file_loc': 'http://fedoraproject.org/wiki/Micha%C5%82Bentkowski/FEver' }, username, password) + print "Bug %s created!" % res[0] diff --git a/fever/fever.py b/fever/fever.py new file mode 100644 index 0000000..5fdd690 --- /dev/null +++ b/fever/fever.py @@ -0,0 +1,113 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +# Fever - by Michał Bentkowski 2007 +# licensed under GPL + +# first, let's do some koji things +import koji +session=koji.ClientSession("http://koji.fedoraproject.org/kojihub") + +# now, import the other things we need + +from commons import download, rpmvercmp, vercmpsort +import re +from xml.sax.saxutils import unescape + +#set timeout TODO: should be set in config file +import socket +socket.setdefaulttimeout(45) + +import sys + +class Fever: + def __init__(self, debug=0, + listformat="\* (?P<name>.*?) (?P<regex>.*) (?P<url>.*?)\n", + listlocation="http://fedoraproject.org/wiki/PackageMaintainers/FEver"): + self.debug=debug + #self.listformat=listformat + #self.lislocation=listlocation + # it's sane to download a site with a list of packages at once + site=download(listlocation, debug) + # and let's parse it! + self.pkglist={} # this var will keep all info of packages + for package in re.finditer(listformat, site): + dict=package.groupdict() #retrieve dictionary with name regex and url + name=dict['name'] + del dict['name'] # we don't need name in dict anymore + # sometimes there are escaped chars like < in regex + # so we need to unescape them first + dict['regex']=unescape(dict['regex']) + self.pkglist[name]=dict + self.pkglist[name]['checked']=False + if debug >= 2: + print "%s parsed. Data: %s" % (name,dict) + + def getPkgSiteVersion(self,pkgname): + # download a proper site and get a package version + site=download(self.pkglist[pkgname]['url'], self.debug) + regex=self.pkglist[pkgname]['regex'] + versions=vercmpsort( re.findall(regex, site) ) # find all versions and sort'em + return versions[0] # we need only the newest one + + def getPkgKojiVersion(self, pkgname): + # first, we need koji's package id + pkgid=session.getPackageID(pkgname) + # now, list all builds + builds=session.listBuilds(pkgid) + # extract all versions and sort'em + versions=vercmpsort( [x['version'] for x in session.listBuilds(pkgid)]) + return versions[0] # return the newest one + + def getPkgList(self): + return self.pkglist + + def getPkgInfo(self, pkgname): + return self.pkglist[pkgname] + + def checkPackage(self, pkgname): + # this is probably the most important function, + # it checks if repo version is newer than the available one. + # Returns 0 if versions match or koji version is newer than site version + # (it may happen if there's something wrong with regex) and 1 if a package's + # owner need to update his package, -1 - if error. + if self.debug >= 1: + print 'Checking %s...' % pkgname + try: + sitever=self.getPkgSiteVersion(pkgname) + kojiver=self.getPkgKojiVersion(pkgname) + except: + # if no version were found, we don't need this package anymore + if self.debug >= 1: + print "%s won't be checked. Error. %s" % (pkgname, str(sys.exc_info())) + self.pkglist[pkgname]['checked']=False + return -1 + if self.debug >= 2: + print '%s: koji: %s; site: %s' % (pkgname, kojiver, sitever) + compare=rpmvercmp(kojiver, sitever) + self.pkglist[pkgname]['kojiver']=kojiver + self.pkglist[pkgname]['sitever']=sitever + self.pkglist[pkgname]['checked']=True + if compare == -1: #if a newer version's available + self.pkglist[pkgname]['uptodate']=False + return 1 + else: # if isn't + self.pkglist[pkgname]['uptodate']=True + return 0 + + def checkAllPackages(self): + # simple loop to check all packages at once. + for package in self.pkglist.keys(): + result=self.checkPackage(package) + + def isPackageUpToDate(self,pkgname): + # just check if a given package is up to date + return self.pkglist[pkgname]['uptodate'] + + def listUpToDate(self): + # list all up-to-date packages + return [dict([(k,v)]) for k,v in self.pkglist.iteritems() if v['checked']==True and v['uptodate']==True] + + def listNotUpToDate(self): + # list all not-up-to-date packages + return [dict([(k,v)]) for k,v in self.pkglist.iteritems() if v['checked']==True and v['uptodate']==False] |