Add noeval to PYSONDecoder

issue1616
review15071002
This commit is contained in:
Cédric Krier
2015-03-10 23:47:38 +01:00
parent e985252f2d
commit b7776731a6
4 changed files with 84 additions and 34 deletions
+1
View File
@@ -1,3 +1,4 @@
* Add noeval on PYSONDecoder
* Add __repr__ to PYSON
* Remove safe_eval
* Add ModelView.view_attributes
+3 -3
View File
@@ -50,15 +50,15 @@ Instance method:
Returns a string representation of a given PYSON statement.
``object`` contains a PYSON statement.
.. class:: PYSONDecoder()
.. class:: PYSONDecoder([context[, noeval]])
Decoder for string into PYSON statement representation.
Decoder for string into the evaluated or not PYSON statement.
Instance method:
.. method:: PYSONDecoder.decode(object)
Returns a PYSON statement representation of a given string.
Returns a PYSON statement evaluated or not of a given string.
``object`` contains a string.
Statements
+57 -31
View File
@@ -121,24 +121,30 @@ class PYSONEncoder(json.JSONEncoder):
class PYSONDecoder(json.JSONDecoder):
def __init__(self, context=None):
def __init__(self, context=None, noeval=False):
self.__context = context or {}
self.noeval = noeval
super(PYSONDecoder, self).__init__(object_hook=self._object_hook)
def _object_hook(self, dct):
if '__class__' in dct:
klass = globals().get(dct['__class__'])
if klass and hasattr(klass, 'eval'):
return klass.eval(dct, self.__context)
klass = CONTEXT.get(dct['__class__'])
if klass:
if not self.noeval:
return klass.eval(dct, self.__context)
else:
dct = dct.copy()
del dct['__class__']
return klass(**dct)
return dct
class Eval(PYSON):
def __init__(self, value, default=''):
def __init__(self, v, d=''):
super(Eval, self).__init__()
self._value = value
self._default = default
self._value = v
self._default = d
@property
def __repr_params__(self):
@@ -165,13 +171,13 @@ class Eval(PYSON):
class Not(PYSON):
def __init__(self, value):
def __init__(self, v):
super(Not, self).__init__()
if isinstance(value, PYSON):
assert value.types() == set([bool]), 'value must be boolean'
if isinstance(v, PYSON):
assert v.types() == set([bool]), 'value must be boolean'
else:
assert isinstance(value, bool), 'value must be boolean'
self._value = value
assert isinstance(v, bool), 'value must be boolean'
self._value = v
@property
def __repr_params__(self):
@@ -193,9 +199,9 @@ class Not(PYSON):
class Bool(PYSON):
def __init__(self, value):
def __init__(self, v):
super(Bool, self).__init__()
self._value = value
self._value = v
@property
def __repr_params__(self):
@@ -217,8 +223,9 @@ class Bool(PYSON):
class And(PYSON):
def __init__(self, *statements):
def __init__(self, *statements, **kwargs):
super(And, self).__init__()
statements = list(statements) + kwargs.get('s', [])
for statement in statements:
if isinstance(statement, PYSON):
assert statement.types() == set([bool]), \
@@ -227,7 +234,7 @@ class And(PYSON):
assert isinstance(statement, bool), \
'statement must be boolean'
assert len(statements) >= 2, 'must have at least 2 statements'
self._statements = list(statements)
self._statements = statements
@property
def __repr_params__(self):
@@ -261,16 +268,17 @@ class Or(And):
class Equal(PYSON):
def __init__(self, statement1, statement2):
def __init__(self, s1, s2):
statement1, statement2 = s1, s2
super(Equal, self).__init__()
if isinstance(statement1, PYSON):
types1 = statement1.types()
else:
types1 = reduced_type(set([type(statement1)]))
types1 = reduced_type(set([type(s1)]))
if isinstance(statement2, PYSON):
types2 = statement2.types()
else:
types2 = reduced_type(set([type(statement2)]))
types2 = reduced_type(set([type(s2)]))
assert types1 == types2, 'statements must have the same type'
self._statement1 = statement1
self._statement2 = statement2
@@ -296,7 +304,8 @@ class Equal(PYSON):
class Greater(PYSON):
def __init__(self, statement1, statement2, equal=False):
def __init__(self, s1, s2, e=False):
statement1, statement2, equal = s1, s2, e
super(Greater, self).__init__()
for i in (statement1, statement2):
if isinstance(i, PYSON):
@@ -363,7 +372,8 @@ class Less(Greater):
class If(PYSON):
def __init__(self, condition, then_statement, else_statement=None):
def __init__(self, c, t, e=None):
condition, then_statement, else_statement = c, t, e
super(If, self).__init__()
if isinstance(condition, PYSON):
assert condition.types() == set([bool]), \
@@ -413,7 +423,8 @@ class If(PYSON):
class Get(PYSON):
def __init__(self, obj, key, default=''):
def __init__(self, v, k, d=''):
obj, key, default = v, k, d
super(Get, self).__init__()
if isinstance(obj, PYSON):
assert obj.types() == set([dict]), 'obj must be a dict'
@@ -453,7 +464,8 @@ class Get(PYSON):
class In(PYSON):
def __init__(self, key, obj):
def __init__(self, k, v):
key, obj = k, v
super(In, self).__init__()
if isinstance(key, PYSON):
assert key.types().issubset(set([basestring, int])), \
@@ -495,7 +507,13 @@ class In(PYSON):
class Date(PYSON):
def __init__(self, year=None, month=None, day=None,
delta_years=0, delta_months=0, delta_days=0):
delta_years=0, delta_months=0, delta_days=0, **kwargs):
year = kwargs.get('y', year)
month = kwargs.get('M', month)
day = kwargs.get('d', day)
delta_years = kwargs.get('dy', delta_years)
delta_months = kwargs.get('dM', delta_months)
delta_days = kwargs.get('dd', delta_days)
super(Date, self).__init__()
for i in (year, month, day, delta_years, delta_months, delta_days):
if isinstance(i, PYSON):
@@ -548,10 +566,18 @@ class DateTime(Date):
hour=None, minute=None, second=None, microsecond=None,
delta_years=0, delta_months=0, delta_days=0,
delta_hours=0, delta_minutes=0, delta_seconds=0,
delta_microseconds=0):
delta_microseconds=0, **kwargs):
hour = kwargs.get('h', hour)
minute = kwargs.get('m', minute)
second = kwargs.get('s', second)
microsecond = kwargs.get('ms', microsecond)
delta_hours = kwargs.get('dh', delta_hours)
delta_minutes = kwargs.get('dm', delta_minutes)
delta_seconds = kwargs.get('ds', delta_seconds)
delta_microseconds = kwargs.get('dms', delta_microseconds)
super(DateTime, self).__init__(year=year, month=month, day=day,
delta_years=delta_years, delta_months=delta_months,
delta_days=delta_days)
delta_days=delta_days, **kwargs)
for i in (hour, minute, second, microsecond,
delta_hours, delta_minutes, delta_seconds, delta_microseconds):
if isinstance(i, PYSON):
@@ -616,15 +642,15 @@ class DateTime(Date):
class Len(PYSON):
def __init__(self, value):
def __init__(self, v):
super(Len, self).__init__()
if isinstance(value, PYSON):
assert value.types().issubset(set([dict, list, basestring])), \
if isinstance(v, PYSON):
assert v.types().issubset(set([dict, list, basestring])), \
'value must be a dict or a list or a string'
else:
assert isinstance(value, (dict, list, basestring)), \
assert isinstance(v, (dict, list, basestring)), \
'value must be a dict or list or a string'
self._value = value
self._value = v
@property
def __repr_params__(self):
+23
View File
@@ -569,6 +569,29 @@ class PYSONTestCase(unittest.TestCase):
self.assertEqual(repr(expr),
"If(Not(In('company', Eval('context', {}))), '=', '!=')")
def test_noeval(self):
decoder = pyson.PYSONDecoder(noeval=True)
encoder = pyson.PYSONEncoder()
for instance in [
pyson.Eval('test', 0),
pyson.Not(True),
pyson.Bool('test'),
pyson.And(True, False, True),
pyson.Or(False, True, True),
pyson.Equal('foo', 'bar'),
pyson.Greater(1, 0),
pyson.Less(0, 1),
pyson.If(True, 'foo', 'bar'),
pyson.Get({'foo': 'bar'}, 'foo', 'default'),
pyson.In('foo', ['foo', 'bar']),
pyson.Date(),
pyson.DateTime(),
pyson.Len([1, 2, 3]),
]:
self.assertEqual(decoder.decode(encoder.encode(instance)).pyson(),
instance.pyson())
def suite():
return unittest.TestLoader().loadTestsFromTestCase(PYSONTestCase)