From: Troy Dack <troy@tkdack.com>
To: gentoo-dev@gentoo.org
Subject: [gentoo-dev] Portage http interface
Date: 16 Nov 2002 02:26:15 +1100 [thread overview]
Message-ID: <1037373976.32414.9.camel@waterhouse.internal.lan> (raw)
[-- Attachment #1: Type: text/plain, Size: 666 bytes --]
Hi all,
I've just started playing with/learning about python and while reading
the docs noticed that it had a http server module. So I thought I'd
have a bash at throwing together a webmin type front end for portage.
Th results are attached. It's not very functional at the moment, but I
thought I'd share it and get peoples opinions.
Installation is simple:
1. Save the attachment somewhere comfortable as: portageserver.py
2. make it executable (chmod o+x portageserver.py)
3. run it /path/to/portageserver.py
Usage is even easier, just point your browser @ http://localhost:9000
Let me know what you think.
Thanks
--
Troy Dack
http://linux.tkdack.com
[-- Attachment #2: portageserver.py --]
[-- Type: text/x-python, Size: 5578 bytes --]
#!/usr/bin/env python2.2
import SocketServer
import BaseHTTPServer
import sys
import os
import cgi
import socket
import urllib
import portage
from string import *
class ClientAbortedException(Exception):
pass
class PortageServer(BaseHTTPServer.HTTPServer):
def __init__(self):
SocketServer.TCPServer.__init__(
self,
('127.0.0.1', 9000),
PortageRequestHandler)
def server_bind(self):
# set SO_REUSEADDR (if available on this platform)
if hasattr(socket, 'SOL_SOCKET') and hasattr(socket, 'SO_REUSEADDR'):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
BaseHTTPServer.HTTPServer.server_bind(self)
class PortageRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
VERSION_SHORT=1
VERSION_RELEASE=2
installcache = portage.db["/"]["vartree"]
PortageTree = {}
for node in portage.portdb.cp_all():
if not PortageTree.has_key(split(node, "/")[0]):
# need to make a new key first
PortageTree[split(node, "/")[0]] = []
# add the package to the list for this category
PortageTree[split(node, "/")[0]].append(split(node, "/")[1])
categories = PortageTree.keys()
categories.sort()
def do_GET(self):
try:
self._perform_GET()
except ClientAbortedException:
pass
def _perform_GET(self):
path = self.translate_path()
if path is None:
self.send_error(400, 'Illegal URL construction')
if len(path) == 0:
self._rootdir()
elif (len(path) == 2) and (path[0] == 'category'):
self._categorydir(path[1])
return
def _rootdir(self):
self.send_response(200)
self.send_header("Content-Type", 'text/html')
self.end_headers()
self.wfile.write("""
<html>
<head>
<title>Gentoo Portage</title>
</head>
<body>
<h1>Categories</h1>
<p><b>""" + str(len(self.PortageTree)) + """</b> Categories</p>\n""")
for category in self.categories:
self.wfile.write("""
<a href="/category/""" + category + """">""" + category + "</a> ( " + str(len(self.PortageTree[category])) + " ) </br>")
self.wfile.write("""
</body>
</html>""")
return
def _categorydir(self, category):
self.send_response(200)
self.send_header("Content-Type", 'text/html')
self.end_headers()
self.wfile.write("""
<html>
<head>
<title>Gentoo Portage - """ + category + """</title>
</head>
<body>
<h1>Packages in: """ + category + """ </h1>
<p><b>""" + str(len(self.PortageTree[category])) + """</b> Packages</p>
<a href="/">Back</a>
<table>
<tr>
<td style="text-align: center">
Emerge?
</td>
<td>
Package Name
</td>
<td>
Latest Available
</td>
<td>
Latest Installed
</td>
<td>
Description
</td>
</tr>""")
i = 0
for app in self.PortageTree[category]:
if i % 2 == 0:
rowcolor = "white"
else:
rowcolor = "light grey"
match = category + "/" + app
masked = ""
full_package = portage.portdb.xmatch("bestmatch-visible",match)
if not full_package:
#no match found; we don't want to query description
full_package=portage.best(portage.portdb.xmatch("match-all",match))
if not full_package:
continue
else:
masked = """</br><span style="color: red;">** Masked **</span>"""
rowcolor = "pink"
try:
full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0]
except KeyError:
print "emerge: search: aux_get() failed, skipping"
continue
myver = self.getVersion(full_package, self.VERSION_RELEASE)
i += 1
self.wfile.write("""
<tr style="background-color: """ + rowcolor + """;">
<td style="text-align: center">
<input type="checkbox">
</td>
<td>
""" + app + """
</td>
<td>
""" + myver + """
</td>
<td>
""" + self.getInstallationStatus(match) + masked + """
</td>
<td>
""" + full_desc + """
</td>
</tr>""")
self.wfile.write("""
</table>
</body>
</html>""")
return
def getVersion(self,full_package,detail):
if len(full_package) > 1:
package_parts = portage.catpkgsplit(full_package)
if detail == self.VERSION_RELEASE and package_parts[3] != 'r0':
result = package_parts[2]+ "-" + package_parts[3]
else:
result = package_parts[2]
else:
result = ""
return result
def getInstallationStatus(self,package):
installed_package = portage.portdb.xmatch("bestmatch-visible", package)
result = ""
version = self.getVersion(installed_package,self.VERSION_RELEASE)
if len(version) > 0:
result = version
else:
result = "Not Installed"
return result
def translate_path(self):
parts = split(urllib.unquote(self.path), '/')
parts = filter(None, parts)
while 1:
try:
parts.remove('.')
except ValueError:
break
while 1:
try:
idx = parts.index('..')
except ValueError:
break
if idx == 0:
# illegal path: the '..' attempted to go above the root
return None
del parts[idx-1:idx+1]
return parts
# Main Program
if __name__ == '__main__':
svr = PortageServer()
print "Portage Server: serving on port 8080..."
svr.serve_forever()
[-- Attachment #3: Type: text/plain, Size: 37 bytes --]
--
gentoo-dev@gentoo.org mailing list
next reply other threads:[~2002-11-15 15:27 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-11-15 15:26 Troy Dack [this message]
2002-11-16 8:49 ` [gentoo-dev] Portage http interface Peter Ruskin
2002-11-16 9:39 ` Troy Dack
2002-11-16 10:36 ` Peter Ruskin
2002-11-16 11:43 ` Troy Dack
2002-11-16 12:49 ` Peter Ruskin
2002-11-16 11:47 ` José Fonseca
2002-11-16 12:55 ` Peter Ruskin
2002-11-19 19:55 ` Per Wigren
2002-11-16 13:42 ` Alexander Futasz
2002-11-16 14:10 ` Troy Dack
2002-11-16 14:39 ` Johannes Findeisen
2002-11-16 15:22 ` Troy Dack
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1037373976.32414.9.camel@waterhouse.internal.lan \
--to=troy@tkdack.com \
--cc=gentoo-dev@gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox