diff --git a/gluon/globals.py b/gluon/globals.py index 29fb3f0d..9d17fae6 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -349,14 +349,14 @@ class Request(Storage): current.session.forget() redirect(URL(scheme='https', args=self.args, vars=self.vars)) - def restful(self): + def restful(self, ignore_extension=False): def wrapper(action, request=self): def f(_action=action, *a, **b): request.is_restful = True env = request.env is_json = env.content_type=='application/json' method = env.request_method - if len(request.args) and '.' in request.args[-1]: + if not ignore_extension and len(request.args) and '.' in request.args[-1]: request.args[-1], _, request.extension = request.args[-1].rpartition('.') current.response.headers['Content-Type'] = \ contenttype('.' + request.extension.lower()) diff --git a/gluon/tests/test_globals.py b/gluon/tests/test_globals.py index 1ad85001..390079ce 100644 --- a/gluon/tests/test_globals.py +++ b/gluon/tests/test_globals.py @@ -10,27 +10,76 @@ import re import unittest from gluon.globals import Request, Response, Session +from gluon.rewrite import regex_url_in from gluon import URL from gluon._compat import basestring + def setup_clean_session(): - request = Request(env={}) - request.application = 'a' - request.controller = 'c' - request.function = 'f' - request.folder = 'applications/admin' - response = Response() - session = Session() - session.connect(request, response) + request = Request(env={}) + request.application = 'a' + request.controller = 'c' + request.function = 'f' + request.folder = 'applications/admin' + response = Response() + session = Session() + session.connect(request, response) + from gluon.globals import current + current.request = request + current.response = response + current.session = session + return current + + +class testRequest(unittest.TestCase): + + def setUp(self): from gluon.globals import current - current.request = request - current.response = response - current.session = session - return current + current.response = Response() + + def test_restful_simple(self): + env = {'request_method': 'GET', 'PATH_INFO': '/welcome/default/index/1.pdf'} + r = Request(env) + regex_url_in(r, env) + + @r.restful() + def simple_rest(): + def GET(*args, **vars): + return args[0] + return locals() + + self.assertEqual(simple_rest(), '1') + + def test_restful_calls_post(self): + env = {'request_method': 'POST', 'PATH_INFO': '/welcome/default/index'} + r = Request(env) + regex_url_in(r, env) + + @r.restful() + def post_rest(): + def POST(*args, **vars): + return 'I posted' + return locals() + + self.assertEqual(post_rest(), 'I posted') + + def test_restful_ignore_extension(self): + env = {'request_method': 'GET', 'PATH_INFO': '/welcome/default/index/127.0.0.1'} + r = Request(env) + regex_url_in(r, env) + + @r.restful(ignore_extension=True) + def ignore_rest(): + def GET(*args, **vars): + return args[0] + return locals() + + self.assertEqual(ignore_rest(), '127.0.0.1') + class testResponse(unittest.TestCase): - #port from python 2.7, needed for 2.5 and 2.6 tests + # port from python 2.7, needed for 2.5 and 2.6 tests def assertRegexpMatches(self, text, expected_regexp, msg=None): """Fail the test unless the text matches the regular expression.""" if isinstance(expected_regexp, basestring): @@ -99,8 +148,8 @@ class testResponse(unittest.TestCase): response.files.append(URL('a', 'static', 'css/file.css')) content = return_includes(response) self.assertEqual(content, - '' + - '') + '' + + '') response = Response() response.files.append(('js', 'http://maps.google.com/maps/api/js?sensor=false')) @@ -109,12 +158,11 @@ class testResponse(unittest.TestCase): response.files.append(URL('a', 'static', 'css/file.ts')) content = return_includes(response) self.assertEqual(content, - '' + - '' + - '' + - '' - ) - + '' + + '' + + '' + + '' + ) response = Response() response.files.append(URL('a', 'static', 'css/file.js')) @@ -122,13 +170,13 @@ class testResponse(unittest.TestCase): content = return_includes(response, extensions=['css']) self.assertEqual(content, '') - #regr test for #628 + # regr test for #628 response = Response() response.files.append('http://maps.google.com/maps/api/js?sensor=false') content = return_includes(response) self.assertEqual(content, '') - #regr test for #628 + # regr test for #628 response = Response() response.files.append(('js', 'http://maps.google.com/maps/api/js?sensor=false')) content = return_includes(response) @@ -147,7 +195,7 @@ class testResponse(unittest.TestCase): def test_cookies(self): current = setup_clean_session() cookie = str(current.response.cookies) - session_key='%s=%s'%(current.response.session_id_name,current.response.session_id) + session_key = '%s=%s' % (current.response.session_id_name, current.response.session_id) self.assertRegexpMatches(cookie, r'^Set-Cookie: ') self.assertTrue(session_key in cookie) self.assertTrue('Path=/' in cookie) diff --git a/gluon/tests/test_validators.py b/gluon/tests/test_validators.py index 77a7e6b5..e534fbd8 100644 --- a/gluon/tests/test_validators.py +++ b/gluon/tests/test_validators.py @@ -235,6 +235,11 @@ class TestValidators(unittest.TestCase): self.assertEqual(sorted(rtn), [('%d' % george_id, 'george'), ('%d' % costanza_id, 'costanza')]) rtn = IS_IN_DB(db, db.person.id, db.person.name, error_message='oops', sort=True).options(zero=True) self.assertEqual(rtn, [('', ''), ('%d' % costanza_id, 'costanza'), ('%d' % george_id, 'george')]) + # Test None + rtn = IS_IN_DB(db, 'person.id', '%(name)s', error_message='oops')(None) + self.assertEqual(rtn, (None, 'oops')) + rtn = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops')(None) + self.assertEqual(rtn, (None, 'oops')) # Test using the set it made for options vldtr = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops') vldtr.options() diff --git a/gluon/validators.py b/gluon/validators.py index 3d04f215..d7fa6260 100644 --- a/gluon/validators.py +++ b/gluon/validators.py @@ -20,7 +20,8 @@ import urllib import struct import decimal import unicodedata -from gluon._compat import StringIO, long, basestring, unicodeT, to_unicode, urllib_unquote, unichr, to_bytes, PY2, to_unicode, to_native, urlparse + +from gluon._compat import StringIO, long, basestring, unicodeT, to_unicode, urllib_unquote, unichr, to_bytes, PY2, to_unicode, to_native, string_types, urlparse from gluon.utils import simple_hash, web2py_uuid, DIGEST_ALG_BY_SIZE from pydal.objects import Field, FieldVirtual, FieldMethod from functools import reduce @@ -658,7 +659,7 @@ class IS_IN_DB(Validator): return (values, None) else: if field.type in ('id', 'integer'): - if isinstance(value, (int, long)) or value.isdigit(): + if isinstance(value, (int, long)) or (isinstance(value, string_types) and value.isdigit()): value = int(value) elif self.auto_add: value = self.maybe_add(table, self.fieldnames[0], value)