fix validators, updated gluon/contrib/ipaddr
This commit is contained in:
+33
-32
@@ -21,7 +21,7 @@ import urllib
|
||||
import struct
|
||||
import decimal
|
||||
import unicodedata
|
||||
from gluon._compat import StringIO, long, unicodeT, to_unicode, urllib_unquote, unichr, to_bytes
|
||||
from gluon._compat import StringIO, long, unicodeT, to_unicode, urllib_unquote, unichr, to_bytes, PY2, to_unicode, to_native
|
||||
from gluon.utils import simple_hash, web2py_uuid, DIGEST_ALG_BY_SIZE
|
||||
from pydal.objects import Field, FieldVirtual, FieldMethod
|
||||
from functools import reduce
|
||||
@@ -192,10 +192,13 @@ class IS_MATCH(Validator):
|
||||
self.regex = re.compile(expression)
|
||||
self.error_message = error_message
|
||||
self.extract = extract
|
||||
self.is_unicode = is_unicode
|
||||
self.is_unicode = is_unicode or (not(PY2))
|
||||
|
||||
def __call__(self, value):
|
||||
if self.is_unicode:
|
||||
if not(PY2): # PY3 convert bytes to unicode
|
||||
value = to_unicode(value)
|
||||
|
||||
if self.is_unicode or not(PY2):
|
||||
if not isinstance(value, unicodeT):
|
||||
match = self.regex.search(str(value).decode('utf8'))
|
||||
else:
|
||||
@@ -267,7 +270,7 @@ class IS_EXPR(Validator):
|
||||
return (value, self.expression(value))
|
||||
# for backward compatibility
|
||||
self.environment.update(value=value)
|
||||
exec ('__ret__=' + self.expression) in self.environment
|
||||
exec ('__ret__=' + self.expression, self.environment)
|
||||
if self.environment['__ret__']:
|
||||
return (value, None)
|
||||
return (value, translate(self.error_message))
|
||||
@@ -333,7 +336,7 @@ class IS_LENGTH(Validator):
|
||||
return (value, None)
|
||||
elif isinstance(value, str):
|
||||
try:
|
||||
lvalue = len(value.decode('utf8'))
|
||||
lvalue = len(to_unicode(value))
|
||||
except:
|
||||
lvalue = len(value)
|
||||
if self.minsize <= lvalue <= self.maxsize:
|
||||
@@ -341,6 +344,9 @@ class IS_LENGTH(Validator):
|
||||
elif isinstance(value, unicodeT):
|
||||
if self.minsize <= len(value) <= self.maxsize:
|
||||
return (value.encode('utf8'), None)
|
||||
elif isinstance(value, (bytes, bytearray)):
|
||||
if self.minsize <= len(value) <= self.maxsize:
|
||||
return (value, None)
|
||||
elif isinstance(value, (tuple, list)):
|
||||
if self.minsize <= len(value) <= self.maxsize:
|
||||
return (value, None)
|
||||
@@ -448,7 +454,7 @@ class IS_IN_SET(Validator):
|
||||
else:
|
||||
items = [(k, self.labels[i]) for (i, k) in enumerate(self.theset)]
|
||||
if self.sort:
|
||||
items.sort(options_sorter)
|
||||
items.sort(key=lambda o: str(o[1]).upper())
|
||||
if zero and not self.zero is None and not self.multiple:
|
||||
items.insert(0, ('', self.zero))
|
||||
return items
|
||||
@@ -594,7 +600,7 @@ class IS_IN_DB(Validator):
|
||||
self.build_set()
|
||||
items = [(k, self.labels[i]) for (i, k) in enumerate(self.theset)]
|
||||
if self.sort:
|
||||
items.sort(options_sorter)
|
||||
items.sort(key=lambda o: str(o[1]).upper())
|
||||
if zero and self.zero is not None and not self.multiple:
|
||||
items.insert(0, ('', self.zero))
|
||||
return items
|
||||
@@ -717,10 +723,7 @@ class IS_NOT_IN_DB(Validator):
|
||||
self.record_id = id
|
||||
|
||||
def __call__(self, value):
|
||||
if isinstance(value, unicodeT):
|
||||
value = value.encode('utf8')
|
||||
else:
|
||||
value = str(value)
|
||||
value = to_native(str(value))
|
||||
if not value.strip():
|
||||
return (value, translate(self.error_message))
|
||||
if value in self.allowed_override:
|
||||
@@ -1455,7 +1458,7 @@ def unicode_to_ascii_authority(authority):
|
||||
import encodings.idna
|
||||
for label in labels:
|
||||
if label:
|
||||
asciiLabels.append(encodings.idna.ToASCII(label))
|
||||
asciiLabels.append(to_native(encodings.idna.ToASCII(label)))
|
||||
else:
|
||||
# encodings.idna.ToASCII does not accept an empty string, but
|
||||
# it is necessary for us to allow for empty labels so that we
|
||||
@@ -1525,6 +1528,7 @@ def unicode_to_ascii_url(url, prepend_scheme):
|
||||
scheme = str(scheme) + '://'
|
||||
else:
|
||||
scheme = ''
|
||||
|
||||
return scheme + unicode_to_ascii_authority(authority) +\
|
||||
escape_unicode(path) + escape_unicode(query) + str(fragment)
|
||||
|
||||
@@ -2083,7 +2087,6 @@ class IS_URL(Validator):
|
||||
may be modified to (1) prepend a scheme, and/or (2) convert a
|
||||
non-compliant unicode URL into a compliant US-ASCII version.
|
||||
"""
|
||||
|
||||
if self.mode == 'generic':
|
||||
subMethod = IS_GENERIC_URL(error_message=self.error_message,
|
||||
allowed_schemes=self.allowed_schemes,
|
||||
@@ -2101,7 +2104,7 @@ class IS_URL(Validator):
|
||||
else:
|
||||
try:
|
||||
asciiValue = unicode_to_ascii_url(value, self.prepend_scheme)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
# If we are not able to convert the unicode url into a
|
||||
# US-ASCII URL, then the URL is not valid
|
||||
return (value, translate(self.error_message))
|
||||
@@ -2477,7 +2480,7 @@ class IS_LOWER(Validator):
|
||||
"""
|
||||
|
||||
def __call__(self, value):
|
||||
return (value.decode('utf8').lower().encode('utf8'), None)
|
||||
return (to_bytes(to_unicode(value).lower()), None)
|
||||
|
||||
|
||||
class IS_UPPER(Validator):
|
||||
@@ -2492,7 +2495,7 @@ class IS_UPPER(Validator):
|
||||
"""
|
||||
|
||||
def __call__(self, value):
|
||||
return (value.decode('utf8').upper().encode('utf8'), None)
|
||||
return (to_bytes(to_unicode(value).upper()), None)
|
||||
|
||||
|
||||
def urlify(s, maxlen=80, keep_underscores=False):
|
||||
@@ -2501,11 +2504,10 @@ def urlify(s, maxlen=80, keep_underscores=False):
|
||||
if (keep_underscores): underscores are retained in the string
|
||||
else: underscores are translated to hyphens (default)
|
||||
"""
|
||||
if isinstance(s, str):
|
||||
s = s.decode('utf-8') # to unicode
|
||||
s = to_unicode(s) # to unicode
|
||||
s = s.lower() # to lowercase
|
||||
s = unicodedata.normalize('NFKD', s) # replace special characters
|
||||
s = s.encode('ascii', 'ignore') # encode as ASCII
|
||||
s = to_native(s, charset='ascii', errors='ignore') # encode as ASCII
|
||||
s = re.sub('&\w+?;', '', s) # strip html entities
|
||||
if keep_underscores:
|
||||
s = re.sub('\s+', '-', s) # whitespace to hyphens
|
||||
@@ -2912,8 +2914,7 @@ def calc_entropy(string):
|
||||
other = set()
|
||||
seen = set()
|
||||
lastset = None
|
||||
if isinstance(string, str):
|
||||
string = unicode(string, encoding='utf8')
|
||||
string = to_unicode(string)
|
||||
for c in string:
|
||||
# classify this character
|
||||
inset = otherset
|
||||
@@ -3057,7 +3058,7 @@ class IS_STRONG(object):
|
||||
if not self.error_message:
|
||||
if self.estring:
|
||||
return (value, '|'.join(failures))
|
||||
from html import XML
|
||||
from gluon.html import XML
|
||||
return (value, XML('<br />'.join(failures)))
|
||||
else:
|
||||
return (value, translate(self.error_message))
|
||||
@@ -3134,24 +3135,24 @@ class IS_IMAGE(Validator):
|
||||
and self.minsize[1] <= height <= self.maxsize[1]
|
||||
value.file.seek(0)
|
||||
return (value, None)
|
||||
except:
|
||||
except Exception as e:
|
||||
return (value, translate(self.error_message))
|
||||
|
||||
def __bmp(self, stream):
|
||||
if stream.read(2) == 'BM':
|
||||
if stream.read(2) == b'BM':
|
||||
stream.read(16)
|
||||
return struct.unpack("<LL", stream.read(8))
|
||||
return (-1, -1)
|
||||
|
||||
def __gif(self, stream):
|
||||
if stream.read(6) in ('GIF87a', 'GIF89a'):
|
||||
if stream.read(6) in (b'GIF87a', b'GIF89a'):
|
||||
stream = stream.read(5)
|
||||
if len(stream) == 5:
|
||||
return tuple(struct.unpack("<HHB", stream)[:-1])
|
||||
return (-1, -1)
|
||||
|
||||
def __jpeg(self, stream):
|
||||
if stream.read(2) == '\xFF\xD8':
|
||||
if stream.read(2) == b'\xFF\xD8':
|
||||
while True:
|
||||
(marker, code, length) = struct.unpack("!BBH", stream.read(4))
|
||||
if marker != 0xFF:
|
||||
@@ -3164,9 +3165,9 @@ class IS_IMAGE(Validator):
|
||||
return (-1, -1)
|
||||
|
||||
def __png(self, stream):
|
||||
if stream.read(8) == '\211PNG\r\n\032\n':
|
||||
if stream.read(8) == b'\211PNG\r\n\032\n':
|
||||
stream.read(4)
|
||||
if stream.read(4) == "IHDR":
|
||||
if stream.read(4) == b"IHDR":
|
||||
return struct.unpack("!LL", stream.read(8))
|
||||
return (-1, -1)
|
||||
|
||||
@@ -3367,7 +3368,7 @@ class IS_IPV4(Validator):
|
||||
if isinstance(value, str):
|
||||
temp.append(value.split('.'))
|
||||
elif isinstance(value, (list, tuple)):
|
||||
if len(value) == len(filter(lambda item: isinstance(item, int), value)) == 4:
|
||||
if len(value) == len(list(filter(lambda item: isinstance(item, int), value))) == 4:
|
||||
temp.append(value)
|
||||
else:
|
||||
for item in value:
|
||||
@@ -3510,7 +3511,7 @@ class IS_IPV6(Validator):
|
||||
from gluon.contrib import ipaddr as ipaddress
|
||||
|
||||
try:
|
||||
ip = ipaddress.IPv6Address(value.decode('utf-8'))
|
||||
ip = ipaddress.IPv6Address(to_unicode(value))
|
||||
ok = True
|
||||
except ipaddress.AddressValueError:
|
||||
return (value, translate(self.error_message))
|
||||
@@ -3522,7 +3523,7 @@ class IS_IPV6(Validator):
|
||||
self.subnets = [self.subnets]
|
||||
for network in self.subnets:
|
||||
try:
|
||||
ipnet = ipaddress.IPv6Network(network.decode('utf-8'))
|
||||
ipnet = ipaddress.IPv6Network(to_unicode(network))
|
||||
except (ipaddress.NetmaskValueError, ipaddress.AddressValueError):
|
||||
return (value, translate('invalid subnet provided'))
|
||||
if ip in ipnet:
|
||||
@@ -3739,7 +3740,7 @@ class IS_IPADDRESS(Validator):
|
||||
IPv6Address)
|
||||
|
||||
try:
|
||||
ip = IPAddress(value.decode('utf-8'))
|
||||
ip = IPAddress(to_unicode(value))
|
||||
except ValueError:
|
||||
return (value, translate(self.error_message))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user