API 文档

优质
小牛编辑
136浏览
2023-12-01

moduleweb.application

Web application (from web.py)

classapplication(self, mapping=(), fvars={}, autoreload=None)

Application to delegate requests based on path.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): return "hello"
>>>
>>> app.request("/hello").data
'hello'

methodadd_mapping(self, pattern, classname)

methodadd_processor(self, processor)

Adds a processor to the application.

>>> urls = ("/(.*)", "echo")
>>> app = application(urls, globals())
>>> class echo:
...     def GET(self, name): return name
...
>>>
>>> def hello(handler): return "hello, " +  handler()
...
>>> app.add_processor(hello)
>>> app.request("/web.py").data
'hello, web.py'

methodbrowser(self)

methodcgirun(self, *middleware)

Return a CGI handler. This is mostly useful with Google App Engine. There you can just do:

main = app.cgirun()

methodgaerun(self, *middleware)

Starts the program in a way that will work with Google app engine, no matter which version you are using (2.5 / 2.7)

If it is 2.5, just normally start it with app.gaerun()

If it is 2.7, make sure to change the app.yaml handler to point to the global variable that contains the result of app.gaerun()

For example:

in app.yaml (where code.py is where the main code is located)

handlers:
- url: /.*
  script: code.app

Make sure that the app variable is globally accessible

methodget_parent_app(self)

methodhandle(self)

methodhandle_with_processors(self)

methodinit_mapping(self, mapping)

methodinternalerror(self)

Returns HTTPError with '500 internal error' message

methodload(self, env)

Initializes ctx using env.

methodnotfound(self)

Returns HTTPError with '404 not found' message

methodrequest(self, localpart='/', method='GET', data=None, host='0.0.0.0:8080', headers=None, https=False, **kw)

Makes request to this application for the specified path and method. Response will be a storage object with data, status and headers.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): 
...         web.header('Content-Type', 'text/plain')
...         return "hello"
...
>>> response = app.request("/hello")
>>> response.data
'hello'
>>> response.status
'200 OK'
>>> response.headers['Content-Type']
'text/plain'

To use https, use https=True.

>>> urls = ("/redirect", "redirect")
>>> app = application(urls, globals())
>>> class redirect:
...     def GET(self): raise web.seeother("/foo")
...
>>> response = app.request("/redirect")
>>> response.headers['Location']
'http://0.0.0.0:8080/foo'
>>> response = app.request("/redirect", https=True)
>>> response.headers['Location']
'https://0.0.0.0:8080/foo'

The headers argument specifies HTTP headers as a mapping object such as a dict.

>>> urls = ('/ua', 'uaprinter')
>>> class uaprinter:
...     def GET(self):
...         return 'your user-agent is ' + web.ctx.env['HTTP_USER_AGENT']
... 
>>> app = application(urls, globals())
>>> app.request('/ua', headers = {
...      'User-Agent': 'a small jumping bean/1.0 (compatible)'
... }).data
'your user-agent is a small jumping bean/1.0 (compatible)'

methodrun(self, *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.

middleware is a list of WSGI middleware which is applied to the resulting WSGI function.

methodstop(self)

Stops the http server started by run.

methodwsgifunc(self, *middleware)

Returns a WSGI-compatible function for this application.

classauto_application(self)

Application similar to application but urls are constructed automatically using metaclass.

>>> app = auto_application()
>>> class hello(app.page):
...     def GET(self): return "hello, world"
...
>>> class foo(app.page):
...     path = '/foo/.*'
...     def GET(self): return "foo"
>>> app.request("/hello").data
'hello, world'
>>> app.request('/foo/bar').data
'foo'

methodadd_mapping(self, pattern, classname)

methodadd_processor(self, processor)

Adds a processor to the application.

>>> urls = ("/(.*)", "echo")
>>> app = application(urls, globals())
>>> class echo:
...     def GET(self, name): return name
...
>>>
>>> def hello(handler): return "hello, " +  handler()
...
>>> app.add_processor(hello)
>>> app.request("/web.py").data
'hello, web.py'

methodbrowser(self)

methodcgirun(self, *middleware)

Return a CGI handler. This is mostly useful with Google App Engine. There you can just do:

main = app.cgirun()

methodgaerun(self, *middleware)

Starts the program in a way that will work with Google app engine, no matter which version you are using (2.5 / 2.7)

If it is 2.5, just normally start it with app.gaerun()

If it is 2.7, make sure to change the app.yaml handler to point to the global variable that contains the result of app.gaerun()

For example:

in app.yaml (where code.py is where the main code is located)

handlers:
- url: /.*
  script: code.app

Make sure that the app variable is globally accessible

methodget_parent_app(self)

methodhandle(self)

methodhandle_with_processors(self)

methodinit_mapping(self, mapping)

methodinternalerror(self)

Returns HTTPError with '500 internal error' message

methodload(self, env)

Initializes ctx using env.

methodnotfound(self)

Returns HTTPError with '404 not found' message

methodrequest(self, localpart='/', method='GET', data=None, host='0.0.0.0:8080', headers=None, https=False, **kw)

Makes request to this application for the specified path and method. Response will be a storage object with data, status and headers.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): 
...         web.header('Content-Type', 'text/plain')
...         return "hello"
...
>>> response = app.request("/hello")
>>> response.data
'hello'
>>> response.status
'200 OK'
>>> response.headers['Content-Type']
'text/plain'

To use https, use https=True.

>>> urls = ("/redirect", "redirect")
>>> app = application(urls, globals())
>>> class redirect:
...     def GET(self): raise web.seeother("/foo")
...
>>> response = app.request("/redirect")
>>> response.headers['Location']
'http://0.0.0.0:8080/foo'
>>> response = app.request("/redirect", https=True)
>>> response.headers['Location']
'https://0.0.0.0:8080/foo'

The headers argument specifies HTTP headers as a mapping object such as a dict.

>>> urls = ('/ua', 'uaprinter')
>>> class uaprinter:
...     def GET(self):
...         return 'your user-agent is ' + web.ctx.env['HTTP_USER_AGENT']
... 
>>> app = application(urls, globals())
>>> app.request('/ua', headers = {
...      'User-Agent': 'a small jumping bean/1.0 (compatible)'
... }).data
'your user-agent is a small jumping bean/1.0 (compatible)'

methodrun(self, *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.

middleware is a list of WSGI middleware which is applied to the resulting WSGI function.

methodstop(self)

Stops the http server started by run.

methodwsgifunc(self, *middleware)

Returns a WSGI-compatible function for this application.

classsubdir_application(self, mapping=(), fvars={}, autoreload=None)

Application to delegate requests based on path.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): return "hello"
>>>
>>> app.request("/hello").data
'hello'

methodadd_mapping(self, pattern, classname)

methodadd_processor(self, processor)

Adds a processor to the application.

>>> urls = ("/(.*)", "echo")
>>> app = application(urls, globals())
>>> class echo:
...     def GET(self, name): return name
...
>>>
>>> def hello(handler): return "hello, " +  handler()
...
>>> app.add_processor(hello)
>>> app.request("/web.py").data
'hello, web.py'

methodbrowser(self)

methodcgirun(self, *middleware)

Return a CGI handler. This is mostly useful with Google App Engine. There you can just do:

main = app.cgirun()

methodgaerun(self, *middleware)

Starts the program in a way that will work with Google app engine, no matter which version you are using (2.5 / 2.7)

If it is 2.5, just normally start it with app.gaerun()

