|
From: <wgh...@us...> - 2009-08-20 21:41:28
|
Revision: 22475
http://personalrobots.svn.sourceforge.net/personalrobots/?rev=22475&view=rev
Author: wghassan
Date: 2009-08-20 21:41:17 +0000 (Thu, 20 Aug 2009)
Log Message:
-----------
pyclearsilver initial checkin. used by webui
Added Paths:
-----------
pkg/trunk/sandbox/web/pyclearsilver/
pkg/trunk/sandbox/web/pyclearsilver/manifest.xml
pkg/trunk/sandbox/web/pyclearsilver/src/
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/CSPage.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/__init__.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/autoreloader.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/cgistarter.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/fixedpoint.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/guid.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/handle_error.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/hdfhelp.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/httpResponses.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/log.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/odb.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/odb_mysql.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/odb_postgres.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/odb_sqlite.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/odb_sqlite3.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/profiler.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/rebuild_sqlitedb.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/scaffold.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/edit.cs
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/list.cs
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/show.cs
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/sorttable.js
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/style.css
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/templates/tables.cs
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/test.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/test_odb.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/trans/
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/trans/__init__.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/trans/db_trans.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/trans/trans.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/trans/tstart.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/who_calls.py
pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/wordwrap.py
Added: pkg/trunk/sandbox/web/pyclearsilver/manifest.xml
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/manifest.xml (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/manifest.xml 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,11 @@
+<package>
+<description brief="Python Clearsilver">
+Converts ROS topics to JSON for Web requests.
+</description>
+<author>Scott Hassan/ha...@wi...</author>
+<license>BSD</license>
+<review status="experimental" notes=""/>
+<url>http://pr.willowgarage.com/wiki/iros</url>
+<sysdepend os="ubuntu" package="python-clearsilver"/>
+</package>
+
Property changes on: pkg/trunk/sandbox/web/pyclearsilver/manifest.xml
___________________________________________________________________
Added: svn:executable
+ *
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/CSPage.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/CSPage.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/CSPage.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,423 @@
+#!/usr/bin/env python
+
+import neo_cgi, neo_cs
+import sys, os, string
+import time
+from log import *
+
+# errors thrown...
+NoPageName = "NoPageName"
+NoDisplayMethod = "NoDisplayMethod"
+
+# errors signaled back to here
+Redirected = "Redirected"
+DisplayDone = "DisplayDone"
+DisplayError = "DisplayError"
+
+class Context:
+ def __init__ (self):
+ self.argv = sys.argv
+ self.stdin = sys.stdin
+ self.stdout = sys.stdout
+ self.stderr = sys.stderr
+ self.environ = os.environ
+
+ def setStatus(self, request, status):
+ if request:
+ request['status'] = str(status)
+
+
+class CSPage:
+ _pagename = None
+
+ def __init__(self, context, pagename=None,readDefaultHDF=1,israwpage=0,
+ parseCGI=1, makePUT=0, **parms):
+ if pagename is None: pagename = self._pagename
+ if not pagename: raise NoPageName, "missing pagename"
+ self.pagename = pagename
+ self.readDefaultHDF = readDefaultHDF
+ self._israwpage = israwpage
+ self.context = context
+ self._pageparms = parms
+
+ self._error_template = None
+
+ self.page_start_time = time.time()
+
+ if makePUT:
+ context.environ['REQUEST_METHOD'] = 'PUT'
+
+ neo_cgi.cgiWrap(context.stdin, context.stdout, context.environ)
+ neo_cgi.IgnoreEmptyFormVars(1)
+ self.ncgi = neo_cgi.CGI()
+
+ if parseCGI:
+ self.ncgi.parse()
+
+ self._path_num = 0
+ domain = self.ncgi.hdf.getValue("CGI.ServerName","")
+ domain = self.ncgi.hdf.getValue("HTTP.Host", domain)
+ self.domain = domain
+ self.subclassinit()
+ self.setPaths([self.ncgi.hdf.getValue("CGI.DocumentRoot","")])
+
+ self._sent_headers = 0
+ self._reply_headers = {}
+ self._reply_code = 200
+
+ if self.ncgi.hdf.getValue("CGI.HTTPS", ""):
+ self.http = "https://"
+ else:
+ self.http = "http://"
+
+ def __setitem__(self, key, value):
+ self._reply_headers[string.lower(key)] = value
+ self.ncgi.hdf.setValue("cgiout.other.%s" % key, "%s: %s" % (key, value))
+
+ def __getitem__(self, key):
+ return self._reply_headers[string.lower(key)]
+
+ def has_key(self, key):
+ return self._reply_headers.has_key(string.lower(key))
+
+ def subclassinit(self):
+ pass
+
+ def clearPaths(self):
+ self.ncgi.hdf.removeTree("hdf.loadpaths")
+
+ def setPaths(self, paths):
+ for path in paths:
+ self.ncgi.hdf.setValue("hdf.loadpaths.%d" % self._path_num, path)
+ self._path_num = self._path_num + 1
+
+ def redirectUri(self,redirectTo):
+ ncgi = self.ncgi
+ if ncgi.hdf.getIntValue("Cookie.debug",0) == 1:
+ ncgi.hdf.setValue("CGI.REDIRECT_TO",redirectTo)
+# ncgi.display("dbg/redirect.cs")
+
+ cs = neo_cs.CS(ncgi.hdf)
+ self['Content-Type'] = "text/html"
+ template = """
+Redirect
+<br><br>
+<a href="<?cs var:CGI.REDIRECT_TO ?>"><?cs var:CGI.REDIRECT_TO ?></a>
+"""
+ cs.parseStr(template)
+ page = cs.render()
+
+ self.push(page)
+
+ self.push("<PRE>\n")
+ self.push(neo_cgi.htmlEscape(ncgi.hdf.dump()) + "\n")
+ self.push("</PRE>\n")
+ raise DisplayDone
+
+ self.context.setStatus(self, 302)
+ self.ncgi.redirectUri(redirectTo)
+ raise Redirected, "redirected To: %s" % redirectTo
+
+ ## ----------------------------------
+ ## methods to be overridden in subclass when necessary:
+
+ def setup(self):
+ pass
+
+ def display(self):
+ raise NoDisplayMethod, "no display method present in %s" % repr(self)
+
+ def main(self):
+ hdf = self.ncgi.hdf
+
+ def __call(method):
+ if method.im_func.func_code.co_argcount == 2:
+ method(hdf)
+ else:
+ method()
+
+ __call(self.setup)
+
+ self.handle_actions()
+
+ __call(self.display)
+
+ ## ----------------------------------
+
+ def handle_actions(self):
+ hdf = self.ncgi.hdf
+ #warn(hdf.writeString())
+ hdfobj = hdf.getObj("Query.Action")
+ if hdfobj:
+ firstchild = hdfobj.child()
+ if firstchild:
+ action = firstchild.name()
+ if firstchild.next():
+ raise "multiple actions present!!!"
+
+ method_name = "Action_%s" % action
+ method = getattr(self,method_name)
+ if method.im_func.func_code.co_argcount == 2:
+ apply(method,[hdf])
+ else:
+ apply(method,[])
+
+ def start(self):
+ SHOULD_DISPLAY = 1
+ if self._israwpage:
+ SHOULD_DISPLAY = 0
+
+ ncgi = self.ncgi
+
+ if self.readDefaultHDF:
+ try:
+ if not self.pagename is None:
+ ncgi.hdf.readFile("%s.hdf" % self.pagename)
+ except:
+ debug("Error reading HDF file: %s.hdf" % (self.pagename))
+
+ DISPLAY_ERROR = 0
+ ERROR_MESSAGE = ""
+ # call page main function!
+ try:
+ self.main()
+ except DisplayDone:
+ SHOULD_DISPLAY = 0
+ except Redirected:
+ # catch redirect exceptions
+ SHOULD_DISPLAY = 0
+ except DisplayError, num:
+ ncgi.hdf.setValue("Query.error", str(num))
+ if self._error_template:
+ ncgi.hdf.setValue("Content", self._error_template)
+ else:
+ DISPLAY_ERROR = 1
+ except:
+ SHOULD_DISPLAY = 0
+ DISPLAY_ERROR = 1
+
+ import handle_error
+ handle_error.handleException("Display Failed!")
+ ERROR_MESSAGE = handle_error.exceptionString()
+
+ if DISPLAY_ERROR:
+ #print "Content-Type: text/html\n\n"
+
+ # print the page
+
+ self['Content-Type'] = "text/html"
+
+ # print the page
+
+ self.push("<H1> Error in Page </H1>\n")
+ self.push("A copy of this error report has been submitted to the developers. ")
+ self.push("The details of the error report are below.")
+
+ self.push("<PRE>")
+ self.push(handle_error.exceptionString())
+ self.push("</PRE>\n")
+
+ # print debug info always on page error...
+ self.push("<HR>\n")
+ self.push("<PRE>")
+ self.push(neo_cgi.htmlEscape(ncgi.hdf.dump()))
+ self.push("</PRE>")
+
+
+ etime = time.time() - self.page_start_time
+ ncgi.hdf.setValue("CGI.debug.execute_time","%f" % (etime))
+ #warn("excute_time", etime)
+
+ if SHOULD_DISPLAY and self.pagename:
+ debug_output = ncgi.hdf.getIntValue("page.debug",ncgi.hdf.getIntValue("Cookie.debug",0))
+
+ # hijack the built-in debug output method...
+ if ncgi.hdf.getValue("Query.debug","") == ncgi.hdf.getValue("Config.DebugPassword","1"):
+ ncgi.hdf.setValue("Config.DebugPassword","CSPage.py DEBUG hijack (%s)" %
+ ncgi.hdf.getValue("Config.DebugPassword",""))
+ debug_output = 1
+
+ if not debug_output:
+ ncgi.hdf.setValue("Config.CompressionEnabled","1")
+ else:
+ ncgi.hdf.setValue("Config.CompressionEnabled","0")
+
+ # default display
+ template_name = ncgi.hdf.getValue("Content","%s.cs" % self.pagename)
+ # ncgi.hdf.setValue ("cgiout.charset", "utf-8");
+
+ try:
+ self.context.setStatus(self, 200)
+ ncgi.display(template_name)
+ self._sent_headers = 1
+ except:
+ self['Content-Type'] = 'text/html'
+ self.push("CSPage: Error occured\n")
+ import handle_error
+ self.push("<pre>" + handle_error.exceptionString() + "</pre>")
+ debug_output = 1
+
+
+ # debug output
+ if debug_output:
+ self.push("<HR>\n")
+ self.push("Execution Time: %5.3f<BR><HR>" % (etime))
+ self.push("<PRE>")
+ self.push(neo_cgi.htmlEscape(ncgi.hdf.dump()))
+ self.push("</PRE>")
+ # ncgi.hdf.setValue("hdf.DEBUG",ncgi.hdf.dump())
+ # ncgi.display("debug.cs")
+
+ script_name = ncgi.hdf.getValue("CGI.ScriptName","")
+ if script_name:
+ script_name = string.split(script_name,"/")[-1]
+
+ log ("[%s] etime/dtime: %5.3f/%5.3f %s (%s)" % (self.domain, etime, time.time() - etime - self.page_start_time, script_name, self.pagename))
+ return self._reply_code
+
+ # a protected output function to catch the output errors that occur when
+ # the server is either restarted or the user pushes the stop button on the
+ # browser
+ def output(self, str):
+ try:
+ if len(str) > 8196:
+ import cStringIO
+ fp = cStringIO.StringIO(str)
+ while 1:
+ data = fp.read(8196*8)
+ if not data: break
+ self.context.stdout.write(data)
+ else:
+ self.context.stdout.write(str)
+ except IOError, reason:
+ log("IOError: %s" % (repr(reason)))
+ raise DisplayDone
+
+ def done(self):
+ if not self._sent_headers: self.error(500)
+ self._sent_headers = 0
+
+ raise DisplayDone
+
+ def push(self, data):
+ if not self._sent_headers:
+ headerdata = self.send_headers(dont_send=1)
+ self.output(headerdata + data)
+ else:
+ self.output(data)
+
+
+ def send_headers(self, dont_send=0):
+ self._sent_headers = 1
+
+ message = gHTTPResponses[self._reply_code]
+
+ if self._reply_code != 200:
+ #self['status'] = "%s %s" % (self._reply_code, message)
+ #self.context.setStatus(self, self._reply_code)
+ pass
+ self.context.setStatus(self, self._reply_code)
+ self['connection'] = 'close'
+
+ headers = []
+ #headers.append(self.response(self._reply_code))
+ for (key, value) in self._reply_headers.items():
+ headers.append('%s: %s' % (key, value))
+ headers.append('\r\n')
+
+ if dont_send == 0:
+ self.push(string.join(headers, '\r\n'))
+ else:
+ return string.join(headers, '\r\n')
+
+
+ def allQuery (self, s):
+ l = []
+ if self.ncgi.hdf.getValue ("Query.%s.0" % s, ""):
+ obj = self.ncgi.hdf.getChild ("Query.%s" % s)
+ while obj:
+ l.append(obj.value())
+ obj = obj.next()
+ else:
+ t = self.ncgi.hdf.getValue ("Query.%s" % s, "")
+ if t: l.append(t)
+ return l
+
+
+ def error(self, code, reason=None):
+ self._reply_code = code
+ message = gHTTPResponses[code]
+ s = DEFAULT_ERROR_MESSAGE % {
+ 'code': code, 'message': message, 'reason': reason
+ }
+
+# self['Content-Length'] = len(s)
+# self['Content-Type'] = 'text/html'
+
+# self.push(s)
+ self.context.stdout.write("Content-Type: text/html\n")
+ self.context.setStatus(self, code)
+ self.context.stdout.write("Status: %s\n" % code)
+ self.context.stdout.write(s)
+# self.done()
+
+ raise DisplayDone
+
+
+
+gHTTPResponses = {
+ 100: "Continue",
+ 101: "Switching Protocols",
+ 200: "OK",
+ 201: "Created",
+ 202: "Accepted",
+ 203: "Non-Authoritative Information",
+ 204: "No Content",
+ 205: "Reset Content",
+ 206: "Partial Content",
+ 300: "Multiple Choices",
+ 301: "Moved Permanently",
+ 302: "Moved Temporarily",
+ 303: "See Other",
+ 304: "Not Modified",
+ 305: "Use Proxy",
+ 400: "Bad Request",
+ 401: "Unauthorized",
+ 402: "Payment Required",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 405: "Method Not Allowed",
+ 406: "Not Acceptable",
+ 407: "Proxy Authentication Required",
+ 408: "Request Time-out",
+ 409: "Conflict",
+ 410: "Gone",
+ 411: "Length Required",
+ 412: "Precondition Failed",
+ 413: "Request Entity Too Large",
+ 414: "Request-URI Too Large",
+ 415: "Unsupported Media Type",
+ 500: "Internal Server Error",
+ 501: "Not Implemented",
+ 502: "Bad Gateway",
+ 503: "Service Unavailable",
+ 504: "Gateway Time-out",
+ 505: "HTTP Version not supported"
+ }
+
+# Default error message
+DEFAULT_ERROR_MESSAGE = string.join(
+ ['',
+ '<head>',
+ '<title>%(code)d %(message)s</title>',
+ '</head>',
+ '<body>',
+ '<h1>%(message)s</h1>',
+ '<p>Error code %(code)d.',
+ '<p>Message: %(message)s.',
+ '<p>Reason:\n <pre>%(reason)s</pre>',
+ '</body>',
+ ''
+ ],
+ '\r\n'
+ )
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/__init__.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/__init__.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/__init__.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,9 @@
+versionMajor = 2
+versionMinor = 0
+
+version = (versionMajor, versionMinor)
+
+import odb
+import hdfhelp
+
+
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/autoreloader.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/autoreloader.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/autoreloader.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,61 @@
+#!/neo/opt/bin/python
+
+
+import ihooks, os, sys
+from pyclearsilver.log import *
+
+#ihooks.install(AutoReload())
+
+class AutoReload(ihooks.ModuleImporter):
+ def __init__(self):
+ ihooks.ModuleImporter.__init__(self)
+ self.datestamps = {}
+
+ def import_module(self,name,globals={},locals={},fromlist={}):
+# warn("import_module", name)
+ testpath = name + ".py"
+
+ # stat the file if we have it
+ if os.path.isfile(testpath):
+ stinfo = os.stat(testpath)
+ else:
+ stinfo = None
+
+ if sys.modules.has_key(name):
+# warn("reimporting", testpath)
+ # already imported
+ m = ihooks.ModuleImporter.import_module(self,name,globals,locals,fromlist)
+ try:
+ testpath = m.__file__
+ if os.path.isfile(testpath):
+ stinfo = os.stat(testpath)
+ except AttributeError: pass
+
+ if stinfo:
+
+ stored_time = self.datestamps.get(testpath,0)
+ if stored_time < stinfo.st_mtime:
+
+ self.datestamps[testpath] = stinfo.st_mtime
+ if stored_time:
+ warn("---------------------", name, "changed reloading", stored_time, stinfo.st_mtime, os.getcwd())
+
+ reload(sys.modules[name])
+ else :
+# warn("loading for the first time", testpath)
+ if stinfo:
+ self.datestamps[testpath] = stinfo.st_mtime
+ m = ihooks.ModuleImporter.import_module(self,name,globals,locals,fromlist)
+ try:
+ testpath = m.__file__
+ stinfo = os.stat(testpath)
+ if os.path.isfile(testpath):
+ self.datestamps[testpath] = stinfo.st_mtime
+ except AttributeError:
+ pass
+
+ return m
+
+
+warn("**********************8 installing autoreload")
+ihooks.install(AutoReload())
Property changes on: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/autoreloader.py
___________________________________________________________________
Added: svn:executable
+ *
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/cgistarter.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/cgistarter.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/cgistarter.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,316 @@
+#! /usr/bin/env python
+
+import os, sys, string, time, string
+from pyclearsilver.log import *
+
+#debugfull()
+debugoff()
+
+import gc
+
+try:
+ import warnings
+ warnings.resetwarnings()
+ warnings.filterwarnings("ignore")
+except ImportError:
+ pass
+
+import neo_cgi, neo_cs, neo_util
+
+from pyclearsilver import CSPage
+
+import mimetypes
+mimetypes.init(["/etc/mime.types"])
+
+
+gConfig = None
+def setConfig(config):
+ global gConfig
+ gConfig = config
+
+ if not hasattr(gConfig, "gRequireUsername"): gConfig.gRequireUsername = 0
+ if not hasattr(gConfig, "gDataFilePaths"): gConfig.gDataFilePaths = []
+
+
+def split_path(path):
+ # strip off leading slash, it's no fun!
+ return string.split(path, '/')[1:]
+
+
+class Page:
+ def __init__(self, context):
+ self.context = context
+
+ def setupvars(self):
+
+ self.path = self.context.environ.get("PATH_INFO", '')
+
+ script_name = self.context.environ.get("SCRIPT_NAME",'')
+
+ ## handle the case where the site is located at '/'
+ if not self.path:
+ self.path = script_name
+ script_name = '/'
+
+
+ def start(self):
+ self.setupvars()
+
+ self._path = self.path
+
+ rpath = self._path
+ if not rpath: rpath = '/'
+
+ if rpath == "/": rpath = gConfig.gDefaultPage
+
+ self.path = split_path(rpath)
+
+ username = None
+
+ if len(self.path) == 0:
+ warn("no such path", self.path)
+ self.error(404)
+ return 404
+
+ ## the url form should be:
+ ## /baseuri/username/module/script.py
+
+ cwd = os.getcwd()
+ debug("CWD", cwd)
+
+ module = gConfig.gDefaultModule
+
+ if hasattr(gConfig, "gDataFilePaths"):
+ if self.path[0] in gConfig.gDataFilePaths:
+ fn = apply(os.path.join, [cwd,] + self.path)
+ return outputFile(self.context, fn)
+
+ if gConfig.gRequireUsername:
+ username = self.path[0]
+ n = 1
+ else:
+ n = 0
+
+ debug("self.path", self.path)
+
+ if len(self.path) > 1:
+ module = self.path[n]
+ n = n + 1
+
+ moduleRootPath = apply(os.path.join, ["mod", module])
+ handlerRoot = apply(os.path.join, ["mod", module, "cgibin"])
+ moduleTemplatePath = apply(os.path.join, [cwd, "mod", module, "templates"])
+ systemTemplatePath = apply(os.path.join, [cwd, "templates"])
+ systemJLIBPath = apply(os.path.join, [cwd, "jslib"])
+
+ fn = apply(os.path.join, [cwd, moduleRootPath,] + self.path[n:])
+ debug("fn", fn)
+
+ ## if requesting a file, then just output it to the browser.
+ if os.path.isfile(fn):
+ return outputFile(self.context, fn)
+
+ ## manage the Python module Path
+# sys.path.insert(0, os.path.join(cwd, "pysrc"))
+# sys.path.insert(0, os.path.join(cwd, "pysrc", "base"))
+
+ sys.path.insert(0, os.path.abspath(moduleRootPath))
+ #sys.path.insert(0, os.path.abspath(handlerRoot))
+
+ debug("sys.path", sys.path)
+
+ handlerPath = ''
+
+ ## find the first *real* file in the path
+ ## the rest of the path becomes the pathinfo.
+ m = n
+ for m in range(len(self.path)-1, n-2, -1):
+ handlerPath = apply(os.path.join, [handlerRoot, ] + self.path[n:m+1])
+# warn(m, len(self.path), handlerPath)
+
+ if os.path.isdir(handlerPath):
+ sys.path.insert(0, handlerPath)
+ if os.path.isfile(handlerPath): break
+ if os.path.isdir(handlerPath): break
+
+ if m+1 == len(self.path):
+ pathinfo = ''
+ else:
+ pathinfo = apply(os.path.join, self.path[m+1:])
+
+ if os.path.isdir(handlerPath):
+ modulePath = handlerPath
+ moduleFilename = module + "_index.py"
+ handlerPath = os.path.join(modulePath, moduleFilename)
+ else:
+ modulePath, moduleFilename = os.path.split(handlerPath)
+
+ debug(handlerPath, pathinfo)
+ #warn(handlerPath, pathinfo, modulePath, moduleFilename)
+ #warn("PATH", self.path)
+
+ if not os.path.isfile(handlerPath):
+ self.error(404, handlerPath + " doesn't exist")
+ return 404
+
+ import imp
+
+ moduleName, ext = os.path.splitext(moduleFilename)
+
+ #module = __import__(moduleName)
+ module = __import__("mod.%s.cgibin.%s" % (module, moduleName), {}, {}, (None,))
+
+ os.chdir(modulePath)
+# debug(mod)
+ page = module.run(self.context)
+ page.ncgi.hdf.setValue("CGI.BaseURI", gConfig.gBaseURL)
+
+ if gConfig.gRequireUsername:
+ page.ncgi.hdf.setValue("CGI.Username", username)
+ page.username = username
+
+ if hasattr(page, "checkLoginCookie"):
+ if not page._pageparms.has_key("nologin"):
+ try:
+ page.checkLoginCookie()
+ except CSPage.Redirected:
+ return
+
+ page.ncgi.hdf.setValue("CGI.PathInfo", pathinfo)
+ page.clearPaths()
+ page.setPaths([moduleTemplatePath, systemTemplatePath, systemJLIBPath])
+ ret = page.start()
+
+ try:
+ page.db.close()
+ except AttributeError: pass
+
+ page = None
+
+ return ret
+
+ def error(self, ecode, reason=None):
+ import httpResponses
+ message = httpResponses.gHTTPResponses[ecode]
+
+ template = httpResponses.errorMessage_Default
+ if ecode == 404:
+ template = httpResponses.errorMessage_404
+
+ hdf = neo_util.HDF()
+ hdf.setValue("code", str(ecode))
+ if message: hdf.setValue("message", message)
+ if reason: hdf.setValue("reason", reason)
+
+ for key,val in self.context.environ.items():
+ hdf.setValue("environ." + key, str(val))
+
+ self.context.stdout.write("Content-Type: text/html\r\n")
+ self.context.setStatus(None, ecode)
+ self.context.stdout.write("Status: %s\r\n" % ecode)
+ self.context.stdout.write("\r\n")
+
+ cs = neo_cs.CS(hdf)
+ cs.parseStr(template)
+ page = cs.render()
+
+ self.context.stdout.write(page)
+
+ warn("Error", message, reason)
+
+
+def outputFile(context, fn):
+ fp = open(fn, "rb")
+ data = fp.read()
+ fp.close()
+
+ context.setStatus(None, 200)
+
+ imagetype, encoding = mimetypes.guess_type(fn)
+ debug("imagetype = %s fn = %s" % (imagetype,fn))
+
+ lines = []
+
+ if imagetype:
+ lines.append("Content-Type: %s" % imagetype)
+
+ lines.append("Content-Length: %d" % len(data))
+
+ stat = os.stat(fn)
+ mtime = stat.st_mtime
+ mod_str = time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime(mtime))
+
+ lines.append('Last-Modified: %s GMT' % mod_str)
+
+ expire_time = time.gmtime(time.time() + (360*24*3600))
+ expire_str = time.strftime("%a, %d %b %Y %H:%M:%S", expire_time)
+ lines.append('Expires: %s GMT' % expire_str)
+
+ lines.append("\r\n")
+
+ headers = string.join(lines, "\r\n")
+ context.stdout.write(headers)
+
+ context.stdout.write(data)
+
+ return 200
+
+
+class FakeError:
+ def write(self, s):
+ apache.log_error(s, apache.APLOG_STARTUP)
+
+class ModPythonContext:
+ def __init__ (self, req):
+
+ from mod_python import apache
+
+ self.stdout = apache.CGIStdout(req)
+ self.stdin = apache.CGIStdin(req)
+
+ self.stderr = FakeError()
+ env = apache.build_cgi_env(req)
+
+ self.environ = env
+
+ scriptFilename = self.environ.get("SCRIPT_FILENAME", "")
+ if scriptFilename:
+ path, fn = os.path.split(scriptFilename)
+ os.chdir(path)
+
+ def setStatus(self, request, status):
+ if request:
+ request['status'] = str(status)
+
+
+
+def handler(req):
+ start = time.time()
+
+ from mod_python import apache
+
+ if 1:
+ context = ModPythonContext(req)
+ page = Page(context)
+ page.mod_python_req = req
+
+ gc.enable()
+ ret = page.start()
+ gc.collect()
+
+ ret = apache.OK
+
+ end = time.time()
+ #sys.stderr.write("handler time %s\n" % int((end-start)*1000))
+
+ return ret
+
+
+def main(argv, stdout, environ):
+ context = CSPage.Context()
+ page = Page(context)
+ page.start()
+
+
+if __name__ == "__main__":
+ main(sys.argv, sys.stdout, os.environ)
Property changes on: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/cgistarter.py
___________________________________________________________________
Added: svn:executable
+ *
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/fixedpoint.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/fixedpoint.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/fixedpoint.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,619 @@
+#!/usr/bin/env python
+"""
+FixedPoint objects support decimal arithmetic with a fixed number of
+digits (called the object's precision) after the decimal point. The
+number of digits before the decimal point is variable & unbounded.
+
+The precision is user-settable on a per-object basis when a FixedPoint
+is constructed, and may vary across FixedPoint objects. The precision
+may also be changed after construction via FixedPoint.set_precision(p).
+Note that if the precision of a FixedPoint is reduced via set_precision,
+information may be lost to rounding.
+
+>>> x = FixedPoint("5.55") # precision defaults to 2
+>>> print x
+5.55
+>>> x.set_precision(1) # round to one fraction digit
+>>> print x
+5.6
+>>> print FixedPoint("5.55", 1) # same thing setting to 1 in constructor
+5.6
+>>> repr(x) # returns constructor string that reproduces object exactly
+"FixedPoint('5.6', 1)"
+>>>
+
+When FixedPoint objects of different precision are combined via + - * /,
+the result is computed to the larger of the inputs' precisions, which also
+becomes the precision of the resulting FixedPoint object.
+
+>>> print FixedPoint("3.42") + FixedPoint("100.005", 3)
+103.425
+>>>
+
+When a FixedPoint is combined with other numeric types (ints, floats,
+strings representing a number) via + - * /, then similarly the computation
+is carried out using-- and the result inherits --the FixedPoint's
+precision.
+
+>>> print FixedPoint(1) / 7
+0.14
+>>> print FixedPoint(1, 30) / 7
+0.142857142857142857142857142857
+>>>
+
+The string produced by str(x) (implictly invoked by "print") always
+contains at least one digit before the decimal point, followed by a
+decimal point, followed by exactly x.get_precision() digits. If x is
+negative, str(x)[0] == "-".
+
+The FixedPoint constructor can be passed an int, long, string, float,
+FixedPoint, or any object convertible to a float via float() or to a
+long via long(). Passing a precision is optional; if specified, the
+precision must be a non-negative int. There is no inherent limit on
+the size of the precision, but if very very large you'll probably run
+out of memory.
+
+Note that conversion of floats to FixedPoint can be surprising, and
+should be avoided whenever possible. Conversion from string is exact
+(up to final rounding to the requested precision), so is greatly
+preferred.
+
+>>> print FixedPoint(1.1e30)
+1099999999999999993725589651456.00
+>>> print FixedPoint("1.1e30")
+1100000000000000000000000000000.00
+>>>
+
+The following Python operators and functions accept FixedPoints in the
+expected ways:
+
+ binary + - * / % divmod
+ with auto-coercion of other types to FixedPoint.
+ + - % divmod of FixedPoints are always exact.
+ * / of FixedPoints may lose information to rounding, in
+ which case the result is the infinitely precise answer
+ rounded to the result's precision.
+ divmod(x, y) returns (q, r) where q is a long equal to
+ floor(x/y) as if x/y were computed to infinite precision,
+ and r is a FixedPoint equal to x - q * y; no information
+ is lost. Note that q has the sign of y, and abs(r) < abs(y).
+ unary -
+ == != < > <= >= cmp
+ min max
+ float int long (int and long truncate)
+ abs
+ str repr
+ hash
+ use as dict keys
+ use as boolean (e.g. "if some_FixedPoint:" -- true iff not zero)
+
+Methods unique to FixedPoints:
+ .copy() return new FixedPoint with same value
+ .frac() long(x) + x.frac() == x
+ .get_precision() return the precision(p) of this FixedPoint object
+ .set_precision(p) set the precision of this FixedPoint object
+
+Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+"""
+
+# Released to the public domain 28-Mar-2001,
+# by Tim Peters (ti...@ho...).
+
+
+# 28-Mar-01 ver 0.0,4
+# Use repr() instead of str() inside __str__, because str(long) changed
+# since this was first written (used to produce trailing "L", doesn't
+# now).
+#
+# 09-May-99 ver 0,0,3
+# Repaired __sub__(FixedPoint, string); was blowing up.
+# Much more careful conversion of float (now best possible).
+# Implemented exact % and divmod.
+#
+# 14-Oct-98 ver 0,0,2
+# Added int, long, frac. Beefed up docs. Removed DECIMAL_POINT
+# and MINUS_SIGN globals to discourage bloating this class instead
+# of writing formatting wrapper classes (or subclasses)
+#
+# 11-Oct-98 ver 0,0,1
+# posted to c.l.py
+
+__copyright__ = "Copyright (C) Python Software Foundation"
+__author__ = "Tim Peters"
+__version__ = 0, 1, 0
+
+def bankersRounding(self, dividend, divisor, quotient, remainder):
+ """
+ rounding via nearest-even
+ increment the quotient if
+ the remainder is more than half of the divisor
+ or the remainder is exactly half the divisor and the quotient is odd
+ """
+ c = cmp(remainder << 1, divisor)
+ # c < 0 <-> remainder < divisor/2, etc
+ if c > 0 or (c == 0 and (quotient & 1) == 1):
+ quotient += 1
+ return quotient
+
+def addHalfAndChop(self, dividend, divisor, quotient, remainder):
+ """
+ the equivalent of 'add half and chop'
+ increment the quotient if
+ the remainder is greater than half of the divisor
+ or the remainder is exactly half the divisor and the quotient is >= 0
+ """
+ c = cmp(remainder << 1, divisor)
+ # c < 0 <-> remainder < divisor/2, etc
+ if c > 0 or (c == 0 and quotient >= 0):
+ quotient += 1
+ return quotient
+
+# 2002-10-20 dougfort - fake classes for pre 2.2 compatibility
+try:
+ object
+except NameError:
+ class object:
+ pass
+ def property(x, y):
+ return None
+
+# The default value for the number of decimal digits carried after the
+# decimal point. This only has effect at compile-time.
+DEFAULT_PRECISION = 2
+
+class FixedPoint(object):
+ """Basic FixedPoint object class,
+ The exact value is self.n / 10**self.p;
+ self.n is a long; self.p is an int
+ """
+ __slots__ = ['n', 'p']
+ def __init__(self, value=0, precision=DEFAULT_PRECISION):
+ self.n = self.p = 0
+ self.set_precision(precision)
+ p = self.p
+
+ if isinstance(value, type("42.3e5")):
+ n, exp = _string2exact(value)
+ # exact value is n*10**exp = n*10**(exp+p)/10**p
+ effective_exp = exp + p
+ if effective_exp > 0:
+ n = n * _tento(effective_exp)
+ elif effective_exp < 0:
+ n = self._roundquotient(n, _tento(-effective_exp))
+ self.n = n
+ return
+
+ if isinstance(value, type(42)) or isinstance(value, type(42L)):
+ self.n = long(value) * _tento(p)
+ return
+
+ if isinstance(value, type(self)):
+ temp = value.copy()
+ temp.set_precision(p)
+ self.n, self.p = temp.n, temp.p
+ return
+
+ if isinstance(value, type(42.0)):
+ # XXX ignoring infinities and NaNs and overflows for now
+ import math
+ f, e = math.frexp(abs(value))
+ assert f == 0 or 0.5 <= f < 1.0
+ # |value| = f * 2**e exactly
+
+ # Suck up CHUNK bits at a time; 28 is enough so that we suck
+ # up all bits in 2 iterations for all known binary double-
+ # precision formats, and small enough to fit in an int.
+ CHUNK = 28
+ top = 0L
+ # invariant: |value| = (top + f) * 2**e exactly
+ while f:
+ f = math.ldexp(f, CHUNK)
+ digit = int(f)
+ assert digit >> CHUNK == 0
+ top = (top << CHUNK) | digit
+ f = f - digit
+ assert 0.0 <= f < 1.0
+ e = e - CHUNK
+
+ # now |value| = top * 2**e exactly
+ # want n such that n / 10**p = top * 2**e, or
+ # n = top * 10**p * 2**e
+ top = top * _tento(p)
+ if e >= 0:
+ n = top << e
+ else:
+ n = self._roundquotient(top, 1L << -e)
+ if value < 0:
+ n = -n
+ self.n = n
+ return
+
+ if isinstance(value, type(42-42j)):
+ raise TypeError("can't convert complex to FixedPoint: " +
+ `value`)
+
+ # can we coerce to a float?
+ yes = 1
+ try:
+ asfloat = float(value)
+ except:
+ yes = 0
+ if yes:
+ self.__init__(asfloat, p)
+ return
+
+ # similarly for long
+ yes = 1
+ try:
+ aslong = long(value)
+ except:
+ yes = 0
+ if yes:
+ self.__init__(aslong, p)
+ return
+
+ raise TypeError("can't convert to FixedPoint: " + `value`)
+
+ def get_precision(self):
+ """Return the precision of this FixedPoint.
+
+ The precision is the number of decimal digits carried after
+ the decimal point, and is an int >= 0.
+ """
+
+ return self.p
+
+ def set_precision(self, precision=DEFAULT_PRECISION):
+ """Change the precision carried by this FixedPoint to p.
+
+ precision must be an int >= 0, and defaults to
+ DEFAULT_PRECISION.
+
+ If precision is less than this FixedPoint's current precision,
+ information may be lost to rounding.
+ """
+
+ try:
+ p = int(precision)
+ except:
+ raise TypeError("precision not convertable to int: " +
+ `precision`)
+ if p < 0:
+ raise ValueError("precision must be >= 0: " + `precision`)
+
+ if p > self.p:
+ self.n = self.n * _tento(p - self.p)
+ elif p < self.p:
+ self.n = self._roundquotient(self.n, _tento(self.p - p))
+ self.p = p
+
+ precision = property(get_precision, set_precision)
+
+ def __str__(self):
+ n, p = self.n, self.p
+ i, f = divmod(abs(n), _tento(p))
+ if p:
+ frac = repr(f)[:-1]
+ frac = "0" * (p - len(frac)) + frac
+ else:
+ frac = ""
+ return "-"[:n<0] + \
+ repr(i)[:-1] + \
+ "." + frac
+
+ def __repr__(self):
+ return "FixedPoint" + `(str(self), self.p)`
+
+ def copy(self):
+ return _mkFP(self.n, self.p, type(self))
+
+ __copy__ = copy
+
+ def __deepcopy__(self, memo):
+ return self.copy()
+
+ def __cmp__(self, other):
+ xn, yn, p = _norm(self, other, FixedPoint=type(self))
+ return cmp(xn, yn)
+
+ def __hash__(self):
+ """ Caution! == values must have equal hashes, and a FixedPoint
+ is essentially a rational in unnormalized form. There's
+ really no choice here but to normalize it, so hash is
+ potentially expensive.
+ n, p = self.__reduce()
+
+ Obscurity: if the value is an exact integer, p will be 0 now,
+ so the hash expression reduces to hash(n). So FixedPoints
+ that happen to be exact integers hash to the same things as
+ their int or long equivalents. This is Good. But if a
+ FixedPoint happens to have a value exactly representable as
+ a float, their hashes may differ. This is a teensy bit Bad.
+ """
+ n, p = self.__reduce()
+ return hash(n) ^ hash(p)
+
+ def __nonzero__(self):
+ """ Returns true if this FixedPoint is not equal to zero"""
+ return self.n != 0
+
+ def __neg__(self):
+ return _mkFP(-self.n, self.p, type(self))
+
+ def __abs__(self):
+ """ Returns new FixedPoint containing the absolute value of this FixedPoint"""
+ if self.n >= 0:
+ return self.copy()
+ else:
+ return -self
+
+ def __add__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ # n1/10**p + n2/10**p = (n1+n2)/10**p
+ return _mkFP(n1 + n2, p, type(self))
+
+ __radd__ = __add__
+
+ def __sub__(self, other):
+ if not isinstance(other, type(self)):
+ other = type(self)(other, self.p)
+ return self.__add__(-other)
+
+ def __rsub__(self, other):
+ return (-self) + other
+
+ def __mul__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ # n1/10**p * n2/10**p = (n1*n2/10**p)/10**p
+ return _mkFP(self._roundquotient(n1 * n2, _tento(p)), p, type(self))
+
+ __rmul__ = __mul__
+
+ def __div__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ if n2 == 0:
+ raise ZeroDivisionError("FixedPoint division")
+ if n2 < 0:
+ n1, n2 = -n1, -n2
+ # n1/10**p / (n2/10**p) = n1/n2 = (n1*10**p/n2)/10**p
+ return _mkFP(self._roundquotient(n1 * _tento(p), n2), p, type(self))
+
+ def __rdiv__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ return _mkFP(n2, p, FixedPoint=type(self)) / self
+
+ def __divmod__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ if n2 == 0:
+ raise ZeroDivisionError("FixedPoint modulo")
+ # floor((n1/10**p)/(n2*10**p)) = floor(n1/n2)
+ q = n1 / n2
+ # n1/10**p - q * n2/10**p = (n1 - q * n2)/10**p
+ return q, _mkFP(n1 - q * n2, p, type(self))
+
+ def __rdivmod__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ return divmod(_mkFP(n2, p), self)
+
+ def __mod__(self, other):
+ return self.__divmod__(other)[1]
+
+ def __rmod__(self, other):
+ n1, n2, p = _norm(self, other, FixedPoint=type(self))
+ return _mkFP(n2, p, type(self)).__mod__(self)
+
+ def __float__(self):
+ """Return the floating point representation of this FixedPoint.
+ Caution! float can lose precision.
+ """
+ n, p = self.__reduce()
+ return float(n) / float(_tento(p))
+
+ def __long__(self):
+ """EJG/DF - Should this round instead?
+ Note e.g. long(-1.9) == -1L and long(1.9) == 1L in Python
+ Note that __int__ inherits whatever __long__ does,
+ and .frac() is affected too
+ """
+ answer = abs(self.n) / _tento(self.p)
+ if self.n < 0:
+ answer = -answer
+ return answer
+
+ def __int__(self):
+ """Return integer value of FixedPoint object."""
+ return int(self.__long__())
+
+ def frac(self):
+ """Return fractional portion as a FixedPoint.
+
+ x.frac() + long(x) == x
+ """
+ return self - long(self)
+
+ def _roundquotient(self, x, y):
+ """
+ Divide x by y,
+ return the result of rounding
+ Developers may substitute their own 'round' for custom rounding
+ y must be > 0
+ """
+ assert y > 0
+ n, leftover = divmod(x, y)
+ return self.round(x, y, n, leftover)
+
+ def __reduce(self):
+ """ Return n, p s.t. self == n/10**p and n % 10 != 0"""
+ n, p = self.n, self.p
+ if n == 0:
+ p = 0
+ while p and n % 10 == 0:
+ p = p - 1
+ n = n / 10
+ return n, p
+
+# 2002-10-04 dougfort - Default to Banker's Rounding for backward compatibility
+FixedPoint.round = bankersRounding
+
+# return 10L**n
+
+def _tento(n, cache={}):
+ """Cached computation of 10**n"""
+ try:
+ return cache[n]
+ except KeyError:
+ answer = cache[n] = 10L ** n
+ return answer
+
+def _norm(x, y, isinstance=isinstance, FixedPoint=FixedPoint,
+ _tento=_tento):
+ """Return xn, yn, p s.t.
+ p = max(x.p, y.p)
+ x = xn / 10**p
+ y = yn / 10**p
+
+ x must be FixedPoint to begin with; if y is not FixedPoint,
+ it inherits its precision from x.
+
+ Note that this method is called a lot, so default-arg tricks are helpful.
+ """
+ assert isinstance(x, FixedPoint)
+ if not isinstance(y, FixedPoint):
+ y = FixedPoint(y, x.p)
+ xn, yn = x.n, y.n
+ xp, yp = x.p, y.p
+ if xp > yp:
+ yn = yn * _tento(xp - yp)
+ p = xp
+ elif xp < yp:
+ xn = xn * _tento(yp - xp)
+ p = yp
+ else:
+ p = xp # same as yp
+ return xn, yn, p
+
+def _mkFP(n, p, FixedPoint=FixedPoint):
+ """Make FixedPoint objext - Return a new FixedPoint object with the selected precision."""
+ f = FixedPoint()
+ #print '_mkFP Debug: %s, value=%s' % (type(f),n)
+ f.n = n
+ f.p = p
+ return f
+
+# crud for parsing strings
+import re
+
+# There's an optional sign at the start, and an optional exponent
+# at the end. The exponent has an optional sign and at least one
+# digit. In between, must have either at least one digit followed
+# by an optional fraction, or a decimal point followed by at least
+# one digit. Yuck.
+
+_parser = re.compile(r"""
+ \s*
+ (?P<sign>[-+])?
+ (
+ (?P<int>\d+) (\. (?P<frac>\d*))?
+ |
+ \. (?P<onlyfrac>\d+)
+ )
+ ([eE](?P<exp>[-+]? \d+))?
+ \s* $
+""", re.VERBOSE).match
+
+del re
+
+
+def _string2exact(s):
+ """Return n, p s.t. float string value == n * 10**p exactly."""
+ m = _parser(s)
+ if m is None:
+ raise ValueError("can't parse as number: " + `s`)
+
+ exp = m.group('exp')
+ if exp is None:
+ exp = 0
+ else:
+ exp = int(exp)
+
+ intpart = m.group('int')
+ if intpart is None:
+ intpart = "0"
+ fracpart = m.group('onlyfrac')
+ else:
+ fracpart = m.group('frac')
+ if fracpart is None or fracpart == "":
+ fracpart = "0"
+ assert intpart
+ assert fracpart
+
+ i, f = long(intpart), long(fracpart)
+ nfrac = len(fracpart)
+ i = i * _tento(nfrac) + f
+ exp = exp - nfrac
+
+ if m.group('sign') == "-":
+ i = -i
+
+ return i, exp
+
+def _test():
+ """Unit testing framework"""
+ fp = FixedPoint
+ o = fp("0.1")
+ assert str(o) == "0.10"
+ t = fp("-20e-2", 5)
+ assert str(t) == "-0.20000"
+ assert t < o
+ assert o > t
+ assert min(o, t) == min(t, o) == t
+ assert max(o, t) == max(t, o) == o
+ assert o != t
+ assert --t == t
+ assert abs(t) > abs(o)
+ assert abs(o) < abs(t)
+ assert o == o and t == t
+ assert t.copy() == t
+ assert o == -t/2 == -.5 * t
+ assert abs(t) == o + o
+ assert abs(o) == o
+ assert o/t == -0.5
+ assert -(t/o) == (-t)/o == t/-o == 2
+ assert 1 + o == o + 1 == fp(" +00.000011e+5 ")
+ assert 1/o == 10
+ assert o + t == t + o == -o
+ assert 2.0 * t == t * 2 == "2" * t == o/o * 2L * t
+ assert 1 - t == -(t - 1) == fp(6L)/5
+ assert t*t == 4*o*o == o*4*o == o*o*4
+ assert fp(2) - "1" == 1
+ assert float(-1/t) == 5.0
+ for p in range(20):
+ assert 42 + fp("1e-20", p) - 42 == 0
+ assert 1/(42 + fp("1e-20", 20) - 42) == fp("100.0E18")
+ o = fp(".9995", 4)
+ assert 1 - o == fp("5e-4", 10)
+ o.set_precision(3)
+ assert o == 1
+ o = fp(".9985", 4)
+ o.set_precision(3)
+ assert o == fp(".998", 10)
+ assert o == o.frac()
+ o.set_precision(100)
+ assert o == fp(".998", 10)
+ o.set_precision(2)
+ assert o == 1
+ x = fp(1.99)
+ assert long(x) == -long(-x) == 1L
+ assert int(x) == -int(-x) == 1
+ assert x == long(x) + x.frac()
+ assert -x == long(-x) + (-x).frac()
+ assert fp(7) % 4 == 7 % fp(4) == 3
+ assert fp(-7) % 4 == -7 % fp(4) == 1
+ assert fp(-7) % -4 == -7 % fp(-4) == -3
+ assert fp(7.0) % "-4.0" == 7 % fp(-4) == -1
+ assert fp("5.5") % fp("1.1") == fp("5.5e100") % fp("1.1e100") == 0
+ assert divmod(fp("1e100"), 3) == (long(fp("1e100")/3), 1)
+
+if __name__ == '__main__':
+ _test()
+
Property changes on: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/fixedpoint.py
___________________________________________________________________
Added: svn:executable
+ *
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/guid.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/guid.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/guid.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,285 @@
+#!/usr/bin/env python
+
+"""
+usage: %(progname)s [args]
+"""
+
+# GUID.py
+# Version 2.1.
+#
+# Copyright (C) 2003 Dr. Conan C. Albrecht <conan_albrechtATbyu.edu>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+##################################################################################################
+### A globally-unique identifier made up of time and ip and 8 random digits: 16 characters wide
+###
+### A globally unique identifier that combines ip, time, and random bits. Since the
+### time is listed first, you can sort records by guid. You can also extract the time
+### and ip if needed.
+###
+### GUIDs make wonderful database keys. They require no access to the
+### database (to get the max index number), they are extremely unique, and they sort
+### automatically by time. GUIDs prevent key clashes when merging
+### two databases together, combining data, or generating keys in distributed
+### systems.
+###
+### There is an Internet Draft for UUIDs, but this module does not implement it.
+### If the draft catches on, perhaps I'll conform the module to it.
+###
+
+
+# Changelog
+# Sometime, 1997 Created the Java version of GUID
+# Went through many versions in Java
+# Sometime, 2002 Created the Python version of GUID, mirroring the Java version
+# November 24, 2003 Changed Python version to be more pythonic, took out object and made just a module
+# December 2, 2003 Fixed duplicating GUIDs. Sometimes they duplicate if multiples are created
+# in the same millisecond (it checks the last 100 GUIDs now and has a larger random part)
+# December 9, 2003 Fixed MAX_RANDOM, which was going over sys.maxint
+# November 21, 2005 Changed to pack the guid using 64 bit encoding 0-9, A-Z, a-z, @, [
+# Now, the guid is only 16 bytes long.
+#
+
+import math
+import random
+import socket
+import os, sys
+import time
+import threading
+import string, struct
+
+import getopt
+
+# The size of the circular queue. Larger sizes give more assurance for uniqueness.
+# Smaller sizes take less memory and are a tiny bit faster
+QUEUE_SIZE = 100
+
+
+#############################
+### global module variables
+
+MAX_RANDOM = sys.maxint # converted to hex goes to 8 chars (at least, in Python 2.3)
+rand = random.Random()
+ip = ''
+lock = threading.RLock()
+lastguid = ''
+try:
+ ip = socket.gethostbyname(socket.gethostname())
+except (socket.gaierror): # if we don't have an ip, default to someting in the 10.x.x.x private range
+ ip = '10'
+ for i in range(3):
+ ip += '.' + str(rand.randrange(1, 254))
+hexip = ''.join(["%04x" % long(i) for i in ip.split('.')]) # leave space for ip v6 (65K in each sub)
+ipaddrStr = socket.inet_aton(ip)
+(ipaddr, ) = struct.unpack(">I", ipaddrStr)
+
+def encode64Char(i):
+ if i<10: return chr(i+48)
+ elif i<38: return chr(i-10+64)
+ elif i<64: return chr(i-38+97)
+ raise Error
+
+def pack64(i, bytes=6):
+ parts = []
+ for j in range(bytes):
+ a = i & 0x3f
+ i = (i >> 6)
+ parts.append(encode64Char(a))
+ parts.reverse()
+ p = string.join(parts, "")
+ return p
+
+def decode64Char(c):
+ n = ord(c)
+ if n>=48 and n<=58:
+ return n-48
+ elif n >= 64 and n <= 91:
+ return n - 54
+ elif n >= 97 and n <= 122:
+ return n - 59
+ raise Error
+
+def unpack64(s, bytes=6):
+ i = 0L
+
+ for j in range(bytes):
+ c = s[j]
+ a = decode64Char(c)
+ i = i | a
+ if j < bytes-1:
+ i = i << 6
+ return i
+
+if 0:
+ for i in range(64):
+ c = encode64Char(i)
+ j = decode64Char(c)
+ if i != j:
+ print i, c, j
+
+ipaddr64 = pack64(ipaddr)
+
+#######################################
+### A simple circular set
+### to ensure we don't duplicate
+### GUIDs in the same millisecond
+
+class CircularSet:
+ '''A circular set. A set that maxes at a given size, replacing the oldest element after maximum size.
+ This implementation is NOT thread safe. (generate() below is thread safe, though)
+ '''
+ def __init__(self):
+ self.queue = []
+ self.queue_map = {} # for efficiency, we keep a map of everything
+ self.queueindex = 0
+
+ def add(self, val):
+ '''Adds a value to the queue'''
+ # check to see if we have this value. If so, throw an exception
+ assert not self.queue_map.has_key(val), 'This value is already in the set!'
+
+ # add the new one to the list
+ if len(self.queue) > self.queueindex:
+ # first remove the previous key at this location
+ del self.queue_map[self.queue[self.queueindex]]
+ self.queue[self.queueindex] = val
+ else:
+ self.queue.append(val)
+
+ # now add to the map for efficiency
+ self.queue_map[val] = val
+
+ # increment the queue index
+ self.queueindex += 1
+ if self.queueindex >= QUEUE_SIZE:
+ self.queueindex = 0
+
+queue = CircularSet()
+
+#################################
+### Public module functions
+
+
+def generate(time_t = None):
+ '''Generates a new guid'''
+ global lock, queue # since we modify the module variable
+ if time_t > 1136102400:
+ raise ValueError, "time_t is too large %s" % time_t
+
+ try:
+ lock.acquire() # can't generate two guids at the same time
+ while 1:
+ # time part
+ if time_t == None:
+ t = long(time.time() * 100)
+ else:
+ t = time_t * 100
+
+ # random part
+ r = int(rand.random() * MAX_RANDOM) & 0xffff
+ n = 0L | (long(t)<<48) | (ipaddr<<16) | r
+ guid = pack64(n, bytes=16)
+
+ try:
+ queue.add(guid) # throws the AssertionError if this GUID is a duplicate of the queue
+ return guid
+ except AssertionError: # signals we already have this GUID in the queue
+ pass
+ finally:
+ lock.release()
+
+InvalidGUID = "Invalid GUID"
+
+def extract_time(guid):
+ '''Extracts the time portion out of the guid and returns the
+ number of seconds since the epoch as a float'''
+ if len(guid) != 16: raise InvalidGUID
+ n = unpack64(guid, bytes=16)
+ t = long(n >> 48) / 100
+ return t
+
+
+def extract_ip(guid):
+ '''Extracts the ip portion out of the guid and returns it
+ as a string like 10.10.10.10'''
+
+ if len(guid) != 16: raise InvalidGUID
+
+ n = unpack64(guid, bytes=16)
+ n = n >> 16
+ n = n & 0xffffffffL
+
+ ip = struct.pack(">L", n)
+ ipaddrStr = socket.inet_ntoa(ip)
+ return ipaddrStr
+
+
+def extract_random(guid):
+ '''Extracts the random bits from the guid (returns the bits in decimal)'''
+ if len(guid) != 16: raise InvalidGUID
+
+ n = unpack64(guid, bytes=16)
+ r = int(n & 0xffff)
+ return r
+
+
+### TESTING OF GUID CLASS ###
+def test():
+ pass
+
+def usage(progname):
+ print __doc__ % vars()
+
+def main(argv, stdout, environ):
+ progname = argv[0]
+ optlist, args = getopt.getopt(argv[1:], "", ["help", "test", "debug"])
+
+ testflag = 0
+
+ for (field, val) in optlist:
+ if field == "--help":
+ usage(progname)
+ return
+ elif field == "--debug":
+ debugfull()
+ elif field == "--test":
+ testflag = 1
+
+ if testflag:
+ test()
+ return
+
+ guids = []
+ if len(args) == 0:
+ guids.append(generate())
+ else:
+ for arg in args:
+ guids.append(arg)
+
+ for guid in guids:
+ print "GUID:", guid
+ print "Time:", time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(extract_time(guid)))
+ print "IP: ", extract_ip(guid)
+ print "Rand:", extract_random(guid)
+ print
+
+
+if __name__ == "__main__":
+ main(sys.argv, sys.stdout, os.environ)
+
+
Added: pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/handle_error.py
===================================================================
--- pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/handle_error.py (rev 0)
+++ pkg/trunk/sandbox/web/pyclearsilver/src/pyclearsilver/handle_error.py 2009-08-20 21:41:17 UTC (rev 22475)
@@ -0,0 +1,109 @@
+
+import traceback, sys, string, time, socket, os
+import who_calls
+
+#DUMP_DIR = "/neo/data/bugs"
+DUMP_DIR = "/tmp/bugs"
+if os.environ.has_key('PYCLEARSILVER_BUGS_PATH'):
+ DUMP_DIR = os.environ['PYCLEARSILVER_BUGS_PATH']
+
+Warning = "handle_error.Warning"
+
+# levels
+LV_MESSAGE = "LV_MESSAGE"
+LV_WARNING = "LV_WARNING"
+LV_ERROR = "LV_ERROR"
+
+Count = 0
+
+gErrorCount = 0
+DISABLE_DUMP = 0
+
+def exceptionReason():
+ return "%s.%s" % (str(sys.exc_type), str(sys.exc_value))
+
+def exceptionString():
+ tb_list = traceback.format_exception(sys.exc_type,sys.exc_value,sys.exc_traceback)
+ return string.join(tb_list,"")
+
+ #### old way
+ import StringIO
+ ## get the traceback message
+ sfp = StringIO.StringIO()
+ traceback.print_exc(file=sfp)
+ exception = sfp.getvalue()
+ sfp.close()
+
+ return exception
+
+
+def handleException (msg=None, lvl=LV_ERROR, dump = 1):
+ global gErrorCount
+ gErrorCount = gErrorCount + 1
+
+ tb_list = traceback.format_exception(sys.exc_type,sys.exc_value,sys.exc_traceback)
+ if msg:
+ sys.stderr.write ("%s\n" % msg)
+ else:
+ msg = "Unhandled Exception"
+
+ sys.stderr.write (string.join(tb_list,""))
+ try:
+ if dump: dump_bug(lvl, "handleException", msg, string.join(tb_list, ""))
+ except:
+ handleException("Unable to dump_bug", dump = 0)
+
+def handleWarning (msg=""):
+ header = "*** handleWarning: %s\n" % msg
+ sys.stderr.write(header)
+ tb = who_calls.pretty_who_calls(strip=1) + "\n"
+ sys.stderr.write(tb)
+
+ try:
+ dump_bug(LV_WARNING, "handleException", msg, tb)
+ except:
+ handleException("Unable to dump_bug", dump = 0)
+
+def checkPaths():
+ paths = (DUMP_DIR,
+ os.path.join (DUMP_DIR, "tmp"),
+ os.path.join (DUMP_DIR, "new"))
+ for path in paths:
+ if not os.path.isdir(path):
+ os.mkdir(path, 0755)
+
+
+def dump_bug (level, etype, msg, location=None, nhdf=None):
+ global DISABLE_DUMP
+ if DISABLE_DUMP: return
+
+ now = int(time.time())
+ pid = os.getpid()
+
+ import neo_cgi, neo_util
+ hdf = neo_util.HDF()
+ hdf.setValue("Required.Level", level)
+ hdf.setValue("Required.When", str(int(time.time())))
+ hdf.setValue("Required.Type", etype)
+ hdf.setValue("Required.Title", msg)
+ hdf.setValue("Optional.Hostname", socket.gethostname())
+ if location:
+ hdf.setValue("Optional.Location", location)
+
+ for (key, value) in os.environ...
[truncated message content] |