Permalink
Browse files

Add support for cleaning params without defaults

Move `clean_bool` method into class structure with additional
simple methods. This makes it simply reference and user in user code
  • Loading branch information...
1 parent b4e1ebb commit 4a11b8a43c50c1e976e26ab280a1957edd9c6bb1 @bruth committed May 2, 2013
Showing with 78 additions and 24 deletions.
  1. +46 −24 restlib2/params.py
  2. +32 −0 restlib2/tests/cases.py
View
@@ -1,18 +1,3 @@
-def clean_bool(value, allow_none=False):
- if isinstance(value, bool):
- return value
-
- if isinstance(value, basestring):
- value = value.lower()
- if value in ('t', 'true', '1', 'yes'):
- return True
- if value in ('f', 'false', '0', 'no'):
- return False
- if allow_none and value is None:
- return
- raise ValueError
-
-
class ParametizerMetaclass(type):
def __new__(cls, name, bases, attrs):
new_cls = type.__new__(cls, name, bases, attrs)
@@ -41,28 +26,65 @@ def clean(self, params=None, defaults=None):
if defaults is None:
defaults = self.param_defaults
- cleaned = defaults.copy()
- cleaned.update(params)
+ cleaned = {}
+
+ # Gather both sets of keys since there may be methods defined
+ # without a default value specified.
+ keys = set(defaults.keys() + params.keys())
+
+ for key in keys:
+ # Add the default value for non-existant keys in params
+ if key not in params:
+ cleaned[key] = defaults[key]
+ continue
- for key in cleaned:
method = 'clean_{0}'.format(key)
+
+ value = params[key]
+
+ # Attempt to clean the value
if hasattr(self, method):
- value = cleaned[key]
cleaner = getattr(self, method)
-
+
# If any kind of error occurs while cleaning, revert to
# the default value
try:
# Unpack single item lists
if isinstance(value, (list, tuple)):
value = map(cleaner, value)
- if len(value) == 1:
- value = value[0]
else:
value = cleaner(value)
except Exception:
- value = defaults.get(key)
+ value = defaults.get(key, value)
+
+ # Unpack single values
+ if isinstance(value, (list, tuple)) and len(value) == 1:
+ value = value[0]
- cleaned[key] = value
+ cleaned[key] = value
return cleaned
+
+
+class ParamCleaners(object):
+ "Container of various common cleaners for parameters."
+
+ def clean_int(self, value):
+ return int(value)
+
+ def clean_float(self, value):
+ return float(value)
+
+ def clean_string(self, value):
+ return value.strip()
+
+ def clean_bool(self, value):
+ value = value.lower()
+ if value in ('t', 'true', '1', 'yes'):
+ return True
+ if value in ('f', 'false', '0', 'no'):
+ return False
+ raise ValueError
+
+
+param_cleaners = ParamCleaners()
View
@@ -2,6 +2,7 @@
from django.test.client import RequestFactory
from django.test import TestCase
from django.conf.urls import patterns, url
+from restlib2.params import Parametizer, param_cleaners
from restlib2.resources import Resource
from restlib2.mixins import TemplateResponseMixin
from restlib2.http import codes
@@ -425,3 +426,34 @@ def test_template(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, '<h1>Hello from testserver</h1>\n')
+
+
+class ParametizerTestCase(TestCase):
+ def test_base(self):
+ p = Parametizer()
+ self.assertEqual(p.clean(), {})
+ self.assertEqual(p.clean({}), {})
+ self.assertEqual(p.clean({}, {}), {})
+ self.assertEqual(p.clean({}, {'foo': 1}), {'foo': 1})
+ self.assertEqual(p.clean({'foo': 1}), {'foo': 1})
+ self.assertEqual(p.clean({'foo': 2}, {'foo': 1, 'bar': 1}),
+ {'foo': 2, 'bar': 1})
+
+ def test(self):
+ class P(Parametizer):
+ page = 1
+ query = ''
+
+ def clean_page(self, value):
+ return param_cleaners.clean_int(value)
+
+ def clean_query(self, value):
+ return param_cleaners.clean_string(value)
+
+ p = P()
+
+ self.assertEqual(p.clean(), {'page': 1, 'query': ''})
+ self.assertEqual(p.clean({'page': '2'}), {'page': 2, 'query': ''})
+ self.assertEqual(p.clean({'query': ' foo '}), {'page': 1, 'query': 'foo'})
+ self.assertEqual(p.clean({'something': 'else'}),
+ {'page': 1, 'query': '', 'something': 'else'})

0 comments on commit 4a11b8a

Please sign in to comment.