SOURCES: rpmlist.py (NEW) - inspired by the Java API documentation...

witekfl witekfl at pld-linux.org
Thu Oct 25 18:08:18 CEST 2007


Author: witekfl                      Date: Thu Oct 25 16:08:18 2007 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- inspired by the Java API documentation
- feel free to improve it

---- Files affected:
SOURCES:
   rpmlist.py (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/rpmlist.py
diff -u /dev/null SOURCES/rpmlist.py:1.1
--- /dev/null	Thu Oct 25 18:08:18 2007
+++ SOURCES/rpmlist.py	Thu Oct 25 18:08:13 2007
@@ -0,0 +1,319 @@
+#!/usr/bin/python
+# vim:fileencoding=UTF-8
+# $Revision$, $Date$
+
+import BaseHTTPServer, cgi, datetime, locale, os, poldek, re, rpm, sys, urllib
+
+TYP_RPM = 0
+TYP_POLDEK = 1
+grupy = {}
+pakiety = []
+index_html = '''<html><head><title>RPM View</title></head><frameset cols="20%,80%"><frameset rows="30%,70%">
+<frame src="/grupy" name="a" /><frame src="/gr?n=A" name="b" /></frameset><frame src="about:blank" name="c" /></frameset></html>'''
+
+rpm_pattern = re.compile('^(.*)-(.*)-(.*)\.(.*)$')
+poldek_pattern = re.compile('(.*);')
+
+def compare(a, b):
+	"Compare two packages by name."
+	global TYP_RPM
+	(pak1, napis1, typ1) = a
+	(pak2, napis2, typ2) = b
+	w = cmp(napis1, napis2)
+	if w == 0:
+		if typ1 == TYP_RPM:
+			return 1
+		else:
+			return -1
+	return w
+
+def sort_and_uniq():
+	"Sorts packages and remove duplicates."
+	global pakiety
+	pakiety.sort(compare)
+	liczba = len(pakiety)
+	lista = []
+	for i in xrange(liczba - 2):
+		(pkg, napis, typ) = pakiety[i]
+		(pkg_next, napis_next, typ_next) = pakiety[i + 1]
+		if (napis != napis_next):
+			lista.append((pkg, napis, typ))
+	pakiety = lista
+
+def show_groups():
+	"Show groups."
+	global grupy
+	html = '<a href="reload">Reload database</a><hr/>\nGroups<br/>\n<pre>\n<a href="gr?n=A" target="b">All</a>\n'
+	nazwy = grupy.keys()
+	nazwy.sort()
+	for gr in nazwy:
+		html += '<a href="gr?n=' + gr + '" target="b">' + gr + '</a>\n'
+	return html
+
+def show_packages(lista):
+	"Show packages from given list."
+	html = '<pre>\n'
+	for (gr, napis, typ) in lista:
+		html += '<a href="pkgs?n=' + urllib.quote(napis) + '" target="c">' + napis + '</a>\n'
+	html += '</pre>\n'
+	return html
+
+def show_packages_from_group(name="A"):
+	"Show packages from given group. A means all packages."
+	global pakiety
+	if name == "A":
+		html = '<br/>All packages:<br/>\n'
+		html += show_packages(pakiety)
+	else:
+		html = '<br/>Packages from group(' + name + '):<br/>\n'
+		lista = [(gr, napis, typ) for (gr, napis, typ) in pakiety if gr == name]
+		html += show_packages(lista)
+	return html
+
+def load_packages():
+	"Load installed packages and from poldek's database."
+	global grupy, pakiety, pak, pyl
+	grupy = {}
+	pakiety = []
+	pak.load_packages()
+	pyl.load_packages()
+	sort_and_uniq()
+
+class RPM_package:
+	"Contains methods related to installed packages."
+	def load_packages(self):
+		"Load info about installed packages."
+		global TYP_RPM, grupy, pakiety
+		ts = rpm.TransactionSet()
+		ts.openDB()
+		for h in ts.dbMatch():
+			gr = h[rpm.RPMTAG_GROUP]
+			napis = "%s-%s-%s.%s" % (h[rpm.RPMTAG_NAME], h[rpm.RPMTAG_VERSION], h[rpm.RPMTAG_RELEASE], h[rpm.RPMTAG_ARCH])
+			if grupy.has_key(gr):
+				grupy[gr] += 1
+			else:
+				grupy[gr] = 1
+			pakiety.append((gr, napis, TYP_RPM))
+		ts.closeDB()
+
+	def optional_tags(self, h, name, flags, version):
+		"Helper function."
+		html = ''
+		ile = len(h[name])
+		for i in xrange(ile):
+			html += h[name][i] + ' '
+			f = h[flags][i]
+			if f & rpm.RPMSENSE_LESS:
+				html += '<'
+			if f & rpm.RPMSENSE_GREATER:
+				html += '>'
+			if f & rpm.RPMSENSE_EQUAL:
+				html += '='
+			html += ' ' + h[version][i] + '\n'
+		return html
+
+	def package_info(self, name):
+		"Show info about an installed package with given name-version-release.arch ."
+		global pakiety, rpm_pattern
+		html = '<hr/>'
+		m = rpm_pattern.search(name)
+		if not m:
+			return False
+		n = m.group(1)
+		ver = m.group(2)
+		rel = m.group(3)
+		arch = m.group(4)
+		ts = rpm.TransactionSet()
+		mi = ts.dbMatch('name', n)
+		mi.pattern('version', rpm.RPMMIRE_DEFAULT, ver)
+		mi.pattern('release', rpm.RPMMIRE_DEFAULT, rel)
+		mi.pattern('arch', rpm.RPMMIRE_DEFAULT, arch)
+		found = False
+		for h in mi:
+			found = True
+			html += 'Package: ' + '%s-%s-%s.%s<br/>\n' % (h[rpm.RPMTAG_NAME], h[rpm.RPMTAG_VERSION], h[rpm.RPMTAG_RELEASE], h[rpm.RPMTAG_ARCH])
+			if h[rpm.RPMTAG_EPOCH]:
+				html += 'Epoch: %d<br/>\n' % (h[rpm.RPMTAG_EPOCH])
+			html += 'Group: ' + h[rpm.RPMTAG_GROUP] + '<br/>\n'
+			html += 'Size: %d<br/>\n' % h[rpm.RPMTAG_SIZE]
+			if h[rpm.RPMTAG_URL]:
+				html += 'URL: <a href="' + h[rpm.RPMTAG_URL] + '">' + h[rpm.RPMTAG_URL] + '</a><br/>\n'
+			build_date = datetime.datetime.fromtimestamp(h[rpm.RPMTAG_BUILDTIME])
+			html += 'Build time: ' + str(build_date) + '<br/>\n'
+			if h[rpm.RPMTAG_INSTALLTIME]:
+				install_date = datetime.datetime.fromtimestamp(h[rpm.RPMTAG_INSTALLTIME])
+				html += 'Install time: ' + str(install_date) + '<br/>\n'
+			html += 'Build host: ' + h[rpm.RPMTAG_BUILDHOST] + '<br/>\n'
+			if h[rpm.RPMTAG_SOURCERPM]:
+				html += "Source rpm: " + h[rpm.RPMTAG_SOURCERPM] + '<br/>\n'
+			html += 'Summary: ' + h[rpm.RPMTAG_SUMMARY] + '<br/>\n'
+			html += 'Description: <pre>' + h[rpm.RPMTAG_DESCRIPTION] + '</pre><hr/>\nProvides: <pre>'
+
+			html += self.optional_tags(h, rpm.RPMTAG_PROVIDENAME, rpm.RPMTAG_PROVIDEFLAGS, rpm.RPMTAG_PROVIDEVERSION)
+
+			html += '</pre><hr/>Requires: <pre>'
+			html += self.optional_tags(h, rpm.RPMTAG_REQUIRENAME, rpm.RPMTAG_REQUIREFLAGS, rpm.RPMTAG_REQUIREVERSION)
+
+			html += '</pre><hr/>Suggests: <pre>'
+			html += self.optional_tags(h, rpm.RPMTAG_SUGGESTSNAME, rpm.RPMTAG_SUGGESTSFLAGS, rpm.RPMTAG_SUGGESTSVERSION)
+			html += '</pre><hr/>Files: <pre>'
+			for plik in h[rpm.RPMTAG_OLDFILENAMES]:
+				html += plik + '\n'
+			html += '</pre><hr/>Changelog:<br/><pre>\n'
+			try:
+				html += h[rpm.RPMTAG_CHANGELOGTEXT][0]
+			except TypeError:
+				pass
+			html += '</pre><hr/>\n'
+		if found:
+			return html
+		return False
+
+class Pyldek:
+	"Contains methods related to poldek's packages."
+	def __init__(self):
+		ctx = poldek.poldek_ctx()
+		ctx.load_config()
+
+		if not ctx.setup():
+			raise RuntimeError, "poldek setup failed"
+
+		self.ctx = ctx
+		self.cctx = poldek.poclidek_ctx(ctx)
+
+	def return_packages(self):
+		cmd = self.cctx.rcmd()
+		if cmd.execute("ls"):
+			return cmd.packages
+
+	def load_packages(self):
+		"Load information about packages from poldek's database."
+		global TYP_POLDEK, grupy, pakiety
+		self.cctx.load_packages(self.cctx.LOAD_ALL)
+		packages = self.return_packages()
+		for pkg in packages:
+			gr = pkg.group
+			napis = "%s-%s-%s.%s" % (pkg.name, pkg.ver, pkg.rel, pkg.arch())
+			if grupy.has_key(gr):
+				grupy[gr] += 1
+			else:
+				grupy[gr] = 1
+			pakiety.append((gr, napis, TYP_POLDEK))
+
+	def package_info(self, name):
+		"Show info about package given as name-version-release.arch ."
+		html = '<hr/>'
+		cmd = self.cctx.rcmd()
+		command = "ls %s" % name
+		if not cmd.execute(command):
+			return html
+		packages = cmd.packages
+		for pkg in packages:
+			inf = pkg.uinf()
+			if not inf:
+				continue
+			html += 'Package: ' + '%s-%s-%s.%s<br/>\n' % (pkg.name, pkg.ver, pkg.rel, pkg.arch())
+			if pkg.epoch:
+				html += 'Epoch: %d<br/>\n' % (pkg.epoch)
+			html += 'Group: ' + pkg.group + '<br/>\n'
+			html += 'Size: %d<br/>\n' % pkg.size
+			if inf.url:
+				html += 'URL: <a href="' + inf.url + '">' + inf.url + '</a><br/>\n'
+			build_date = datetime.datetime.fromtimestamp(pkg.btime)
+			html += 'Build time: ' + str(build_date) + '<br/>\n'
+			if pkg.itime:
+				install_date = datetime.datetime.fromtimestamp(pkg.itime)
+				html += 'Install time: ' + str(install_date) + '<br/>\n'
+			html += 'Build host: ' + inf.buildhost + '<br/>\n'
+#			if h[rpm.RPMTAG_SOURCERPM]:
+#				html += "Source rpm: " + h[rpm.RPMTAG_SOURCERPM] + '<br/>\n'
+			html += 'Summary: ' + inf.summary + '<br/>\n'
+			html += 'Description: <pre>' + inf.description + '</pre><hr/>\nProvides: <pre>'
+
+			for prov in pkg.provides:
+				html += str(prov) + '\n'
+			html += '</pre><hr/>Requires: <pre>'
+
+			for req in pkg.requires:
+				html += str(req) + '\n'
+
+			html += '</pre><hr/>Suggests: <pre>'
+			for sug in pkg.suggests:
+				html += str(sug) + '\n'
+			html += '</pre><hr/>Files: <pre>'
+			for (filename, filesize, filemode) in pkg.files:
+				html += filename + '\n'
+#			html += '</pre><hr/>Changelog:<br/><pre>\n'
+#			try:
+#				html += h[rpm.RPMTAG_CHANGELOGTEXT][0]
+#			except TypeError:
+#				pass
+			html += '</pre><hr/>\n'
+		return html
+
+
+
+class Serwer(BaseHTTPServer.BaseHTTPRequestHandler):
+	"Server WWW."
+	def send_html(self, html):
+		"Sends response."
+		global content_type
+		self.send_response(200)
+		self.send_header('Content-Type', content_type)
+		self.end_headers()
+		self.wfile.write(html)
+
+	def do_GET(self):
+		"GET method handler."
+		global pak, pyl, pakiety, grupy
+		if self.path == '/':
+			global index_html
+			self.send_html(index_html)
+		elif self.path == '/reload':
+			load_packages()
+			html = show_groups()
+			self.send_html(html)
+		elif self.path == '/grupy':
+			html = show_groups()
+			self.send_html(html)
+		else:
+			lista = cgi.parse_qsl(self.path)
+			if len(lista) >= 1:
+				(prefix, name) = lista[0]
+				if prefix == '/gr?n':
+					html = show_packages_from_group(name)	
+					self.send_html(html)
+				elif prefix == '/pkgs?n':
+					global poldek_pattern
+					html = pak.package_info(name)
+					if not html:
+						m = poldek_pattern.search(name)
+						if m:
+							html = pyl.package_info(m.group(1))
+						else:
+							html = pyl.package_info(name)
+					self.send_html(html)
+			else:
+				self.send_error(404)
+
+def run(server_class = BaseHTTPServer.HTTPServer, handler_class = Serwer, port = 9999):
+	"Starts a http server."
+        server_address = ('', port)
+        httpd = server_class(server_address, handler_class)
+        httpd.serve_forever()
+
+
+if __name__ == '__main__':
+	locale.setlocale(locale.LC_ALL, '')
+	content_type = 'text/html; charset=%s' % locale.nl_langinfo(locale.CODESET)
+	pak = RPM_package()
+	poldek.lib_init()
+	pyl = Pyldek()
+	load_packages()
+
+	if len(sys.argv) > 1:
+		p = int(sys.argv[1])
+	else:
+		p = 9999
+	sys.stderr.write('Started on port %d\n' % p)
+	run(port=p)
================================================================


More information about the pld-cvs-commit mailing list