%PDF- %PDF-
| Direktori : /lib/python3/dist-packages/dnslib/ |
| Current File : //lib/python3/dist-packages/dnslib/ranges.py |
# -*- coding: utf-8 -*-
"""
Wrapper around property builtin to restrict attribute to defined
integer value range (throws ValueError).
Intended to ensure that values packed with struct are in the
correct range
>>> class T(object):
... a = range_property('a',-100,100)
... b = B('b')
... c = H('c')
... d = I('d')
... e = instance_property('e',(int,bool))
>>> t = T()
>>> for i in [0,100,-100]:
... t.a = i
... assert t.a == i
>>> t.a = 101
Traceback (most recent call last):
...
ValueError: Attribute 'a' must be between -100-100 [101]
>>> t.a = -101
Traceback (most recent call last):
...
ValueError: Attribute 'a' must be between -100-100 [-101]
>>> t.a = 'blah'
Traceback (most recent call last):
...
ValueError: Attribute 'a' must be between -100-100 [blah]
>>> t.e = 999
>>> t.e = False
>>> t.e = None
Traceback (most recent call last):
...
ValueError: Attribute 'e' must be instance of ...
>>> check_range("test",123,0,255)
>>> check_range("test",999,0,255)
Traceback (most recent call last):
...
ValueError: Attribute 'test' must be between 0-255 [999]
>>> check_instance("test",123,int)
>>> check_instance("test","xxx",int)
Traceback (most recent call last):
...
ValueError: Attribute 'test' must be instance of ...
"""
import sys
if sys.version < '3':
int_types = (int, long,)
byte_types = (str,bytearray)
else:
int_types = (int,)
byte_types = (bytes,bytearray)
def check_instance(name,val,types):
if not isinstance(val,types):
raise ValueError("Attribute '%s' must be instance of %s [%s]" %
(name,types,type(val)))
def check_bytes(name,val):
return check_instance(name,val,byte_types)
def instance_property(attr,types):
def getter(obj):
return getattr(obj,"_%s" % attr)
def setter(obj,val):
if isinstance(val,types):
setattr(obj,"_%s" % attr,val)
else:
raise ValueError("Attribute '%s' must be instance of %s [%s]" %
(attr,types,type(val)))
return property(getter,setter)
def BYTES(attr):
return instance_property(attr,byte_types)
def check_range(name,val,min,max):
if not (isinstance(val,int_types) and min <= val <= max):
raise ValueError("Attribute '%s' must be between %d-%d [%s]" %
(name,min,max,val))
def range_property(attr,min,max):
def getter(obj):
return getattr(obj,"_%s" % attr)
def setter(obj,val):
if isinstance(val,int_types) and min <= val <= max:
setattr(obj,"_%s" % attr,val)
else:
raise ValueError("Attribute '%s' must be between %d-%d [%s]" %
(attr,min,max,val))
return property(getter,setter)
def B(attr):
"""
Unsigned Byte
"""
return range_property(attr,0,255)
def H(attr):
"""
Unsigned Short
"""
return range_property(attr,0,65535)
def I(attr):
"""
Unsigned Long
"""
return range_property(attr,0,4294967295)
def ntuple_range(attr,n,min,max):
f = lambda x : isinstance(x,int_types) and min <= x <= max
def getter(obj):
return getattr(obj,"_%s" % attr)
def setter(obj,val):
if len(val) != n:
raise ValueError("Attribute '%s' must be tuple with %d elements [%s]" %
(attr,n,val))
if all(map(f,val)):
setattr(obj,"_%s" % attr,val)
else:
raise ValueError("Attribute '%s' elements must be between %d-%d [%s]" %
(attr,min,max,val))
return property(getter,setter)
def IP4(attr):
return ntuple_range(attr,4,0,255)
def IP6(attr):
return ntuple_range(attr,16,0,255)
if __name__ == '__main__':
import doctest,sys
sys.exit(0 if doctest.testmod(optionflags=doctest.ELLIPSIS).failed == 0 else 1)