1- import unittest
21from dataclasses import dataclass
32from typing import List , Dict
43
4+ import pytest
5+
56from linkml_runtime .utils .eval_utils import eval_expr
67
78
@@ -24,90 +25,58 @@ class Container:
2425 person_index : Dict [str , Person ] = None
2526
2627
27- class EvalUtilsTestCase (unittest .TestCase ):
28- """
29- Tests for linkml_runtime.utils.eval_utils
30- """
31-
32- def test_eval_expressions (self ):
33- """
34- Tests evaluation of expressions using eval_expr
35- """
36- x = eval_expr ("1 + 2" )
37- self .assertEqual (x , 3 )
38- self .assertEqual (eval_expr ("1 + 2 + 3" ), 6 )
39- x = eval_expr ("{z} + 2" , z = 1 )
40- self .assertEqual (x , 3 )
41- self .assertIsNone (eval_expr ('{x} + {y}' , x = 5 , y = None ))
42- x = eval_expr ("'x' + 'y'" )
43- assert x == 'xy'
44- #x = eval_expr("'{x}' + '{y}'", x='a', y='b')
45- #self.assertEqual(x, 'ab')
46- self .assertEqual (eval_expr ("['a','b'] + ['c','d']" ), ['a' , 'b' , 'c' , 'd' ])
47- self .assertEqual (eval_expr ("{x} + {y}" , x = ['a' , 'b' ], y = ['c' , 'd' ]), ['a' , 'b' , 'c' , 'd' ])
48- self .assertEqual (eval_expr ("{'a': 1}" ), {'a' : 1 })
49- self .assertEqual (eval_expr ("max([1, 5, 2])" ), 5 )
50- self .assertEqual (eval_expr ("max({x})" , x = [1 , 5 , 2 ]), 5 )
51- self .assertEqual (eval_expr ("True" ), True )
52- self .assertEqual (eval_expr ("False" ), False )
53- self .assertEqual (eval_expr ("1 + 1 == 3" ), False )
54- self .assertEqual (eval_expr ("1 < 2" ), True )
55- self .assertEqual (eval_expr ("1 <= 1" ), True )
56- self .assertEqual (eval_expr ("1 >= 1" ), True )
57- self .assertEqual (eval_expr ("2 > 1" ), True )
58- self .assertEqual (eval_expr ("'EQ' if {x} == {y} else 'NEQ'" , x = 1 , y = 1 ), 'EQ' )
59- self .assertEqual (eval_expr ("'EQ' if {x} == {y} else 'NEQ'" , x = 1 , y = 2 ), 'NEQ' )
60- self .assertEqual (eval_expr ("'NOT_NULL' if x else 'NULL'" , x = 1 ), 'NOT_NULL' )
61- self .assertEqual (eval_expr ("'NOT_NULL' if x else 'NULL'" , x = None ), 'NULL' )
62- self .assertEqual (eval_expr ("'EQ' if {x} == {y} else 'NEQ'" , x = 1 , y = 2 ), 'NEQ' )
63- case = "case(({x} < 25, 'LOW'), ({x} > 75, 'HIGH'), (True, 'MEDIUM'))"
64- self .assertEqual (eval_expr (case , x = 10 ), 'LOW' )
65- self .assertEqual (eval_expr (case , x = 100 ), 'HIGH' )
66- self .assertEqual (eval_expr (case , x = 50 ), 'MEDIUM' )
67- self .assertEqual (eval_expr ('x' , x = 'a' ), 'a' )
68- self .assertEqual (eval_expr ('x+y' , x = 1 , y = 2 ), 3 )
69- # todo
70- self .assertEqual (eval_expr ('x["a"] + y' , x = {'a' : 1 }, y = 2 ), 3 )
71- self .assertEqual (eval_expr ('x["a"]["b"] + y' , x = {'a' : {'b' : 1 }}, y = 2 ), 3 )
72- p = Person (name = 'x' , aliases = ['a' , 'b' , 'c' ], address = Address (street = '1 x street' ))
73- self .assertEqual (eval_expr ('p.name' , p = p ), 'x' )
74- self .assertEqual (eval_expr ('p.address.street' , p = p ), '1 x street' )
75- self .assertEqual (eval_expr ('len(p.aliases)' , p = p ), 3 )
76- self .assertEqual (eval_expr ('p.aliases' , p = p ), p .aliases )
77- p2 = Person (name = 'x2' , aliases = ['a2' , 'b2' , 'c2' ], address = Address (street = '2 x street' ))
78- c = Container (persons = [p , p2 ])
79- x = eval_expr ('c.persons.name' , c = c )
80- self .assertEqual (x , ['x' , 'x2' ])
81- x = eval_expr ('c.persons.address.street' , c = c )
82- self .assertEqual (x , ['1 x street' , '2 x street' ])
83- x = eval_expr ('strlen(c.persons.address.street)' , c = c )
84- self .assertEqual (x , [10 , 10 ])
85- c = Container (person_index = {p .name : p , p2 .name : p2 })
86- x = eval_expr ('c.person_index.name' , c = c )
87- #print(x)
88- self .assertEqual (x , ['x' , 'x2' ])
89- x = eval_expr ('c.person_index.address.street' , c = c )
90- self .assertEqual (x , ['1 x street' , '2 x street' ])
91- x = eval_expr ('strlen(c.person_index.name)' , c = c )
92- self .assertEqual (x , [1 , 2 ])
93- #self.assertEqual('x', eval_expr('"x" if True else "y"'))
94-
95- def test_no_eval_prohibited (self ):
96- """
97- Ensure that certain patterns cannot be evaluated
28+ def test_eval_expressions ():
29+ assert eval_expr ("1 + 2" ) == 3
30+ assert eval_expr ("1 + 2 + 3" ) == 6
31+ assert eval_expr ("{z} + 2" , z = 1 ) == 3
32+ assert eval_expr ('{x} + {y}' , x = 5 , y = None ) is None
33+ assert eval_expr ("'x' + 'y'" ) == 'xy'
34+ assert eval_expr ("['a','b'] + ['c','d']" ) == ['a' , 'b' , 'c' , 'd' ]
35+ assert eval_expr ("{x} + {y}" , x = ['a' , 'b' ], y = ['c' , 'd' ]) == ['a' , 'b' , 'c' , 'd' ]
36+ assert eval_expr ("{'a': 1}" ) == {'a' : 1 }
37+ assert eval_expr ("max([1, 5, 2])" ) == 5
38+ assert eval_expr ("max({x})" , x = [1 , 5 , 2 ]) == 5
39+ assert eval_expr ("True" ) is True
40+ assert eval_expr ("False" ) is False
41+ assert eval_expr ("1 + 1 == 3" ) is False
42+ assert eval_expr ("1 < 2" ) is True
43+ assert eval_expr ("1 <= 1" ) is True
44+ assert eval_expr ("1 >= 1" ) is True
45+ assert eval_expr ("2 > 1" ) is True
46+ assert eval_expr ("'EQ' if {x} == {y} else 'NEQ'" , x = 1 , y = 1 ) == 'EQ'
47+ assert eval_expr ("'EQ' if {x} == {y} else 'NEQ'" , x = 1 , y = 2 ) == 'NEQ'
48+ assert eval_expr ("'NOT_NULL' if x else 'NULL'" , x = 1 ) == 'NOT_NULL'
49+ assert eval_expr ("'NOT_NULL' if x else 'NULL'" , x = None ) == 'NULL'
50+ assert eval_expr ("'EQ' if {x} == {y} else 'NEQ'" , x = 1 , y = 2 ) == 'NEQ'
51+ case = "case(({x} < 25, 'LOW'), ({x} > 75, 'HIGH'), (True, 'MEDIUM'))"
52+ assert eval_expr (case , x = 10 ) == 'LOW'
53+ assert eval_expr (case , x = 100 ) == 'HIGH'
54+ assert eval_expr (case , x = 50 ) == 'MEDIUM'
55+ assert eval_expr ('x' , x = 'a' ) == 'a'
56+ assert eval_expr ('x+y' , x = 1 , y = 2 ) == 3
57+ assert eval_expr ('x["a"] + y' , x = {'a' : 1 }, y = 2 ) == 3
58+ assert eval_expr ('x["a"]["b"] + y' , x = {'a' : {'b' : 1 }}, y = 2 ) == 3
59+ p = Person (name = 'x' , aliases = ['a' , 'b' , 'c' ], address = Address (street = '1 x street' ))
60+ assert eval_expr ('p.name' , p = p ) == 'x'
61+ assert eval_expr ('p.address.street' , p = p ) == '1 x street'
62+ assert eval_expr ('len(p.aliases)' , p = p ) == 3
63+ assert eval_expr ('p.aliases' , p = p ) == p .aliases
64+ p2 = Person (name = 'x2' , aliases = ['a2' , 'b2' , 'c2' ], address = Address (street = '2 x street' ))
65+ c = Container (persons = [p , p2 ])
66+ assert eval_expr ('c.persons.name' , c = c ) == ['x' , 'x2' ]
67+ assert eval_expr ('c.persons.address.street' , c = c ) == ['1 x street' , '2 x street' ]
68+ assert eval_expr ('strlen(c.persons.address.street)' , c = c ) == [10 , 10 ]
69+ c = Container (person_index = {p .name : p , p2 .name : p2 })
70+ assert eval_expr ('c.person_index.name' , c = c ) == ['x' , 'x2' ]
71+ assert eval_expr ('c.person_index.address.street' , c = c ) == ['1 x street' , '2 x street' ]
72+ assert eval_expr ('strlen(c.person_index.name)' , c = c ) == [1 , 2 ]
9873
99- See `<https://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string>`_
100- """
101- with self .assertRaises (NotImplementedError ):
102- eval_expr ("__import__('os').listdir()" )
10374
104- def test_funcs (self ):
105- """
106- Not yet implemented
107- """
108- with self .assertRaises (NotImplementedError ):
109- eval_expr ("my_func([1,2,3])" )
75+ def test_no_eval_prohibited ():
76+ with pytest .raises (NotImplementedError ):
77+ eval_expr ("__import__('os').listdir()" )
11078
11179
112- if __name__ == '__main__' :
113- unittest .main ()
80+ def test_funcs ():
81+ with pytest .raises (NotImplementedError ):
82+ eval_expr ("my_func([1,2,3])" )
0 commit comments