Skip to content

Commit 130c3ae

Browse files
authored
Merge pull request #24 from adesor/isinstance-check-validations
Isinstance check validations
2 parents 83fa9b9 + 84dfd9b commit 130c3ae

File tree

8 files changed

+110
-35
lines changed

8 files changed

+110
-35
lines changed

.travis.yml

Lines changed: 0 additions & 6 deletions
This file was deleted.

filters/tests/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.conf import settings
2+
3+
settings.configure()
File renamed without changes.

filters/tests/test_validations.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import unittest
2+
from nose2.tools.such import helper
3+
from voluptuous import Invalid
4+
from filters import validations
5+
6+
INT = 1
7+
LONG = long(INT)
8+
INT_FLOAT = float(INT)
9+
INT_STR = str(INT)
10+
INT_UNICODE = unicode(INT)
11+
ALNUM_STR = "hello123"
12+
ALNUM_UNICODE = unicode(ALNUM_STR)
13+
NON_INT_FLOAT = 1.5
14+
NON_INT_STR = str(NON_INT_FLOAT)
15+
NON_INT_UNICODE = unicode(NON_INT_FLOAT)
16+
NON_ALNUM_STR = "hello 123"
17+
NON_ALNUM_UNICODE = unicode(NON_ALNUM_STR)
18+
INT_CSV = "1,2,3"
19+
NON_INT_CSV = "a,b,c"
20+
21+
22+
class BaseValidationTestCase(object):
23+
def f(self, v):
24+
return self.base_function()(v)
25+
26+
def transform_val(self, v):
27+
return v
28+
29+
def test_valid_values(self):
30+
for v in self.valid_values:
31+
self.assertEqual(self.f(v), self.transform_val(v))
32+
33+
def test_invalid_values(self):
34+
for v in self.invalid_values:
35+
self.assertRaises(Invalid, self.f, v)
36+
37+
38+
class IntegerLikeTestCase(BaseValidationTestCase, unittest.TestCase):
39+
base_function = validations.IntegerLike
40+
valid_values = [
41+
INT, LONG, INT_FLOAT, INT_STR, INT_UNICODE
42+
]
43+
invalid_values = [
44+
NON_INT_FLOAT, NON_INT_STR, ALNUM_STR, ALNUM_UNICODE,
45+
NON_INT_UNICODE, NON_ALNUM_STR, NON_ALNUM_UNICODE
46+
]
47+
48+
49+
class AlphanumericTestCase(BaseValidationTestCase, unittest.TestCase):
50+
base_function = validations.Alphanumeric
51+
valid_values = [
52+
INT, LONG, INT_FLOAT, INT_STR, INT_UNICODE, ALNUM_STR, ALNUM_UNICODE
53+
]
54+
invalid_values = [
55+
NON_INT_FLOAT, NON_INT_STR, NON_INT_UNICODE, NON_ALNUM_STR,
56+
NON_ALNUM_UNICODE
57+
]
58+
59+
60+
class StrictlyAlphanumericTestCase(BaseValidationTestCase, unittest.TestCase):
61+
base_function = validations.StrictlyAlphanumeric
62+
valid_values = [ALNUM_STR, ALNUM_UNICODE]
63+
invalid_values = [
64+
INT, LONG, INT_FLOAT, NON_INT_FLOAT, NON_INT_STR, NON_INT_UNICODE,
65+
NON_ALNUM_STR, NON_ALNUM_UNICODE, INT_STR, INT_UNICODE
66+
]
67+
68+
69+
class CSVofIntegersTestCase(BaseValidationTestCase, unittest.TestCase):
70+
base_function = validations.CSVofIntegers
71+
transform_val = lambda self, v: map(int, v.split(","))
72+
valid_values = [INT_CSV, INT_STR, INT_UNICODE]
73+
invalid_values = [
74+
INT_FLOAT, ALNUM_STR, ALNUM_UNICODE, NON_INT_FLOAT, NON_INT_STR,
75+
NON_INT_UNICODE, NON_ALNUM_STR, NON_ALNUM_UNICODE, NON_INT_CSV,
76+
INT, LONG
77+
]
File renamed without changes.

filters/validations.py

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
# This module is define and keep all generic type of data-validations.
2-
import six
3-
import re
2+
import sys
3+
import numbers
44
from voluptuous import Invalid
55
from django.utils.dateparse import parse_datetime, parse_date
66