If it is 2.7, make sure to change the app.yaml handler to point to the global variable that contains the result of app.gaerun()

For example:

in app.yaml (where code.py is where the main code is located)

handlers:
- url: /.*
  script: code.app

Make sure that the app variable is globally accessible

methodget_parent_app(self)

methodhandle(self)

methodhandle_with_processors(self)

methodinit_mapping(self, mapping)

methodinternalerror(self)

Returns HTTPError with '500 internal error' message

methodload(self, env)

Initializes ctx using env.

methodnotfound(self)

Returns HTTPError with '404 not found' message

methodrequest(self, localpart='/', method='GET', data=None, host='0.0.0.0:8080', headers=None, https=False, **kw)

Makes request to this application for the specified path and method. Response will be a storage object with data, status and headers.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): 
...         web.header('Content-Type', 'text/plain')
...         return "hello"
...
>>> response = app.request("/hello")
>>> response.data
'hello'
>>> response.status
'200 OK'
>>> response.headers['Content-Type']
'text/plain'

To use https, use https=True.

>>> urls = ("/redirect", "redirect")
>>> app = application(urls, globals())
>>> class redirect:
...     def GET(self): raise web.seeother("/foo")
...
>>> response = app.request("/redirect")
>>> response.headers['Location']
'http://0.0.0.0:8080/foo'
>>> response = app.request("/redirect", https=True)
>>> response.headers['Location']
'https://0.0.0.0:8080/foo'

The headers argument specifies HTTP headers as a mapping object such as a dict.

>>> urls = ('/ua', 'uaprinter')
>>> class uaprinter:
...     def GET(self):
...         return 'your user-agent is ' + web.ctx.env['HTTP_USER_AGENT']
... 
>>> app = application(urls, globals())
>>> app.request('/ua', headers = {
...      'User-Agent': 'a small jumping bean/1.0 (compatible)'
... }).data
'your user-agent is a small jumping bean/1.0 (compatible)'

methodrun(self, *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.

middleware is a list of WSGI middleware which is applied to the resulting WSGI function.

methodstop(self)

Stops the http server started by run.

methodwsgifunc(self, *middleware)

Returns a WSGI-compatible function for this application.

classsubdomain_application(self, mapping=(), fvars={}, autoreload=None)

Application to delegate requests based on the host.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): return "hello"
>>>
>>> mapping = (r"hello\.example\.com", app)
>>> app2 = subdomain_application(mapping)
>>> app2.request("/hello", host="hello.example.com").data
'hello'
>>> response = app2.request("/hello", host="something.example.com")
>>> response.status
'404 Not Found'
>>> response.data
'not found'

methodadd_mapping(self, pattern, classname)

methodadd_processor(self, processor)

Adds a processor to the application.

>>> urls = ("/(.*)", "echo")
>>> app = application(urls, globals())
>>> class echo:
...     def GET(self, name): return name
...
>>>
>>> def hello(handler): return "hello, " +  handler()
...
>>> app.add_processor(hello)
>>> app.request("/web.py").data
'hello, web.py'

methodbrowser(self)

methodcgirun(self, *middleware)

Return a CGI handler. This is mostly useful with Google App Engine. There you can just do:

main = app.cgirun()

methodgaerun(self, *middleware)

Starts the program in a way that will work with Google app engine, no matter which version you are using (2.5 / 2.7)

If it is 2.5, just normally start it with app.gaerun()

If it is 2.7, make sure to change the app.yaml handler to point to the global variable that contains the result of app.gaerun()

For example:

in app.yaml (where code.py is where the main code is located)

handlers:
- url: /.*
  script: code.app

Make sure that the app variable is globally accessible

methodget_parent_app(self)

methodhandle(self)

methodhandle_with_processors(self)

methodinit_mapping(self, mapping)

methodinternalerror(self)

Returns HTTPError with '500 internal error' message

methodload(self, env)

Initializes ctx using env.

methodnotfound(self)

Returns HTTPError with '404 not found' message

methodrequest(self, localpart='/', method='GET', data=None, host='0.0.0.0:8080', headers=None, https=False, **kw)

Makes request to this application for the specified path and method. Response will be a storage object with data, status and headers.

>>> urls = ("/hello", "hello")
>>> app = application(urls, globals())
>>> class hello:
...     def GET(self): 
...         web.header('Content-Type', 'text/plain')
...         return "hello"
...
>>> response = app.request("/hello")
>>> response.data
'hello'
>>> response.status
'200 OK'
>>> response.headers['Content-Type']
'text/plain'

To use https, use https=True.

>>> urls = ("/redirect", "redirect")
>>> app = application(urls, globals())
>>> class redirect:
...     def GET(self): raise web.seeother("/foo")
...
>>> response = app.request("/redirect")
>>> response.headers['Location']
'http://0.0.0.0:8080/foo'
>>> response = app.request("/redirect", https=True)
>>> response.headers['Location']
'https://0.0.0.0:8080/foo'

The headers argument specifies HTTP headers as a mapping object such as a dict.

>>> urls = ('/ua', 'uaprinter')
>>> class uaprinter:
...     def GET(self):
...         return 'your user-agent is ' + web.ctx.env['HTTP_USER_AGENT']
... 
>>> app = application(urls, globals())
>>> app.request('/ua', headers = {
...      'User-Agent': 'a small jumping bean/1.0 (compatible)'
... }).data
'your user-agent is a small jumping bean/1.0 (compatible)'

