[pygr-notify] [pygr commit] r106 - contrib

codesite-noreply at google.com codesite-noreply at google.com
Fri Sep 19 09:37:49 PDT 2008


Author: istvan.albert
Date: Fri Sep 19 09:37:34 2008
New Revision: 106

Added:
    contrib/datalisting_httpserver.py   (contents, props changed)

Log:
Added a simple httpserver that generates a page that lists the pygr.Data  
resources. See docstrings for usage.

Added: contrib/datalisting_httpserver.py
==============================================================================
--- (empty file)
+++ contrib/datalisting_httpserver.py	Fri Sep 19 09:37:34 2008
@@ -0,0 +1,159 @@
+"""
+Starts a webserver on a specified host and port that lists all the  
available pygr.Data
+resources as a hierarchical tree.
+
+Usage:
+
+run the module on its own or execute the module level function with the  
signature:
+
+start_server(host='localhost', port=8080)
+
+$Rev$
+$Author$
+$Date$
+"""
+import sys
+import pygr.Data
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+
+def info( msg, stream=sys.stdout ):
+    "A logging function that prints messages to a stream"
+    stream.write( 'INFO: %s\n' % msg)
+    stream.flush()
+
+def human_bytes( value ):
+    """
+    Returns a size as human readable bytes
+
+    >>> human_bytes(100), human_bytes(10**4), human_bytes(10**8),  
human_bytes(10**10)
+    ('100 bytes', '9 Kbytes', '95 Mbytes', '9 Gbytes')
+    """
+    if value < 1024: return "%s bytes" % value
+    elif value < 1048576: return "%s Kbytes" % int(value/1024)
+    elif value < 1073741824: return "%s Mbytes" % int(value/1048576)
+    else: return "%s Gbytes" % int(value/1073741824)
+
+class RequestHandler(BaseHTTPRequestHandler):
+
+    def mime_headers(self, code=200, mimetype="text/html"):
+        "Sets server headers"
+        self.send_response(code)
+        self.send_header('Content-type', mimetype )
+        self.end_headers()
+
+    def write(self, msg):
+        "Write to the return page"
+        self.wfile.write( str(msg) )
+
+    def do_GET(self):
+        try:
+            self.mime_headers()
+            page = html_page()
+            self.write( page )
+        except Exception, exc:
+            self.send_error(500,'%s' % exc)
+
+class Leaf( object ):
+    "Represents an end node of the tree"
+    def __init__(self, name, attrs):
+        self.name = name
+        self.size = human_bytes (attrs['pickle_size'])
+        self.doc  = attrs['__doc__']
+
+    def render(self, depth):
+        "Renders a node as html"
+        shift = '\t'* depth
+        tags = [ '<div class="leaf">%(name)s' % self.__dict__ ]
+        tags.append( '\t<div class="doc">%(doc)s</div>' % self.__dict__ )
+        tags.append( '\t<div class="doc">Size=%(size)s</div>' %  
self.__dict__ )
+        tags.append( '</div>' )
+        tags = [ shift + t for t in tags ]
+        return '\n'.join(tags)
+
+class Tree(object):
+    "Represents a tree and allows it to be rendered as HTML"
+    def __init__(self):
+        self.root = {}
+        self.leafcount = 0
+
+    def build( self, data ):
+        """
+        Builds a tree based on pygr.Data.dir('', asDict=True) type  
dictionary
+
+        """
+
+        # will extract the hierarchy from the dot separated fields
+        for fields, values in data.items():
+            base  = self.root
+            elems = fields.split('.') + [ None ]
+            for name, next in zip(elems, elems[1:]):
+                if name not in base:
+                    if next is None:
+                        base[name] = Leaf( name=name, attrs=values )
+                        self.leafcount += 1
+                    else:
+                        base[name] = {}
+                base = base[name]
+
+    def render( self, root=None, depth=0, out=None):
+        "Renders the tree as HTML"
+        root = root or self.root
+        out  = out or []
+        shift = '\t' * depth # makes it look nicer in plaintext
+        for name, node in root.items():
+            if isinstance(node, Leaf):
+                out.append( node.render( depth=depth ) )
+            else:
+                out.append( shift + '<div class="node">%s' % name )
+                self.render( root=node, depth=depth+1, out=out )
+                out.append( shift + "</div>" )
+        return out
+
+def html_page():
+    "Builds the HTML page that will be returned"
+
+    reload( pygr.Data )
+
+    data = pygr.Data.dir('', asDict=True)
+
+    tree = Tree()
+    tree.build( data )
+    found = tree.leafcount
+
+    page = []
+    page.append("<html><head>")
+    page.append("""
+    <style type="text/css">
+        body  { font-family: arial  }
+        .node { padding-left: 50px; font-weight:bold; font-family: arial  }
+        .leaf { padding-left: 50px; }
+        .doc  { padding-left: 50px; font-weight:normal;}
+    </style>
+    """)
+    page.append("</head>")
+    page.append("<h2>pygr.Data resource listing: found %s  
resources</h2>" % found)
+
+    page.extend( tree.render() )
+    page.append("</body></html>")
+
+    return '\n'.join(page)
+
+def server_start(host='localhost', port=8080):
+    """
+    Starts a HTTP server on the host and port specified as parameters
+    The server will list the available pygr.Data entities
+    """
+    try:
+        server = HTTPServer((host, port), RequestHandler)
+        info("starting httpserver on '%s:%s'"  % (host, port) )
+        server.serve_forever()
+    except KeyboardInterrupt:
+        inf( '^C received, shutting down server' )
+        server.socket.close()
+
+if __name__ == '__main__':
+
+    #print html_page()
+
+    server_start(host='localhost', port=8080)
+
\ No newline at end of file



More information about the pygr-notify mailing list