7+
# Forward compatibility with Python 3.x
8+
if sys.version_info.major == 3:
9+
basestring = str
10+
711

812
def IntegerLike(msg=None):
913
'''
@@ -14,13 +18,11 @@ def IntegerLike(msg=None):
1418
- str or unicode composed only of digits
1519
'''
1620
def fn(value):
17-
if not (
18-
isinstance(value, int) or
19-
(isinstance(value, float) and value.is_integer()) or
20-
(isinstance(value, str) and value.isdigit()) or
21-
((isinstance(value, unicode) and value.isdigit() or
22-
isinstance(value, long)) if six.PY2 else None)
23-
):
21+
if not any([
22+
isinstance(value, numbers.Integral),
23+
(isinstance(value, float) and value.is_integer()),
24+
(isinstance(value, basestring) and value.isdigit())
25+
]):
2426
raise Invalid(msg or (
2527
'Invalid input <{0}>; expected an integer'.format(value))
2628
)
@@ -38,13 +40,11 @@ def Alphanumeric(msg=None):
3840
- str or unicode composed only of alphanumeric characters
3941
'''
4042
def fn(value):
41-
if not (
42-
isinstance(value, int) or
43-
(isinstance(value, float) and value.is_integer()) or
44-
(isinstance(value, str) and value.isalnum()) or
45-
((isinstance(value, unicode) and value.isdigit() or
46-
isinstance(value, long)) if six.PY2 else None)
47-
):
43+
if not any([
44+
isinstance(value, numbers.Integral),
45+
(isinstance(value, float) and value.is_integer()),
46+
(isinstance(value, basestring) and value.isalnum())
47+
]):
4848
raise Invalid(msg or (
4949
'Invalid input <{0}>; expected an integer'.format(value))
5050
)
@@ -53,10 +53,6 @@ def fn(value):
5353
return fn
5454

5555

56-
re_alphabets = re.compile('[A-Za-z]')
57-
re_digits = re.compile('[0-9]')
58-
59-
6056
def StrictlyAlphanumeric(msg=None):
6157
'''
6258
Checks whether a value is:
@@ -65,9 +61,10 @@ def StrictlyAlphanumeric(msg=None):
6561
'''
6662
def fn(value):
6763
if not (
68-
(isinstance(value, str) or (isinstance(value, unicode) if six.PY2 else None)) and
69-
re_alphabets.search(value) and
70-
re_digits.search(value)
64+
isinstance(value, basestring) and
65+
value.isalnum() and not
66+
value.isdigit() and not
67+
value.isalpha()
7168
):
7269
raise Invalid(msg or (
7370
'Invalid input <{0}>; expected an integer'.format(value))
@@ -97,12 +94,12 @@ def fn(value):
9794
def CSVofIntegers(msg=None):
9895
'''
9996
Checks whether a value is list of integers.
100-
Returns list of integers or just one integer in
97+
Returns list of integers or just one integer in
10198
list if there is only one element in given CSV string.
10299
'''
103100
def fn(value):
104101
try:
105-
if isinstance(value, six.text_type):
102+
if isinstance(value, basestring):
106103
if ',' in value:
107104
value = list(map(
108105
int, filter(
@@ -114,6 +111,8 @@ def fn(value):
114111
return value
115112
else:
116113
return [int(value)]
114+
else:
115+
raise ValueError
117116
except ValueError:
118117
raise Invalid(
119118
'<{0}> is not a valid csv of integers'.format(value)

setup.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
packages=['filters'],
3333
include_package_data=True,
3434
description=(
35-
'A django app to apply filters on drf querysets '
36-
'using query params with validations using voluptuous.'
37-
),
35+
'A django app to apply filters on drf querysets '
36+
'using query params with validations using voluptuous.'
37+
),
3838
long_description=README,
3939
url=__url__,
4040
download_url=__download_url__,
@@ -51,5 +51,7 @@
5151
'License :: OSI Approved :: MIT License',
5252
'Programming Language :: Python :: 2.7',
5353
],
54-
keywords='drf-url-filters, filters, queryparamters',
54+
keywords='drf-url-filters, filters, queryparameters',
55+
test_suite='nose2.collector.collector',
56+
tests_require=['nose2'],
5557
)

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)