validatos no longer depend on T
This commit is contained in:
+8
-4
@@ -24,8 +24,9 @@ from gluon.template import parse_template
|
|||||||
from gluon.restricted import restricted, compile2
|
from gluon.restricted import restricted, compile2
|
||||||
from gluon.fileutils import mktree, listdir, read_file, write_file
|
from gluon.fileutils import mktree, listdir, read_file, write_file
|
||||||
from gluon.myregex import regex_expose, regex_longcomments
|
from gluon.myregex import regex_expose, regex_longcomments
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.dal import DAL, Field
|
from gluon.dal import DAL, Field
|
||||||
|
from gluon.validators import Validator
|
||||||
from pydal.base import BaseAdapter
|
from pydal.base import BaseAdapter
|
||||||
from gluon.sqlhtml import SQLFORM, SQLTABLE
|
from gluon.sqlhtml import SQLFORM, SQLTABLE
|
||||||
from gluon.cache import Cache
|
from gluon.cache import Cache
|
||||||
@@ -423,16 +424,19 @@ def build_environment(request, response, session, store_current=True):
|
|||||||
r'^%s/%s/\w+\.py$' % (request.controller, request.function)
|
r'^%s/%s/\w+\.py$' % (request.controller, request.function)
|
||||||
]
|
]
|
||||||
|
|
||||||
t = environment['T'] = translator(os.path.join(request.folder, 'languages'),
|
T = environment['T'] = TranslatorFactory(os.path.join(request.folder, 'languages'),
|
||||||
request.env.http_accept_language)
|
request.env.http_accept_language)
|
||||||
c = environment['cache'] = Cache(request)
|
c = environment['cache'] = Cache(request)
|
||||||
|
|
||||||
|
# configure the validator to use the t translator
|
||||||
|
Validator.translator = T
|
||||||
|
|
||||||
if store_current:
|
if store_current:
|
||||||
current.globalenv = environment
|
current.globalenv = environment
|
||||||
current.request = request
|
current.request = request
|
||||||
current.response = response
|
current.response = response
|
||||||
current.session = session
|
current.session = session
|
||||||
current.T = t
|
current.T = T
|
||||||
current.cache = c
|
current.cache = c
|
||||||
|
|
||||||
if is_jython: # jython hack
|
if is_jython: # jython hack
|
||||||
|
|||||||
+3
-3
@@ -457,7 +457,7 @@ def pickle_lazyT(c):
|
|||||||
copyreg.pickle(lazyT, pickle_lazyT)
|
copyreg.pickle(lazyT, pickle_lazyT)
|
||||||
|
|
||||||
|
|
||||||
class translator(object):
|
class TranslatorFactory(object):
|
||||||
"""
|
"""
|
||||||
This class is instantiated by gluon.compileapp.build_environment
|
This class is instantiated by gluon.compileapp.build_environment
|
||||||
as the T object
|
as the T object
|
||||||
@@ -742,8 +742,8 @@ class translator(object):
|
|||||||
try:
|
try:
|
||||||
otherT = self.otherTs[index]
|
otherT = self.otherTs[index]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
otherT = self.otherTs[index] = translator(self.langpath,
|
otherT = self.otherTs[index] = TranslatorFactory(self.langpath,
|
||||||
self.http_accept_language)
|
self.http_accept_language)
|
||||||
if language:
|
if language:
|
||||||
otherT.force(language)
|
otherT.force(language)
|
||||||
return otherT
|
return otherT
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import unittest
|
|||||||
|
|
||||||
|
|
||||||
from gluon.compileapp import run_controller_in, run_view_in, compile_application, remove_compiled_application
|
from gluon.compileapp import run_controller_in, run_view_in, compile_application, remove_compiled_application
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.storage import Storage, List
|
from gluon.storage import Storage, List
|
||||||
from gluon import fileutils
|
from gluon import fileutils
|
||||||
from gluon.dal import DAL, Field, Table
|
from gluon.dal import DAL, Field, Table
|
||||||
@@ -50,7 +50,7 @@ class TestAppAdmin(unittest.TestCase):
|
|||||||
request.env.remote_addr = '127.0.0.1'
|
request.env.remote_addr = '127.0.0.1'
|
||||||
response = Response()
|
response = Response()
|
||||||
session = Session()
|
session = Session()
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
session.connect(request, response)
|
session.connect(request, response)
|
||||||
current.request = request
|
current.request = request
|
||||||
current.response = response
|
current.response = response
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.dal import DAL, Field
|
from gluon.dal import DAL, Field
|
||||||
from gluon.authapi import AuthAPI
|
from gluon.authapi import AuthAPI
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
@@ -24,7 +24,7 @@ class TestAuthAPI(unittest.TestCase):
|
|||||||
self.request.folder = 'applications/admin'
|
self.request.folder = 'applications/admin'
|
||||||
self.response = Response()
|
self.response = Response()
|
||||||
self.session = Session()
|
self.session = Session()
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
self.session.connect(self.request, self.response)
|
self.session.connect(self.request, self.response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
self.current = current
|
self.current = current
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class TestCache(unittest.TestCase):
|
|||||||
s = Storage({'application': 'admin',
|
s = Storage({'application': 'admin',
|
||||||
'folder': 'applications/admin'})
|
'folder': 'applications/admin'})
|
||||||
cache = Cache(s)
|
cache = Cache(s)
|
||||||
db = DAL(check_reserved=['all'])
|
db = DAL('sqlite:memory', check_reserved=['all'])
|
||||||
db.define_table('t_a', Field('f_a'))
|
db.define_table('t_a', Field('f_a'))
|
||||||
db.t_a.insert(f_a='test')
|
db.t_a.insert(f_a='test')
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class TestDALSubclass(unittest.TestCase):
|
|||||||
|
|
||||||
def testSerialization(self):
|
def testSerialization(self):
|
||||||
from gluon._compat import pickle
|
from gluon._compat import pickle
|
||||||
db = DAL(check_reserved=['all'])
|
db = DAL('sqlite:memory', check_reserved=['all'])
|
||||||
db.define_table('t_a', Field('f_a'))
|
db.define_table('t_a', Field('f_a'))
|
||||||
db.t_a.insert(f_a='test')
|
db.t_a.insert(f_a='test')
|
||||||
a = db(db.t_a.id > 0).select(cacheable=True)
|
a = db(db.t_a.id > 0).select(cacheable=True)
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class TestTranslations(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_plain(self):
|
def test_plain(self):
|
||||||
T = languages.translator(self.langpath, self.http_accept_language)
|
T = languages.TranslatorFactory(self.langpath, self.http_accept_language)
|
||||||
self.assertEqual(str(T('Hello World')),
|
self.assertEqual(str(T('Hello World')),
|
||||||
'Hello World')
|
'Hello World')
|
||||||
self.assertEqual(str(T('Hello World## comment')),
|
self.assertEqual(str(T('Hello World## comment')),
|
||||||
@@ -340,7 +340,7 @@ class TestMessages(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_decode(self):
|
def test_decode(self):
|
||||||
T = languages.translator(self.langpath, self.http_accept_language)
|
T = languages.TranslatorFactory(self.langpath, self.http_accept_language)
|
||||||
messages = Messages(T)
|
messages = Messages(T)
|
||||||
messages.update({'email_sent':'Email sent', 'test': "ä"})
|
messages.update({'email_sent':'Email sent', 'test': "ä"})
|
||||||
self.assertEqual(to_unicode(messages.email_sent, 'utf-8'), 'Email sent')
|
self.assertEqual(to_unicode(messages.email_sent, 'utf-8'), 'Email sent')
|
||||||
@@ -359,7 +359,7 @@ class TestHTMLTag(unittest.TestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def test_decode(self):
|
def test_decode(self):
|
||||||
T = languages.translator(self.langpath, self.http_accept_language)
|
T = languages.TranslatorFactory(self.langpath, self.http_accept_language)
|
||||||
elem = SPAN(T("Complete"))
|
elem = SPAN(T("Complete"))
|
||||||
self.assertEqual(elem.flatten(), "Complete")
|
self.assertEqual(elem.flatten(), "Complete")
|
||||||
elem = SPAN(T("Cannot be empty", language="ru"))
|
elem = SPAN(T("Cannot be empty", language="ru"))
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import datetime
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.scheduler import JobGraph, Scheduler, CronParser
|
from gluon.scheduler import JobGraph, Scheduler, CronParser
|
||||||
from gluon.dal import DAL
|
from gluon.dal import DAL
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ class BaseTestScheduler(unittest.TestCase):
|
|||||||
'folder': 'applications/welcome',
|
'folder': 'applications/welcome',
|
||||||
'controller': 'default'})
|
'controller': 'default'})
|
||||||
current.request = s
|
current.request = s
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
current.T = T
|
current.T = T
|
||||||
self.db = DAL('sqlite://dummy2.db', check_reserved=['all'])
|
self.db = DAL('sqlite://dummy2.db', check_reserved=['all'])
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import decimal
|
|||||||
from gluon.serializers import *
|
from gluon.serializers import *
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
# careful with the import path 'cause of isinstance() checks
|
# careful with the import path 'cause of isinstance() checks
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.html import SPAN
|
from gluon.html import SPAN
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ class TestSerializers(unittest.TestCase):
|
|||||||
obj = {'a': decimal.Decimal('4.312312312312')}
|
obj = {'a': decimal.Decimal('4.312312312312')}
|
||||||
self.assertEqual(json(obj), u'{"a": "4.312312312312"}')
|
self.assertEqual(json(obj), u'{"a": "4.312312312312"}')
|
||||||
# lazyT translated
|
# lazyT translated
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
lazy_translation = T('abc')
|
lazy_translation = T('abc')
|
||||||
self.assertEqual(json(lazy_translation), u'"abc"')
|
self.assertEqual(json(lazy_translation), u'"abc"')
|
||||||
# html helpers are xml()ed before too
|
# html helpers are xml()ed before too
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from pydal.objects import Table
|
|||||||
from gluon.tools import Auth, Mail
|
from gluon.tools import Auth, Mail
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.http import HTTP
|
from gluon.http import HTTP
|
||||||
from gluon.validators import *
|
from gluon.validators import *
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ class TestSQLFORM(unittest.TestCase):
|
|||||||
request.folder = 'applications/admin'
|
request.folder = 'applications/admin'
|
||||||
response = Response()
|
response = Response()
|
||||||
session = Session()
|
session = Session()
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
session.connect(request, response)
|
session.connect(request, response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
current.request = request
|
current.request = request
|
||||||
@@ -355,7 +355,7 @@ class TestSQLTABLE(unittest.TestCase):
|
|||||||
request.folder = 'applications/admin'
|
request.folder = 'applications/admin'
|
||||||
response = Response()
|
response = Response()
|
||||||
session = Session()
|
session = Session()
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
session.connect(request, response)
|
session.connect(request, response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
current.request = request
|
current.request = request
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from gluon.tools import Auth, Mail, Recaptcha2, prettydate, Expose
|
|||||||
from gluon._compat import PY2, to_bytes
|
from gluon._compat import PY2, to_bytes
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon.languages import translator
|
from gluon.languages import TranslatorFactory
|
||||||
from gluon.http import HTTP
|
from gluon.http import HTTP
|
||||||
from gluon import SPAN, H3, TABLE, TR, TD, A, URL, current
|
from gluon import SPAN, H3, TABLE, TR, TD, A, URL, current
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ class TestAuthJWT(unittest.TestCase):
|
|||||||
# request.folder = 'applications/admin'
|
# request.folder = 'applications/admin'
|
||||||
# response = Response()
|
# response = Response()
|
||||||
# session = Session()
|
# session = Session()
|
||||||
# T = translator('', 'en')
|
# T = TranslatorFactory('', 'en')
|
||||||
# session.connect(request, response)
|
# session.connect(request, response)
|
||||||
# from gluon.globals import current
|
# from gluon.globals import current
|
||||||
# current.request = request
|
# current.request = request
|
||||||
@@ -434,7 +434,7 @@ class TestAuthJWT(unittest.TestCase):
|
|||||||
# # request.folder = 'applications/admin'
|
# # request.folder = 'applications/admin'
|
||||||
# # response = Response()
|
# # response = Response()
|
||||||
# # session = Session()
|
# # session = Session()
|
||||||
# # T = translator('', 'en')
|
# # T = TranslatorFactory('', 'en')
|
||||||
# # session.connect(request, response)
|
# # session.connect(request, response)
|
||||||
# # from gluon.globals import current
|
# # from gluon.globals import current
|
||||||
# # current.request = request
|
# # current.request = request
|
||||||
@@ -495,7 +495,7 @@ class TestAuth(unittest.TestCase):
|
|||||||
self.request.folder = 'applications/admin'
|
self.request.folder = 'applications/admin'
|
||||||
self.response = Response()
|
self.response = Response()
|
||||||
self.session = Session()
|
self.session = Session()
|
||||||
T = translator('', 'en')
|
T = TranslatorFactory('', 'en')
|
||||||
self.session.connect(self.request, self.response)
|
self.session.connect(self.request, self.response)
|
||||||
from gluon.globals import current
|
from gluon.globals import current
|
||||||
self.current = current
|
self.current = current
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ class TestValidators(unittest.TestCase):
|
|||||||
|
|
||||||
def test_MISC(self):
|
def test_MISC(self):
|
||||||
""" Test miscelaneous utility functions and some general behavior guarantees """
|
""" Test miscelaneous utility functions and some general behavior guarantees """
|
||||||
from gluon.validators import translate, options_sorter, Validator, UTC
|
from gluon.validators import 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(('A', 'A'), ('a', 'a')), -1)
|
self.assertEqual(options_sorter(('A', 'A'), ('a', 'a')), -1)
|
||||||
self.assertEqual(options_sorter(('b', 'b'), ('a', 'a')), 1)
|
self.assertEqual(options_sorter(('b', 'b'), ('a', 'a')), 1)
|
||||||
|
|||||||
+97
-101
@@ -12,6 +12,7 @@ Validators
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import math
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
import cgi
|
import cgi
|
||||||
@@ -19,17 +20,19 @@ import json
|
|||||||
import struct
|
import struct
|
||||||
import decimal
|
import decimal
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
import encodings.idna
|
||||||
|
|
||||||
from gluon._compat import StringIO, integer_types, basestring, unicodeT, urllib_unquote, unichr, to_bytes, PY2, \
|
from pydal._compat import StringIO, integer_types, basestring, unicodeT, urllib_unquote, \
|
||||||
to_unicode, to_native, string_types, urlparse
|
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, Table
|
||||||
from pydal.objects import Field, FieldVirtual, FieldMethod
|
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
|
from gluon.utils import simple_hash, web2py_uuid, DIGEST_ALG_BY_SIZE
|
||||||
|
from gluon._compat import ipaddress
|
||||||
|
|
||||||
regex_isint = re.compile('^[+-]?\d+$')
|
regex_isint = re.compile('^[+-]?\d+$')
|
||||||
|
|
||||||
JSONErrors = (NameError, TypeError, ValueError, AttributeError,
|
JSONErrors = (NameError, TypeError, ValueError, AttributeError, KeyError)
|
||||||
KeyError)
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'ANY_OF',
|
'ANY_OF',
|
||||||
@@ -70,25 +73,19 @@ __all__ = [
|
|||||||
'IS_JSON',
|
'IS_JSON',
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
|
||||||
from gluon.globals import current
|
|
||||||
have_current = True
|
|
||||||
except ImportError:
|
|
||||||
have_current = False
|
|
||||||
|
|
||||||
|
|
||||||
def translate(text):
|
|
||||||
if text is None:
|
|
||||||
return None
|
|
||||||
elif isinstance(text, (str, unicodeT)) and have_current:
|
|
||||||
if hasattr(current, 'T'):
|
|
||||||
return str(current.T(text))
|
|
||||||
return str(text)
|
|
||||||
|
|
||||||
|
|
||||||
def options_sorter(x, y):
|
def options_sorter(x, y):
|
||||||
return (str(x[1]).upper() > str(y[1]).upper() and 1) or -1
|
return (str(x[1]).upper() > str(y[1]).upper() and 1) or -1
|
||||||
|
|
||||||
|
def translator(text):
|
||||||
|
if text is None:
|
||||||
|
return None
|
||||||
|
text = Validator.translator(text)
|
||||||
|
return str(text)
|
||||||
|
|
||||||
|
class ValidationError(Exception):
|
||||||
|
|
||||||
|
def __init__(self, error):
|
||||||
|
self.error = error
|
||||||
|
|
||||||
class Validator(object):
|
class Validator(object):
|
||||||
"""
|
"""
|
||||||
@@ -128,6 +125,8 @@ class Validator(object):
|
|||||||
Notice that default error messages are not translated.
|
Notice that default error messages are not translated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
translator = staticmethod(lambda text: text)
|
||||||
|
|
||||||
def formatter(self, value):
|
def formatter(self, value):
|
||||||
"""
|
"""
|
||||||
For some validators returns a formatted version (matching the validator)
|
For some validators returns a formatted version (matching the validator)
|
||||||
@@ -135,9 +134,15 @@ class Validator(object):
|
|||||||
"""
|
"""
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def __call__(self, value):
|
def validate(self, value):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
try:
|
||||||
|
return self.validate(value), None
|
||||||
|
except ValidationError as e:
|
||||||
|
return value, e.message
|
||||||
|
|
||||||
|
|
||||||
class IS_MATCH(Validator):
|
class IS_MATCH(Validator):
|
||||||
"""
|
"""
|
||||||
@@ -210,7 +215,7 @@ class IS_MATCH(Validator):
|
|||||||
match = self.regex.search(value.encode('utf8'))
|
match = self.regex.search(value.encode('utf8'))
|
||||||
if match is not None:
|
if match is not None:
|
||||||
return (self.extract and match.group() or value, None)
|
return (self.extract and match.group() or value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_EQUAL_TO(Validator):
|
class IS_EQUAL_TO(Validator):
|
||||||
@@ -239,7 +244,7 @@ class IS_EQUAL_TO(Validator):
|
|||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
if value == self.expression:
|
if value == self.expression:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_EXPR(Validator):
|
class IS_EXPR(Validator):
|
||||||
@@ -273,7 +278,7 @@ class IS_EXPR(Validator):
|
|||||||
exec('__ret__=' + self.expression, self.environment)
|
exec('__ret__=' + self.expression, self.environment)
|
||||||
if self.environment['__ret__']:
|
if self.environment['__ret__']:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_LENGTH(Validator):
|
class IS_LENGTH(Validator):
|
||||||
@@ -352,8 +357,8 @@ class IS_LENGTH(Validator):
|
|||||||
return (value, None)
|
return (value, None)
|
||||||
elif self.minsize <= len(str(value)) <= self.maxsize:
|
elif self.minsize <= len(str(value)) <= self.maxsize:
|
||||||
return (str(value), None)
|
return (str(value), None)
|
||||||
return (value, translate(self.error_message)
|
return (value, translator(self.error_message) %
|
||||||
% dict(min=self.minsize, max=self.maxsize))
|
dict(min=self.minsize, max=self.maxsize))
|
||||||
|
|
||||||
|
|
||||||
class IS_JSON(Validator):
|
class IS_JSON(Validator):
|
||||||
@@ -383,7 +388,7 @@ class IS_JSON(Validator):
|
|||||||
else:
|
else:
|
||||||
return (json.loads(value), None)
|
return (json.loads(value), None)
|
||||||
except JSONErrors:
|
except JSONErrors:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
def formatter(self, value):
|
def formatter(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -473,11 +478,11 @@ class IS_IN_SET(Validator):
|
|||||||
thestrset = [str(x) for x in self.theset]
|
thestrset = [str(x) for x in self.theset]
|
||||||
failures = [x for x in values if not str(x) in thestrset]
|
failures = [x for x in values if not str(x) in thestrset]
|
||||||
if failures and self.theset:
|
if failures and self.theset:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
if self.multiple:
|
if self.multiple:
|
||||||
if isinstance(self.multiple, (tuple, list)) and \
|
if isinstance(self.multiple, (tuple, list)) and \
|
||||||
not self.multiple[0] <= len(values) < self.multiple[1]:
|
not self.multiple[0] <= len(values) < self.multiple[1]:
|
||||||
return (values, translate(self.error_message))
|
return (values, translator(self.error_message))
|
||||||
return (values, None)
|
return (values, None)
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
@@ -515,7 +520,6 @@ class IS_IN_DB(Validator):
|
|||||||
delimiter=None,
|
delimiter=None,
|
||||||
auto_add=False,
|
auto_add=False,
|
||||||
):
|
):
|
||||||
from pydal.objects import Table
|
|
||||||
if hasattr(dbset, 'define_table'):
|
if hasattr(dbset, 'define_table'):
|
||||||
self.dbset = dbset()
|
self.dbset = dbset()
|
||||||
else:
|
else:
|
||||||
@@ -636,13 +640,13 @@ class IS_IN_DB(Validator):
|
|||||||
if self.auto_add:
|
if self.auto_add:
|
||||||
value = str(self.maybe_add(table, self.fieldnames[0], value))
|
value = str(self.maybe_add(table, self.fieldnames[0], value))
|
||||||
else:
|
else:
|
||||||
return (values, translate(self.error_message))
|
return (values, translator(self.error_message))
|
||||||
new_values.append(value)
|
new_values.append(value)
|
||||||
values = new_values
|
values = new_values
|
||||||
|
|
||||||
if isinstance(self.multiple, (tuple, list)) and \
|
if isinstance(self.multiple, (tuple, list)) and \
|
||||||
not self.multiple[0] <= len(values) < self.multiple[1]:
|
not self.multiple[0] <= len(values) < self.multiple[1]:
|
||||||
return (values, translate(self.error_message))
|
return (values, translator(self.error_message))
|
||||||
if self.theset:
|
if self.theset:
|
||||||
if not [v for v in values if v not in self.theset]:
|
if not [v for v in values if v not in self.theset]:
|
||||||
return (values, None)
|
return (values, None)
|
||||||
@@ -664,12 +668,12 @@ class IS_IN_DB(Validator):
|
|||||||
elif self.auto_add:
|
elif self.auto_add:
|
||||||
value = self.maybe_add(table, self.fieldnames[0], value)
|
value = self.maybe_add(table, self.fieldnames[0], value)
|
||||||
else:
|
else:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
if self.theset:
|
if self.theset:
|
||||||
if str(value) in self.theset:
|
if str(value) in self.theset:
|
||||||
@@ -683,7 +687,7 @@ class IS_IN_DB(Validator):
|
|||||||
return self._and(value)
|
return self._and(value)
|
||||||
else:
|
else:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_NOT_IN_DB(Validator):
|
class IS_NOT_IN_DB(Validator):
|
||||||
@@ -704,8 +708,6 @@ class IS_NOT_IN_DB(Validator):
|
|||||||
allowed_override=[],
|
allowed_override=[],
|
||||||
ignore_common_filters=False,
|
ignore_common_filters=False,
|
||||||
):
|
):
|
||||||
|
|
||||||
from pydal.objects import Table
|
|
||||||
if isinstance(field, Table):
|
if isinstance(field, Table):
|
||||||
field = field._id
|
field = field._id
|
||||||
|
|
||||||
@@ -725,7 +727,7 @@ class IS_NOT_IN_DB(Validator):
|
|||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
value = to_native(str(value))
|
value = to_native(str(value))
|
||||||
if not value.strip():
|
if not value.strip():
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
if value in self.allowed_override:
|
if value in self.allowed_override:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
(tablename, fieldname) = str(self.field).split('.')
|
(tablename, fieldname) = str(self.field).split('.')
|
||||||
@@ -738,11 +740,11 @@ class IS_NOT_IN_DB(Validator):
|
|||||||
fields = [table[f] for f in id]
|
fields = [table[f] for f in id]
|
||||||
row = subset.select(*fields, **dict(limitby=(0, 1), orderby_on_limitby=False)).first()
|
row = subset.select(*fields, **dict(limitby=(0, 1), orderby_on_limitby=False)).first()
|
||||||
if row and any(str(row[f]) != str(id[f]) for f in id):
|
if row and any(str(row[f]) != str(id[f]) for f in id):
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
else:
|
else:
|
||||||
row = subset.select(table._id, field, limitby=(0, 1), orderby_on_limitby=False).first()
|
row = subset.select(table._id, field, limitby=(0, 1), orderby_on_limitby=False).first()
|
||||||
if row and str(row[table._id]) != str(id):
|
if row and str(row[table._id]) != str(id):
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
|
|
||||||
@@ -758,7 +760,7 @@ def range_error_message(error_message, what_to_enter, minimum, maximum):
|
|||||||
error_message += ' less than or equal to %(max)g'
|
error_message += ' less than or equal to %(max)g'
|
||||||
if type(maximum) in integer_types:
|
if type(maximum) in integer_types:
|
||||||
maximum -= 1
|
maximum -= 1
|
||||||
return translate(error_message) % dict(min=minimum, max=maximum)
|
return translator(error_message) % dict(min=minimum, max=maximum)
|
||||||
|
|
||||||
|
|
||||||
class IS_INT_IN_RANGE(Validator):
|
class IS_INT_IN_RANGE(Validator):
|
||||||
@@ -1043,7 +1045,7 @@ class IS_NOT_EMPTY(Validator):
|
|||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
value, empty = is_empty(value, empty_regex=self.empty_regex)
|
value, empty = is_empty(value, empty_regex=self.empty_regex)
|
||||||
if empty:
|
if empty:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
|
|
||||||
@@ -1199,7 +1201,7 @@ class IS_EMAIL(Validator):
|
|||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
if not(isinstance(value, (basestring, unicodeT))) or not value or '@' not in value:
|
if not(isinstance(value, (basestring, unicodeT))) or not value or '@' not in value:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
body, domain = value.rsplit('@', 1)
|
body, domain = value.rsplit('@', 1)
|
||||||
|
|
||||||
@@ -1222,7 +1224,7 @@ class IS_EMAIL(Validator):
|
|||||||
if (not self.banned or not self.banned.match(domain)) \
|
if (not self.banned or not self.banned.match(domain)) \
|
||||||
and (not self.forced or self.forced.match(domain)):
|
and (not self.forced or self.forced.match(domain)):
|
||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_LIST_OF_EMAILS(object):
|
class IS_LIST_OF_EMAILS(object):
|
||||||
@@ -1253,7 +1255,7 @@ class IS_LIST_OF_EMAILS(object):
|
|||||||
return (value, None)
|
return (value, None)
|
||||||
else:
|
else:
|
||||||
return (value,
|
return (value,
|
||||||
translate(self.error_message) % ', '.join(bad_emails))
|
translator(self.error_message) % ', '.join(bad_emails))
|
||||||
|
|
||||||
def formatter(self, value, row=None):
|
def formatter(self, value, row=None):
|
||||||
return ', '.join(value or [])
|
return ', '.join(value or [])
|
||||||
@@ -1456,7 +1458,6 @@ def unicode_to_ascii_authority(authority):
|
|||||||
# We use the ToASCII operation because we are about to put the authority
|
# We use the ToASCII operation because we are about to put the authority
|
||||||
# into an IDN-unaware slot
|
# into an IDN-unaware slot
|
||||||
asciiLabels = []
|
asciiLabels = []
|
||||||
import encodings.idna
|
|
||||||
for label in labels:
|
for label in labels:
|
||||||
if label:
|
if label:
|
||||||
asciiLabels.append(to_native(encodings.idna.ToASCII(label)))
|
asciiLabels.append(to_native(encodings.idna.ToASCII(label)))
|
||||||
@@ -1613,7 +1614,7 @@ class IS_GENERIC_URL(Validator):
|
|||||||
# if we dont have anything or the URL misuses the '%' character
|
# if we dont have anything or the URL misuses the '%' character
|
||||||
|
|
||||||
if not value or self.GENERIC_URL.search(value):
|
if not value or self.GENERIC_URL.search(value):
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
if '#' in value:
|
if '#' in value:
|
||||||
url, fragment_part = value.split('#')
|
url, fragment_part = value.split('#')
|
||||||
@@ -1625,7 +1626,7 @@ class IS_GENERIC_URL(Validator):
|
|||||||
try:
|
try:
|
||||||
components = urlparse.urlparse(urllib_unquote(value))._asdict()
|
components = urlparse.urlparse(urllib_unquote(value))._asdict()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
# Clean up the scheme before we check it
|
# Clean up the scheme before we check it
|
||||||
scheme = components['scheme']
|
scheme = components['scheme']
|
||||||
@@ -1653,7 +1654,7 @@ class IS_GENERIC_URL(Validator):
|
|||||||
else:
|
else:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
# else the URL is not valid
|
# else the URL is not valid
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
# Sources (obtained 2017-Nov-11):
|
# Sources (obtained 2017-Nov-11):
|
||||||
# http://data.iana.org/TLD/tlds-alpha-by-domain.txt
|
# http://data.iana.org/TLD/tlds-alpha-by-domain.txt
|
||||||
@@ -2089,7 +2090,7 @@ class IS_HTTP_URL(Validator):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
# else the HTTP URL is not valid
|
# else the HTTP URL is not valid
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_URL(Validator):
|
class IS_URL(Validator):
|
||||||
@@ -2239,7 +2240,7 @@ class IS_URL(Validator):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If we are not able to convert the unicode url into a
|
# If we are not able to convert the unicode url into a
|
||||||
# US-ASCII URL, then the URL is not valid
|
# US-ASCII URL, then the URL is not valid
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
methodResult = subMethod(asciiValue)
|
methodResult = subMethod(asciiValue)
|
||||||
# if the validation of the US-ASCII version of the value failed
|
# if the validation of the US-ASCII version of the value failed
|
||||||
if not methodResult[1] is None:
|
if not methodResult[1] is None:
|
||||||
@@ -2321,7 +2322,7 @@ class IS_TIME(Validator):
|
|||||||
pass
|
pass
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
return (ivalue, translate(self.error_message))
|
return (ivalue, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
# A UTC class.
|
# A UTC class.
|
||||||
@@ -2352,7 +2353,7 @@ class IS_DATE(Validator):
|
|||||||
|
|
||||||
def __init__(self, format='%Y-%m-%d',
|
def __init__(self, format='%Y-%m-%d',
|
||||||
error_message='Enter date as %(format)s'):
|
error_message='Enter date as %(format)s'):
|
||||||
self.format = translate(format)
|
self.format = translator(format)
|
||||||
self.error_message = str(error_message)
|
self.error_message = str(error_message)
|
||||||
self.extremes = {}
|
self.extremes = {}
|
||||||
|
|
||||||
@@ -2367,7 +2368,7 @@ class IS_DATE(Validator):
|
|||||||
return (value, None)
|
return (value, None)
|
||||||
except:
|
except:
|
||||||
self.extremes.update(IS_DATETIME.nice(self.format))
|
self.extremes.update(IS_DATETIME.nice(self.format))
|
||||||
return (ovalue, translate(self.error_message) % self.extremes)
|
return (ovalue, translator(self.error_message) % self.extremes)
|
||||||
|
|
||||||
def formatter(self, value):
|
def formatter(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -2416,7 +2417,7 @@ class IS_DATETIME(Validator):
|
|||||||
def __init__(self, format='%Y-%m-%d %H:%M:%S',
|
def __init__(self, format='%Y-%m-%d %H:%M:%S',
|
||||||
error_message='Enter date and time as %(format)s',
|
error_message='Enter date and time as %(format)s',
|
||||||
timezone=None):
|
timezone=None):
|
||||||
self.format = translate(format)
|
self.format = translator(format)
|
||||||
self.error_message = str(error_message)
|
self.error_message = str(error_message)
|
||||||
self.extremes = {}
|
self.extremes = {}
|
||||||
self.timezone = timezone
|
self.timezone = timezone
|
||||||
@@ -2435,7 +2436,7 @@ class IS_DATETIME(Validator):
|
|||||||
return (value, None)
|
return (value, None)
|
||||||
except:
|
except:
|
||||||
self.extremes.update(IS_DATETIME.nice(self.format))
|
self.extremes.update(IS_DATETIME.nice(self.format))
|
||||||
return (ovalue, translate(self.error_message) % self.extremes)
|
return (ovalue, translator(self.error_message) % self.extremes)
|
||||||
|
|
||||||
def formatter(self, value):
|
def formatter(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -2503,9 +2504,9 @@ class IS_DATE_IN_RANGE(IS_DATE):
|
|||||||
if msg is not None:
|
if msg is not None:
|
||||||
return (value, msg)
|
return (value, msg)
|
||||||
if self.minimum and self.minimum > value:
|
if self.minimum and self.minimum > value:
|
||||||
return (ovalue, translate(self.error_message) % self.extremes)
|
return (ovalue, translator(self.error_message) % self.extremes)
|
||||||
if self.maximum and value > self.maximum:
|
if self.maximum and value > self.maximum:
|
||||||
return (ovalue, translate(self.error_message) % self.extremes)
|
return (ovalue, translator(self.error_message) % self.extremes)
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
|
|
||||||
@@ -2559,9 +2560,9 @@ class IS_DATETIME_IN_RANGE(IS_DATETIME):
|
|||||||
if msg is not None:
|
if msg is not None:
|
||||||
return (value, msg)
|
return (value, msg)
|
||||||
if self.minimum and self.minimum > value:
|
if self.minimum and self.minimum > value:
|
||||||
return (ovalue, translate(self.error_message) % self.extremes)
|
return (ovalue, translator(self.error_message) % self.extremes)
|
||||||
if self.maximum and value > self.maximum:
|
if self.maximum and value > self.maximum:
|
||||||
return (ovalue, translate(self.error_message) % self.extremes)
|
return (ovalue, translator(self.error_message) % self.extremes)
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
|
|
||||||
@@ -2579,11 +2580,11 @@ class IS_LIST_OF(Validator):
|
|||||||
ivalue = [ivalue]
|
ivalue = [ivalue]
|
||||||
ivalue = [i for i in ivalue if str(i).strip()]
|
ivalue = [i for i in ivalue if str(i).strip()]
|
||||||
if self.minimum is not None and len(ivalue) < self.minimum:
|
if self.minimum is not None and len(ivalue) < self.minimum:
|
||||||
return (ivalue, translate(self.error_message or
|
return (ivalue, translator(self.error_message or 'Minimum length is %(min)s') %
|
||||||
'Minimum length is %(min)s') % dict(min=self.minimum, max=self.maximum))
|
dict(min=self.minimum, max=self.maximum))
|
||||||
if self.maximum is not None and len(ivalue) > self.maximum:
|
if self.maximum is not None and len(ivalue) > self.maximum:
|
||||||
return (ivalue, translate(self.error_message or
|
return (ivalue, translator(self.error_message or 'Maximum length is %(max)s') %
|
||||||
'Maximum length is %(max)s') % dict(min=self.minimum, max=self.maximum))
|
dict(min=self.minimum, max=self.maximum))
|
||||||
new_value = []
|
new_value = []
|
||||||
other = self.other
|
other = self.other
|
||||||
if self.other:
|
if self.other:
|
||||||
@@ -2721,7 +2722,7 @@ class IS_SLUG(Validator):
|
|||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
if self.check and value != urlify(value, self.maxlen, self.keep_underscores):
|
if self.check and value != urlify(value, self.maxlen, self.keep_underscores):
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
return (urlify(value, self.maxlen, self.keep_underscores), None)
|
return (urlify(value, self.maxlen, self.keep_underscores), None)
|
||||||
|
|
||||||
|
|
||||||
@@ -2750,7 +2751,7 @@ class ANY_OF(Validator):
|
|||||||
if error is None:
|
if error is None:
|
||||||
break
|
break
|
||||||
if error is not None and self.error_message is not None:
|
if error is not None and self.error_message is not None:
|
||||||
error = translate(self.error_message)
|
error = translator(self.error_message)
|
||||||
return value, error
|
return value, error
|
||||||
|
|
||||||
def formatter(self, value):
|
def formatter(self, value):
|
||||||
@@ -3038,7 +3039,7 @@ class CRYPT(object):
|
|||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
v = value and str(value)[:self.max_length]
|
v = value and str(value)[:self.max_length]
|
||||||
if not v or len(v) < self.min_length:
|
if not v or len(v) < self.min_length:
|
||||||
return ('', translate(self.error_message))
|
return ('', translator(self.error_message))
|
||||||
if isinstance(value, LazyCrypt):
|
if isinstance(value, LazyCrypt):
|
||||||
return (value, None)
|
return (value, None)
|
||||||
return (LazyCrypt(self, value), None)
|
return (LazyCrypt(self, value), None)
|
||||||
@@ -3056,7 +3057,6 @@ otherset = frozenset(
|
|||||||
|
|
||||||
def calc_entropy(string):
|
def calc_entropy(string):
|
||||||
""" calculates a simple entropy for a given string """
|
""" calculates a simple entropy for a given string """
|
||||||
import math
|
|
||||||
alphabet = 0 # alphabet size
|
alphabet = 0 # alphabet size
|
||||||
other = set()
|
other = set()
|
||||||
seen = set()
|
seen = set()
|
||||||
@@ -3149,49 +3149,49 @@ class IS_STRONG(object):
|
|||||||
if self.entropy is not None:
|
if self.entropy is not None:
|
||||||
entropy = calc_entropy(value)
|
entropy = calc_entropy(value)
|
||||||
if entropy < self.entropy:
|
if entropy < self.entropy:
|
||||||
failures.append(translate("Entropy (%(have)s) less than required (%(need)s)")
|
failures.append(translator("Entropy (%(have)s) less than required (%(need)s)")
|
||||||
% dict(have=entropy, need=self.entropy))
|
% dict(have=entropy, need=self.entropy))
|
||||||
if isinstance(self.min, int) and self.min > 0:
|
if isinstance(self.min, int) and self.min > 0:
|
||||||
if not len(value) >= self.min:
|
if not len(value) >= self.min:
|
||||||
failures.append(translate("Minimum length is %s") % self.min)
|
failures.append(translator("Minimum length is %s") % self.min)
|
||||||
if isinstance(self.max, int) and self.max > 0:
|
if isinstance(self.max, int) and self.max > 0:
|
||||||
if not len(value) <= self.max:
|
if not len(value) <= self.max:
|
||||||
failures.append(translate("Maximum length is %s") % self.max)
|
failures.append(translator("Maximum length is %s") % self.max)
|
||||||
if isinstance(self.special, int):
|
if isinstance(self.special, int):
|
||||||
all_special = [ch in value for ch in self.specials]
|
all_special = [ch in value for ch in self.specials]
|
||||||
if self.special > 0:
|
if self.special > 0:
|
||||||
if not all_special.count(True) >= self.special:
|
if not all_special.count(True) >= self.special:
|
||||||
failures.append(translate("Must include at least %s of the following: %s")
|
failures.append(translator("Must include at least %s of the following: %s")
|
||||||
% (self.special, self.specials))
|
% (self.special, self.specials))
|
||||||
elif self.special is 0:
|
elif self.special is 0:
|
||||||
if len(all_special) > 0:
|
if len(all_special) > 0:
|
||||||
failures.append(translate("May not contain any of the following: %s")
|
failures.append(translator("May not contain any of the following: %s")
|
||||||
% self.specials)
|
% self.specials)
|
||||||
if self.invalid:
|
if self.invalid:
|
||||||
all_invalid = [ch in value for ch in self.invalid]
|
all_invalid = [ch in value for ch in self.invalid]
|
||||||
if all_invalid.count(True) > 0:
|
if all_invalid.count(True) > 0:
|
||||||
failures.append(translate("May not contain any of the following: %s")
|
failures.append(translator("May not contain any of the following: %s")
|
||||||
% self.invalid)
|
% self.invalid)
|
||||||
if isinstance(self.upper, int):
|
if isinstance(self.upper, int):
|
||||||
all_upper = re.findall("[A-Z]", value)
|
all_upper = re.findall("[A-Z]", value)
|
||||||
if self.upper > 0:
|
if self.upper > 0:
|
||||||
if not len(all_upper) >= self.upper:
|
if not len(all_upper) >= self.upper:
|
||||||
failures.append(translate("Must include at least %s uppercase")
|
failures.append(translator("Must include at least %s uppercase")
|
||||||
% str(self.upper))
|
% str(self.upper))
|
||||||
elif self.upper is 0:
|
elif self.upper is 0:
|
||||||
if len(all_upper) > 0:
|
if len(all_upper) > 0:
|
||||||
failures.append(
|
failures.append(
|
||||||
translate("May not include any uppercase letters"))
|
translator("May not include any uppercase letters"))
|
||||||
if isinstance(self.lower, int):
|
if isinstance(self.lower, int):
|
||||||
all_lower = re.findall("[a-z]", value)
|
all_lower = re.findall("[a-z]", value)
|
||||||
if self.lower > 0:
|
if self.lower > 0:
|
||||||
if not len(all_lower) >= self.lower:
|
if not len(all_lower) >= self.lower:
|
||||||
failures.append(translate("Must include at least %s lowercase")
|
failures.append(translator("Must include at least %s lowercase")
|
||||||
% str(self.lower))
|
% str(self.lower))
|
||||||
elif self.lower is 0:
|
elif self.lower is 0:
|
||||||
if len(all_lower) > 0:
|
if len(all_lower) > 0:
|
||||||
failures.append(
|
failures.append(
|
||||||
translate("May not include any lowercase letters"))
|
translator("May not include any lowercase letters"))
|
||||||
if isinstance(self.number, int):
|
if isinstance(self.number, int):
|
||||||
all_number = re.findall("[0-9]", value)
|
all_number = re.findall("[0-9]", value)
|
||||||
if self.number > 0:
|
if self.number > 0:
|
||||||
@@ -3199,20 +3199,19 @@ class IS_STRONG(object):
|
|||||||
if self.number > 1:
|
if self.number > 1:
|
||||||
numbers = "numbers"
|
numbers = "numbers"
|
||||||
if not len(all_number) >= self.number:
|
if not len(all_number) >= self.number:
|
||||||
failures.append(translate("Must include at least %s %s")
|
failures.append(translator("Must include at least %s %s")
|
||||||
% (str(self.number), numbers))
|
% (str(self.number), numbers))
|
||||||
elif self.number is 0:
|
elif self.number is 0:
|
||||||
if len(all_number) > 0:
|
if len(all_number) > 0:
|
||||||
failures.append(translate("May not include any numbers"))
|
failures.append(translator("May not include any numbers"))
|
||||||
if len(failures) == 0:
|
if len(failures) == 0:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
if not self.error_message:
|
if not self.error_message:
|
||||||
if self.estring:
|
if self.estring:
|
||||||
return (value, '|'.join(failures))
|
return (value, '|'.join(map(str, failures)))
|
||||||
from gluon.html import XML
|
return (value, ', '.join(failures))
|
||||||
return (value, XML('<br />'.join(failures)))
|
|
||||||
else:
|
else:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_IMAGE(Validator):
|
class IS_IMAGE(Validator):
|
||||||
@@ -3304,7 +3303,7 @@ class IS_IMAGE(Validator):
|
|||||||
value.file.seek(0)
|
value.file.seek(0)
|
||||||
return (value, None)
|
return (value, None)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
def __bmp(self, stream):
|
def __bmp(self, stream):
|
||||||
if stream.read(2) == b'BM':
|
if stream.read(2) == b'BM':
|
||||||
@@ -3397,7 +3396,7 @@ class IS_UPLOAD_FILENAME(Validator):
|
|||||||
try:
|
try:
|
||||||
string = value.filename
|
string = value.filename
|
||||||
except:
|
except:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
if self.case == 1:
|
if self.case == 1:
|
||||||
string = string.lower()
|
string = string.lower()
|
||||||
elif self.case == 2:
|
elif self.case == 2:
|
||||||
@@ -3409,9 +3408,9 @@ class IS_UPLOAD_FILENAME(Validator):
|
|||||||
if dot == -1:
|
if dot == -1:
|
||||||
dot = len(string)
|
dot = len(string)
|
||||||
if self.filename and not self.filename.match(string[:dot]):
|
if self.filename and not self.filename.match(string[:dot]):
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
elif self.extension and not self.extension.match(string[dot + 1:]):
|
elif self.extension and not self.extension.match(string[dot + 1:]):
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
else:
|
else:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
@@ -3581,7 +3580,7 @@ class IS_IPV4(Validator):
|
|||||||
ok = False
|
ok = False
|
||||||
if ok:
|
if ok:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_IPV6(Validator):
|
class IS_IPV6(Validator):
|
||||||
@@ -3674,13 +3673,11 @@ class IS_IPV6(Validator):
|
|||||||
self.error_message = error_message
|
self.error_message = error_message
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
from gluon._compat import ipaddress
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ip = ipaddress.IPv6Address(to_unicode(value))
|
ip = ipaddress.IPv6Address(to_unicode(value))
|
||||||
ok = True
|
ok = True
|
||||||
except ipaddress.AddressValueError:
|
except ipaddress.AddressValueError:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
if self.subnets:
|
if self.subnets:
|
||||||
# iterate through self.subnets to see if value is a member
|
# iterate through self.subnets to see if value is a member
|
||||||
@@ -3691,7 +3688,7 @@ class IS_IPV6(Validator):
|
|||||||
try:
|
try:
|
||||||
ipnet = ipaddress.IPv6Network(to_unicode(network))
|
ipnet = ipaddress.IPv6Network(to_unicode(network))
|
||||||
except (ipaddress.NetmaskValueError, ipaddress.AddressValueError):
|
except (ipaddress.NetmaskValueError, ipaddress.AddressValueError):
|
||||||
return (value, translate('invalid subnet provided'))
|
return (value, translator('invalid subnet provided'))
|
||||||
if ip in ipnet:
|
if ip in ipnet:
|
||||||
ok = True
|
ok = True
|
||||||
|
|
||||||
@@ -3722,7 +3719,7 @@ class IS_IPV6(Validator):
|
|||||||
if ok:
|
if ok:
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
|
|
||||||
class IS_IPADDRESS(Validator):
|
class IS_IPADDRESS(Validator):
|
||||||
@@ -3897,7 +3894,6 @@ class IS_IPADDRESS(Validator):
|
|||||||
self.error_message = error_message
|
self.error_message = error_message
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
from gluon._compat import ipaddress
|
|
||||||
IPAddress = ipaddress.ip_address
|
IPAddress = ipaddress.ip_address
|
||||||
IPv6Address = ipaddress.IPv6Address
|
IPv6Address = ipaddress.IPv6Address
|
||||||
IPv4Address = ipaddress.IPv4Address
|
IPv4Address = ipaddress.IPv4Address
|
||||||
@@ -3905,12 +3901,12 @@ class IS_IPADDRESS(Validator):
|
|||||||
try:
|
try:
|
||||||
ip = IPAddress(to_unicode(value))
|
ip = IPAddress(to_unicode(value))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return (value, translate(self.error_message))
|
return (value, translator(self.error_message))
|
||||||
|
|
||||||
if self.is_ipv4 and isinstance(ip, IPv6Address):
|
if self.is_ipv4 and isinstance(ip, IPv6Address):
|
||||||
retval = (value, translate(self.error_message))
|
retval = (value, translator(self.error_message))
|
||||||
elif self.is_ipv6 and isinstance(ip, IPv4Address):
|
elif self.is_ipv6 and isinstance(ip, IPv4Address):
|
||||||
retval = (value, translate(self.error_message))
|
retval = (value, translator(self.error_message))
|
||||||
elif self.is_ipv4 or isinstance(ip, IPv4Address):
|
elif self.is_ipv4 or isinstance(ip, IPv4Address):
|
||||||
retval = IS_IPV4(
|
retval = IS_IPV4(
|
||||||
minip=self.minip,
|
minip=self.minip,
|
||||||
@@ -3934,6 +3930,6 @@ class IS_IPADDRESS(Validator):
|
|||||||
error_message=self.error_message
|
error_message=self.error_message
|
||||||
)(value)
|
)(value)
|
||||||
else:
|
else:
|
||||||
retval = (value, translate(self.error_message))
|
retval = (value, translator(self.error_message))
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
|
|||||||
Reference in New Issue
Block a user