Riaan's SysAdmin Blog

My tips, howtos, gotchas, snippets and stuff. Use at your own risk!

Python

webpy Example

A short write up on how to bootstrap a webpy app and at the same time show how to make a system call with popen.  I based this short app on the skeleton example here: http://webpy.org/skeleton/0.3

Just a note on where my test live for my own reference later.

$ pwd
/DATA/src/hvInfo

$ ls
call1.py call.pyc config.pyc hvInfo.pyc my test with spaces_ and more... templates view.pyc web.py-0.37
call.py config.py hvInfo.py index.html simpleHTTP.py view.py web web.py-0.37.tar

Main python app:

hvInfo.py

import web
import view, config
from view import render

urls = (
  '/', 'index'
)

class index:
  def GET(self):
    return render.base(view.listing())

if __name__ == "__main__": 
  app = web.application(urls, globals())
  app.run()

Define some functions here:

call.py

import config
#from subprocess import Popen, PIPE
import subprocess

def listing_experiment1():
    cmd = "ls -l ~/"
    p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
    #out, err = p.communicate()
    #print "Return code: ", p.returncode
    #return out.rstrip(), err.rstrip()
    outputlines = filter(lambda x:len(x)>0,(line.strip() for line in p.stdout))
    return outputlines
    #return out.replace('\n','<br>')

    ##return config.DB.select('items', **k)

def dir_listing():
  ## http://stackoverflow.com/questions/8880461/python-subprocess-output-to-list-or-file
  ls_lines = subprocess.check_output(['ls', '-l']).splitlines()
  ## I want to pass output as separate fields but space as a delimiter won't do the trick since filenames can have spaces...
  ls_arr= []
  for item in ls_lines:
    if not "total" in item:
      f = item.split()
      #fname = item.join(str(v) for v in item.index if v > 7)
      fname = ""
      for idx,val in enumerate(f):
        if idx > 7:
          fname = fname + str(val) + " "
      fname = fname[:-1]
      ls_fields = [f[0],f[1],f[2],f[3],f[4],f[5]+"-"+f[6]+"-"+f[7],fname]
      ls_arr.append(ls_fields)
  return ls_arr

Lets maintain a config file. Especially when DB access becomes necessary.

config.py

import web
#DB = web.database(dbn='postgres', db='appname', user='username', pw='')
cache = False

Following MVC type framework.  It makes sense to keep presentation separate.

view.py

import web
import call
import config

t_globals = dict(
  datestr=web.datestr,
)
render = web.template.render('templates/', cache=config.cache, 
    globals=t_globals)
render._keywords['globals']['render'] = render

def listing():
    l = call.dir_listing()
    return render.listing(l)

Templates as follow:

$ cat templates/base.html
$def with (page, title=None)
<html><head>
<title>hvInfo\
$if title: : $title\
</title>
</head><body>
<h1><a href="/">hvInfo</a></h1>
$:page   
</body></html>
$ cat templates/listing.html
$def with (items)
  <table>
  $for item in items:
    <tr><td>$item[0]<td>$item[1]<td>$item[2]<td>$item[3]<td>$item[4]<td>$item[5]<td><b>$item[6]</b>
  </table>
$ cat templates/item.html
$def with (item)

$item

Run web server as follow:

$ python hvInfo.py
http://0.0.0.0:8080/

Test in browser at this link: http://localhost:8080/

admin

Bio Info for Riaan