web.py 0.2 API documentation
init.py
main()
cheetah.py
upvars(level=2)- Guido van Rossum sez: don’t use this function.
render(template, terms=None, asTemplate=False, base=None, isString=False):- Renders a template, caching where it can.
templateis the name of a file containing the a template in thetemplates/folder, unlessisString, in which case it’s the template itself.termsis a dictionary used to fill the template. If it’s None, then the caller’s local variables are used instead, plus context, if it’s not already set, is set tocontext.If asTemplate is False, it
outputs the template directly. Otherwise, it returns the template object.If the template is a potential base template (that is, something other templates) can extend, then base should be a string with the name of the template. The template will be cached and made available for future calls to
render.Requires Cheetah.
class WebSafe(Filter)
db.py
Supports Firebird, MySQL, PostgreSQL, and SQLite.
class UnknownParamstyle(Exception)- raised for unsupported db paramstyles
(currently supported: qmark, numeric, format, pyformat)
aparam()- Returns the appropriate string to be used to interpolate
a value with the current
web.ctx.db_moduleor simply %s if there isn’t one.>>> aparam() '%s' reparam(string_, dictionary)- Takes a string and a dictionary and interpolates the string
using values from the dictionary. Returns an
SQLQueryfor the result.>>> reparam("s = $s", dict(s=True)) <sql: "s = 't'"> sqlify(obj)- converts
objto its proper SQL version>>> sqlify(None) 'NULL' >>> sqlify(True) "'t'" >>> sqlify(3) '3' class SQLQuery- You can pass this sort of thing as a clause in any db function.
Otherwise, you can pass a dictionary to the keyword argument
varsand the function will call reparam for you. class SQLLiteral- Protects a string from
sqlquote.>>> insert('foo', time=SQLLiteral('NOW()'), _test=True) <sql: 'INSERT INTO foo (time) VALUES (NOW())'> sqlquote(a)- Ensures
ais quoted properly for use in a SQL query.>>> 'WHERE x = ' + sqlquote(True) + ' AND y = ' + sqlquote(3) <sql: "WHERE x = 't' AND y = 3"> class UnknownDB(Exception)- raised for unsupported dbms
connect(dbn, **keywords)- Connects to the specified database.
dbncurrently must be “postgres”, “mysql”, or “sqlite”.If DBUtils is installed, connection pooling will be used.
class TransactionError(Exception): pass class transaction:- A context that can be used in conjunction with “with” statements to implement SQL transactions. Starts a transaction on enter, rolls it back if there’s an error; otherwise it commits it at the end.
transact()- Start a transaction.
commit()- Commits a transaction.
rollback(care=True)- Rolls back a transaction.
query(sql_query, vars=None, processed=False, _test=False)- Execute SQL query
sql_queryusing dictionaryvarsto interpolate it. Ifprocessed=True,varsis areparam-style list to use instead of interpolating.>>> query("SELECT * FROM foo", _test=True) <sql: 'SELECT * FROM foo'> >>> query("SELECT * FROM foo WHERE x = $x", vars=dict(x='f'), _test=True) <sql: "SELECT * FROM foo WHERE x = 'f'"> >>> query("SELECT * FROM foo WHERE x = " + sqlquote('f'), _test=True) <sql: "SELECT * FROM foo WHERE x = 'f'"> sqllist(lst)- Converts the arguments for use in something like a WHERE clause.
>>> sqllist(['a', 'b']) 'a, b' >>> sqllist('foo') 'foo' >>> sqllist(u'foo') u'foo' sqlors(left, lst)left is a SQL clause liketablename.arg = ` andlstis a list of values. Returns a reparam-style pair featuring the SQL that ORs together the clause for each item in the lst.>>> sqlors('foo = ', []) <sql: '2+2=5'> >>> sqlors('foo = ', [1]) <sql: 'foo = 1'> >>> sqlors('foo = ', 1) <sql: 'foo = 1'> >>> sqlors('foo = ', [1,2,3]) <sql: '(foo = 1 OR foo = 2 OR foo = 3)'>sqlwhere(dictionary, grouping=' AND ')- Converts a
dictionaryto an SQL WHERE clauseSQLQuery.>>> sqlwhere({'cust_id': 2, 'order_id':3}) <sql: 'order_id = 3 AND cust_id = 2'> >>> sqlwhere({'cust_id': 2, 'order_id':3}, grouping=', ') <sql: 'order_id = 3, cust_id = 2'> select(tables, vars=None, what='*', where=None, order=None, group=None, limit=None, offset=None, _test=False):- Selects
whatfromtableswith clauseswhere,order,group,limit, andoffset. Uses vars to interpolate. Otherwise, each clause can be a SQLQuery.>>> select('foo', _test=True) <sql: 'SELECT * FROM foo'> >>> select(['foo', 'bar'], where="foo.bar_id = bar.id", limit=5, _test=True) <sql: 'SELECT * FROM foo, bar WHERE foo.bar_id = bar.id LIMIT 5'> insert(tablename, seqname=None, _test=False, **values)- Inserts
valuesintotablename. Returns current sequence ID. Setseqnameto the ID if it’s not the default, or toFalseif there isn’t one.>>> insert('foo', joe='bob', a=2, _test=True) <sql: "INSERT INTO foo (a, joe) VALUES (2, 'bob')"> update(tables, where, vars=None, _test=False, **values)- Update
tableswith clausewhere(interpolated usingvars) and settingvalues.>>> joe = 'Joseph' >>> update('foo', where='name = $joe', name='bob', age=5, ... vars=locals(), _test=True) <sql: "UPDATE foo SET age = 5, name = 'bob' WHERE name = 'Joseph'"> delete(table, where=None, using=None, vars=None, _test=False)- Deletes from
tablewith clauseswhereandusing.>>> name = 'Joe' >>> delete('foo', where='name = $name', vars=locals(), _test=True) <sql: "DELETE FROM foo WHERE name = 'Joe'">
debugerror.py
djangoerror()debugerror()- A replacement for
internalerrorthat presents a nice page with lots of debug information for the programmer.(Based on the beautiful 500 page from Django, designed by Wilson Miner.)
emailerrors(email_address, olderror)- Wraps the old
internalerrorhandler (pass asolderror) to additionally email all errors toemail_address, to aid in debugging production websites.Emails contain a normal text traceback as well as an attachment containing the nice
debugerrorpage.
form.py
attrget(obj, attr, value=None)class Form- init(self, *inputs, **kw)
inputsis a list of form objects. The only keyword accepted is “validators” which is a list of Validator objects. class Input(object)- init(self, name, *validators, **attrs)
nameis the name of the object. It is the default value for the “description” attribute for the HTML form element. The keywords, stored in the dictionaryattrs, accepted are: “description”, “value”, “pre”, “post”, “id”, and “class_” class Textbox(Input)class Password(Input)class Textarea(Input)class Dropdown(Input)class Radio(Input)class Checkbox(Input)class Button(Input)class Hidden(Input)class File(Input)class Validatorclass regexp(Validator)
http.py
prefixurl(base='')- Sorry, this function is really difficult to explain. Maybe some other time.
expires(delta)- Outputs an
Expiresheader fordeltafrom now.deltais atimedeltaobject or a number of seconds. lastmodified(date_obj)- Outputs a
Last-Modifiedheader fordatetime. modified(date=None, etag=None)redirect(url, status='301 Moved Permanently')- Returns a
statusredirect to the new URL.urlis joined with the base URL so that things likeredirect("about")will work properly. found(url)- A
302 Foundredirect. seeother(url)- A
303 See Otherredirect. tempredirect(url)- A
307 Temporary Redirectredirect. write(cgi_response)- Converts a standard CGI-style string response into
headerandoutputcalls. urlencode(query)- Same as urllib.urlencode, but supports unicode strings.
>>> urlencode({'text':'foo bar'}) 'text=foo+bar' changequery(query=None, **kw)- Imagine you’re at
/foo?a=1&b=2. Thenchangequery(a=3)will return/foo?a=3&b=2– the same URL but with the arguments you requested changed. url(path=None, **kw)- Makes url by concatinating web.ctx.homepath and path and the query string created using the arguments.
background(func)- A function decorator to run a long-running function as a background thread. GOTCHA in postgres: Until the foreground task ends, any db access by background task will necessarily get old data from before the foreground task started because psycopg2 begins a transaction in the foreground task until it quits.
backgrounder(func)class Reloader- Before every request, checks to see if any loaded modules have changed on disk and, if so, reloads them.
profiler(app)- Outputs basic profiling information at the bottom of each response.
httpserver.py
runbasic(func, server_address=("0.0.0.0", 8080))- Runs a simple HTTP server hosting WSGI app
func. The directorystatic/is hosted statically.Based on WsgiServer from Colin Stewart.
runsimple(func, server_address=("0.0.0.0", 8080))- Runs CherryPy WSGI server hosting WSGI app
func. The directorystatic/is hosted statically.
net.py
validipaddr(address)- returns True if
addressis a valid IPv4 address validipport(port)- returns True if
portis a valid IPv4 port validip(ip, defaultaddr="0.0.0.0", defaultport=8080)- returns
(ip_address, port)from stringip_addr_port validaddr(string_)- returns either (ip_address, port) or “/path/to/socket” from string_
>>> validaddr('/path/to/socket') '/path/to/socket' >>> validaddr('8000') ('0.0.0.0', 8000) >>> validaddr('127.0.0.1') ('127.0.0.1', 8080) >>> validaddr('127.0.0.1:8000') ('127.0.0.1', 8000) >>> validaddr('fff') Traceback (most recent call last): ... ValueError: fff is not a valid IP address/port urlquote(val)- Quotes a string for use in a URL.
>>> urlquote('://?f=1&j=1') '%3A//%3Ff%3D1%26j%3D1' >>> urlquote(None) '' >>> urlquote(u'\u203d') '%E2%80%BD' httpdate(date_obj)- Formats a datetime object for use in HTTP headers.
>>> import datetime >>> httpdate(datetime.datetime(1970, 1, 1, 1, 1, 1)) 'Thu, 01 Jan 1970 01:01:01 GMT' parsehttpdate(string_)- Parses an HTTP date into a datetime object.
>>> parsehttpdate('Thu, 01 Jan 1970 01:01:01 GMT') datetime.datetime(1970, 1, 1, 1, 1, 1) htmlquote(text)- Encodes
textfor raw use in HTML.>>> htmlquote("<'&\\">") '<'&">' htmlunquote(text)- Decodes
textthat’s HTML quoted.>>> htmlunquote('<'&">') '<\\'&">' websafe(val)- Converts
valso that it’s safe for use in UTF-8 HTML.>>> websafe("<'&\\">") '<'&">' >>> websafe(None) '' >>> websafe(u'\u203d') '\\xe2\\x80\\xbd'
request.py
handle(mapping, fvars=None)- Call the appropriate function based on the url to function mapping in
mapping. If no module for the function is specified, look up the function infvars. Iffvarsis empty, using the caller’s context.mappingshould be a tuple of paired regular expressions with function name substitutions.handlewill import modules as necessary. nomethod(cls)- Returns a
405 Method Not Allowederror forcls. autodelegate(prefix='')- Returns a method that takes one argument and calls the method named prefix+arg,
calling
notfound()if there isn’t one. Example:urls = ('/prefs/(.*)', 'prefs') class prefs: GET = autodelegate('GET_') def GET_password(self): pass def GET_privacy(self): passGET_passwordwould get called for/prefs/passwordwhileGET_privacyforGET_privacygets called for/prefs/privacy.If a user visits
/prefs/password/changethenGET_password(self, '/change')is called. webpyfunc(inp, fvars, autoreload=False)- If
inpis a url mapping, returns a function that calls handle. run(inp, fvars, *middleware)- Starts handling requests. If called in a CGI or FastCGI context, it will follow
that protocol. If called from the command line, it will start an HTTP
server on the port named in the first command line argument, or, if there
is no argument, on port 8080.
inputis a callable, then it’s called with no arguments. Otherwise, it’s amappingobject to be passed tohandle(...).Caveat: So that
reloaderwill work correctly, input has to be a variable, it can’t be a tuple passed in directly.middlewareis a list of WSGI middleware which is applied to the resulting WSGI function.
template.py
class ParseError(Exception): pass class Parser:class TemplateParser(Parser)class Stowage(storage)class WTF(AssertionError): pass class SecurityError(Exception):- The template seems to be trying to do something naughty.
class Templateclass Handleclass Fill(Handle)class renderfrender(fn, *a, **kw)test()- r”"”Doctest for testing template module.
>>> t = Template >>> t('1')() '1\n' >>> t('$def with ()\n1')() '1\n' >>> t('$def with (a)\n$a')(1) '1\n' >>> t('$def with (a=0)\n$a')(1) '1\n' >>> t('$def with (a=0)\n$a')(a=1) '1\n' >>> t('$if 1: 1')() '1\n' >>> t('$if 1:\n 1')() '1\n' >>> t('$if 0: 0\n$elif 1: 1')() '1\n' >>> t('$if 0: 0\n$elif None: 0\n$else: 1')() '1\n' >>> t('$if (0 < 1) and (1 < 2): 1')() '1\n' >>> t('$for x in [1, 2, 3]: $x')() '1\n2\n3\n' >>> t('$for x in []: 0\n$else: 1')() '1\n' >>> t('$def with (a)\n$while a and a.pop(): 1')([1, 2, 3]) '1\n1\n1\n' >>> t('$while 0: 0\n$else: 1')() '1\n' >>> t('$ a = 1\n$a')() '1\n' >>> t('$# 0')() '' >>> t('$def with (d)\n$for k, v in d.iteritems(): $k')({1: 1}) '1\n' >>> t('$def with (a)\n$(a)')(1) '1\n' >>> t('$def with (a)\n$a')(1) '1\n' >>> t('$def with (a)\n$a.b')(storage(b=1)) '1\n' >>> t('$def with (a)\n$a[0]')([1]) '1\n' >>> t('${0 or 1}')() '1\n' >>> t('$ a = [1]\n$a[0]')() '1\n' >>> t('$ a = {1: 1}\n$a.keys()[0]')() '1\n' >>> t('$ a = []\n$if not a: 1')() '1\n' >>> t('$ a = {}\n$if not a: 1')() '1\n' >>> t('$ a = -1\n$a')() '-1\n' >>> t('$ a = "1"\n$a')() '1\n' >>> t('$if 1 is 1: 1')() '1\n' >>> t('$if not 0: 1')() '1\n' >>> t('$if 1:\n $if 1: 1')() '1\n' >>> t('$ a = 1\n$a')() '1\n' >>> t('$ a = 1.\n$a')() '1.0\n' >>> t('$({1: 1}.keys()[0])')() '1\n' >>> t('$for x in [1, 2, 3]:\n\t$x')() ' 1\n 2\n 3\n' >>> t('$def with (a)\n$:a')(1) '1\n' >>> t('$def with (a)\n$a')(u'\u203d') '\xe2\x80\xbd\n' >>> t(u'$def with (a)\n$a $:a')(u'\u203d') '\xe2\x80\xbd \xe2\x80\xbd\n' >>> t(u'$def with ()\nfoo')() 'foo\n' >>> def f(x): return x ... >>> t(u'$def with (f)\n$:f("x")')(f) 'x\n' >>> t(u'$def with (f)\n$:f(x="x")')(f) 'x\n' >>> x = t('$var foo: bar')() >>> str(x) '' >>> x.foo 'bar\n'
see also template.py doc
utils.py
class Storage(dict)- A Storage object is like a dictionary except
obj.foocan be used in addition toobj['foo'].>>> o = storage(a=1) >>> o.a 1 >>> o['a'] 1 >>> o.a = 2 >>> o['a'] 2 >>> del o.a >>> o.a Traceback (most recent call last): ... AttributeError: 'a' storify(mapping, *requireds, **defaults)- Creates a
storageobject from dictionarymapping, raisingKeyErrorif d doesn’t have all of the keys inrequiredsand using the default values for keys found indefaults.For example,
storify({'a':1, 'c':3}, b=2, c=0)will return the equivalent ofstorage({'a':1, 'b':2, 'c':3}).If a
storifyvalue is a list (e.g. multiple values in a form submission),storifyreturns the last element of the list, unless the key appears indefaultsas a list. Thus:>>> storify({'a':[1, 2]}).a 2 >>> storify({'a':[1, 2]}, a=[]).a [1, 2] >>> storify({'a':1}, a=[]).a [1] >>> storify({}, a=[]).a []Similarly, if the value has a
valueattribute,storify will return _its_ value, unless the key appears indefaults` as a dictionary.>>> storify({'a':storage(value=1)}).a 1 >>> storify({'a':storage(value=1)}, a={}).a <Storage {'value': 1}> >>> storify({}, a={}).a {} rstrips(text, remove)- removes the string
removefrom the right oftext>>> rstrips("foobar", "bar") 'foo' lstrips(text, remove)- removes the string
removefrom the left oftext>>> lstrips("foobar", "foo") 'bar' strips(text, remove)- removes the string
removefrom the both sides oftext»> strips(“foobarfoo”, “foo”) ‘bar’ utf8(text)- Encodes text in utf-8.
» utf8(u’\u1234’) # doctest doesn’t seem to like utf-8 ‘\xe1\x88\xb4’>>> utf8('hello') 'hello' >>> utf8(42) '42' class TimeoutError(Exception): pass def timelimit(timeout):- A decorator to limit a function to
timeoutseconds, raisingTimeoutErrorif it takes longer.>>> import time >>> def meaningoflife(): ... time.sleep(.2) ... return 42 >>> >>> timelimit(.1)(meaningoflife)() Traceback (most recent call last): ... TimeoutError: took too long >>> timelimit(1)(meaningoflife)() 42Caveat: The function isn’t stopped after
timeoutseconds but continues executing in a separate thread. (There seems to be no way to kill a thread.)inspired by http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/473878
class Memoize- ‘Memoizes’ a function, caching its return values for each input.
>>> import time >>> def meaningoflife(): ... time.sleep(.2) ... return 42 >>> fastlife = memoize(meaningoflife) >>> meaningoflife() 42 >>> timelimit(.1)(meaningoflife)() Traceback (most recent call last): ... TimeoutError: took too long >>> fastlife() 42 >>> timelimit(.1)(fastlife)() 42 re_subm(pat, repl, string)- Like re.sub, but returns the replacement and the match object.
>>> t, m = re_subm('g(oo+)fball', r'f\\1lish', 'goooooofball') >>> t 'foooooolish' >>> m.groups() ('oooooo',) group(seq, size)- Returns an iterator over a series of lists of length size from iterable.
>>> list(group([1,2,3,4], 2)) [1, 2], [3, 4](/1, 2], [3, 4) class IterBetter- Returns an object that can be used as an iterator
but can also be used via getitem (although it
cannot go backwards – that is, you cannot request
iterbetter[0]after requestingiterbetter[1]).>>> import itertools >>> c = iterbetter(itertools.count()) >>> c[1] 1 >>> c[5] 5 >>> c[3] Traceback (most recent call last): ... IndexError: already passed 3 dictreverse(mapping)-
dictreverse({1: 2, 3: 4}) {2: 1, 4: 3}
dictfind(dictionary, element)- Returns a key whose value in
dictionaryiselementor, if none exists, None.>>> d = {1:2, 3:4} >>> dictfind(d, 4) 3 >>> dictfind(d, 5) dictfindall(dictionary, element)- Returns the keys whose values in
dictionaryareelementor, if none exists, [].>>> d = {1:4, 3:4} >>> dictfindall(d, 4) [1, 3] >>> dictfindall(d, 5) [] dictincr(dictionary, element)- Increments
elementindictionary, setting it to one if it doesn’t exist.>>> d = {1:2, 3:4} >>> dictincr(d, 1) 3 >>> d[1] 3 >>> dictincr(d, 5) 1 >>> d[5] 1 dictadd(*dicts)- Returns a dictionary consisting of the keys in the argument dictionaries.
If they share a key, the value from the last argument is used.
>>> dictadd({1: 0, 2: 0}, {2: 1, 3: 1}) {1: 0, 2: 1, 3: 1} listget(lst, ind, default=None)- Returns
lst[ind]if it exists,defaultotherwise.>>> listget(['a'], 0) 'a' >>> listget(['a'], 1) >>> listget(['a'], 1, 'b') 'b' intget(integer, default=None)- Returns
integeras an int ordefaultif it can’t.>>> intget('3') 3 >>> intget('3a') >>> intget('3a', 0) 0 datestr(then, now=None)- Converts a (UTC) datetime object to a nice string representation.
>>> from datetime import datetime, timedelta >>> d = datetime(1970, 5, 1) >>> datestr(d, now=d) '0 microseconds ago' >>> for t, v in { ... timedelta(microseconds=1): '1 microsecond ago', ... timedelta(microseconds=2): '2 microseconds ago', ... -timedelta(microseconds=1): '1 microsecond from now', ... -timedelta(microseconds=2): '2 microseconds from now', ... timedelta(microseconds=2000): '2 milliseconds ago', ... timedelta(seconds=2): '2 seconds ago', ... timedelta(seconds=2*60): '2 minutes ago', ... timedelta(seconds=2*60*60): '2 hours ago', ... timedelta(days=2): '2 days ago', ... }.iteritems(): ... assert datestr(d, now=d+t) == v >>> datestr(datetime(1970, 1, 1), now=d) 'January 1' >>> datestr(datetime(1969, 1, 1), now=d) 'January 1, 1969' >>> datestr(datetime(1970, 6, 1), now=d) 'June 1, 1970' numify(string)- Removes all non-digit characters from
string.>>> numify('800-555-1212') '8005551212' >>> numify('800.555.1212') '8005551212' denumify(string, pattern)- Formats
stringaccording topattern, where the letter X gets replaced by characters fromstring.>>> denumify("8005551212", "(XXX) XXX-XXXX") '(800) 555-1212' dateify(datestring)- Formats a numified
datestringproperly. class CaptureStdout- Captures everything
funcprints to stdout and returns it instead.>>> def idiot(): ... print "foo" >>> capturestdout(idiot)() 'foo\\n'WARNING: Not threadsafe!
class Profile- Profiles
funcand returns a tuple containing its output and a string with human-readable profiling information.>>> import time >>> out, inf = profile(time.sleep)(.001) >>> out >>> inf[:10].strip() 'took 0.0' tryall(context, prefix=None)- Tries a series of functions and prints their results.
contextis a dictionary mapping names to values; the value will only be tried if it’s callable.>>> tryall(dict(j=lambda: True)) j: True ---------------------------------------- results: True: 1For example, you might have a file
test/stuff.pywith a series of functions testing various things in it. At the bottom, have a line:if __name__ == "__main__": tryall(globals())Then you can run
python test/stuff.pyand get the results of all the tests. class ThreadedDict- Takes a dictionary that maps threads to objects. When a thread tries to get or set an attribute or item of the threadeddict, it passes it on to the object for that thread in dictionary.
autoassign(self, locals)- Automatically assigns local variables to
self.>>> self = storage() >>> autoassign(self, dict(a=1, b=2)) >>> self <Storage {'a': 1, 'b': 2}>Generally used in
__init__methods, as in:def __init__(self, foo, bar, baz=1): autoassign(self, locals()) to36(q)- Converts an integer to base 36 (a useful scheme for human-sayable IDs).
>>> to36(35) 'z' >>> to36(119292) '2k1o' >>> int(to36(939387374), 36) 939387374 >>> to36(0) '0' >>> to36(-393) Traceback (most recent call last): ... ValueError: must supply a positive integer safemarkdown(text)- Converts text to HTML following the rules of Markdown, but blocking any
outside HTML input, so that only the things supported by Markdown
can be used. Also converts raw URLs to links.
(requires markdown.py)
sendmail(from_address, to_address, subject, message, headers=None, **kw)- Sends the email message
messagewith mail and envelope headers for fromfrom_address_toto_addresswithsubject. Additional email headers can be specified with the dictionary `headers.If
web.config.smtp_serveris set, it will send the message to that SMTP server. Otherwise it will look for/usr/lib/sendmail, the typical location for the sendmail-style binary.
webapi.py
badrequest()- Return a
400 Bad Requesterror. notfound()- Returns a
404 Not Founderror. gone()- Returns a
410 Goneerror. internalerror()- Returns a
500 Internal Servererror. header(hdr, value, unique=False)- Adds the header
hdr: valuewith the response.If
uniqueis True and a header with that name already exists, it doesn’t add a new one. output(string_)- Appends
string_to the response. flush()input(*requireds, **defaults)- Returns a
storageobject with the GET and POST arguments. Seestorifyfor howrequiredsanddefaultswork. data()- Returns the data sent with the request.
setcookie(name, value, expires="", domain=None, secure=False)- Sets a cookie.
cookies(*requireds, **defaults)- Returns a
storageobject with all the cookies in it. Seestorifyfor howrequiredsanddefaultswork. debug(*args)- Prints a prettyprinted version of
argsto stderr. load()- Loads a new context for the thread.
You can ask for a function to be run at loadtime by adding it to the dictionary
loadhooks. unload()- Unloads the context for the thread.
You can ask for a function to be run at loadtime by adding it ot the dictionary
unloadhooks. wsgifunc(func, *middleware)- Returns a WSGI-compatible function from a webpy-function.
ctx- A
storageobject containing various information about the request:
`environ` (aka `env`)
: A dictionary containing the standard WSGI environment variables.
`host`
: The domain (`Host` header) requested by the user.
`home`
: The base path for the application.
`ip`
: The IP address of the requester.
`method`
: The HTTP method used.
`path`
: The path request.
`query`
: If there are no query arguments, the empty string. Otherwise, a `?` followed
by the query string.
`fullpath`
: The full path requested, including query arguments (`== path + query`).
### Response Data
`status` (default: "200 OK")
: The status code to be used in the response.
`headers`
: A list of 2-tuples to be used in the response.
`output`
: A string to be used as the response. ## wsgi.py
runfcgi(func, addr=('localhost', 8000))- Runs a WSGI function as a FastCGI server.
runscgi(func, addr=('localhost', 4000))- Runs a WSGI function as an SCGI server.
runwsgi(func)- Runs a WSGI-compatible
funcusing FCGI, SCGI, or a simple web server, as appropriate based on context andsys.argv.
