import urllib import sys import tempfile import re from time import strftime, localtime from xml.sax.saxutils import unescape #global constants: # 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 TemporaryFile object""" 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 def rpmvercmp(a, b): 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 class Packages: def __init__(self,verbose=False): self.verbose = verbose self.packages={} def addPackage(self,pkgname,available_version,repo_version): self.packages[pkgname]={"aver": available_version, "rver": repo_version} def getPackagesData(self): return self.packages def getPackageData(self,pkgname): return self.packages[pkgname] def addAndCheck(self,pkgname,available_version,repo_version): self.addPackage(pkgname,available_version,repo_version) return self.checkPkgUpToDate(pkgname) def checkPkgUpToDate(self,pkgname): aver,rver=self.packages[pkgname]["aver"],self.packages[pkgname]["rver"] compare=rpmvercmp(aver,rver) if compare == 1: compare=False else: compare=True return (compare, aver, rver) def checkAllUpToDate(self): for package in self.packages: yield (package,)+self.checkPkgUpToDate(package) class FEver: def __init__(self, verbose=False): self.log="" self.verbose=verbose self.Packages=Packages() def __call__(self, \ FEver_site="http://fedoraproject.org/wiki/Micha%C5%82Bentkowski/FEver", \ pkg_format="\* (.*?) (.*) (.*?)\n"): site_content=download(FEver_site , self.verbose).read() pkglist=re.findall(pkg_format,site_content) try: self.repo_versions except AttributeError: self.getAndParseRepoSite() for (pkgname, pkgregex, pkgsite) in pkglist: pkgregex=unescape(pkgregex) try: aversions=self.getAndParsePackageSite(pkgname,pkgregex,pkgsite) available_version=aversions[0] except: exc=sys.exc_info() self.addLog("%s: %s %s" % (pkgname,str(exc[0]),str(exc[1]))) self.addLog("%s %s %s %s" % (pkgname, pkgregex, pkgsite, str(aversions))) continue self.addLog("%s added to database. Versions: %s; %s" % (pkgname, available_version, self.repo_versions[pkgname])) self.Packages.addPackage(pkgname, available_version, self.repo_versions[pkgname]) def getAndParsePackageSite(self, pkgname, pkgregex, pkgsite): pkgsite_content=download(pkgsite,self.verbose).read() self.addLog("%s downloaded." % pkgsite) available_versions=re.findall(pkgregex,pkgsite_content) if available_versions == []: self.addLog("Getting version of %s failed." % pkgsite) return [] available_versions=vercmpsort(available_versions) return available_versions def getAndParseRepoSite(self, \ reposite="http://fedoraproject.org/extras/development/SRPMS/", \ repoformat='href="(.*)-(.*?)-.*?\.fc.\.src.rpm"'): reporegex=re.compile(repoformat) site_content=download(reposite, self.verbose).read() self.addLog("RepoSite parsed") self.repo_versions=dict( reporegex.findall(site_content) ) return self.repo_versions def addLog(self,logEntry): if self.verbose == True: print logEntry self.log+=strftime("%d.%m.%y, %H:%M:%S: ",localtime())+logEntry+"\n" def getLog(self): return self.log