methodrun(self, *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.

middleware is a list of WSGI middleware which is applied to the resulting WSGI function.

methodstop(self)

Stops the http server started by run.

methodwsgifunc(self, *middleware)

Returns a WSGI-compatible function for this application.

functionloadhook(h)

Converts a load hook into an application processor.

>>> app = auto_application()
>>> def f(): "something done before handling request"
...
>>> app.add_processor(loadhook(f))

functionunloadhook(h)

Converts an unload hook into an application processor.

>>> app = auto_application()
>>> def f(): "something done after handling request"
...
>>> app.add_processor(unloadhook(f))

functionautodelegate(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): pass

GET_password would get called for /prefs/password while GET_privacy for GET_privacy gets called for /prefs/privacy.

If a user visits /prefs/password/change then GET_password(self, '/change') is called.

moduleweb.contrib.template

Interface to various templating engines.

classrender_cheetah(self, path)

Rendering interface to Cheetah Templates.

Example:

render = render_cheetah('templates')
render.hello(name="cheetah")

classrender_genshi(self, *a, **kwargs)

Rendering interface genshi templates. Example:

for xml/html templates.

render = render_genshi(['templates/'])
render.hello(name='genshi')

For text templates:

render = render_genshi(['templates/'], type='text')
render.hello(name='genshi')

classrender_mako(self, *a, **kwargs)

Rendering interface to Mako Templates.

Example:

render = render_mako(directories=['templates'])
render.hello(name="mako")

classcache(self, render)

Cache for any rendering interface.

Example:

render = cache(render_cheetah("templates/"))
render.hello(name='cache')

moduleweb.db

Database API (part of web.py)

typeUnknownParamstyle

raised for unsupported db paramstyles

(currently supported: qmark, numeric, format, pyformat)

typeUnknownDB

raised for unsupported dbms

typeTransactionError

functionsqllist(lst)

Converts the arguments for use in something like a WHERE clause.

>>> sqllist(['a', 'b'])
'a, b'
>>> sqllist('a')
'a'
>>> sqllist(u'abc')
u'abc'

functionsqlors(left, lst)

left is a SQL clause liketablename.arg = ` and lst is 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: '1=2'>
>>> 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 OR 1=2)'>

functionreparam(string_, dictionary)

Takes a string and a dictionary and interpolates the string using values from the dictionary. Returns an SQLQuery for the result.

>>> reparam("s = $s", dict(s=True))
<sql: "s = 't'">
>>> reparam("s IN $s", dict(s=[1, 2]))
<sql: 's IN (1, 2)'>

functionsqlquote(a)

Ensures a is quoted properly for use in a SQL query.

>>> 'WHERE x = ' + sqlquote(True) + ' AND y = ' + sqlquote(3)
<sql: "WHERE x = 't' AND y = 3">
>>> 'WHERE x = ' + sqlquote(True) + ' AND y IN ' + sqlquote([2, 3])
<sql: "WHERE x = 't' AND y IN (2, 3)">

typeSQLQuery(self, items=None)

You can pass this sort of thing as a clause in any db function. Otherwise, you can pass a dictionary to the keyword argument vars and the function will call reparam for you.

Internally, consists of items, which is a list of strings and SQLParams, which get concatenated to produce the actual query.

methodappend(self, value)

functionjoin(items, sep=' ', prefix=None, suffix=None, target=None)

Joins multiple queries.

SQLQuery.join(['a', 'b'], ', ') <sql: 'a, b'>

Optinally, prefix and suffix arguments can be provided.

SQLQuery.join(['a', 'b'], ', ', prefix='(', suffix=')') <sql: '(a, b)'>

If target argument is provided, the items are appended to target instead of creating a new SQLQuery.

methodquery(self, paramstyle=None)

Returns the query part of the sql query.

q = SQLQuery(["SELECT * FROM test WHERE name=", SQLParam('joe')]) q.query() 'SELECT * FROM test WHERE name=%s' q.query(paramstyle='qmark') 'SELECT * FROM test WHERE name=?'

methodvalues(self)

Returns the values of the parameters used in the sql query.

q = SQLQuery(["SELECT * FROM test WHERE name=", SQLParam('joe')]) q.values() ['joe']

typeSQLParam(self, value)

Parameter in SQLQuery.

>>> q = SQLQuery(["SELECT * FROM test WHERE name=", SQLParam("joe")])
>>> q
<sql: "SELECT * FROM test WHERE name='joe'">
>>> q.query()
'SELECT * FROM test WHERE name=%s'
>>> q.values()
['joe']

methodget_marker(self, paramstyle='pyformat')

methodsqlquery(self)

typesqlparam(self, value)

Parameter in SQLQuery.

>>> q = SQLQuery(["SELECT * FROM test WHERE name=", SQLParam("joe")])
>>> q
<sql: "SELECT * FROM test WHERE name='joe'">
>>> q.query()
'SELECT * FROM test WHERE name=%s'
>>> q.values()
['joe']

methodget_marker(self, paramstyle='pyformat')

methodsqlquery(self)

classSQLLiteral(self, v)

Protects a string from sqlquote.

>>> sqlquote('NOW()')
<sql: "'NOW()'">
>>> sqlquote(SQLLiteral('NOW()'))
<sql: 'NOW()'>

classsqlliteral(self, v)

Protects a string from sqlquote.

>>> sqlquote('NOW()')
<sql: "'NOW()'">
>>> sqlquote(SQLLiteral('NOW()'))
<sql: 'NOW()'>

functiondatabase(dburl=None, **params)

Creates appropriate database using params.

Pooling will be enabled if DBUtils module is available. Pooling can be disabled by passing pooling=False in params.

classDB(self, db_module, keywords)

Database

propertyctx

methoddelete(self, table, where, using=None, vars=None, _test=False)

Deletes from table with clauses where and using.

>>> db = DB(None, {})
>>> name = 'Joe'
>>> db.delete('foo', where='name = $name', vars=locals(), _test=True)
<sql: "DELETE FROM foo WHERE name = 'Joe'">

methodgen_clause(self, sql, val, vars)

methodinsert(self, tablename, seqname=None, _test=False, **values)

Inserts values into tablename. Returns current sequence ID. Set seqname to the ID if it's not the default, or to False if there isn't one.

>>> db = DB(None, {})
>>> q = db.insert('foo', name='bob', age=2, created=SQLLiteral('NOW()'), _test=True)
>>> q
<sql: "INSERT INTO foo (age, name, created) VALUES (2, 'bob', NOW())">
>>> q.query()
'INSERT INTO foo (age, name, created) VALUES (%s, %s, NOW())'
>>> q.values()
[2, 'bob']

methodmultiple_insert(self, tablename, values, seqname=None, _test=False)

Inserts multiple rows into tablename. The values must be a list of dictioanries, one for each row to be inserted, each with the same set of keys. Returns the list of ids of the inserted rows.
Set seqname to the ID if it's not the default, or to False if there isn't one.

>>> db = DB(None, {})
>>> db.supports_multiple_insert = True
>>> values = [{"name": "foo", "email": "foo@example.com"}, {"name": "bar", "email": "bar@example.com"}]
>>> db.multiple_insert('person', values=values, _test=True)
<sql: "INSERT INTO person (name, email) VALUES ('foo', 'foo@example.com'), ('bar', 'bar@example.com')">

methodquery(self, sql_query, vars=None, processed=False, _test=False)

Execute SQL query sql_query using dictionary vars to interpolate it. If processed=True, vars is a reparam-style list to use instead of interpolating.

>>> db = DB(None, {})
>>> db.query("SELECT * FROM foo", _test=True)
<sql: 'SELECT * FROM foo'>
>>> db.query("SELECT * FROM foo WHERE x = $x", vars=dict(x='f'), _test=True)
<sql: "SELECT * FROM foo WHERE x = 'f'">
>>> db.query("SELECT * FROM foo WHERE x = " + sqlquote('f'), _test=True)
<sql: "SELECT * FROM foo WHERE x = 'f'">

methodselect(self, tables, vars=None, what='*', where=None, order=None, group=None, limit=None, offset=None, _test=False)

Selects what from tables with clauses where, order, group, limit, and offset. Uses vars to interpolate. Otherwise, each clause can be a SQLQuery.

>>> db = DB(None, {})
>>> db.select('foo', _test=True)
<sql: 'SELECT * FROM foo'>
>>> db.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'>
>>> db.select('foo', where={'id': 5}, _test=True)
<sql: 'SELECT * FROM foo WHERE id = 5'>

methodsql_clauses(self, what, tables, where, group, order, limit, offset)

methodtransaction(self)

Start a transaction.

methodupdate(self, tables, where, vars=None, _test=False, **values)

Update tables with clause where (interpolated using vars) and setting values.

>>> db = DB(None, {})
>>> name = 'Joseph'
>>> q = db.update('foo', where='name = $name', name='bob', age=2,
...     created=SQLLiteral('NOW()'), vars=locals(), _test=True)
>>> q
<sql: "UPDATE foo SET age = 2, name = 'bob', created = NOW() WHERE name = 'Joseph'">
>>> q.query()
'UPDATE foo SET age = %s, name = %s, created = NOW() WHERE name = %s'
>>> q.values()
[2, 'bob', 'Joseph']

methodwhere(self, table, what='*', order=None, group=None, limit=None, offset=None, _test=False, **kwargs)

Selects from table where keys are equal to values in kwargs.

>>> db = DB(None, {})
>>> db.where('foo', bar_id=3, _test=True)
<sql: 'SELECT * FROM foo WHERE bar_id = 3'>
>>> db.where('foo', source=2, crust='dewey', _test=True)
<sql: "SELECT * FROM foo WHERE source = 2 AND crust = 'dewey'">
>>> db.where('foo', _test=True)
<sql: 'SELECT * FROM foo'>

moduleweb.debugerror

pretty debug errors (part of web.py)

portions adapted from Django Copyright (c) 2005, the Lawrence Journal-World Used under the modified BSD license: http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5</p></div></p>

functiondebugerror()

A replacement for internalerror that presents a nice page with lots of debug information for the programmer.

(Based on the beautiful 500 page from Django, designed by Wilson Miner.)

functiondjangoerror()

functionemailerrors(to_address, olderror, from_address=None)

Wraps the old internalerror handler (pass as olderror) to additionally email all errors to to_address, to aid in debugging production websites.

Emails contain a normal text traceback as well as an attachment containing the nice debugerror page.

moduleweb.form

HTML forms (part of web.py)

typeAttributeList

List of atributes of input.

a = AttributeList(type='text', name='x', value=20) a <attrs: 'type="text" name="x" value="20"'>

methodcopy(self)

typeButton(self, name, *validators, **attrs)

HTML Button.

Button("save").render() u'' Button("action", value="save", html="Save Changes").render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeCheckbox(self, name, *validators, **attrs)

Checkbox input.

Checkbox('foo', value='bar', checked=True).render() u'' Checkbox('foo', value='bar').render() u'' c = Checkbox('foo', value='bar') c.validate('on') True c.render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeDropdown(self, name, args, *validators, **attrs)

Dropdown/select input.

Dropdown(name='foo', args=['a', 'b', 'c'], value='b').render() u'\n a\n b\n c\n\n' Dropdown(name='foo', args=[('a', 'aa'), ('b', 'bb'), ('c', 'cc')], value='b').render() u'\n aa\n bb\n cc\n\n'

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeFile(self, name, *validators, **attrs)

File input.

File(name='f').render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeForm(self, *inputs, **kw)

HTML form.

>>> f = Form(Textbox("x"))
>>> f.render()
u'<table>\n    <tr><th><label for="x">x</label></th><td><input type="text" name="x"/></td></tr>\n</table>'

methodfill(self, source=None, **kw)

methodget(self, i, default=None)

methodrender(self)

methodrender_css(self)

methodrendernote(self, note)

methodvalidates(self, source=None, _validate=True, **kw)

typeGroupedDropdown(self, name, args, *validators, **attrs)

Grouped Dropdown/select input.

GroupedDropdown(name='cartype', args=(('Swedish Cars', ('Volvo', 'Saab')), ('German Cars', ('Mercedes', 'Audi'))), value='Audi').render() u'\n \n Volvo\n Saab\n \n \n Mercedes\n Audi\n \n\n' GroupedDropdown(name='cartype', args=(('Swedish Cars', (('v', 'Volvo'), ('s', 'Saab'))), ('German Cars', (('m', 'Mercedes'), ('a', 'Audi')))), value='a').render() u'\n \n Volvo\n Saab\n \n \n Mercedes\n Audi\n \n\n'

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeHidden(self, name, *validators, **attrs)

Hidden Input.

Hidden(name='foo', value='bar').render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeInput(self, name, *validators, **attrs)

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typePassword(self, name, *validators, **attrs)

Password input.

Password(name='password', value='secret').render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeRadio(self, name, args, *validators, **attrs)

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeTextarea(self, name, *validators, **attrs)

Textarea input.

Textarea(name='foo', value='bar').render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

typeTextbox(self, name, *validators, **attrs)

Textbox input.

Textbox(name='foo', value='bar').render() u'' Textbox(name='foo', value=0).render() u''

methodaddatts(self)

methodget_default_id(self)

methodget_type(self)

methodget_value(self)

methodis_hidden(self)

methodrender(self)

methodrendernote(self, note)

methodset_value(self, value)

methodvalidate(self, value)

classValidator(self, msg, test, jstest=None)

methodvalid(self, value)

functionattrget(obj, attr, value=None)

classregexp(self, rexp, msg)

methodvalid(self, value)

moduleweb.http

HTTP Utilities (from web.py)

functionexpires(delta)

Outputs an Expires header for delta from now. delta is a timedelta object or a number of seconds.

functionlastmodified(date_obj)

Outputs a Last-Modified header for datetime.

functionprefixurl(base='')

Sorry, this function is really difficult to explain. Maybe some other time.

functionmodified(date=None, etag=None)

Checks to see if the page has been modified since the version in the requester's cache.

When you publish pages, you can include Last-Modified and ETag with the date the page was last modified and an opaque token for the particular version, respectively. When readers reload the page, the browser sends along the modification date and etag value for the version it has in its cache. If the page hasn't changed, the server can just return 304 Not Modified and not have to send the whole page again.

This function takes the last-modified date date and the ETag etag and checks the headers to see if they match. If they do, it returns True, or otherwise it raises NotModified error. It also sets Last-Modified and ETag output headers.

functionchangequery(query=None, **kw)

Imagine you're at /foo?a=1&b=2. Then changequery(a=3) will return /foo?a=3&b=2 -- the same URL but with the arguments you requested changed.

functionurl(path=None, doseq=False, **kw)

Makes url by concatenating web.ctx.homepath and path and the query string created using the arguments.

functionprofiler(app)

Outputs basic profiling information at the bottom of each response.

moduleweb.httpserver

functionrunsimple(func, server_address=('0.0.0.0', 8080))

Runs CherryPy WSGI server hosting WSGI app func. The directory static/ is hosted statically.

moduleweb.net

Network Utilities (from web.py)

functionvalidipaddr(address)

Returns True if address is a valid IPv4 address.

>>> validipaddr('192.168.1.1')
True
>>> validipaddr('192.168.1.800')
False
>>> validipaddr('192.168.1')
False

functionvalidip6addr(address)

Returns True if address is a valid IPv6 address.

>>> validip6addr('::')
True
>>> validip6addr('aaaa:bbbb:cccc:dddd::1')
True
>>> validip6addr('1:2:3:4:5:6:7:8:9:10')
False
>>> validip6addr('12:10')
False

functionvalidipport(port)

Returns True if port is a valid IPv4 port.

>>> validipport('9000')
True
>>> validipport('foo')
False
>>> validipport('1000000')
False

functionvalidip(ip, defaultaddr='0.0.0.0', defaultport=8080)

Returns (ip_address, port) from string ip_addr_port

validip('1.2.3.4') ('1.2.3.4', 8080) validip('80') ('0.0.0.0', 80) validip('192.168.0.1:85') ('192.168.0.1', 85) validip('::') ('::', 8080) validip('[::]:88') ('::', 88) validip('[::1]:80') ('::1', 80)

functionvalidaddr(string_)

Returns either (ipaddress, 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)
>>> validip('[::1]:80')
('::1', 80)
>>> validaddr('fff')
Traceback (most recent call last):
    ...
ValueError: fff is not a valid IP address/port

functionurlquote(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'

functionhttpdate(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'

functionparsehttpdate(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)

functionhtmlquote(text)

Encodes text for raw use in HTML.

>>> htmlquote(u"<'&\">")
u'&lt;'&amp;&quot;&gt;'

functionhtmlunquote(text)

Decodes text that's HTML quoted.

>>> htmlunquote(u'&lt;'&amp;&quot;&gt;')
u'<\'&">'

functionwebsafe(val)

Converts val so that it is safe for use in Unicode HTML.

websafe("<'&\">") u'<'&">' websafe(None) u'' websafe(u'\u203d') u'\u203d' websafe('\xe2\x80\xbd') u'\u203d'

moduleweb.session

Session Management (from web.py)

typeSession(self, app, store, initializer=None)

Session management for web.py

methodexpired(self)

Called when an expired session is atime

methodkill(self)

Kill the session, make it no longer available

typeSessionExpired(self, message)

classStore(self)

Base class for session stores

methodcleanup(self, timeout)

removes all the expired sessions

methoddecode(self, session_data)

decodes the data to get back the session dict

methodencode(self, session_dict)

encodes session dict as a string

classDiskStore(self, root)

Store for saving a session on disk.

>>> import tempfile
>>> root = tempfile.mkdtemp()
>>> s = DiskStore(root)
>>> s['a'] = 'foo'
>>> s['a']
'foo'
>>> time.sleep(0.01)
>>> s.cleanup(0.01)
>>> s['a']
Traceback (most recent call last):
    ...
KeyError: 'a'

methodcleanup(self, timeout)

methoddecode(self, session_data)

decodes the data to get back the session dict

methodencode(self, session_dict)

encodes session dict as a string

classDBStore(self, db, table_name)

Store for saving a session in database Needs a table with the following columns:

session_id CHAR(128) UNIQUE NOT NULL,
atime DATETIME NOT NULL default current_timestamp,
data TEXT

methodcleanup(self, timeout)

methoddecode(self, session_data)

decodes the data to get back the session dict

methodencode(self, session_dict)

encodes session dict as a string

moduleweb.template

simple, elegant templating (part of web.py)

Template design:

Template string is split into tokens and the tokens are combined into nodes. Parse tree is a nodelist. TextNode and ExpressionNode are simple nodes and for-loop, if-loop etc are block nodes, which contain multiple child nodes.

Each node can emit some python string. python string emitted by the root node is validated for safeeval and executed using python in the given environment.

Enough care is taken to make sure the generated code and the template has line to line match, so that the error messages can point to exact line number in template. (It doesn't work in some cases still.)

Grammar:

template -> defwith sections 
defwith -> '$def with (' arguments ')' | ''
sections -> section*
section -> block | assignment | line
assignment -> '$ ' <assignment expression>
line -> (text|expr)*
text -> <any characters other than $>
expr -> '$' pyexpr | '$(' pyexpr ')' | '${' pyexpr '}'
pyexpr -> <python expression>

classTemplate(self, text, filename='<template>', filter=None, globals=None, builtins=None, extensions=None)

methodcompile_template(self, template_string, filename)

methodcreate_parser(self)

functiongenerate_code(text, filename, parser=None)

methodmake_env(self, globals, builtins)

functionnormalize_text(text)

Normalizes template text by correcting , tabs and BOM chars.

classRender(self, loc='templates', cache=None, base=None, **keywords)

The most preferred way of using templates.

render = web.template.render('templates')
print render.foo()

Optional parameter base can be used to pass output of every template through the base template.

render = web.template.render('templates', base='layout')

classrender(self, loc='templates', cache=None, base=None, **keywords)

The most preferred way of using templates.

render = web.template.render('templates')
print render.foo()

Optional parameter base can be used to pass output of every template through the base template.

render = web.template.render('templates', base='layout')

functionfrender(path, **keywords)

Creates a template from the given file path.

typeParseError

typeSecurityError

The template seems to be trying to do something naughty.

functiontest()

Doctest for testing template module.

Define a utility function to run template test.

>>> class TestResult:
...     def __init__(self, t): self.t = t
...     def __getattr__(self, name): return getattr(self.t, name)
...     def __repr__(self): return repr(unicode(self))
...
>>> def t(code, **keywords):
...     tmpl = Template(code, **keywords)
...     return lambda *a, **kw: TestResult(tmpl(*a, **kw))
...

Simple tests.

>>> t('1')()
u'1\n'
>>> t('$def with ()\n1')()
u'1\n'
>>> t('$def with (a)\n$a')(1)
u'1\n'
>>> t('$def with (a=0)\n$a')(1)
u'1\n'
>>> t('$def with (a=0)\n$a')(a=1)
u'1\n'

Test complicated expressions.

>>> t('$def with (x)\n$x.upper()')('hello')
u'HELLO\n'
>>> t('$(2 * 3 + 4 * 5)')()
u'26\n'
>>> t('${2 * 3 + 4 * 5}')()
u'26\n'
>>> t('$def with (limit)\nkeep $(limit)ing.')('go')
u'keep going.\n'
>>> t('$def with (a)\n$a.b[0]')(storage(b=[1]))
u'1\n'

Test html escaping.

>>> t('$def with (x)\n$x', filename='a.html')('<html>')
u'&lt;html&gt;\n'
>>> t('$def with (x)\n$x', filename='a.txt')('<html>')
u'<html>\n'

Test if, for and while.

>>> t('$if 1: 1')()
u'1\n'
>>> t('$if 1:\n    1')()
u'1\n'
>>> t('$if 1:\n    1\\')()
u'1'
>>> t('$if 0: 0\n$elif 1: 1')()
u'1\n'
>>> t('$if 0: 0\n$elif None: 0\n$else: 1')()
u'1\n'
>>> t('$if 0 < 1 and 1 < 2: 1')()
u'1\n'
>>> t('$for x in [1, 2, 3]: $x')()
u'1\n2\n3\n'
>>> t('$def with (d)\n$for k, v in d.iteritems(): $k')({1: 1})
u'1\n'
>>> t('$for x in [1, 2, 3]:\n\t$x')()
u'    1\n    2\n    3\n'
>>> t('$def with (a)\n$while a and a.pop():1')([1, 2, 3])
u'1\n1\n1\n'

The space after : must be ignored.

>>> t('$if True: foo')()
u'foo\n'

Test loop.xxx.

>>> t("$for i in range(5):$loop.index, $loop.parity")()
u'1, odd\n2, even\n3, odd\n4, even\n5, odd\n'
>>> t("$for i in range(2):\n    $for j in range(2):$loop.parent.parity $loop.parity")()
u'odd odd\nodd even\neven odd\neven even\n'

Test assignment.

>>> t('$ a = 1\n$a')()
u'1\n'
>>> t('$ a = [1]\n$a[0]')()
u'1\n'
>>> t('$ a = {1: 1}\n$a.keys()[0]')()
u'1\n'
>>> t('$ a = []\n$if not a: 1')()
u'1\n'
>>> t('$ a = {}\n$if not a: 1')()
u'1\n'
>>> t('$ a = -1\n$a')()
u'-1\n'
>>> t('$ a = "1"\n$a')()
u'1\n'

Test comments.

>>> t('$# 0')()
u'\n'
>>> t('hello$#comment1\nhello$#comment2')()
u'hello\nhello\n'
>>> t('$#comment0\nhello$#comment1\nhello$#comment2')()
u'\nhello\nhello\n'

Test unicode.

>>> t('$def with (a)\n$a')(u'\u203d')
u'\u203d\n'
>>> t('$def with (a)\n$a')(u'\u203d'.encode('utf-8'))
u'\u203d\n'
>>> t(u'$def with (a)\n$a $:a')(u'\u203d')
u'\u203d \u203d\n'
>>> t(u'$def with ()\nfoo')()
u'foo\n'
>>> def f(x): return x
...
>>> t(u'$def with (f)\n$:f("x")')(f)
u'x\n'
>>> t('$def with (f)\n$:f("x")')(f)
u'x\n'

Test dollar escaping.

>>> t("Stop, $$money isn't evaluated.")()
u"Stop, $money isn't evaluated.\n"
>>> t("Stop, \$money isn't evaluated.")()
u"Stop, $money isn't evaluated.\n"

Test space sensitivity.

>>> t('$def with (x)\n$x')(1)
u'1\n'
>>> t('$def with(x ,y)\n$x')(1, 1)
u'1\n'
>>> t('$(1 + 2*3 + 4)')()
u'11\n'

Make sure globals are working.

>>> t('$x')()
Traceback (most recent call last):
    ...
NameError: global name 'x' is not defined
>>> t('$x', globals={'x': 1})()
u'1\n'

Can't change globals.

>>> t('$ x = 2\n$x', globals={'x': 1})()
u'2\n'
>>> t('$ x = x + 1\n$x', globals={'x': 1})()
Traceback (most recent call last):
    ...
UnboundLocalError: local variable 'x' referenced before assignment

Make sure builtins are customizable.

>>> t('$min(1, 2)')()
u'1\n'
>>> t('$min(1, 2)', builtins={})()
Traceback (most recent call last):
    ...
NameError: global name 'min' is not defined

Test vars.

>>> x = t('$var x: 1')()
>>> x.x
u'1'
>>> x = t('$var x = 1')()
>>> x.x
1
>>> x = t('$var x:  \n    foo\n    bar')()
>>> x.x
u'foo\nbar\n'

Test BOM chars.

>>> t('\xef\xbb\xbf$def with(x)\n$x')('foo')
u'foo\n'

Test for with weird cases.

>>> t('$for i in range(10)[1:5]:\n    $i')()
u'1\n2\n3\n4\n'
>>> t("$for k, v in {'a': 1, 'b': 2}.items():\n    $k $v")()
u'a 1\nb 2\n'
>>> t("$for k, v in ({'a': 1, 'b': 2}.items():\n    $k $v")()
Traceback (most recent call last):
    ...
SyntaxError: invalid syntax

Test datetime.

>>> import datetime
>>> t("$def with (date)\n$date.strftime('%m %Y')")(datetime.datetime(2009, 1, 1))
u'01 2009\n'

moduleweb.utils

General Utilities (part of web.py)

typeStorage

A Storage object is like a dictionary except obj.foo can be used in addition to obj['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'

functionstorify(mapping, *requireds, **defaults)

Creates a storage object from dictionary mapping, raising KeyError if d doesn't have all of the keys in requireds and using the default values for keys found in defaults.

For example, storify({'a':1, 'c':3}, b=2, c=0) will return the equivalent of storage({'a':1, 'b':2, 'c':3}).

If a storify value is a list (e.g. multiple values in a form submission), storify returns the last element of the list, unless the key appears in defaults as 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 value attribute, `storify will return its value, unless the key appears in defaults as a dictionary.

>>> storify({'a':storage(value=1)}).a
1
>>> storify({'a':storage(value=1)}, a={}).a
<Storage {'value': 1}>
>>> storify({}, a={}).a
{}

Optionally, keyword parameter _unicode can be passed to convert all values to unicode.

>>> storify({'x': 'a'}, _unicode=True)
<Storage {'x': u'a'}>
>>> storify({'x': storage(value='a')}, x={}, _unicode=True)
<Storage {'x': <Storage {'value': 'a'}>}>
>>> storify({'x': storage(value='a')}, _unicode=True)
<Storage {'x': u'a'}>

typeCounter

Keeps count of how many times something is added.

c = counter() c.add('x') c.add('x') c.add('x') c.add('x') c.add('x') c.add('y') c <Counter {'y': 1, 'x': 5}> c.most() ['x']

methodadd(self, n)

methodleast(self)

Returns the keys with mininum count.

methodmost(self)

Returns the keys with maximum count.

methodpercent(self, key)

Returns what percentage a certain key is of all entries.

c = counter() c.add('x') c.add('x') c.add('x') c.add('y') c.percent('x') 0.75 c.percent('y') 0.25

methodsorted_items(self)

Returns items sorted by value.

c = counter() c.add('x') c.add('x') c.add('y') c.sorted_items() [('x', 2), ('y', 1)]

methodsorted_keys(self)

Returns keys sorted by value.

c = counter() c.add('x') c.add('x') c.add('y') c.sorted_keys() ['x', 'y']

methodsorted_values(self)

Returns values sorted by value.

c = counter() c.add('x') c.add('x') c.add('y') c.sorted_values() [2, 1]

typecounter

Keeps count of how many times something is added.

c = counter() c.add('x') c.add('x') c.add('x') c.add('x') c.add('x') c.add('y') c <Counter {'y': 1, 'x': 5}> c.most() ['x']

methodadd(self, n)

methodleast(self)

Returns the keys with mininum count.

methodmost(self)

Returns the keys with maximum count.

methodpercent(self, key)

Returns what percentage a certain key is of all entries.

c = counter() c.add('x') c.add('x') c.add('x') c.add('y') c.percent('x') 0.75 c.percent('y') 0.25

methodsorted_items(self)

Returns items sorted by value.

c = counter() c.add('x') c.add('x') c.add('y') c.sorted_items() [('x', 2), ('y', 1)]

methodsorted_keys(self)

Returns keys sorted by value.

c = counter() c.add('x') c.add('x') c.add('y') c.sorted_keys() ['x', 'y']

methodsorted_values(self)

Returns values sorted by value.

c = counter() c.add('x') c.add('x') c.add('y') c.sorted_values() [2, 1]

functionrstrips(text, remove)

removes the string remove from the right of text

>>> rstrips("foobar", "bar")
'foo'

functionlstrips(text, remove)

removes the string remove from the left of text

>>> lstrips("foobar", "foo")
'bar'
>>> lstrips('http://foo.org/', ['http://', 'https://'])
'foo.org/'
>>> lstrips('FOOBARBAZ', ['FOO', 'BAR'])
'BAZ'
>>> lstrips('FOOBARBAZ', ['BAR', 'FOO'])
'BARBAZ'

functionstrips(text, remove)

removes the string remove from the both sides of text

>>> strips("foobarfoo", "foo")
'bar'

functionsafeunicode(obj, encoding='utf-8')

Converts any given object to unicode string.

>>> safeunicode('hello')
u'hello'
>>> safeunicode(2)
u'2'
>>> safeunicode('\xe1\x88\xb4')
u'\u1234'

functionsafestr(obj, encoding='utf-8')

Converts any given object to utf-8 encoded string.

>>> safestr('hello')
'hello'
>>> safestr(u'\u1234')
'\xe1\x88\xb4'
>>> safestr(2)
'2'

functionutf8(obj, encoding='utf-8')

Converts any given object to utf-8 encoded string.

>>> safestr('hello')
'hello'
>>> safestr(u'\u1234')
'\xe1\x88\xb4'
>>> safestr(2)
'2'

typeTimeoutError

functiontimelimit(timeout)

A decorator to limit a function to timeout seconds, raising TimeoutError if 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)()
42

