Add noeval to PYSONDecoder
issue1616 review15071002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Add noeval on PYSONDecoder
|
||||
* Add __repr__ to PYSON
|
||||
* Remove safe_eval
|
||||
* Add ModelView.view_attributes
|
||||
|
||||
+3
-3
@@ -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
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user