#!/usr/bin/env python # -*- coding: utf-8 -*- """Unit tests for http.py """ import unittest import datetime import decimal import re from gluon.validators import * from gluon._compat import PY2, to_bytes class TestValidators(unittest.TestCase): def myassertRegex(self, *args, **kwargs): if PY2: return getattr(self, 'assertRegexpMatches')(*args, **kwargs) return getattr(self, 'assertRegex')(*args, **kwargs) def test_MISC(self): """ Test miscelaneous utility functions and some general behavior guarantees """ from gluon.validators import translate, options_sorter, Validator, UTC self.assertEqual(translate(None), None) self.assertEqual(options_sorter(('a', 'a'), ('a', 'a')), -1) self.assertEqual(options_sorter(('A', 'A'), ('a', 'a')), -1) self.assertEqual(options_sorter(('b', 'b'), ('a', 'a')), 1) self.assertRaises(NotImplementedError, Validator(), 1) utc = UTC() dt = datetime.datetime.now() self.assertEqual(utc.utcoffset(dt), UTC.ZERO) self.assertEqual(utc.dst(dt), UTC.ZERO) self.assertEqual(utc.tzname(dt), 'UTC') def test_IS_MATCH(self): rtn = IS_MATCH('.+')('hello') self.assertEqual(rtn, ('hello', None)) rtn = IS_MATCH('hell')('hello') self.assertEqual(rtn, ('hello', None)) rtn = IS_MATCH('hell.*', strict=False)('hello') self.assertEqual(rtn, ('hello', None)) rtn = IS_MATCH('hello')('shello') self.assertEqual(rtn, ('shello', 'Invalid expression')) rtn = IS_MATCH('hello', search=True)('shello') self.assertEqual(rtn, ('shello', None)) rtn = IS_MATCH('hello', search=True, strict=False)('shellox') self.assertEqual(rtn, ('shellox', None)) rtn = IS_MATCH('.*hello.*', search=True, strict=False)('shellox') self.assertEqual(rtn, ('shellox', None)) rtn = IS_MATCH('.+')('') self.assertEqual(rtn, ('', 'Invalid expression')) rtn = IS_MATCH('hell', strict=True)('hellas') self.assertEqual(rtn, ('hellas', 'Invalid expression')) rtn = IS_MATCH('hell$', strict=True)('hellas') self.assertEqual(rtn, ('hellas', 'Invalid expression')) rtn = IS_MATCH('^.hell$', strict=True)('shell') self.assertEqual(rtn, ('shell', None)) rtn = IS_MATCH(u'hell', is_unicode=True)('àòè') if PY2: self.assertEqual(rtn, ('\xc3\xa0\xc3\xb2\xc3\xa8', 'Invalid expression')) else: self.assertEqual(rtn, ('àòè', 'Invalid expression')) rtn = IS_MATCH(u'hell', is_unicode=True)(u'hell') self.assertEqual(rtn, (u'hell', None)) rtn = IS_MATCH('hell', is_unicode=True)(u'hell') self.assertEqual(rtn, (u'hell', None)) # regr test for #1044 rtn = IS_MATCH('hello')(u'\xff') self.assertEqual(rtn, (u'\xff', 'Invalid expression')) def test_IS_EQUAL_TO(self): rtn = IS_EQUAL_TO('aaa')('aaa') self.assertEqual(rtn, ('aaa', None)) rtn = IS_EQUAL_TO('aaa')('aab') self.assertEqual(rtn, ('aab', 'No match')) def test_IS_EXPR(self): rtn = IS_EXPR('int(value) < 2')('1') self.assertEqual(rtn, ('1', None)) rtn = IS_EXPR('int(value) < 2')('2') self.assertEqual(rtn, ('2', 'Invalid expression')) rtn = IS_EXPR(lambda value: int(value))('1') self.assertEqual(rtn, ('1', 1)) rtn = IS_EXPR(lambda value: int(value) < 2 and 'invalid' or None)('2') self.assertEqual(rtn, ('2', None)) def test_IS_LENGTH(self): rtn = IS_LENGTH()('') self.assertEqual(rtn, ('', None)) rtn = IS_LENGTH()('1234567890') self.assertEqual(rtn, ('1234567890', None)) rtn = IS_LENGTH(maxsize=5, minsize=0)('1234567890') # too long self.assertEqual(rtn, ('1234567890', 'Enter from 0 to 5 characters')) rtn = IS_LENGTH(maxsize=50, minsize=20)('1234567890') # too short self.assertEqual(rtn, ('1234567890', 'Enter from 20 to 50 characters')) rtn = IS_LENGTH()(None) self.assertEqual(rtn, (None, None)) rtn = IS_LENGTH(minsize=0)(None) self.assertEqual(rtn, (None, None)) rtn = IS_LENGTH(minsize=1)(None) self.assertEqual(rtn, (None, 'Enter from 1 to 255 characters')) rtn = IS_LENGTH(minsize=1)([]) self.assertEqual(rtn, ([], 'Enter from 1 to 255 characters')) rtn = IS_LENGTH(minsize=1)([1, 2]) self.assertEqual(rtn, ([1, 2], None)) rtn = IS_LENGTH(minsize=1)([1]) self.assertEqual(rtn, ([1], None)) # test non utf-8 str cpstr = u'lálá'.encode('cp1252') rtn = IS_LENGTH(minsize=4)(cpstr) self.assertEqual(rtn, (cpstr, None)) rtn = IS_LENGTH(maxsize=4)(cpstr) self.assertEqual(rtn, (cpstr, None)) rtn = IS_LENGTH(minsize=0, maxsize=3)(cpstr) self.assertEqual(rtn, (cpstr, 'Enter from 0 to 3 characters')) # test unicode rtn = IS_LENGTH(2)(u'°2') if PY2: self.assertEqual(rtn, ('\xc2\xb02', None)) else: self.assertEqual(rtn, (u'°2', None)) rtn = IS_LENGTH(2)(u'°12') if PY2: self.assertEqual(rtn, (u'\xb012', 'Enter from 0 to 2 characters')) else: self.assertEqual(rtn, (u'°12', 'Enter from 0 to 2 characters')) # test automatic str() rtn = IS_LENGTH(minsize=1)(1) self.assertEqual(rtn, ('1', None)) rtn = IS_LENGTH(minsize=2)(1) self.assertEqual(rtn, (1, 'Enter from 2 to 255 characters')) # test FieldStorage import cgi from io import BytesIO a = cgi.FieldStorage() a.file = BytesIO(b'abc') rtn = IS_LENGTH(minsize=4)(a) self.assertEqual(rtn, (a, 'Enter from 4 to 255 characters')) urlencode_data = b"key2=value2x&key3=value3&key4=value4" urlencode_environ = { 'CONTENT_LENGTH': str(len(urlencode_data)), 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'QUERY_STRING': 'key1=value1&key2=value2y', 'REQUEST_METHOD': 'POST', } fake_stdin = BytesIO(urlencode_data) fake_stdin.seek(0) a = cgi.FieldStorage(fp=fake_stdin, environ=urlencode_environ) rtn = IS_LENGTH(minsize=6)(a) self.assertEqual(rtn, (a, 'Enter from 6 to 255 characters')) a = cgi.FieldStorage() rtn = IS_LENGTH(minsize=6)(a) self.assertEqual(rtn, (a, 'Enter from 6 to 255 characters')) rtn = IS_LENGTH(6)(a) self.assertEqual(rtn, (a, None)) def test_IS_JSON(self): rtn = IS_JSON()('{"a": 100}') self.assertEqual(rtn, ({u'a': 100}, None)) rtn = IS_JSON()('spam1234') self.assertEqual(rtn, ('spam1234', 'Invalid json')) rtn = IS_JSON(native_json=True)('{"a": 100}') self.assertEqual(rtn, ('{"a": 100}', None)) rtn = IS_JSON().formatter(None) self.assertEqual(rtn, None) rtn = IS_JSON().formatter({'a': 100}) self.assertEqual(rtn, '{"a": 100}') rtn = IS_JSON(native_json=True).formatter({'a': 100}) self.assertEqual(rtn, {'a': 100}) def test_IS_IN_SET(self): rtn = IS_IN_SET(['max', 'john'])('max') self.assertEqual(rtn, ('max', None)) rtn = IS_IN_SET(['max', 'john'])('massimo') self.assertEqual(rtn, ('massimo', 'Value not allowed')) rtn = IS_IN_SET(['max', 'john'], multiple=True)(('max', 'john')) self.assertEqual(rtn, (('max', 'john'), None)) rtn = IS_IN_SET(['max', 'john'], multiple=True)(('bill', 'john')) self.assertEqual(rtn, (('bill', 'john'), 'Value not allowed')) rtn = IS_IN_SET(('id1', 'id2'), ['first label', 'second label'])('id1') # Traditional way self.assertEqual(rtn, ('id1', None)) rtn = IS_IN_SET({'id1': 'first label', 'id2': 'second label'})('id1') self.assertEqual(rtn, ('id1', None)) rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)(None) self.assertEqual(rtn, ([], None)) rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)('') self.assertEqual(rtn, ([], None)) rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=True)('id1') self.assertEqual(rtn, (['id1'], None)) rtn = IS_IN_SET(['id1', 'id2'], error_message='oops', multiple=(1, 2))(None) self.assertEqual(rtn, ([], 'oops')) import itertools rtn = IS_IN_SET(itertools.chain(['1', '3', '5'], ['2', '4', '6']))('1') self.assertEqual(rtn, ('1', None)) rtn = IS_IN_SET([('id1', 'first label'), ('id2', 'second label')])('id1') # Redundant way self.assertEqual(rtn, ('id1', None)) rtn = IS_IN_SET([('id1', 'first label'), ('id2', 'second label')]).options(zero=False) self.assertEqual(rtn, [('id1', 'first label'), ('id2', 'second label')]) rtn = IS_IN_SET(['id1', 'id2']).options(zero=False) self.assertEqual(rtn, [('id1', 'id1'), ('id2', 'id2')]) rtn = IS_IN_SET(['id2', 'id1'], sort=True).options(zero=False) self.assertEqual(rtn, [('id1', 'id1'), ('id2', 'id2')]) def test_IS_IN_DB(self): from gluon.dal import DAL, Field db = DAL('sqlite:memory') db.define_table('person', Field('name')) george_id = db.person.insert(name='george') costanza_id = db.person.insert(name='costanza') rtn = IS_IN_DB(db, 'person.id', '%(name)s')(george_id) self.assertEqual(rtn, (george_id, None)) rtn = IS_IN_DB(db, 'person.name', '%(name)s')('george') self.assertEqual(rtn, ('george', None)) rtn = IS_IN_DB(db, db.person, '%(name)s')(george_id) self.assertEqual(rtn, (george_id, None)) rtn = IS_IN_DB(db(db.person.id > 0), db.person, '%(name)s')(george_id) self.assertEqual(rtn, (george_id, None)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', error_message='oops')(george_id + costanza_id) self.assertEqual(rtn, (george_id + costanza_id, 'oops')) rtn = IS_IN_DB(db, db.person.id, '%(name)s')(george_id) self.assertEqual(rtn, (george_id, None)) rtn = IS_IN_DB(db, db.person.id, '%(name)s', error_message='oops')(george_id + costanza_id) self.assertEqual(rtn, (george_id + costanza_id, 'oops')) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True)([george_id, costanza_id]) self.assertEqual(rtn, ([george_id, costanza_id], None)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True, error_message='oops')("I'm not even an id") self.assertEqual(rtn, (["I'm not even an id"], 'oops')) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=True, delimiter=',')('%d,%d' % (george_id, costanza_id)) self.assertEqual(rtn, (('%d,%d' % (george_id, costanza_id)).split(','), None)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=(1, 3), delimiter=',')('%d,%d' % (george_id, costanza_id)) self.assertEqual(rtn, (('%d,%d' % (george_id, costanza_id)).split(','), None)) rtn = IS_IN_DB(db, 'person.id', '%(name)s', multiple=(1, 2), delimiter=',', error_message='oops')('%d,%d' % (george_id, costanza_id)) self.assertEqual(rtn, (('%d,%d' % (george_id, costanza_id)).split(','), 'oops')) rtn = IS_IN_DB(db, db.person.id, '%(name)s', error_message='oops').options(zero=False) 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() rtn = vldtr('george') self.assertEqual(rtn, ('george', None)) rtn = vldtr('jerry') self.assertEqual(rtn, ('jerry', 'oops')) vldtr = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops', multiple=True) vldtr.options() rtn = vldtr(['george', 'costanza']) self.assertEqual(rtn, (['george', 'costanza'], None)) # Test it works with self reference db.define_table('category', Field('parent_id', 'reference category', requires=IS_EMPTY_OR(IS_IN_DB(db, 'category.id', '%(name)s'))), Field('name') ) ret = db.category.validate_and_insert(name='seinfeld') self.assertFalse(list(ret.errors)) ret = db.category.validate_and_insert(name='characters', parent_id=ret.id) self.assertFalse(list(ret.errors)) rtn = IS_IN_DB(db, 'category.id', '%(name)s')(ret.id) self.assertEqual(rtn, (ret.id, None)) # Test _and vldtr = IS_IN_DB(db, 'person.name', '%(name)s', error_message='oops', _and=IS_LENGTH(maxsize=7, error_message='bad')) rtn = vldtr('george') self.assertEqual(rtn, ('george', None)) rtn = vldtr('costanza') self.assertEqual(rtn, ('costanza', 'bad')) rtn = vldtr('jerry') self.assertEqual(rtn, ('jerry', 'oops')) vldtr.options() # test theset with _and rtn = vldtr('jerry') self.assertEqual(rtn, ('jerry', 'oops')) # Test auto_add rtn = IS_IN_DB(db, 'person.id', '%(name)s', error_message='oops')('jerry') self.assertEqual(rtn, ('jerry', 'oops')) rtn = IS_IN_DB(db, 'person.id', '%(name)s', auto_add=True)('jerry') self.assertEqual(rtn, (3, None)) # Test it works with reference table db.define_table('ref_table', Field('name'), Field('person_id', 'reference person') ) ret = db.ref_table.validate_and_insert(name='test reference table') self.assertFalse(list(ret.errors)) ret = db.ref_table.validate_and_insert(name='test reference table', person_id=george_id) self.assertFalse(list(ret.errors)) rtn = IS_IN_DB(db, 'ref_table.person_id', '%(name)s')(george_id) self.assertEqual(rtn, (george_id, None)) # Test it works with reference table.field and keyed table db.define_table('person_keyed', Field('name'), primarykey=['name']) db.person_keyed.insert(name='george') db.person_keyed.insert(name='costanza') rtn = IS_IN_DB(db, 'person_keyed.name')('george') self.assertEqual(rtn, ('george', None)) db.define_table('ref_table_field', Field('name'), Field('person_name', 'reference person_keyed.name') ) ret = db.ref_table_field.validate_and_insert(name='test reference table.field') self.assertFalse(list(ret.errors)) ret = db.ref_table_field.validate_and_insert(name='test reference table.field', person_name='george') self.assertFalse(list(ret.errors)) vldtr = IS_IN_DB(db, 'ref_table_field.person_name', '%(name)s') vldtr.options() rtn = vldtr('george') self.assertEqual(rtn, ('george', None)) # Test it works with list:reference table db.define_table('list_ref_table', Field('name'), Field('person_list', 'list:reference person')) ret = db.list_ref_table.validate_and_insert(name='test list:reference table') self.assertFalse(list(ret.errors)) ret = db.list_ref_table.validate_and_insert(name='test list:reference table', person_list=[george_id,costanza_id]) self.assertFalse(list(ret.errors)) vldtr = IS_IN_DB(db, 'list_ref_table.person_list') vldtr.options() rtn = vldtr([george_id,costanza_id]) self.assertEqual(rtn, ([george_id,costanza_id], None)) # Test it works with list:reference table.field and keyed table #db.define_table('list_ref_table_field', # Field('name'), # Field('person_list', 'list:reference person_keyed.name')) #ret = db.list_ref_table_field.validate_and_insert(name='test list:reference table.field') #self.assertFalse(list(ret.errors)) #ret = db.list_ref_table_field.validate_and_insert(name='test list:reference table.field', person_list=['george','costanza']) #self.assertFalse(list(ret.errors)) #vldtr = IS_IN_DB(db, 'list_ref_table_field.person_list') #vldtr.options() #rtn = vldtr(['george','costanza']) #self.assertEqual(rtn, (['george','costanza'], None)) db.person.drop() db.category.drop() db.person_keyed.drop() db.ref_table.drop() db.ref_table_field.drop() db.list_ref_table.drop() #db.list_ref_table_field.drop() def test_IS_NOT_IN_DB(self): from gluon.dal import DAL, Field db = DAL('sqlite:memory') db.define_table('person', Field('name'), Field('nickname')) db.person.insert(name='george') db.person.insert(name='costanza', nickname='T Bone') rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops')('george') self.assertEqual(rtn, ('george', 'oops')) rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops', allowed_override=['george'])('george') self.assertEqual(rtn, ('george', None)) rtn = IS_NOT_IN_DB(db, 'person.name', error_message='oops')(' ') self.assertEqual(rtn, (' ', 'oops')) rtn = IS_NOT_IN_DB(db, 'person.name')('jerry') self.assertEqual(rtn, ('jerry', None)) rtn = IS_NOT_IN_DB(db, 'person.name')(u'jerry') self.assertEqual(rtn, ('jerry', None)) rtn = IS_NOT_IN_DB(db(db.person.id > 0), 'person.name')(u'jerry') self.assertEqual(rtn, ('jerry', None)) rtn = IS_NOT_IN_DB(db, db.person, error_message='oops')(1) self.assertEqual(rtn, ('1', 'oops')) vldtr = IS_NOT_IN_DB(db, 'person.name', error_message='oops') vldtr.set_self_id({'name': 'costanza', 'nickname': 'T Bone'}) rtn = vldtr('george') self.assertEqual(rtn, ('george', 'oops')) rtn = vldtr('costanza') self.assertEqual(rtn, ('costanza', None)) db.person.drop() def test_IS_INT_IN_RANGE(self): rtn = IS_INT_IN_RANGE(1, 5)('4') self.assertEqual(rtn, (4, None)) rtn = IS_INT_IN_RANGE(1, 5)(4) self.assertEqual(rtn, (4, None)) rtn = IS_INT_IN_RANGE(1, 5)(1) self.assertEqual(rtn, (1, None)) rtn = IS_INT_IN_RANGE(1, 5)(5) self.assertEqual(rtn, (5, 'Enter an integer between 1 and 4')) rtn = IS_INT_IN_RANGE(1, 5)(5) self.assertEqual(rtn, (5, 'Enter an integer between 1 and 4')) rtn = IS_INT_IN_RANGE(1, 5)(3.5) self.assertEqual(rtn, (3.5, 'Enter an integer between 1 and 4')) rtn = IS_INT_IN_RANGE(None, 5)('4') self.assertEqual(rtn, (4, None)) rtn = IS_INT_IN_RANGE(None, 5)('6') self.assertEqual(rtn, ('6', 'Enter an integer less than or equal to 4')) rtn = IS_INT_IN_RANGE(1, None)('4') self.assertEqual(rtn, (4, None)) rtn = IS_INT_IN_RANGE(1, None)('0') self.assertEqual(rtn, ('0', 'Enter an integer greater than or equal to 1')) rtn = IS_INT_IN_RANGE()(6) self.assertEqual(rtn, (6, None)) rtn = IS_INT_IN_RANGE()('abc') self.assertEqual(rtn, ('abc', 'Enter an integer')) def test_IS_FLOAT_IN_RANGE(self): # with None rtn = IS_FLOAT_IN_RANGE(1, 5)(None) self.assertEqual(rtn, (None, 'Enter a number between 1 and 5')) rtn = IS_FLOAT_IN_RANGE(1, 5)('4') self.assertEqual(rtn, (4.0, None)) rtn = IS_FLOAT_IN_RANGE(1, 5)(4) self.assertEqual(rtn, (4.0, None)) rtn = IS_FLOAT_IN_RANGE(1, 5)(1) self.assertEqual(rtn, (1.0, None)) rtn = IS_FLOAT_IN_RANGE(1, 5)(5.25) self.assertEqual(rtn, (5.25, 'Enter a number between 1 and 5')) rtn = IS_FLOAT_IN_RANGE(1, 5)(6.0) self.assertEqual(rtn, (6.0, 'Enter a number between 1 and 5')) rtn = IS_FLOAT_IN_RANGE(1, 5)(3.5) self.assertEqual(rtn, (3.5, None)) rtn = IS_FLOAT_IN_RANGE(1, None)(3.5) self.assertEqual(rtn, (3.5, None)) rtn = IS_FLOAT_IN_RANGE(None, 5)(3.5) self.assertEqual(rtn, (3.5, None)) rtn = IS_FLOAT_IN_RANGE(1, None)(0.5) self.assertEqual(rtn, (0.5, 'Enter a number greater than or equal to 1')) rtn = IS_FLOAT_IN_RANGE(None, 5)(6.5) self.assertEqual(rtn, (6.5, 'Enter a number less than or equal to 5')) rtn = IS_FLOAT_IN_RANGE()(6.5) self.assertEqual(rtn, (6.5, None)) rtn = IS_FLOAT_IN_RANGE()('abc') self.assertEqual(rtn, ('abc', 'Enter a number')) rtn = IS_FLOAT_IN_RANGE()('6,5') self.assertEqual(rtn, ('6,5', 'Enter a number')) rtn = IS_FLOAT_IN_RANGE(dot=',')('6.5') self.assertEqual(rtn, (6.5, None)) # With .formatter(None) rtn = IS_FLOAT_IN_RANGE(dot=',').formatter(None) self.assertEqual(rtn, None) rtn = IS_FLOAT_IN_RANGE(dot=',').formatter(0.25) self.assertEqual(rtn, '0,25') # To trigger str2dec "if not '.' in s:" line rtn = IS_FLOAT_IN_RANGE(dot=',').formatter(1) self.assertEqual(rtn, '1,00') def test_IS_DECIMAL_IN_RANGE(self): # with None rtn = IS_DECIMAL_IN_RANGE(1, 5)(None) self.assertEqual(rtn, (None, 'Enter a number between 1 and 5')) rtn = IS_DECIMAL_IN_RANGE(1, 5)('4') self.assertEqual(rtn, (decimal.Decimal('4'), None)) rtn = IS_DECIMAL_IN_RANGE(1, 5)(4) self.assertEqual(rtn, (decimal.Decimal('4'), None)) rtn = IS_DECIMAL_IN_RANGE(1, 5)(1) self.assertEqual(rtn, (decimal.Decimal('1'), None)) rtn = IS_DECIMAL_IN_RANGE(1, 5)(5.25) self.assertEqual(rtn, (5.25, 'Enter a number between 1 and 5')) rtn = IS_DECIMAL_IN_RANGE(5.25, 6)(5.25) self.assertEqual(rtn, (decimal.Decimal('5.25'), None)) rtn = IS_DECIMAL_IN_RANGE(5.25, 6)('5.25') self.assertEqual(rtn, (decimal.Decimal('5.25'), None)) rtn = IS_DECIMAL_IN_RANGE(1, 5)(6.0) self.assertEqual(rtn, (6.0, 'Enter a number between 1 and 5')) rtn = IS_DECIMAL_IN_RANGE(1, 5)(3.5) self.assertEqual(rtn, (decimal.Decimal('3.5'), None)) rtn = IS_DECIMAL_IN_RANGE(1.5, 5.5)(3.5) self.assertEqual(rtn, (decimal.Decimal('3.5'), None)) rtn = IS_DECIMAL_IN_RANGE(1.5, 5.5)(6.5) self.assertEqual(rtn, (6.5, 'Enter a number between 1.5 and 5.5')) rtn = IS_DECIMAL_IN_RANGE(1.5, None)(6.5) self.assertEqual(rtn, (decimal.Decimal('6.5'), None)) rtn = IS_DECIMAL_IN_RANGE(1.5, None)(0.5) self.assertEqual(rtn, (0.5, 'Enter a number greater than or equal to 1.5')) rtn = IS_DECIMAL_IN_RANGE(None, 5.5)(4.5) self.assertEqual(rtn, (decimal.Decimal('4.5'), None)) rtn = IS_DECIMAL_IN_RANGE(None, 5.5)(6.5) self.assertEqual(rtn, (6.5, 'Enter a number less than or equal to 5.5')) rtn = IS_DECIMAL_IN_RANGE()(6.5) self.assertEqual(rtn, (decimal.Decimal('6.5'), None)) rtn = IS_DECIMAL_IN_RANGE(0, 99)(123.123) self.assertEqual(rtn, (123.123, 'Enter a number between 0 and 99')) rtn = IS_DECIMAL_IN_RANGE(0, 99)('123.123') self.assertEqual(rtn, ('123.123', 'Enter a number between 0 and 99')) rtn = IS_DECIMAL_IN_RANGE(0, 99)('12.34') self.assertEqual(rtn, (decimal.Decimal('12.34'), None)) rtn = IS_DECIMAL_IN_RANGE()('abc') self.assertEqual(rtn, ('abc', 'Enter a number')) rtn = IS_DECIMAL_IN_RANGE()('6,5') self.assertEqual(rtn, ('6,5', 'Enter a number')) rtn = IS_DECIMAL_IN_RANGE(dot=',')('6.5') self.assertEqual(rtn, (decimal.Decimal('6.5'), None)) rtn = IS_DECIMAL_IN_RANGE(1, 5)(decimal.Decimal('4')) self.assertEqual(rtn, (decimal.Decimal('4'), None)) # With .formatter(None) rtn = IS_DECIMAL_IN_RANGE(dot=',').formatter(None) self.assertEqual(rtn, None) rtn = IS_DECIMAL_IN_RANGE(dot=',').formatter(0.25) self.assertEqual(rtn, '0,25') def test_IS_NOT_EMPTY(self): rtn = IS_NOT_EMPTY()(1) self.assertEqual(rtn, (1, None)) rtn = IS_NOT_EMPTY()(0) self.assertEqual(rtn, (0, None)) rtn = IS_NOT_EMPTY()('x') self.assertEqual(rtn, ('x', None)) rtn = IS_NOT_EMPTY()(' x ') self.assertEqual(rtn, (' x ', None)) rtn = IS_NOT_EMPTY()(None) self.assertEqual(rtn, (None, 'Enter a value')) rtn = IS_NOT_EMPTY()('') self.assertEqual(rtn, ('', 'Enter a value')) rtn = IS_NOT_EMPTY()(b'') self.assertEqual(rtn, (b'', 'Enter a value')) rtn = IS_NOT_EMPTY()(' ') self.assertEqual(rtn, (' ', 'Enter a value')) rtn = IS_NOT_EMPTY()(' \n\t') self.assertEqual(rtn, (' \n\t', 'Enter a value')) rtn = IS_NOT_EMPTY()([]) self.assertEqual(rtn, ([], 'Enter a value')) rtn = IS_NOT_EMPTY(empty_regex='def')('def') self.assertEqual(rtn, ('def', 'Enter a value')) rtn = IS_NOT_EMPTY(empty_regex='de[fg]')('deg') self.assertEqual(rtn, ('deg', 'Enter a value')) rtn = IS_NOT_EMPTY(empty_regex='def')('abc') self.assertEqual(rtn, ('abc', None)) def test_IS_ALPHANUMERIC(self): rtn = IS_ALPHANUMERIC()('1') self.assertEqual(rtn, ('1', None)) rtn = IS_ALPHANUMERIC()('') self.assertEqual(rtn, ('', None)) rtn = IS_ALPHANUMERIC()('A_a') self.assertEqual(rtn, ('A_a', None)) rtn = IS_ALPHANUMERIC()('!') self.assertEqual(rtn, ('!', 'Enter only letters, numbers, and underscore')) def test_IS_EMAIL(self): rtn = IS_EMAIL()('a@b.com') self.assertEqual(rtn, ('a@b.com', None)) rtn = IS_EMAIL()('abc@def.com') self.assertEqual(rtn, ('abc@def.com', None)) rtn = IS_EMAIL()('abc@3def.com') self.assertEqual(rtn, ('abc@3def.com', None)) rtn = IS_EMAIL()('abc@def.us') self.assertEqual(rtn, ('abc@def.us', None)) rtn = IS_EMAIL()('abc@d_-f.us') self.assertEqual(rtn, ('abc@d_-f.us', None)) rtn = IS_EMAIL()('@def.com') # missing name self.assertEqual(rtn, ('@def.com', 'Enter a valid email address')) rtn = IS_EMAIL()('"abc@def".com') # quoted name self.assertEqual(rtn, ('"abc@def".com', 'Enter a valid email address')) rtn = IS_EMAIL()('abc+def.com') # no @ self.assertEqual(rtn, ('abc+def.com', 'Enter a valid email address')) rtn = IS_EMAIL()('abc@def.x') # one-char TLD self.assertEqual(rtn, ('abc@def.x', 'Enter a valid email address')) rtn = IS_EMAIL()('abc@def.12') # numeric TLD self.assertEqual(rtn, ('abc@def.12', 'Enter a valid email address')) rtn = IS_EMAIL()('abc@def..com') # double-dot in domain self.assertEqual(rtn, ('abc@def..com', 'Enter a valid email address')) rtn = IS_EMAIL()('abc@.def.com') # dot starts domain self.assertEqual(rtn, ('abc@.def.com', 'Enter a valid email address')) rtn = IS_EMAIL()('abc@def.c_m') # underscore in TLD self.assertEqual(rtn, ('abc@def.c_m', 'Enter a valid email address')) rtn = IS_EMAIL()('NotAnEmail') # missing @ self.assertEqual(rtn, ('NotAnEmail', 'Enter a valid email address')) rtn = IS_EMAIL()('abc@NotAnEmail') # missing TLD self.assertEqual(rtn, ('abc@NotAnEmail', 'Enter a valid email address')) rtn = IS_EMAIL()('customer/department@example.com') self.assertEqual(rtn, ('customer/department@example.com', None)) rtn = IS_EMAIL()('$A12345@example.com') self.assertEqual(rtn, ('$A12345@example.com', None)) rtn = IS_EMAIL()('!def!xyz%abc@example.com') self.assertEqual(rtn, ('!def!xyz%abc@example.com', None)) rtn = IS_EMAIL()('_Yosemite.Sam@example.com') self.assertEqual(rtn, ('_Yosemite.Sam@example.com', None)) rtn = IS_EMAIL()('~@example.com') self.assertEqual(rtn, ('~@example.com', None)) rtn = IS_EMAIL()('.wooly@example.com') # dot starts name self.assertEqual(rtn, ('.wooly@example.com', 'Enter a valid email address')) rtn = IS_EMAIL()('wo..oly@example.com') # adjacent dots in name self.assertEqual(rtn, ('wo..oly@example.com', 'Enter a valid email address')) rtn = IS_EMAIL()('pootietang.@example.com') # dot ends name self.assertEqual(rtn, ('pootietang.@example.com', 'Enter a valid email address')) rtn = IS_EMAIL()('.@example.com') # name is bare dot self.assertEqual(rtn, ('.@example.com', 'Enter a valid email address')) rtn = IS_EMAIL()('Ima.Fool@example.com') self.assertEqual(rtn, ('Ima.Fool@example.com', None)) rtn = IS_EMAIL()('Ima Fool@example.com') # space in name self.assertEqual(rtn, ('Ima Fool@example.com', 'Enter a valid email address')) rtn = IS_EMAIL()('localguy@localhost') # localhost as domain self.assertEqual(rtn, ('localguy@localhost', None)) # test for banned rtn = IS_EMAIL(banned='^.*\.com(|\..*)$')('localguy@localhost') # localhost as domain self.assertEqual(rtn, ('localguy@localhost', None)) rtn = IS_EMAIL(banned='^.*\.com(|\..*)$')('abc@example.com') self.assertEqual(rtn, ('abc@example.com', 'Enter a valid email address')) # test for forced rtn = IS_EMAIL(forced='^.*\.edu(|\..*)$')('localguy@localhost') self.assertEqual(rtn, ('localguy@localhost', 'Enter a valid email address')) rtn = IS_EMAIL(forced='^.*\.edu(|\..*)$')('localguy@example.edu') self.assertEqual(rtn, ('localguy@example.edu', None)) # test for not a string at all rtn = IS_EMAIL(error_message='oops')(42) self.assertEqual(rtn, (42, 'oops')) # test for Internationalized Domain Names, see https://docs.python.org/2/library/codecs.html#module-encodings.idna rtn = IS_EMAIL()('web2py@Alliancefrançaise.nu') self.assertEqual(rtn, ('web2py@Alliancefrançaise.nu', None)) def test_IS_LIST_OF_EMAILS(self): emails = ['localguy@localhost', '_Yosemite.Sam@example.com'] rtn = IS_LIST_OF_EMAILS()(','.join(emails)) self.assertEqual(rtn, (','.join(emails), None)) rtn = IS_LIST_OF_EMAILS()(';'.join(emails)) self.assertEqual(rtn, (';'.join(emails), None)) rtn = IS_LIST_OF_EMAILS()(' '.join(emails)) self.assertEqual(rtn, (' '.join(emails), None)) emails.append('a') rtn = IS_LIST_OF_EMAILS()(';'.join(emails)) self.assertEqual(rtn, ('localguy@localhost;_Yosemite.Sam@example.com;a', 'Invalid emails: a')) rtn = IS_LIST_OF_EMAILS().formatter(['test@example.com', 'dude@example.com']) self.assertEqual(rtn, 'test@example.com, dude@example.com') def test_IS_URL(self): rtn = IS_URL()('http://example.com') self.assertEqual(rtn, ('http://example.com', None)) rtn = IS_URL(error_message='oops')('http://example,com') self.assertEqual(rtn, ('http://example,com', 'oops')) rtn = IS_URL(error_message='oops')('http://www.example.com:8800/a/b/c/d/e/f/g/h') self.assertEqual(rtn, ('http://www.example.com:8800/a/b/c/d/e/f/g/h', None)) rtn = IS_URL(error_message='oops', prepend_scheme='http')('example.com') self.assertEqual(rtn, ('http://example.com', None)) rtn = IS_URL()('http://example.com?q=george&p=22') self.assertEqual(rtn, ('http://example.com?q=george&p=22', None)) rtn = IS_URL(mode='generic', prepend_scheme=None)('example.com') self.assertEqual(rtn, ('example.com', None)) def test_IS_TIME(self): rtn = IS_TIME()('21:30') self.assertEqual(rtn, (datetime.time(21, 30), None)) rtn = IS_TIME()('21-30') self.assertEqual(rtn, (datetime.time(21, 30), None)) rtn = IS_TIME()('21.30') self.assertEqual(rtn, (datetime.time(21, 30), None)) rtn = IS_TIME()('21:30:59') self.assertEqual(rtn, (datetime.time(21, 30, 59), None)) rtn = IS_TIME()('5:30') self.assertEqual(rtn, (datetime.time(5, 30), None)) rtn = IS_TIME()('5:30 am') self.assertEqual(rtn, (datetime.time(5, 30), None)) rtn = IS_TIME()('5:30 pm') self.assertEqual(rtn, (datetime.time(17, 30), None)) rtn = IS_TIME()('5:30 whatever') self.assertEqual(rtn, ('5:30 whatever', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) rtn = IS_TIME()('5:30 20') self.assertEqual(rtn, ('5:30 20', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) rtn = IS_TIME()('24:30') self.assertEqual(rtn, ('24:30', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) rtn = IS_TIME()('21:60') self.assertEqual(rtn, ('21:60', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) rtn = IS_TIME()('21:30::') self.assertEqual(rtn, ('21:30::', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) rtn = IS_TIME()('') self.assertEqual(rtn, ('', 'Enter time as hh:mm:ss (seconds, am, pm optional)')) def test_IS_DATE(self): v = IS_DATE(format="%m/%d/%Y", error_message="oops") rtn = v('03/03/2008') self.assertEqual(rtn, (datetime.date(2008, 3, 3), None)) rtn = v('31/03/2008') self.assertEqual(rtn, ('31/03/2008', 'oops')) rtn = IS_DATE(format="%m/%d/%Y", error_message="oops").formatter(datetime.date(1834, 12, 14)) self.assertEqual(rtn, '12/14/1834') def test_IS_DATETIME(self): v = IS_DATETIME(format="%m/%d/%Y %H:%M", error_message="oops") rtn = v('03/03/2008 12:40') self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 12, 40), None)) rtn = v('31/03/2008 29:40') self.assertEqual(rtn, ('31/03/2008 29:40', 'oops')) # Test timezone is removed and value is properly converted # # https://github.com/web2py/web2py/issues/1094 class DummyTimezone(datetime.tzinfo): ONE = datetime.timedelta(hours=1) def utcoffset(self, dt): return DummyTimezone.ONE def tzname(self, dt): return "UTC+1" def dst(self, dt): return DummyTimezone.ONE def localize(self, dt, is_dst=False): return dt.replace(tzinfo=self) v = IS_DATETIME(format="%Y-%m-%d %H:%M", error_message="oops", timezone=DummyTimezone()) rtn = v('1982-12-14 08:00') self.assertEqual(rtn, (datetime.datetime(1982, 12, 14, 7, 0), None)) def test_IS_DATE_IN_RANGE(self): v = IS_DATE_IN_RANGE(minimum=datetime.date(2008, 1, 1), maximum=datetime.date(2009, 12, 31), format="%m/%d/%Y", error_message="oops") rtn = v('03/03/2008') self.assertEqual(rtn, (datetime.date(2008, 3, 3), None)) rtn = v('03/03/2010') self.assertEqual(rtn, ('03/03/2010', 'oops')) rtn = v(datetime.date(2008, 3, 3)) self.assertEqual(rtn, (datetime.date(2008, 3, 3), None)) rtn = v(datetime.date(2010, 3, 3)) self.assertEqual(rtn, (datetime.date(2010, 3, 3), 'oops')) v = IS_DATE_IN_RANGE(maximum=datetime.date(2009, 12, 31), format="%m/%d/%Y") rtn = v('03/03/2010') self.assertEqual(rtn, ('03/03/2010', 'Enter date on or before 12/31/2009')) v = IS_DATE_IN_RANGE(minimum=datetime.date(2008, 1, 1), format="%m/%d/%Y") rtn = v('03/03/2007') self.assertEqual(rtn, ('03/03/2007', 'Enter date on or after 01/01/2008')) v = IS_DATE_IN_RANGE(minimum=datetime.date(2008, 1, 1), maximum=datetime.date(2009, 12, 31), format="%m/%d/%Y") rtn = v('03/03/2007') self.assertEqual(rtn, ('03/03/2007', 'Enter date in range 01/01/2008 12/31/2009')) def test_IS_DATETIME_IN_RANGE(self): v = IS_DATETIME_IN_RANGE( minimum=datetime.datetime(2008, 1, 1, 12, 20), maximum=datetime.datetime(2009, 12, 31, 12, 20), format="%m/%d/%Y %H:%M", error_message="oops") rtn = v('03/03/2008 12:40') self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 12, 40), None)) rtn = v('03/03/2010 10:34') self.assertEqual(rtn, ('03/03/2010 10:34', 'oops')) rtn = v(datetime.datetime(2008, 3, 3, 0, 0)) self.assertEqual(rtn, (datetime.datetime(2008, 3, 3, 0, 0), None)) rtn = v(datetime.datetime(2010, 3, 3, 0, 0)) self.assertEqual(rtn, (datetime.datetime(2010, 3, 3, 0, 0), 'oops')) v = IS_DATETIME_IN_RANGE(maximum=datetime.datetime(2009, 12, 31, 12, 20), format='%m/%d/%Y %H:%M:%S') rtn = v('03/03/2010 12:20:00') self.assertEqual(rtn, ('03/03/2010 12:20:00', 'Enter date and time on or before 12/31/2009 12:20:00')) v = IS_DATETIME_IN_RANGE(minimum=datetime.datetime(2008, 1, 1, 12, 20), format='%m/%d/%Y %H:%M:%S') rtn = v('03/03/2007 12:20:00') self.assertEqual(rtn, ('03/03/2007 12:20:00', 'Enter date and time on or after 01/01/2008 12:20:00')) v = IS_DATETIME_IN_RANGE(minimum=datetime.datetime(2008, 1, 1, 12, 20), maximum=datetime.datetime(2009, 12, 31, 12, 20), format='%m/%d/%Y %H:%M:%S') rtn = v('03/03/2007 12:20:00') self.assertEqual(rtn, ('03/03/2007 12:20:00', 'Enter date and time in range 01/01/2008 12:20:00 12/31/2009 12:20:00')) v = IS_DATETIME_IN_RANGE(maximum=datetime.datetime(2009, 12, 31, 12, 20), format='%Y-%m-%d %H:%M:%S', error_message='oops') rtn = v('clearly not a date') self.assertEqual(rtn, ('clearly not a date', 'oops')) def test_IS_LIST_OF(self): values = [0, 1, 2, 3, 4] rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(values) self.assertEqual(rtn, (values, None)) values.append(11) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(values) self.assertEqual(rtn, (values, 'Enter an integer between 0 and 9')) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10))(1) self.assertEqual(rtn, ([1], None)) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10), minimum=10)([1, 2]) self.assertEqual(rtn, ([1, 2], 'Minimum length is 10')) rtn = IS_LIST_OF(IS_INT_IN_RANGE(0, 10), maximum=2)([1, 2, 3]) self.assertEqual(rtn, ([1, 2, 3], 'Maximum length is 2')) # regression test for issue 742 rtn = IS_LIST_OF(minimum=1)('') self.assertEqual(rtn, ([], 'Minimum length is 1')) def test_IS_LOWER(self): rtn = IS_LOWER()('ABC') self.assertEqual(rtn, ('abc', None)) rtn = IS_LOWER()(b'ABC') self.assertEqual(rtn, (b'abc', None)) rtn = IS_LOWER()('Ñ') self.assertEqual(rtn, ('ñ', None)) def test_IS_UPPER(self): rtn = IS_UPPER()('abc') self.assertEqual(rtn, ('ABC', None)) rtn = IS_UPPER()(b'abc') self.assertEqual(rtn, (b'ABC', None)) rtn = IS_UPPER()('ñ') self.assertEqual(rtn, ('Ñ', None)) def test_IS_SLUG(self): rtn = IS_SLUG()('abc123') self.assertEqual(rtn, ('abc123', None)) rtn = IS_SLUG()('ABC123') self.assertEqual(rtn, ('abc123', None)) rtn = IS_SLUG()('abc-123') self.assertEqual(rtn, ('abc-123', None)) rtn = IS_SLUG()('abc--123') self.assertEqual(rtn, ('abc-123', None)) rtn = IS_SLUG()('abc 123') self.assertEqual(rtn, ('abc-123', None)) rtn = IS_SLUG()('abc\t_123') self.assertEqual(rtn, ('abc-123', None)) rtn = IS_SLUG()('-abc-') self.assertEqual(rtn, ('abc', None)) rtn = IS_SLUG()('--a--b--_ -c--') self.assertEqual(rtn, ('a-b-c', None)) rtn = IS_SLUG()('abc&123') self.assertEqual(rtn, ('abc123', None)) rtn = IS_SLUG()('abc&123&def') self.assertEqual(rtn, ('abc123def', None)) rtn = IS_SLUG()('ñ') self.assertEqual(rtn, ('n', None)) rtn = IS_SLUG(maxlen=4)('abc123') self.assertEqual(rtn, ('abc1', None)) rtn = IS_SLUG()('abc_123') self.assertEqual(rtn, ('abc-123', None)) rtn = IS_SLUG(keep_underscores=False)('abc_123') self.assertEqual(rtn, ('abc-123', None)) rtn = IS_SLUG(keep_underscores=True)('abc_123') self.assertEqual(rtn, ('abc_123', None)) rtn = IS_SLUG(check=False)('abc') self.assertEqual(rtn, ('abc', None)) rtn = IS_SLUG(check=True)('abc') self.assertEqual(rtn, ('abc', None)) rtn = IS_SLUG(check=False)('a bc') self.assertEqual(rtn, ('a-bc', None)) rtn = IS_SLUG(check=True)('a bc') self.assertEqual(rtn, ('a bc', 'Must be slug')) def test_ANY_OF(self): rtn = ANY_OF([IS_EMAIL(), IS_ALPHANUMERIC()])('a@b.co') self.assertEqual(rtn, ('a@b.co', None)) rtn = ANY_OF([IS_EMAIL(), IS_ALPHANUMERIC()])('abco') self.assertEqual(rtn, ('abco', None)) rtn = ANY_OF([IS_EMAIL(), IS_ALPHANUMERIC()])('@ab.co') self.assertEqual(rtn, ('@ab.co', 'Enter only letters, numbers, and underscore')) rtn = ANY_OF([IS_ALPHANUMERIC(), IS_EMAIL()])('@ab.co') self.assertEqual(rtn, ('@ab.co', 'Enter a valid email address')) rtn = ANY_OF([IS_DATE(), IS_EMAIL()])('a@b.co') self.assertEqual(rtn, ('a@b.co', None)) rtn = ANY_OF([IS_DATE(), IS_EMAIL()])('1982-12-14') self.assertEqual(rtn, (datetime.date(1982, 12, 14), None)) rtn = ANY_OF([IS_DATE(format='%m/%d/%Y'), IS_EMAIL()]).formatter(datetime.date(1834, 12, 14)) self.assertEqual(rtn, '12/14/1834') def test_IS_EMPTY_OR(self): rtn = IS_EMPTY_OR(IS_EMAIL())('abc@def.com') self.assertEqual(rtn, ('abc@def.com', None)) rtn = IS_EMPTY_OR(IS_EMAIL())(' ') self.assertEqual(rtn, (None, None)) rtn = IS_EMPTY_OR(IS_EMAIL(), null='abc')(' ') self.assertEqual(rtn, ('abc', None)) rtn = IS_EMPTY_OR(IS_EMAIL(), null='abc', empty_regex='def')('def') self.assertEqual(rtn, ('abc', None)) rtn = IS_EMPTY_OR(IS_EMAIL())('abc') self.assertEqual(rtn, ('abc', 'Enter a valid email address')) rtn = IS_EMPTY_OR(IS_EMAIL())(' abc ') self.assertEqual(rtn, (' abc ', 'Enter a valid email address')) rtn = IS_EMPTY_OR(IS_IN_SET([('id1', 'first label'), ('id2', 'second label')], zero='zero')).options(zero=False) self.assertEqual(rtn, [('', ''), ('id1', 'first label'), ('id2', 'second label')]) rtn = IS_EMPTY_OR(IS_IN_SET([('id1', 'first label'), ('id2', 'second label')], zero='zero')).options() self.assertEqual(rtn, [('', 'zero'), ('id1', 'first label'), ('id2', 'second label')]) rtn = IS_EMPTY_OR((IS_LOWER(), IS_EMAIL()))('AAA') self.assertEqual(rtn, ('aaa', 'Enter a valid email address')) rtn = IS_EMPTY_OR([IS_LOWER(), IS_EMAIL()])('AAA') self.assertEqual(rtn, ('aaa', 'Enter a valid email address')) def test_CLEANUP(self): rtn = CLEANUP()('helloò') self.assertEqual(rtn, ('hello', None)) def test_CRYPT(self): rtn = str(CRYPT(digest_alg='md5', salt=True)('test')[0]) self.myassertRegex(rtn, r'^md5\$.{16}\$.{32}$') rtn = str(CRYPT(digest_alg='sha1', salt=True)('test')[0]) self.myassertRegex(rtn, r'^sha1\$.{16}\$.{40}$') rtn = str(CRYPT(digest_alg='sha256', salt=True)('test')[0]) self.myassertRegex(rtn, r'^sha256\$.{16}\$.{64}$') rtn = str(CRYPT(digest_alg='sha384', salt=True)('test')[0]) self.myassertRegex(rtn, r'^sha384\$.{16}\$.{96}$') rtn = str(CRYPT(digest_alg='sha512', salt=True)('test')[0]) self.myassertRegex(rtn, r'^sha512\$.{16}\$.{128}$') alg = 'pbkdf2(1000,20,sha512)' rtn = str(CRYPT(digest_alg=alg, salt=True)('test')[0]) self.myassertRegex(rtn, r'^pbkdf2\(1000,20,sha512\)\$.{16}\$.{40}$') rtn = str(CRYPT(digest_alg='md5', key='mykey', salt=True)('test')[0]) self.myassertRegex(rtn, r'^md5\$.{16}\$.{32}$') a = str(CRYPT(digest_alg='sha1', salt=False)('test')[0]) self.assertEqual(CRYPT(digest_alg='sha1', salt=False)('test')[0], a) self.assertEqual(CRYPT(digest_alg='sha1', salt=False)('test')[0], a[6:]) self.assertEqual(CRYPT(digest_alg='md5', salt=False)('test')[0], a) self.assertEqual(CRYPT(digest_alg='md5', salt=False)('test')[0], a[6:]) def test_IS_STRONG(self): rtn = IS_STRONG(es=True)('Abcd1234') self.assertEqual(rtn, ('Abcd1234', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|')) rtn = IS_STRONG(es=True)('Abcd1234!') self.assertEqual(rtn, ('Abcd1234!', None)) rtn = IS_STRONG(es=True, entropy=1)('a') self.assertEqual(rtn, ('a', None)) rtn = IS_STRONG(es=True, entropy=1, min=2)('a') self.assertEqual(rtn, ('a', 'Minimum length is 2')) rtn = IS_STRONG(es=True, entropy=100)('abc123') self.assertEqual(rtn, ('abc123', 'Entropy (32.35) less than required (100)')) rtn = IS_STRONG(es=True, entropy=100)('and') self.assertEqual(rtn, ('and', 'Entropy (14.57) less than required (100)')) rtn = IS_STRONG(es=True, entropy=100)('aaa') self.assertEqual(rtn, ('aaa', 'Entropy (14.42) less than required (100)')) rtn = IS_STRONG(es=True, entropy=100)('a1d') self.assertEqual(rtn, ('a1d', 'Entropy (15.97) less than required (100)')) rtn = IS_STRONG(es=True, entropy=100)('añd') if PY2: self.assertEqual(rtn, ('a\xc3\xb1d', 'Entropy (18.13) less than required (100)')) else: self.assertEqual(rtn, ('añd', 'Entropy (18.13) less than required (100)')) rtn = IS_STRONG()('********') self.assertEqual(rtn, ('********', None)) rtn = IS_STRONG(es=True, max=4)('abcde') self.assertEqual(rtn, ('abcde', '|'.join(['Minimum length is 8', 'Maximum length is 4', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|', 'Must include at least 1 uppercase', 'Must include at least 1 number'])) ) rtn = IS_STRONG(es=True)('abcde') self.assertEqual(rtn, ('abcde', '|'.join(['Minimum length is 8', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|', 'Must include at least 1 uppercase', 'Must include at least 1 number'])) ) rtn = IS_STRONG(upper=0, lower=0, number=0, es=True)('Abcde1') self.assertEqual(rtn, ('Abcde1', '|'.join(['Minimum length is 8', 'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|', 'May not include any uppercase letters', 'May not include any lowercase letters', 'May not include any numbers'])) ) def test_IS_IMAGE(self): class DummyImageFile(object): def __init__(self, filename, ext, width, height): from io import BytesIO import struct self.filename = filename + '.' + ext self.file = BytesIO() if ext == 'bmp': self.file.write(b'BM') self.file.write(b' ' * 16) self.file.write(struct.pack('