Caveat: The function isn't stopped after timeout seconds 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

classMemoize(self, func, expires=None, background=True)

'Memoizes' a function, caching its return values for each input. If expires is specified, values are recalculated after expires seconds. If background is specified, values are recalculated in a separate thread.

>>> calls = 0
>>> def howmanytimeshaveibeencalled():
...     global calls
...     calls += 1
...     return calls
>>> fastcalls = memoize(howmanytimeshaveibeencalled)
>>> howmanytimeshaveibeencalled()
1
>>> howmanytimeshaveibeencalled()
2
>>> fastcalls()
3
>>> fastcalls()
3
>>> import time
>>> fastcalls = memoize(howmanytimeshaveibeencalled, .1, background=False)
>>> fastcalls()
4
>>> fastcalls()
4
>>> time.sleep(.2)
>>> fastcalls()
5
>>> def slowfunc():
...     time.sleep(.1)
...     return howmanytimeshaveibeencalled()
>>> fastcalls = memoize(slowfunc, .2, background=True)
>>> fastcalls()
6
>>> timelimit(.05)(fastcalls)()
6
>>> time.sleep(.2)
>>> timelimit(.05)(fastcalls)()
6
>>> timelimit(.05)(fastcalls)()
6
>>> time.sleep(.2)
>>> timelimit(.05)(fastcalls)()
7
>>> fastcalls = memoize(slowfunc, None, background=True)
>>> threading.Thread(target=fastcalls).start()
>>> time.sleep(.01)
>>> fastcalls()
9

