Index: package_branches/invirt-web/cherrypy/code/ajaxterm.py
===================================================================
--- package_branches/invirt-web/cherrypy/code/ajaxterm.py (revision 2454)
+++ package_branches/invirt-web/cherrypy/code/ajaxterm.py (revision 2455)
@@ -3,11 +3,5 @@
""" Ajaxterm """
-import array,cgi,fcntl,glob,hashlib,mimetypes,optparse,os,pty,random,re,signal,select,sys,threading,time,termios,struct,pwd
-
-os.chdir(os.path.normpath(os.path.dirname(__file__)))
-# Optional: Add QWeb in sys path
-sys.path[0:0]=glob.glob('../../python')
-
-import qweb
+import array,atexit,cgi,fcntl,glob,hashlib,mimetypes,optparse,os,pty,random,re,signal,select,sys,threading,time,termios,struct,pwd
class Terminal:
@@ -372,4 +366,5 @@
self.thread.daemon=True
self.alive=1
+ atexit.register(self.die)
# synchronize methods
for name in ['create','fds','proc_read','proc_write','dump','die','run']:
@@ -454,96 +449,2 @@
except (IOError,OSError):
pass
-
-class AjaxTerm:
- def __init__(self,cmd=None,index_file='ajaxterm.html'):
- self.files={}
- for i in ['css','html','js']:
- for j in glob.glob('*.%s'%i):
- self.files[j]=file(j).read()
- self.files['index']=file(index_file).read()
- self.mime = mimetypes.types_map.copy()
- self.mime['.html']= 'text/html; charset=UTF-8'
- self.multi = Multiplex(cmd)
- self.session = {}
- def __call__(self, environ, start_response):
- req = qweb.QWebRequest(environ, start_response,session=None)
- if req.PATH_INFO.endswith('/u'):
- s=req.REQUEST["s"]
- k=req.REQUEST["k"]
- c=req.REQUEST["c"]
- w=req.REQUEST.int("w")
- h=req.REQUEST.int("h")
- if s in self.session:
- term=self.session[s]
- else:
- if not (w>2 and w<256 and h>2 and h<100):
- w,h=80,25
- term=self.session[s]=self.multi.create(w,h)
- if k:
- self.multi.proc_write(term,k)
- time.sleep(0.002)
- dump=self.multi.dump(term,c)
- req.response_headers['Content-Type']='text/xml'
- if isinstance(dump,str):
- req.write(dump)
- req.response_gzencode=1
- else:
- del self.session[s]
- req.write('')
-# print "sessions %r"%self.session
- else:
- n=os.path.basename(req.PATH_INFO)
- if n in self.files:
- req.response_headers['Content-Type'] = self.mime.get(os.path.splitext(n)[1].lower(), 'application/octet-stream')
- req.write(self.files[n])
- else:
- req.response_headers['Content-Type'] = 'text/html; charset=UTF-8'
- req.write(self.files['index'])
- return req
-
-def main():
- parser = optparse.OptionParser()
- parser.add_option("-p", "--port", dest="port", default="8022", help="Set the TCP port (default: 8022)")
- parser.add_option("-c", "--command", dest="cmd", default=None,help="set the command (default: /bin/login or ssh localhost)")
- parser.add_option("-l", "--log", action="store_true", dest="log",default=0,help="log requests to stderr (default: quiet mode)")
- parser.add_option("-d", "--daemon", action="store_true", dest="daemon", default=0, help="run as daemon in the background")
- parser.add_option("-P", "--pidfile",dest="pidfile",default="/var/run/ajaxterm.pid",help="set the pidfile (default: /var/run/ajaxterm.pid)")
- parser.add_option("-i", "--index", dest="index_file", default="ajaxterm.html",help="default index file (default: ajaxterm.html)")
- parser.add_option("-u", "--uid", dest="uid", help="Set the daemon's user id")
- (o, a) = parser.parse_args()
- if o.daemon:
- pid=os.fork()
- if pid == 0:
- #os.setsid() ?
- os.setpgrp()
- nullin = file('/dev/null', 'r')
- nullout = file('/dev/null', 'w')
- os.dup2(nullin.fileno(), sys.stdin.fileno())
- os.dup2(nullout.fileno(), sys.stdout.fileno())
- os.dup2(nullout.fileno(), sys.stderr.fileno())
- if os.getuid()==0 and o.uid:
- try:
- os.setuid(int(o.uid))
- except:
- os.setuid(pwd.getpwnam(o.uid).pw_uid)
- else:
- try:
- file(o.pidfile,'w+').write(str(pid)+'\n')
- except:
- pass
- print 'AjaxTerm at http://localhost:%s/ pid: %d' % (o.port,pid)
- sys.exit(0)
- else:
- print 'AjaxTerm at http://localhost:%s/' % o.port
- at=AjaxTerm(o.cmd,o.index_file)
-# f=lambda:os.system('firefox http://localhost:%s/&'%o.port)
-# qweb.qweb_wsgi_autorun(at,ip='localhost',port=int(o.port),threaded=0,log=o.log,callback_ready=None)
- try:
- qweb.QWebWSGIServer(at,ip='localhost',port=int(o.port),threaded=0,log=o.log).serve_forever()
- except KeyboardInterrupt,e:
- sys.excepthook(*sys.exc_info())
- at.multi.die()
-
-if __name__ == '__main__':
- main()
-
Index: package_branches/invirt-web/cherrypy/code/qweb.py
===================================================================
--- package_branches/invirt-web/cherrypy/code/qweb.py (revision 2454)
+++ (revision )
@@ -1,1356 +1,0 @@
-#!/usr/bin/python2.3
-#
-# vim:set et ts=4 fdc=0 fdn=2 fdl=0:
-#
-# There are no blank lines between blocks beacause i use folding from:
-# http://www.vim.org/scripts/script.php?script_id=515
-#
-
-"""= QWeb Framework =
-
-== What is QWeb ? ==
-
-QWeb is a python based [http://www.python.org/doc/peps/pep-0333/ WSGI]
-compatible web framework, it provides an infratructure to quickly build web
-applications consisting of:
-
- * A lightweight request handler (QWebRequest)
- * An xml templating engine (QWebXml and QWebHtml)
- * A simple name based controler (qweb_control)
- * A standalone WSGI Server (QWebWSGIServer)
- * A cgi and fastcgi WSGI wrapper (taken from flup)
- * A startup function that starts cgi, factgi or standalone according to the
- evironement (qweb_autorun).
-
-QWeb applications are runnable in standalone mode (from commandline), via
-FastCGI, Regular CGI or by any python WSGI compliant server.
-
-QWeb doesn't provide any database access but it integrates nicely with ORMs
-such as SQLObject, SQLAlchemy or plain DB-API.
-
-Written by Antony Lesuisse (email al AT udev.org)
-
-Homepage: http://antony.lesuisse.org/qweb/trac/
-
-Forum: [http://antony.lesuisse.org/qweb/forum/viewforum.php?id=1 Forum]
-
-== Quick Start (for Linux, MacOS X and cygwin) ==
-
-Make sure you have at least python 2.3 installed and run the following commands:
-
-{{{
-$ wget http://antony.lesuisse.org/qweb/files/QWeb-0.7.tar.gz
-$ tar zxvf QWeb-0.7.tar.gz
-$ cd QWeb-0.7/examples/blog
-$ ./blog.py
-}}}
-
-And point your browser to http://localhost:8080/
-
-You may also try AjaxTerm which uses qweb request handler.
-
-== Download ==
-
- * Version 0.7:
- * Source [/qweb/files/QWeb-0.7.tar.gz QWeb-0.7.tar.gz]
- * Python 2.3 Egg [/qweb/files/QWeb-0.7-py2.3.egg QWeb-0.7-py2.3.egg]
- * Python 2.4 Egg [/qweb/files/QWeb-0.7-py2.4.egg QWeb-0.7-py2.4.egg]
-
- * [/qweb/trac/browser Browse the source repository]
-
-== Documentation ==
-
- * [/qweb/trac/browser/trunk/README.txt?format=raw Read the included documentation]
- * QwebTemplating
-
-== Mailin-list ==
-
- * Forum: [http://antony.lesuisse.org/qweb/forum/viewforum.php?id=1 Forum]
- * No mailing-list exists yet, discussion should happen on: [http://mail.python.org/mailman/listinfo/web-sig web-sig] [http://mail.python.org/pipermail/web-sig/ archives]
-
-QWeb Components:
-----------------
-
-QWeb also feature a simple components api, that enables developers to easily
-produces reusable components.
-
-Default qweb components:
-
- - qweb_static:
- A qweb component to serve static content from the filesystem or from
- zipfiles.
-
- - qweb_dbadmin:
- scaffolding for sqlobject
-
-License
--------
-qweb/fcgi.py wich is BSD-like from saddi.com.
-Everything else is put in the public domain.
-
-
-TODO
-----
- Announce QWeb to python-announce-list@python.org web-sig@python.org
- qweb_core
- rename request methods into
- request_save_files
- response_404
- response_redirect
- response_download
- request callback_generator, callback_function ?
- wsgi callback_server_local
- xml tags explicitly call render_attributes(t_att)?
- priority form-checkbox over t-value (for t-option)
-
-"""
-
-import BaseHTTPServer,SocketServer,Cookie
-import cgi,datetime,email,email.Message,errno,gzip,os,random,re,socket,sys,tempfile,time,types,urllib,urlparse,xml.dom
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
-try:
- import cStringIO as StringIO
-except ImportError:
- import StringIO
-
-#----------------------------------------------------------
-# Qweb Xml t-raw t-esc t-if t-foreach t-set t-call t-trim
-#----------------------------------------------------------
-class QWebEval:
- def __init__(self,data):
- self.data=data
- def __getitem__(self,expr):
- if self.data.has_key(expr):
- return self.data[expr]
- r=None
- try:
- r=eval(expr,self.data)
- except NameError,e:
- pass
- except AttributeError,e:
- pass
- except Exception,e:
- print "qweb: expression error '%s' "%expr,e
- if self.data.has_key("__builtins__"):
- del self.data["__builtins__"]
- return r
- def eval_object(self,expr):
- return self[expr]
- def eval_str(self,expr):
- if expr=="0":
- return self.data[0]
- if isinstance(self[expr],unicode):
- return self[expr].encode("utf8")
- return str(self[expr])
- def eval_format(self,expr):
- try:
- return str(expr%self)
- except:
- return "qweb: format error '%s' "%expr
-# if isinstance(r,unicode):
-# return r.encode("utf8")
- def eval_bool(self,expr):
- if self.eval_object(expr):
- return 1
- else:
- return 0
-class QWebXml:
- """QWeb Xml templating engine
-
- The templating engine use a very simple syntax, "magic" xml attributes, to
- produce any kind of texutal output (even non-xml).
-
- QWebXml:
- the template engine core implements the basic magic attributes:
-
- t-att t-raw t-esc t-if t-foreach t-set t-call t-trim
-
- """
- def __init__(self,x=None,zipname=None):
- self.node=xml.dom.Node
- self._t={}
- self._render_tag={}
- prefix='render_tag_'
- for i in [j for j in dir(self) if j.startswith(prefix)]:
- name=i[len(prefix):].replace('_','-')
- self._render_tag[name]=getattr(self.__class__,i)
-
- self._render_att={}
- prefix='render_att_'
- for i in [j for j in dir(self) if j.startswith(prefix)]:
- name=i[len(prefix):].replace('_','-')
- self._render_att[name]=getattr(self.__class__,i)
-
- if x!=None:
- if zipname!=None:
- import zipfile
- zf=zipfile.ZipFile(zipname, 'r')
- self.add_template(zf.read(x))
- else:
- self.add_template(x)
- def register_tag(self,tag,func):
- self._render_tag[tag]=func
- def add_template(self,x):
- if hasattr(x,'documentElement'):
- dom=x
- elif x.startswith("%s%s%s>"%(name,g_att,pre,inner,name)
- else:
- return "<%s%s/>"%(name,g_att)
-
- # Attributes
- def render_att_att(self,e,an,av,v):
- if an.startswith("t-attf-"):
- att,val=an[7:],self.eval_format(av,v)
- elif an.startswith("t-att-"):
- att,val=(an[6:],self.eval_str(av,v))
- else:
- att,val=self.eval_object(av,v)
- return ' %s="%s"'%(att,cgi.escape(val,1))
-
- # Tags
- def render_tag_raw(self,e,t_att,g_att,v):
- return self.eval_str(t_att["raw"],v)
- def render_tag_rawf(self,e,t_att,g_att,v):
- return self.eval_format(t_att["rawf"],v)
- def render_tag_esc(self,e,t_att,g_att,v):
- return cgi.escape(self.eval_str(t_att["esc"],v))
- def render_tag_escf(self,e,t_att,g_att,v):
- return cgi.escape(self.eval_format(t_att["escf"],v))
- def render_tag_foreach(self,e,t_att,g_att,v):
- expr=t_att["foreach"]
- enum=self.eval_object(expr,v)
- if enum!=None:
- var=t_att.get('as',expr).replace('.','_')
- d=v.copy()
- size=-1
- if isinstance(enum,types.ListType):
- size=len(enum)
- elif isinstance(enum,types.TupleType):
- size=len(enum)
- elif hasattr(enum,'count'):
- size=enum.count()
- d["%s_size"%var]=size
- d["%s_all"%var]=enum
- index=0
- ru=[]
- for i in enum:
- d["%s_value"%var]=i
- d["%s_index"%var]=index
- d["%s_first"%var]=index==0
- d["%s_even"%var]=index%2
- d["%s_odd"%var]=(index+1)%2
- d["%s_last"%var]=index+1==size
- if index%2:
- d["%s_parity"%var]='odd'
- else:
- d["%s_parity"%var]='even'
- if isinstance(i,types.DictType):
- d.update(i)
- else:
- d[var]=i
- ru.append(self.render_element(e,g_att,d))
- index+=1
- return "".join(ru)
- else:
- return "qweb: t-foreach %s not found."%expr
- def render_tag_if(self,e,t_att,g_att,v):
- if self.eval_bool(t_att["if"],v):
- return self.render_element(e,g_att,v)
- else:
- return ""
- def render_tag_call(self,e,t_att,g_att,v):
- # TODO t-prefix
- if t_att.has_key("import"):
- d=v
- else:
- d=v.copy()
- d[0]=self.render_element(e,g_att,d)
- return self.render(t_att["call"],d)
- def render_tag_set(self,e,t_att,g_att,v):
- if t_att.has_key("eval"):
- v[t_att["set"]]=self.eval_object(t_att["eval"],v)
- else:
- v[t_att["set"]]=self.render_element(e,g_att,v)
- return ""
-
-#----------------------------------------------------------
-# QWeb HTML (+deprecated QWebFORM and QWebOLD)
-#----------------------------------------------------------
-class QWebURL:
- """ URL helper
- assert req.PATH_INFO== "/site/admin/page_edit"
- u = QWebURL(root_path="/site/",req_path=req.PATH_INFO)
- s=u.url2_href("user/login",{'a':'1'})
- assert s=="../user/login?a=1"
-
- """
- def __init__(self, root_path="/", req_path="/",defpath="",defparam={}):
- self.defpath=defpath
- self.defparam=defparam
- self.root_path=root_path
- self.req_path=req_path
- self.req_list=req_path.split("/")[:-1]
- self.req_len=len(self.req_list)
- def decode(self,s):
- h={}
- for k,v in cgi.parse_qsl(s,1):
- h[k]=v
- return h
- def encode(self,h):
- return urllib.urlencode(h.items())
- def request(self,req):
- return req.REQUEST
- def copy(self,path=None,param=None):
- npath=self.defpath
- if path:
- npath=path
- nparam=self.defparam.copy()
- if param:
- nparam.update(param)
- return QWebURL(self.root_path,self.req_path,npath,nparam)
- def path(self,path=''):
- if not path:
- path=self.defpath
- pl=(self.root_path+path).split('/')
- i=0
- for i in range(min(len(pl), self.req_len)):
- if pl[i]!=self.req_list[i]:
- break
- else:
- i+=1
- dd=self.req_len-i
- if dd<0:
- dd=0
- return '/'.join(['..']*dd+pl[i:])
- def href(self,path='',arg={}):
- p=self.path(path)
- tmp=self.defparam.copy()
- tmp.update(arg)
- s=self.encode(tmp)
- if len(s):
- return p+"?"+s
- else:
- return p
- def form(self,path='',arg={}):
- p=self.path(path)
- tmp=self.defparam.copy()
- tmp.update(arg)
- r=''.join([''%(k,cgi.escape(str(v),1)) for k,v in tmp.items()])
- return (p,r)
-class QWebField:
- def __init__(self,name=None,default="",check=None):
- self.name=name
- self.default=default
- self.check=check
- # optional attributes
- self.type=None
- self.trim=1
- self.required=1
- self.cssvalid="form_valid"
- self.cssinvalid="form_invalid"
- # set by addfield
- self.form=None
- # set by processing
- self.input=None
- self.css=None
- self.value=None
- self.valid=None
- self.invalid=None
- self.validate(1)
- def validate(self,val=1,update=1):
- if val:
- self.valid=1
- self.invalid=0
- self.css=self.cssvalid
- else:
- self.valid=0
- self.invalid=1
- self.css=self.cssinvalid
- if update and self.form:
- self.form.update()
- def invalidate(self,update=1):
- self.validate(0,update)
-class QWebForm:
- class QWebFormF:
- pass
- def __init__(self,e=None,arg=None,default=None):
- self.fields={}
- # all fields have been submitted
- self.submitted=False
- self.missing=[]
- # at least one field is invalid or missing
- self.invalid=False
- self.error=[]
- # all fields have been submitted and are valid
- self.valid=False
- # fields under self.f for convenience
- self.f=self.QWebFormF()
- if e:
- self.add_template(e)
- # assume that the fields are done with the template
- if default:
- self.set_default(default,e==None)
- if arg!=None:
- self.process_input(arg)
- def __getitem__(self,k):
- return self.fields[k]
- def set_default(self,default,add_missing=1):
- for k,v in default.items():
- if self.fields.has_key(k):
- self.fields[k].default=str(v)
- elif add_missing:
- self.add_field(QWebField(k,v))
- def add_field(self,f):
- self.fields[f.name]=f
- f.form=self
- setattr(self.f,f.name,f)
- def add_template(self,e):
- att={}
- for (an,av) in e.attributes.items():
- an=str(an)
- if an.startswith("t-"):
- att[an[2:]]=av.encode("utf8")
- for i in ["form-text", "form-password", "form-radio", "form-checkbox", "form-select","form-textarea"]:
- if att.has_key(i):
- name=att[i].split(".")[-1]
- default=att.get("default","")
- check=att.get("check",None)
- f=QWebField(name,default,check)
- if i=="form-textarea":
- f.type="textarea"
- f.trim=0
- if i=="form-checkbox":
- f.type="checkbox"
- f.required=0
- self.add_field(f)
- for n in e.childNodes:
- if n.nodeType==n.ELEMENT_NODE:
- self.add_template(n)
- def process_input(self,arg):
- for f in self.fields.values():
- if arg.has_key(f.name):
- f.input=arg[f.name]
- f.value=f.input
- if f.trim:
- f.input=f.input.strip()
- f.validate(1,False)
- if f.check==None:
- continue
- elif callable(f.check):
- pass
- elif isinstance(f.check,str):
- v=f.check
- if f.check=="email":
- v=r"/^[^@#!& ]+@[A-Za-z0-9-][.A-Za-z0-9-]{0,64}\.[A-Za-z]{2,5}$/"
- if f.check=="date":
- v=r"/^(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/"
- if not re.match(v[1:-1],f.input):
- f.validate(0,False)
- else:
- f.value=f.default
- self.update()
- def validate_all(self,val=1):
- for f in self.fields.values():
- f.validate(val,0)
- self.update()
- def invalidate_all(self):
- self.validate_all(0)
- def update(self):
- self.submitted=True
- self.valid=True
- self.errors=[]
- for f in self.fields.values():
- if f.required and f.input==None:
- self.submitted=False
- self.valid=False
- self.missing.append(f.name)
- if f.invalid:
- self.valid=False
- self.error.append(f.name)
- # invalid have been submitted and
- self.invalid=self.submitted and self.valid==False
- def collect(self):
- d={}
- for f in self.fields.values():
- d[f.name]=f.value
- return d
-class QWebURLEval(QWebEval):
- def __init__(self,data):
- QWebEval.__init__(self,data)
- def __getitem__(self,expr):
- r=QWebEval.__getitem__(self,expr)
- if isinstance(r,str):
- return urllib.quote_plus(r)
- else:
- return r
-class QWebHtml(QWebXml):
- """QWebHtml
- QWebURL:
- QWebField:
- QWebForm:
- QWebHtml:
- an extended template engine, with a few utility class to easily produce
- HTML, handle URLs and process forms, it adds the following magic attributes:
-
- t-href t-action t-form-text t-form-password t-form-textarea t-form-radio
- t-form-checkbox t-form-select t-option t-selected t-checked t-pager
-
- # explication URL:
- # v['tableurl']=QWebUrl({p=afdmin,saar=,orderby=,des=,mlink;meta_active=})
- # t-href="tableurl?desc=1"
- #
- # explication FORM: t-if="form.valid()"
- # Foreach i
- # email:
- #
- #
- # Simple forms:
- #
- #
- #
- #
- #
- #
- #