Merge branch 'master' of github.com:web2py/web2py
This commit is contained in:
@@ -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
@@ -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__':
|
||||||
|
|||||||
@@ -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
@@ -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()
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user