functionre_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',)

functiongroup(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]]
>>> list(group([1,2,3,4,5], 2))
[[1, 2], [3, 4], [5]]

functionuniq(seq, key=None)

Removes duplicate elements from a list while preserving the order of the rest.

>>> uniq([9,0,2,1,0])
[9, 0, 2, 1]

The value of the optional key parameter should be a function that takes a single argument and returns a key to test the uniqueness.

>>> uniq(["Foo", "foo", "bar"], key=lambda s: s.lower())
['Foo', 'bar']

functioniterview(x)

Takes an iterable x and returns an iterator over it which prints its progress to stderr as it iterates through.

classIterBetter(self, iterator)

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 requesting iterbetter[1]).

>>> import itertools
>>> c = iterbetter(itertools.count())
>>> c[1]
1
>>> c[5]
5
>>> c[3]
Traceback (most recent call last):
    ...
IndexError: already passed 3

It is also possible to get the first value of the iterator or None.

>>> c = iterbetter(iter([3, 4, 5]))
>>> print c.first()
3
>>> c = iterbetter(iter([]))
>>> print c.first()
None

For boolean test, IterBetter peeps at first value in the itertor without effecting the iteration.

>>> c = iterbetter(iter(range(5)))
>>> bool(c)
True
>>> list(c)
[0, 1, 2, 3, 4]
>>> c = iterbetter(iter([]))
>>> bool(c)
False
>>> list(c)
[]

