Merge branch 'master' of github.com:web2py/web2py

This commit is contained in:
mdipierro
2015-05-03 10:31:37 -05:00
6 changed files with 81 additions and 31 deletions
+2 -2
View File
@@ -7,11 +7,11 @@
# Language from default.py or 'en' (if the file is not found) is used as # Language from default.py or 'en' (if the file is not found) is used as
# a default_language # a default_language
# #
# See <web2py-root-dir>/router.example.py for parameter's detail # See <web2py-root-dir>/examples/routes.parametric.example.py for parameter's detail
#------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------
# To enable this route file you must do the steps: # To enable this route file you must do the steps:
# #
# 1. rename <web2py-root-dir>/router.example.py to routes.py # 1. rename <web2py-root-dir>/examples/routes.parametric.example.py to routes.py
# 2. rename this APP/routes.example.py to APP/routes.py # 2. rename this APP/routes.example.py to APP/routes.py
# (where APP - is your application directory) # (where APP - is your application directory)
# 3. restart web2py (or reload routes in web2py admin interfase) # 3. restart web2py (or reload routes in web2py admin interfase)
+24 -26
View File
@@ -269,53 +269,51 @@ class FastStorage(dict):
class List(list): class List(list):
""" """
Like a regular python list but a[i] if i is out of bounds returns None Like a regular python list but a[i] if i is out of bounds returns None
instead of `IndexOutOfBounds` instead of `IndexOutOfBounds`.
""" """
def __call__(self, i, default=DEFAULT, cast=None, otherwise=None): def __call__(self, i, default=None, cast=None, otherwise=None):
"""Allows to use a special syntax for fast-check of `request.args()` """Allows to use a special syntax for fast-check of `request.args()`
validity validity
Args: Args:
i: index i: index
default: use this value if arg not found default: use this value if arg not found
cast: type cast cast: type cast
otherwise: can be: otherwise: can be:
- None: results in a 404 - None: results in a 404
- str: redirect to this address - str: redirect to this address
- callable: calls the function (nothing is passed) - callable: calls the function (nothing is passed)
Example: Example:
You can use:: You can use::
request.args(0,default=0,cast=int,otherwise='http://error_url') request.args(0,default=0,cast=int,otherwise='http://error_url')
request.args(0,default=0,cast=int,otherwise=lambda:...) request.args(0,default=0,cast=int,otherwise=lambda:...)
""" """
value = self[i] or default
try:
if cast:
value = cast(value)
if not value and otherwise:
raise ValueError('Otherwise will raised.')
except (ValueError, TypeError):
from http import HTTP, redirect
if otherwise is None:
raise HTTP(404)
elif isinstance(otherwise, str):
redirect(otherwise)
elif callable(otherwise):
return otherwise()
else:
raise RuntimeError("invalid otherwise")
return value
def __getitem__(self, i):
n = len(self) n = len(self)
if 0 <= i < n or -n <= i < 0: if 0 <= i < n or -n <= i < 0:
value = self[i] return super(List, self).__getitem__(i)
elif default is DEFAULT: return None
value = None
else:
value, cast = default, False
if cast:
try:
value = cast(value)
except (ValueError, TypeError):
from http import HTTP, redirect
if otherwise is None:
raise HTTP(404)
elif isinstance(otherwise, str):
redirect(otherwise)
elif callable(otherwise):
return otherwise()
else:
raise RuntimeError("invalid otherwise")
return value
if __name__ == '__main__': if __name__ == '__main__':
+34 -1
View File
@@ -13,6 +13,7 @@ fix_sys_path(__file__)
from storage import Storage from storage import Storage
from cache import CacheInRam, CacheOnDisk, Cache from cache import CacheInRam, CacheOnDisk, Cache
from gluon.dal import DAL, Field
oldcwd = None oldcwd = None
@@ -30,6 +31,11 @@ def tearDownModule():
if oldcwd: if oldcwd:
os.chdir(oldcwd) os.chdir(oldcwd)
oldcwd = None oldcwd = None
try:
os.unlink('dummy.db')
except:
pass
class TestCache(unittest.TestCase): class TestCache(unittest.TestCase):
@@ -107,7 +113,34 @@ class TestCache(unittest.TestCase):
cache.clear(regex=r'a*') cache.clear(regex=r'a*')
self.assertEqual(cache('a1', lambda: 2, 0), 2) self.assertEqual(cache('a1', lambda: 2, 0), 2)
self.assertEqual(cache('a2', lambda: 3, 100), 3) self.assertEqual(cache('a2', lambda: 3, 100), 3)
return
def testDALcache(self):
s = Storage({'application': 'admin',
'folder': 'applications/admin'})
cache = Cache(s)
db = DAL(check_reserved=['all'])
db.define_table('t_a', Field('f_a'))
db.t_a.insert(f_a='test')
db.commit()
a = db(db.t_a.id > 0).select(cache=(cache.ram, 60), cacheable=True)
b = db(db.t_a.id > 0).select(cache=(cache.ram, 60), cacheable=True)
self.assertEqual(a.as_csv(), b.as_csv())
c = db(db.t_a.id > 0).select(cache=(cache.disk, 60), cacheable=True)
d = db(db.t_a.id > 0).select(cache=(cache.disk, 60), cacheable=True)
self.assertEqual(c.as_csv(), d.as_csv())
self.assertEqual(a.as_csv(), c.as_csv())
self.assertEqual(b.as_csv(), d.as_csv())
e = db(db.t_a.id > 0).select(cache=(cache.disk, 60))
f = db(db.t_a.id > 0).select(cache=(cache.disk, 60))
self.assertEqual(e.as_csv(), f.as_csv())
self.assertEqual(a.as_csv(), f.as_csv())
g = db(db.t_a.id > 0).select(cache=(cache.ram, 60))
h = db(db.t_a.id > 0).select(cache=(cache.ram, 60))
self.assertEqual(g.as_csv(), h.as_csv())
self.assertEqual(a.as_csv(), h.as_csv())
db.t_a.drop()
db.close()
if __name__ == '__main__': if __name__ == '__main__':
setUpModule() # pre-python-2.7 setUpModule() # pre-python-2.7
+16 -1
View File
@@ -4,6 +4,7 @@
Unit tests for gluon.dal Unit tests for gluon.dal
""" """
import os
import unittest import unittest
from fix_path import fix_sys_path from fix_path import fix_sys_path
@@ -12,8 +13,15 @@ fix_sys_path(__file__)
from gluon.dal import DAL, Field from gluon.dal import DAL, Field
def tearDownModule():
try:
os.unlink('dummy.db')
except:
pass
class TestDALSubclass(unittest.TestCase): class TestDALSubclass(unittest.TestCase):
def testRun(self): def testRun(self):
from gluon.serializers import custom_json, xml from gluon.serializers import custom_json, xml
from gluon import sqlhtml from gluon import sqlhtml
@@ -22,19 +30,26 @@ class TestDALSubclass(unittest.TestCase):
self.assertEqual(db.serializers['xml'], xml) self.assertEqual(db.serializers['xml'], xml)
self.assertEqual(db.representers['rows_render'], sqlhtml.represent) self.assertEqual(db.representers['rows_render'], sqlhtml.represent)
self.assertEqual(db.representers['rows_xml'], sqlhtml.SQLTABLE) self.assertEqual(db.representers['rows_xml'], sqlhtml.SQLTABLE)
db.close()
def testSerialization(self): def testSerialization(self):
import pickle import pickle
db = DAL(check_reserved=['all']) db = DAL(check_reserved=['all'])
db.define_table('t_a', Field('f_a')) db.define_table('t_a', Field('f_a'))
db.t_a.insert(f_a='test') db.t_a.insert(f_a='test')
a = db(db.t_a.id>0).select(cacheable=True) a = db(db.t_a.id > 0).select(cacheable=True)
s = pickle.dumps(a) s = pickle.dumps(a)
b = pickle.loads(s) b = pickle.loads(s)
self.assertEqual(a.db, b.db) self.assertEqual(a.db, b.db)
db.t_a.drop()
db.close()
""" TODO: """ TODO:
class TestDefaultValidators(unittest.TestCase): class TestDefaultValidators(unittest.TestCase):
def testRun(self): def testRun(self):
pass pass
""" """
if __name__ == '__main__':
unittest.main()
tearDownModule()
+4
View File
@@ -125,8 +125,12 @@ class TestList(unittest.TestCase):
def test_listcall(self): def test_listcall(self):
a = List((1, 2, 3)) a = List((1, 2, 3))
self.assertEqual(a(1), 2) self.assertEqual(a(1), 2)
self.assertEqual(a[1], 2)
self.assertEqual(a(3), None)
self.assertEqual(a[3], None)
self.assertEqual(a(-1), 3) self.assertEqual(a(-1), 3)
self.assertEqual(a(-5), None) self.assertEqual(a(-5), None)
self.assertEqual(a[-5], None)
self.assertEqual(a(-5, default='x'), 'x') self.assertEqual(a(-5, default='x'), 'x')
self.assertEqual(a(-3, cast=str), '1') self.assertEqual(a(-3, cast=str), '1')
a.append('1234') a.append('1234')
+1 -1
View File
@@ -62,7 +62,7 @@ do_start()
start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \ start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \
&& return 1 && return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE \ start-stop-daemon --start --quiet -m --pidfile $PIDFILE \
${DAEMON_USER:+--chuid $DAEMON_USER} --chdir $DAEMON_DIR \ ${DAEMON_USER:+--chuid $DAEMON_USER} --chdir $DAEMON_DIR \
--background --exec $DAEMON -- $DAEMON_ARGS \ --background --exec $DAEMON -- $DAEMON_ARGS \
|| return 2 || return 2