Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"""
Evaluate an expression.
It can be:
None - return None
'some-value -- return some-value (it's a constant)
or an expression to find in values or graphnodes
or @functionname(args) - for defined functions...
We may add other kinds of expressions in the future...
"""
if not isinstance(expression, six.string_types):
# print('RETURNING NONSTRING:', expression, file=sys.stderr)
return expression
expression = str(expression.strip())
if not hasattr(context, "get") or not hasattr(context, "__setitem__"):
context = ExpressionContext(context)
# print('''EVALUATE('%s') (%s):''' % (expression, type(expression))
# The value of this parameter is a constant...
if expression.startswith('"'):
if expression[-1] != '"':
print("unquoted constant string '%s'" % expression, file=sys.stderr)
# print('''Constant string: "%s"''' % (expression[1:-1]), file=sys.stderr)
return expression[1:-1] if expression[-1] == '"' else None
if (expression.startswith("0x") or expression.startswith("0X")) and len(expression) > 3:
return int(expression[2:], 16)
if expression.isdigit():
return int(expression, 8) if expression.startswith("0") else int(expression)
if expression.find("(") >= 0:
value = GraphNodeExpression.functioncall(expression, context)
context[expression] = value
return value
# if expression.startswith('$'):
expressionstring = args[-1]
if not isinstance(expressionstring, six.string_types):
print(
"FOREACH expression must be a string, not %s" % type(expressionstring), file=sys.stderr
)
return False
# print('OBJECTLIST is:', objectlist, file=sys.stderr)
for obj in objectlist:
# print('OBJ is:', obj, file=sys.stderr)
for key in obj:
item = obj[key]
if not hasattr(item, "__contains__") or not hasattr(item, "__iter__"):
print("UNSUITABLE FOREACH CONTEXT[%s]: %s" % (key, item), file=sys.stderr)
continue
# print(sys.stderr, 'CREATING CONTEXT[%s]: %s' % (key, item), file=sys.stderr)
itemcontext = ExpressionContext(item)
# print('CONTEXT IS:', itemcontext, file=sys.stderr)
value = GraphNodeExpression.evaluate(expressionstring, itemcontext)
# print('VALUE of %s IS [%s] in context: %s' % (str(args), value, item), file=sys.stderr)
if value is None:
anynone = True
elif not value:
return False
return None if anynone else True
def contexttests():
"GraphNodeExpression tests that need a context"
lsattrs = """{
"/var/log/audit/": {"owner": "root", "group": "root", "type": "d", "perms": {"owner":{"read":true, "write":true, "exec":true, "setid":false}, "group": {"read":true, "write":false, "exec":true, "setid":false}, "other": {"read":false, "write":false, "exec":false}, "sticky":false}, "octal": "0750"},
"/var/log/audit/audit.log": {"owner": "root", "group": "root", "type": "-", "perms": {"owner":{"read":true, "write":true, "exec":false, "setid":false}, "group": {"read":false, "write":false, "exec":false, "setid":false}, "other": {"read":false, "write":false, "exec":false}, "sticky":false}, "octal": "0600"},
"/var/log/audit/audit.log.1": {"owner": "root", "group": "root", "type": "-", "perms": {"owner":{"read":true, "write":false, "exec":false, "setid":false}, "group": {"read":false, "write":false, "exec":false, "setid":false}, "other": {"read":false, "write":false, "exec":false}, "sticky":false}, "octal": "0400"}
}"""
lscontext = ExpressionContext(pyConfigContext(lsattrs))
Pie_context = ExpressionContext(
(
pyConfigContext(
{
"a": {"b": "c", "pie": 3, "pi": 3, "const": "constant"},
"f": {"g": "h", "pie": "3", "pi": 3, "const": "constant"},
}
),
pyConfigContext({"math": {"pi": 3.14159, "pie": 3, "const": "constant"}}),
pyConfigContext({"geography": {"Europe": "big", "const": "constant"}}),
)
)
complicated_context = ExpressionContext(pyConfigContext({"a": {"b": {"pie": 3}}}))
argcontext = ExpressionContext(
pyConfigContext('{"argv": ["command-name-suffix", "thing-one", "thang-two"]}')
)
def contexttests():
"GraphNodeExpression tests that need a context"
lsattrs = """{
"/var/log/audit/": {"owner": "root", "group": "root", "type": "d", "perms": {"owner":{"read":true, "write":true, "exec":true, "setid":false}, "group": {"read":true, "write":false, "exec":true, "setid":false}, "other": {"read":false, "write":false, "exec":false}, "sticky":false}, "octal": "0750"},
"/var/log/audit/audit.log": {"owner": "root", "group": "root", "type": "-", "perms": {"owner":{"read":true, "write":true, "exec":false, "setid":false}, "group": {"read":false, "write":false, "exec":false, "setid":false}, "other": {"read":false, "write":false, "exec":false}, "sticky":false}, "octal": "0600"},
"/var/log/audit/audit.log.1": {"owner": "root", "group": "root", "type": "-", "perms": {"owner":{"read":true, "write":false, "exec":false, "setid":false}, "group": {"read":false, "write":false, "exec":false, "setid":false}, "other": {"read":false, "write":false, "exec":false}, "sticky":false}, "octal": "0400"}
}"""
lscontext = ExpressionContext(pyConfigContext(lsattrs))
Pie_context = ExpressionContext(
(
pyConfigContext(
{
"a": {"b": "c", "pie": 3, "pi": 3, "const": "constant"},
"f": {"g": "h", "pie": "3", "pi": 3, "const": "constant"},
}
),
pyConfigContext({"math": {"pi": 3.14159, "pie": 3, "const": "constant"}}),
pyConfigContext({"geography": {"Europe": "big", "const": "constant"}}),
)
)
complicated_context = ExpressionContext(pyConfigContext({"a": {"b": {"pie": 3}}}))
argcontext = ExpressionContext(
pyConfigContext('{"argv": ["command-name-suffix", "thing-one", "thang-two"]}')
return self.values[key]
for obj in self.objects:
ret = None
try:
# print('GETTING %s in %s: %s' % (key, type(obj), obj), file=sys.stderr)
ret = obj.get(key, None)
if ret is None and hasattr(obj, "deepget"):
ret = obj.deepget(key, None)
# print('RETURNED %s' % ret, file=sys.stderr)
# Too general exception catching...
# pylint: disable=W0703
except Exception as e:
ret = None
print("OOPS: self.objects = %s / exception %s" % (str(self.objects), e), sys.stderr)
print("OOPS: OUR object = %s (%s)" % (str(obj), type(obj)), file=sys.stderr)
ret = ExpressionContext._fixvalue(ret)
if ret is not None:
self.values[key] = ret
return ret
if self.prefix is not None:
ret = ExpressionContext._fixvalue(obj.get("%s.%s" % (self.prefix, key), None))
if ret is not None:
self.values[key] = ret
return ret
return alternative
lscontext = ExpressionContext(pyConfigContext(lsattrs))
Pie_context = ExpressionContext(
(
pyConfigContext(
{
"a": {"b": "c", "pie": 3, "pi": 3, "const": "constant"},
"f": {"g": "h", "pie": "3", "pi": 3, "const": "constant"},
}
),
pyConfigContext({"math": {"pi": 3.14159, "pie": 3, "const": "constant"}}),
pyConfigContext({"geography": {"Europe": "big", "const": "constant"}}),
)
)
complicated_context = ExpressionContext(pyConfigContext({"a": {"b": {"pie": 3}}}))
argcontext = ExpressionContext(
pyConfigContext('{"argv": ["command-name-suffix", "thing-one", "thang-two"]}')
)
assert FOREACH(("EQ(False, $perms.group.write, $perms.other.write)",), lscontext) is True
assert FOREACH(("EQ($pi, 3)",), Pie_context) is False
assert FOREACH(("EQ($pie, 3)",), Pie_context) is None
assert FOREACH(("$a", "EQ($pie, 3)"), complicated_context) is True
assert FOREACH(("$a", "EQ($pie, 3.14159)"), complicated_context) is False
assert FOREACH(("$a", "EQ($pi, 3.14159)"), complicated_context) is None
assert FOREACH(("EQ($const, constant)",), Pie_context) is True
assert GraphNodeExpression.evaluate("EQ($math.pie, 3)", Pie_context) is True
assert FOREACH(("EQ($group, root)",), lscontext) is True
assert FOREACH(("EQ($owner, root)",), lscontext) is True
assert FOREACH(("AND(EQ($owner, root), EQ($group, root))",), lscontext) is True
assert argmatch(("thing-(.*)",), argcontext) == "one"
assert argmatch(("THING-(.*)", "$argv", "I"), argcontext) == "one"