From 380b4917241acf850ec837702e0ab75c591edb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Botaro?= Date: Mon, 4 May 2015 12:41:06 -0300 Subject: [PATCH 1/4] Return old behaviours - Better documented List - Otherwise not binded with cast --- gluon/storage.py | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/gluon/storage.py b/gluon/storage.py index 4a1e46a7..eebec539 100644 --- a/gluon/storage.py +++ b/gluon/storage.py @@ -22,7 +22,8 @@ import gluon.portalocker as portalocker __all__ = ['List', 'Storage', 'Settings', 'Messages', 'StorageList', 'load_storage', 'save_storage'] -DEFAULT = lambda: 0 +def DEFAULT(): + return 0 class Storage(dict): @@ -271,28 +272,38 @@ class FastStorage(dict): class List(list): """ - Like a regular python list but a[i] if i is out of bounds returns None - instead of `IndexOutOfBounds`. + Like a regular python list but callable. + When a(i) is called if i is out of bounds returns None + instead of `IndexError`. """ def __call__(self, i, default=DEFAULT, cast=None, otherwise=None): - """Allows to use a special syntax for fast-check of `request.args()` - validity - Args: + """Allows to use a special syntax for fast-check of + `request.args()` validity. + :params: i: index default: use this value if arg not found cast: type cast - otherwise: can be: - - None: results in a 404 - - str: redirect to this address - - callable: calls the function (nothing is passed) + otherwise: + will be executed when: + - casts fail + - value not found, dont have default and otherwise is + especified + can be: + - None: results in a 404 + - str: redirect to this address + - callable: calls the function (nothing is passed) Example: You can use:: request.args(0,default=0,cast=int,otherwise='http://error_url') request.args(0,default=0,cast=int,otherwise=lambda:...) """ - value = self[i] - if not value and default is not DEFAULT: + n = len(self) + if 0 <= i < n or -n <= i < 0: + value = self[i] + elif default is DEFAULT: + value = None + else: value, cast, otherwise = default, False, False try: if cast: @@ -311,13 +322,6 @@ class List(list): raise RuntimeError("invalid otherwise") return value - def __getitem__(self, i): - n = len(self) - if 0 <= i < n or -n <= i < 0: - return super(List, self).__getitem__(i) - return None - - if __name__ == '__main__': import doctest doctest.testmod() From a0ee64988439a4c80c27c4843841936c4bba5ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Botaro?= Date: Mon, 4 May 2015 12:49:14 -0300 Subject: [PATCH 2/4] Update tests - new tests to verify old behaviour - test otherwise without cast and defaut - verify if behave like a list - more test with call function --- gluon/tests/test_storage.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/gluon/tests/test_storage.py b/gluon/tests/test_storage.py index e518e4d2..810b5b63 100644 --- a/gluon/tests/test_storage.py +++ b/gluon/tests/test_storage.py @@ -120,17 +120,14 @@ class TestStorageList(unittest.TestCase): class TestList(unittest.TestCase): + """ Tests Storage.List (fast-check for request.args()) """ def test_listcall(self): a = List((1, 2, 3)) 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(-5), None) - self.assertEqual(a[-5], None) self.assertEqual(a(-5, default='x'), 'x') self.assertEqual(a(-3, cast=str), '1') a.append('1234') @@ -139,8 +136,24 @@ class TestList(unittest.TestCase): a.append('x') self.assertRaises(HTTP, a, 4, cast=int) b = List() + # default is always returned when especified self.assertEqual(b(0, cast=int, default=None), None) - self.assertEqual(b(0, cast=int, default=None, otherwise='something'), None) + self.assertEqual(b(0, cast=int, default=None, otherwise='teste'), None) + self.assertEqual(b(0, cast=int, default='a', otherwise='teste'), 'a') + # if don't have value and otherwise is especified it will called + self.assertEqual(b(0, otherwise=lambda: 'something'), 'something') + self.assertEqual(b(0, cast=int, otherwise=lambda: 'something'), + 'something') + # except if default is especified + self.assertEqual(b(0, default=0, otherwise=lambda: 'something'), 0) + + def test_listgetitem(self): + '''Mantains list behaviour.''' + a = List((1, 2, 3)) + self.assertEqual(a[0], 1) + with self.assertRaises(IndexError): + a[3] + self.assertEqual(a[::-1], [3, 2, 1]) if __name__ == '__main__': From cdca2793e0d66c631c7669f5d5e3aa5869e8f428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Botaro?= Date: Mon, 4 May 2015 12:55:44 -0300 Subject: [PATCH 3/4] Maintain py2.6k compability --- gluon/tests/test_storage.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/gluon/tests/test_storage.py b/gluon/tests/test_storage.py index 810b5b63..ca047e95 100644 --- a/gluon/tests/test_storage.py +++ b/gluon/tests/test_storage.py @@ -151,8 +151,6 @@ class TestList(unittest.TestCase): '''Mantains list behaviour.''' a = List((1, 2, 3)) self.assertEqual(a[0], 1) - with self.assertRaises(IndexError): - a[3] self.assertEqual(a[::-1], [3, 2, 1]) From 5ef7a8e9a10b4c600018a5febfe0843f6736f195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Botaro?= Date: Thu, 14 May 2015 12:24:58 -0300 Subject: [PATCH 4/4] maintains web2py pattern --- gluon/storage.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gluon/storage.py b/gluon/storage.py index eebec539..1bb507f5 100644 --- a/gluon/storage.py +++ b/gluon/storage.py @@ -22,8 +22,7 @@ import gluon.portalocker as portalocker __all__ = ['List', 'Storage', 'Settings', 'Messages', 'StorageList', 'load_storage', 'save_storage'] -def DEFAULT(): - return 0 +DEFAULT = lambda: 0 class Storage(dict):