fix tests

Change-Id: I53e9143121a6d01dbd1733f6fcd71fe1a9a9e3e3
Reviewed-on: https://forge.frm2.tum.de/review/16260
Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
Enrico Faulhaber 2017-09-18 12:00:29 +02:00
parent ee5f749aad
commit 0c63522eab
2 changed files with 106 additions and 118 deletions

View File

@ -23,7 +23,6 @@
from .errors import ProgrammingError
from collections import OrderedDict
# Only export these classes for 'from secop.datatypes import *'
__all__ = [
@ -44,16 +43,16 @@ class DataType(object):
def validate(self, value):
"""validate a external representation and return an internal one"""
raise NotImplemented
raise NotImplementedError
def export(self, value):
"""returns a python object fit for external serialisation or logging"""
raise NotImplemented
raise NotImplementedError
def from_string(self, text):
"""interprets a given string and returns a validated (internal) value"""
# to evaluate values from configfiles, etc...
raise NotImplemented
raise NotImplementedError
# goodie: if called, validate
def __call__(self, value):
@ -63,15 +62,15 @@ class DataType(object):
class FloatRange(DataType):
"""Restricted float type"""
def __init__(self, min=None, max=None):
self.min = None if min is None else float(min)
self.max = None if max is None else float(max)
def __init__(self, minval=None, maxval=None):
self.min = None if minval is None else float(minval)
self.max = None if maxval is None else float(maxval)
# note: as we may compare to Inf all comparisons would be false
if (self.min or float('-inf')) <= (self.max or float('+inf')):
if min is None and max is None:
if minval is None and maxval is None:
self.as_json = ['double']
else:
self.as_json = ['double', min, max]
self.as_json = ['double', minval, maxval]
else:
raise ValueError('Max must be larger then min!')
@ -113,9 +112,9 @@ class FloatRange(DataType):
class IntRange(DataType):
"""Restricted int type"""
def __init__(self, min=None, max=None):
self.min = int(min) if min is not None else min
self.max = int(max) if max is not None else max
def __init__(self, minval=None, maxval=None):
self.min = int(minval) if minval is not None else minval
self.max = int(maxval) if maxval is not None else maxval
if self.min is not None and self.max is not None and self.min > self.max:
raise ValueError('Max must be larger then min!')
if self.min is None and self.max is None:
@ -210,29 +209,28 @@ class EnumType(DataType):
class BLOBType(DataType):
minsize = None
maxsize = None
def __init__(self, maxsize=None, minsize=0):
def __init__(self, minsize=0, maxsize=None):
# if only one arg is given it is maxsize!
if maxsize is None and minsize:
maxsize = minsize
minsize = 0
if maxsize is None:
raise ValueError('BLOBType needs a maximum number of Bytes count!')
minsize, maxsize = min(minsize, maxsize), max(minsize, maxsize)
self.minsize = minsize
self.maxsize = maxsize
if minsize < 0:
raise ValueError('sizes must be bigger than or equal to 0!')
if minsize:
self.as_json = ['blob', maxsize, minsize]
elif maxsize:
self.as_json = ['blob', maxsize]
else:
self.as_json = ['blob']
if minsize is not None and maxsize is not None and minsize > maxsize:
raise ValueError('maxsize must be bigger than minsize!')
self.as_json = ['blob', maxsize]
def __repr__(self):
if self.maxsize:
return 'BLOB(%s, %s)' % (str(self.minsize), str(self.maxsize))
if self.minsize:
return 'BLOB(%d)' % self.minsize
return 'BLOB()'
return 'BLOB(%s, %s)' % (
str(self.minsize) if self.minsize else 'unspecified',
str(self.maxsize) if self.maxsize else 'unspecified')
return 'BLOB(%s)' % (str(self.minsize) if self.minsize else 'unspecified')
def validate(self, value):
"""return the validated (internal) value or raise"""
@ -259,29 +257,28 @@ class BLOBType(DataType):
class StringType(DataType):
as_json = ['string']
minsize = None
maxsize = None
def __init__(self, minsize=0, maxsize=None):
# if only one arg is given it is maxsize!
if maxsize is None and minsize:
maxsize = minsize
minsize = 0
self.as_json = ['string', maxsize]
elif maxsize or minsize:
def __init__(self, maxsize=None, minsize=0):
if maxsize is None:
raise ValueError('StringType needs a maximum bytes count!')
minsize, maxsize = min(minsize, maxsize), max(minsize, maxsize)
if minsize < 0:
raise ValueError('sizes must be >= 0')
if minsize:
self.as_json = ['string', maxsize, minsize]
else:
self.as_json = ['string']
self.as_json = ['string', maxsize]
self.minsize = minsize
self.maxsize = maxsize
if minsize is not None and maxsize is not None and minsize > maxsize:
raise ValueError('maxsize must be bigger than minsize!')
def __repr__(self):
if self.maxsize:
return 'StringType(%s, %s)' % (
str(self.minsize), str(self.maxsize))
if self.minsize:
return 'StringType(%d)' % str(self.minsize)
return 'StringType()'
return 'StringType(%s, %s)' % (
str(self.minsize) or 'unspecified', str(self.maxsize) or 'unspecified')
return 'StringType(%d)' % str(self.maxsize)
def validate(self, value):
"""return the validated (internal) value or raise"""
@ -339,36 +336,32 @@ class BoolType(DataType):
class ArrayOf(DataType):
def __init__(self, subtype, minsize=0, maxsize=None):
minsize = None
maxsize = None
def __init__(self, subtype, maxsize=None, minsize=0):
self.subtype = subtype
if not isinstance(subtype, DataType):
raise ValueError(
'ArrayOf only works with DataType objs as first argument!')
if maxsize is None:
raise ValueError('ArrayOf needs a maximum size')
minsize, maxsize = min(minsize, maxsize), max(minsize, maxsize)
if minsize < 0:
raise ValueError('sizes must be > 0')
if maxsize < 1:
raise ValueError('Maximum size must be >= 1!')
# if only one arg is given, it is maxsize!
if minsize and not maxsize:
maxsize = minsize
minsize = 0
self.as_json = ['array', subtype.as_json, maxsize]
elif maxsize:
if minsize:
self.as_json = ['array', subtype.as_json, maxsize, minsize]
else:
self.as_json = ['array', subtype.as_json]
self.minsize = minsize or 0
self.as_json = ['array', subtype.as_json, maxsize]
self.minsize = minsize
self.maxsize = maxsize
self.subtype = subtype
if self.maxsize is not None and self.minsize > maxsize:
raise ValueError('minsize must be less than or equal to maxsize!')
if self.minsize < 0:
raise ValueError('Minimum size must be >= 0!')
if self.maxsize is not None and self.maxsize < 1:
raise ValueError('Maximum size must be >= 1!')
if self.maxsize is not None and self.minsize > self.maxsize:
raise ValueError('Maximum size must be >= Minimum size')
def __repr__(self):
return 'ArrayOf(%s, %s, %s)' % (
repr(self.subtype), self.minsize, self.maxsize)
repr(self.subtype), self.minsize or 'unspecified', self.maxsize or 'unspecified')
def validate(self, value):
"""validate a external representation to an internal one"""
@ -391,7 +384,8 @@ class ArrayOf(DataType):
return [self.subtype.export(elem) for elem in value]
def from_string(self, text):
value = eval(text) # XXX: !!!
# XXX: parse differntly than using eval!
value = eval(text) # pylint: disable=W0123
return self.validate(value)
@ -429,7 +423,8 @@ class TupleOf(DataType):
return [sub.export(elem) for sub, elem in zip(self.subtypes, value)]
def from_string(self, text):
value = eval(text) # XXX: !!!
# XXX: parse differntly than using eval!
value = eval(text) # pylint: disable=W0123
return self.validate(tuple(value))
@ -476,7 +471,8 @@ class StructOf(DataType):
for k, v in value.items())
def from_string(self, text):
value = eval(text) # XXX: !!!
# XXX: parse differntly than using eval!
value = eval(text) # pylint: disable=W0123
return self.validate(dict(value))
@ -484,8 +480,8 @@ class StructOf(DataType):
class Command(DataType):
IS_COMMAND = True
def __init__(self, argtypes=[], resulttype=None):
for arg in argsin:
def __init__(self, argtypes=tuple(), resulttype=None):
for arg in argtypes:
if not isinstance(arg, DataType):
raise ValueError('Command: Argument types must be DataTypes!')
if resulttype is not None:
@ -537,15 +533,12 @@ class Command(DataType):
# XXX: derive from above classes automagically!
DATATYPES = dict(
bool=lambda: BoolType(),
bool=BoolType,
int=lambda _min=None, _max=None: IntRange(_min, _max),
double=lambda _min=None, _max=None: FloatRange(_min, _max),
blob=lambda _max=None, _min=None: BLOBType(
_min, _max) if _min else BLOBType(_max),
string=lambda _max=None, _min=None: StringType(
_min, _max) if _min else StringType(_max),
array=lambda subtype, _max=None, _min=None: ArrayOf(
get_datatype(subtype), _min, _max) if _min else ArrayOf(getdatatype(subtype), _min),
blob=lambda _max=None, _min=0: BLOBType(_max, _min),
string=lambda _max=None, _min=0: StringType(_max, _min),
array=lambda subtype, _max=None, _min=0: ArrayOf(get_datatype(subtype), _max, _min),
tuple=lambda subtypes: TupleOf(*map(get_datatype, subtypes)),
enum=lambda kwds: EnumType(**kwds),
struct=lambda named_subtypes: StructOf(
@ -567,12 +560,6 @@ def get_datatype(json):
if json is None:
return json
if not isinstance(json, list):
import mlzlog
if mlzlog.log is None:
mlzlog.initLogging('xxxxxxxxx')
mlzlog.getLogger('datatypes').warning(
"WARNING: invalid datatype specified! trying fallback mechanism. ymmv!")
return get_datatype([json])
raise ValueError(
'Can not interpret datatype %r, it should be a list!', json)
if len(json) < 1:
@ -588,6 +575,6 @@ def get_datatype(json):
args = json[1:]
try:
return DATATYPES[base](*args)
except (TypeError, AttributeError) as exc:
except (TypeError, AttributeError):
raise ValueError('Invalid datatype descriptor in %r', json)
raise ValueError('can not convert %r to datatype', json)

View File

@ -21,11 +21,12 @@
# *****************************************************************************
"""test data types."""
import sys
sys.path.insert(0, sys.path[0] + '/..')
# no fixtures needed
import pytest
import sys
sys.path.insert(0, sys.path[0] + '/..')
from secop.datatypes import DataType, FloatRange, IntRange, \
EnumType, BLOBType, StringType, BoolType, ArrayOf, TupleOf, StructOf, \
@ -36,10 +37,10 @@ def test_DataType():
dt = DataType()
assert dt.as_json == ['undefined']
with pytest.raises(TypeError):
with pytest.raises(NotImplementedError):
dt = DataType()
dt.validate('')
dt.export()
dt.export('')
def test_FloatRange():
@ -119,8 +120,8 @@ def test_EnumType():
def test_BLOBType():
# test constructor catching illegal arguments
dt = BLOBType()
assert dt.as_json == ['blob']
with pytest.raises(ValueError):
dt = BLOBType()
dt = BLOBType(10)
assert dt.as_json == ['blob', 10]
@ -144,8 +145,8 @@ def test_BLOBType():
def test_StringType():
# test constructor catching illegal arguments
dt = StringType()
assert dt.as_json == ['string']
with pytest.raises(ValueError):
dt = StringType()
dt = StringType(12)
assert dt.as_json == ['string', 12]
@ -179,21 +180,21 @@ def test_BoolType():
with pytest.raises(ValueError):
dt.validate('av')
assert dt.validate('true') == True
assert dt.validate('off') == False
assert dt.validate(1) == True
assert dt.validate('true') is True
assert dt.validate('off') is False
assert dt.validate(1) is True
assert dt.export('false') == False
assert dt.export(0) == False
assert dt.export('on') == True
assert dt.export('false') is False
assert dt.export(0) is False
assert dt.export('on') is True
def test_ArrayOf():
# test constructor catching illegal arguments
with pytest.raises(ValueError):
ArrayOf(int)
dt = ArrayOf(IntRange(-10, 10))
assert dt.as_json == ['array', ['int', -10, 10]]
with pytest.raises(ValueError):
ArrayOf(IntRange(-10,10))
dt = ArrayOf(IntRange(-10, 10), 5)
assert dt.as_json == ['array', ['int', -10, 10], 5]
@ -230,12 +231,12 @@ def test_TupleOf():
def test_StructOf():
# test constructor catching illegal arguments
with pytest.raises(TypeError):
StructOf(IntRange)
StructOf(IntRange) # pylint: disable=E1121
with pytest.raises(ProgrammingError):
StructOf(IntRange=1)
dt = StructOf(a_string=StringType(), an_int=IntRange(0, 999))
assert dt.as_json == ['struct', {'a_string': ['string'],
dt = StructOf(a_string=StringType(55), an_int=IntRange(0, 999))
assert dt.as_json == ['struct', {'a_string': ['string', 55],
'an_int': ['int', 0, 999],
}]
@ -295,18 +296,18 @@ def test_get_datatype():
with pytest.raises(ValueError):
get_datatype(['enum', [1, 2, 3]])
assert isinstance(get_datatype(['blob']), BLOBType)
assert isinstance(get_datatype(['blob', 1]), BLOBType)
assert isinstance(get_datatype(['blob', 1, 10]), BLOBType)
assert isinstance(get_datatype(['blob', 10, 1]), BLOBType)
with pytest.raises(ValueError):
get_datatype(['blob', 10, -10])
with pytest.raises(ValueError):
get_datatype(['blob', 10, -10, 1])
assert isinstance(get_datatype(['string']), StringType)
with pytest.raises(ValueError):
get_datatype(['string'])
assert isinstance(get_datatype(['string', 1]), StringType)
assert isinstance(get_datatype(['string', 1, 10]), StringType)
assert isinstance(get_datatype(['string', 10, 1]), StringType)
with pytest.raises(ValueError):
get_datatype(['string', 10, -10])
@ -319,15 +320,15 @@ def test_get_datatype():
get_datatype(['array', 1])
with pytest.raises(ValueError):
get_datatype(['array', [1], 2, 3])
assert isinstance(get_datatype(['array', ['blob']]), ArrayOf)
assert isinstance(get_datatype(['array', ['blob']]).subtype, BLOBType)
assert isinstance(get_datatype(['array', ['blob', 1], 1]), ArrayOf)
assert isinstance(get_datatype(['array', ['blob', 1], 1]).subtype, BLOBType)
with pytest.raises(ValueError):
get_datatype(['array', ['blob'], -10])
get_datatype(['array', ['blob', 1], -10])
with pytest.raises(ValueError):
get_datatype(['array', ['blob'], -10, 10])
get_datatype(['array', ['blob', 1], 10, -10])
assert isinstance(get_datatype(['array', ['blob'], 1, 10]), ArrayOf)
assert isinstance(get_datatype(['array', ['blob', 1], 10, 1]), ArrayOf)
with pytest.raises(ValueError):
get_datatype(['tuple'])
@ -335,16 +336,16 @@ def test_get_datatype():
get_datatype(['tuple', 1])
with pytest.raises(ValueError):
get_datatype(['tuple', [1], 2, 3])
assert isinstance(get_datatype(['tuple', [['blob']]]), TupleOf)
assert isinstance(get_datatype(['tuple', [['blob', 1]]]), TupleOf)
assert isinstance(get_datatype(
['tuple', [['blob']]]).subtypes[0], BLOBType)
['tuple', [['blob', 1]]]).subtypes[0], BLOBType)
with pytest.raises(ValueError):
get_datatype(['tuple', [['blob']], -10])
get_datatype(['tuple', [['blob', 1]], -10])
with pytest.raises(ValueError):
get_datatype(['tuple', [['blob']], -10, 10])
get_datatype(['tuple', [['blob', 1]], 10, -10])
assert isinstance(get_datatype(['tuple', [['blob'], ['int']]]), TupleOf)
assert isinstance(get_datatype(['tuple', [['blob', 1], ['int']]]), TupleOf)
with pytest.raises(ValueError):
get_datatype(['struct'])
@ -352,14 +353,14 @@ def test_get_datatype():
get_datatype(['struct', 1])
with pytest.raises(ValueError):
get_datatype(['struct', [1], 2, 3])
assert isinstance(get_datatype(['struct', {'blob': ['blob']}]), StructOf)
assert isinstance(get_datatype(['struct', {'blob': ['blob', 1]}]), StructOf)
assert isinstance(get_datatype(
['struct', {'blob': ['blob']}]).named_subtypes['blob'], BLOBType)
['struct', {'blob': ['blob', 1]}]).named_subtypes['blob'], BLOBType)
with pytest.raises(ValueError):
get_datatype(['struct', [['blob']], -10])
get_datatype(['struct', [['blob', 1]], -10])
with pytest.raises(ValueError):
get_datatype(['struct', [['blob']], -10, 10])
get_datatype(['struct', [['blob', 1]], 10, -10])
assert isinstance(get_datatype(
['struct', {'blob': ['blob'], 'int':['int']}]), StructOf)
['struct', {'blob': ['blob', 1], 'int':['int']}]), StructOf)