methodfirst(self, default=None)

Returns the first element of the iterator or None when there are no elements.

If the optional argument default is specified, that is returned instead of None when there are no elements.

functionsafeiter(it, cleanup=None, ignore_errors=True)

Makes an iterator safe by ignoring the exceptions occured during the iteration.

functionsafewrite(filename, content)

Writes the content to a temp file and then moves the temp file to given filename to avoid overwriting the existing file in case of errors.

functiondictreverse(mapping)

Returns a new dictionary with keys and values swapped.

>>> dictreverse({1: 2, 3: 4})
{2: 1, 4: 3}

functiondictfind(dictionary, element)

Returns a key whose value in dictionary is element or, if none exists, None.

>>> d = {1:2, 3:4}
>>> dictfind(d, 4)
3
>>> dictfind(d, 5)

functiondictfindall(dictionary, element)

Returns the keys whose values in dictionary are element or, if none exists, [].

>>> d = {1:4, 3:4}
>>> dictfindall(d, 4)
[1, 3]
>>> dictfindall(d, 5)
[]

functiondictincr(dictionary, element)

Increments element in dictionary, 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

functiondictadd(*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}

functionrequeue(queue, index=-1)

Returns the element at index after moving it to the beginning of the queue.

x = [1, 2, 3, 4] requeue(x) 4 x [4, 1, 2, 3]

functionrestack(stack, index=0)

Returns the element at index after moving it to the top of stack.

x = [1, 2, 3, 4] restack(x) 1 x [2, 3, 4, 1]

functionlistget(lst, ind, default=None)

Returns lst[ind] if it exists, default otherwise.

>>> listget(['a'], 0)
'a'
>>> listget(['a'], 1)
>>> listget(['a'], 1, 'b')
'b'

functionintget(integer, default=None)

Returns integer as an int or default if it can't.

>>> intget('3')
3
>>> intget('3a')
>>> intget('3a', 0)
0

functiondatestr(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'
>>> datestr(None)
''

functionnumify(string)

Removes all non-digit characters from string.

>>> numify('800-555-1212')
'8005551212'
>>> numify('800.555.1212')
'8005551212'

functiondenumify(string, pattern)

Formats string according to pattern, where the letter X gets replaced by characters from string.

>>> denumify("8005551212", "(XXX) XXX-XXXX")
'(800) 555-1212'

functioncommify(n)

Add commas to an integer n.

>>> commify(1)
'1'
>>> commify(123)
'123'
>>> commify(1234)
'1,234'
>>> commify(1234567890)
'1,234,567,890'
>>> commify(123.0)
'123.0'
>>> commify(1234.5)
'1,234.5'
>>> commify(1234.56789)
'1,234.56789'
>>> commify('%.2f' % 1234.5)
'1,234.50'
>>> commify(None)
>>>

functiondateify(datestring)

Formats a numified datestring properly.

functionnthstr(n)

Formats an ordinal. Doesn't handle negative numbers.

>>> nthstr(1)
'1st'
>>> nthstr(0)
'0th'
>>> [nthstr(x) for x in [2, 3, 4, 5, 10, 11, 12, 13, 14, 15]]
['2nd', '3rd', '4th', '5th', '10th', '11th', '12th', '13th', '14th', '15th']
>>> [nthstr(x) for x in [91, 92, 93, 94, 99, 100, 101, 102]]
['91st', '92nd', '93rd', '94th', '99th', '100th', '101st', '102nd']
>>> [nthstr(x) for x in [111, 112, 113, 114, 115]]
['111th', '112th', '113th', '114th', '115th']

functioncond(predicate, consequence, alternative=None)

Function replacement for if-else to use in expressions.

>>> x = 2
>>> cond(x % 2 == 0, "even", "odd")
'even'
>>> cond(x % 2 == 0, "even", "odd") + '_row'
'even_row'

classCaptureStdout(self, func)

Captures everything func prints to stdout and returns it instead.

>>> def idiot():
...     print "foo"
>>> capturestdout(idiot)()
'foo\n'

WARNING: Not threadsafe!

classcapturestdout(self, func)

Captures everything func prints to stdout and returns it instead.

>>> def idiot():
...     print "foo"
>>> capturestdout(idiot)()
'foo\n'

WARNING: Not threadsafe!

classProfile(self, func)

Profiles func and 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'

functiontryall(context, prefix=None)

Tries a series of functions and prints their results. context is 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: 1

For example, you might have a file test/stuff.py with 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.py and get the results of all the tests.

typeThreadedDict(self)

Thread local storage.

>>> d = ThreadedDict()
>>> d.x = 1
>>> d.x
1
>>> import threading
>>> def f(): d.x = 2
...
>>> t = threading.Thread(target=f)
>>> t.start()
>>> t.join()
>>> d.x
1

methodclear(self)

functionclear_all()

Clears all ThreadedDict instances.

methodcopy(self)

methodget(self, key, default=None)

methodhas_key(self, key)

methoditems(self)

methoditer(self)

methoditeritems(self)

methoditerkeys(self)

methoditervalues(self)

methodkeys(self)

methodpop(self, key, *args)

methodpopitem(self)

methodsetdefault(self, key, default=None)

methodupdate(self, *args, **kwargs)

methodvalues(self)

functionautoassign(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())

functionto36(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

functionsafemarkdown(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)

functionsendmail(from_address, to_address, subject, message, headers=None, **kw)

Sends the email message message with mail and envelope headers for from from_address_ to to_address with subject. Additional email headers can be specified with the dictionary `headers.

Optionally cc, bcc and attachments can be specified as keyword arguments. Attachments must be an iterable and each attachment can be either a filename or a file object or a dictionary with filename, content and optionally content_type keys.

If web.config.smtp_server is set, it will send the message to that SMTP server. Otherwise it will look for /usr/sbin/sendmail, the typical location for the sendmail-style binary. To use sendmail from a different path, set web.config.sendmail_path.

moduleweb.webapi

Web API (wrapper around WSGI) (from web.py)

functionheader(hdr, value, unique=False)

Adds the header hdr: value with the response.

If unique is True and a header with that name already exists, it doesn't add a new one.

functiondebug(*args)

Prints a prettyprinted version of args to stderr.

functionwrite(x)

functioninput(*requireds, **defaults)

Returns a storage object with the GET and POST arguments. See storify for how requireds and defaults work.

functiondata()

Returns the data sent with the request.

functionsetcookie(name, value, expires='', domain=None, secure=False, httponly=False, path=None)

Sets a cookie.

functioncookies(*requireds, **defaults)

Returns a storage object with all the request cookies in it.

See storify for how requireds and defaults work.

This is forgiving on bad HTTP_COOKIE input, it tries to parse at least the cookies it can.

The values are converted to unicode if _unicode=True is passed.

typeHTTPError(self, status, headers={}, data='')

typeOK(self, data='', headers={})

200 OK status

typeCreated(self, data='Created', headers={})

201 Created status

typeAccepted(self, data='Accepted', headers={})

202 Accepted status

typeNoContent(self, data='No Content', headers={})

204 No Content status

typeok(self, data='', headers={})

200 OK status

typecreated(self, data='Created', headers={})

201 Created status

typeaccepted(self, data='Accepted', headers={})

202 Accepted status

typenocontent(self, data='No Content', headers={})

204 No Content status

typeRedirect(self, url, status='301 Moved Permanently', absolute=False)

A 301 Moved Permanently redirect.

typeFound(self, url, absolute=False)

A 302 Found redirect.

typeSeeOther(self, url, absolute=False)

A 303 See Other redirect.

typeNotModified(self)

A 304 Not Modified status.

typeTempRedirect(self, url, absolute=False)

A 307 Temporary Redirect redirect.

typeredirect(self, url, status='301 Moved Permanently', absolute=False)

A 301 Moved Permanently redirect.

typefound(self, url, absolute=False)

A 302 Found redirect.

typeseeother(self, url, absolute=False)

A 303 See Other redirect.

typenotmodified(self)

A 304 Not Modified status.

typetempredirect(self, url, absolute=False)

A 307 Temporary Redirect redirect.

typeBadRequest(self, message=None)

400 Bad Request error.

typeUnauthorized(self, message=None)

401 Unauthorized error.

typeForbidden(self, message=None)

403 Forbidden error.

functionNotFound(message=None)

Returns HTTPError with '404 Not Found' error from the active application.

typeNoMethod(self, cls=None)

A 405 Method Not Allowed error.

typeNotAcceptable(self, message=None)

406 Not Acceptable error.

typeConflict(self, message=None)

409 Conflict error.

typeGone(self, message=None)

410 Gone error.

typePreconditionFailed(self, message=None)

412 Precondition Failed error.

typeUnsupportedMediaType(self, message=None)

415 Unsupported Media Type error.

functionUnavailableForLegalReasons(message=None)

Returns HTTPError with '415 Unavailable For Legal Reasons' error from the active application.

typebadrequest(self, message=None)

400 Bad Request error.

typeunauthorized(self, message=None)

401 Unauthorized error.

typeforbidden(self, message=None)

403 Forbidden error.

functionnotfound(message=None)

Returns HTTPError with '404 Not Found' error from the active application.

typenomethod(self, cls=None)

A 405 Method Not Allowed error.

typenotacceptable(self, message=None)

406 Not Acceptable error.

typeconflict(self, message=None)

409 Conflict error.

typegone(self, message=None)

410 Gone error.

typepreconditionfailed(self, message=None)

412 Precondition Failed error.

typeunsupportedmediatype(self, message=None)

415 Unsupported Media Type error.

functionunavailableforlegalreasons(message=None)

Returns HTTPError with '415 Unavailable For Legal Reasons' error from the active application.

functionInternalError(message=None)

Returns HTTPError with '500 internal error' error from the active application.

functioninternalerror(message=None)

Returns HTTPError with '500 internal error' error from the active application.

moduleweb.webopenid

openid.py: an openid library for web.py

Notes:

  • This will create a file called .openidsecretkey in the current directory with your secret key in it. If someone has access to this file they can log in as any user. And if the app can't find this file for any reason (e.g. you moved the app somewhere else) then each currently logged in user will get logged out.

  • State must be maintained through the entire auth process -- this means that if you have multiple web.py processes serving one set of URLs or if you restart your app often then log ins will fail. You have to replace sessions and store for things to work.

  • We set cookies starting with "openid_".

functionform(openid_loc)

classhost(self)

methodGET(self)

methodPOST(self)

functionlogout()

functionstatus()

moduleweb.wsgi

WSGI Utilities (from web.py)

functionintget(integer, default=None)

Returns integer as an int or default if it can't.

>>> intget('3')
3
>>> intget('3a')
>>> intget('3a', 0)
0

functionlistget(lst, ind, default=None)

Returns lst[ind] if it exists, default otherwise.

>>> listget(['a'], 0)
'a'
>>> listget(['a'], 1)
>>> listget(['a'], 1, 'b')
'b'

functionrunfcgi(func, addr=('localhost', 8000))

Runs a WSGI function as a FastCGI server.

functionrunscgi(func, addr=('localhost', 4000))

Runs a WSGI function as an SCGI server.

functionrunwsgi(func)

Runs a WSGI-compatible func using FCGI, SCGI, or a simple web server, as appropriate based on context and sys.argv.

functionvalidaddr(string_)

Returns either (ipaddress, 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)
>>> validip('[::1]:80')
('::1', 80)
>>> validaddr('fff')
Traceback (most recent call last):
    ...
ValueError: fff is not a valid IP address/port

functionvalidip(ip, defaultaddr='0.0.0.0', defaultport=8080)

Returns (ip_address, port) from string ip_addr_port

validip('1.2.3.4') ('1.2.3.4', 8080) validip('80') ('0.0.0.0', 80) validip('192.168.0.1:85') ('192.168.0.1', 85) validip('::') ('::', 8080) validip('[::]:88') ('::', 88) validip('[::1]:80') ('::1', 80)

</div>