Skip to content

Commit 02e17e5

Browse files
committed
Update unit tests
1 parent ce106b5 commit 02e17e5

File tree

5 files changed

+306
-17
lines changed

5 files changed

+306
-17
lines changed

tests/expressions/test_interpreter_coverage1.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ def inner():
590590
outer()
591591
"""
592592
tree = parser.parse(code)
593-
with pytest.raises(SyntaxError, match="No binding for nonlocal 'x'"):
593+
with pytest.raises(SyntaxError, match="no binding for nonlocal 'x'"):
594594
interpreter.execute(tree)
595595

596596

@@ -625,7 +625,7 @@ def func():
625625
nonlocal y
626626
"""
627627
tree = parser.parse(code)
628-
with pytest.raises(SyntaxError, match="No binding for nonlocal 'y'"):
628+
with pytest.raises(SyntaxError, match="no binding for nonlocal 'y'"):
629629
interpreter.execute(tree)
630630

631631

@@ -1369,9 +1369,7 @@ def inner():
13691369
outer()
13701370
"""
13711371
tree = parser.parse(code)
1372-
with pytest.raises(
1373-
SyntaxError, match="No binding for nonlocal 'x' found in outer scopes"
1374-
):
1372+
with pytest.raises(SyntaxError, match="no binding for nonlocal 'x' found"):
13751373
interpreter.execute(tree)
13761374

13771375
# Test nonlocal declaration in nested functions

tests/expressions/test_interpreter_coverage2.py

Lines changed: 293 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ def complex_func(a, b=1, *args, c, d=2, **kwargs):
676676
(1, 1, (), 3, 2, {}),
677677
(1, 2, (3, 4), 5, 6, {"x": 7}),
678678
(1, 2, (), 3, 4, {"x": 5, "y": 6}),
679-
"missing required keyword-only argument 'c'",
679+
"complex_func() missing 1 required keyword-only argument: 'c'",
680680
]
681681

682682
# Test function with nonlocal and closure
@@ -1081,3 +1081,295 @@ class Score:
10811081
tree = parser.parse(code)
10821082
result = interpreter.execute(tree)
10831083
assert result == [85, "Value must be >= 0", "Value must be <= 100"]
1084+
1085+
1086+
def test_function_call_edge_cases():
1087+
"""Test edge cases in function calls."""
1088+
parser = ExpressionsParser()
1089+
interpreter = ExpressionsInterpreter()
1090+
1091+
# Test function call with invalid arguments
1092+
code = """
1093+
def func(a, b, *, c):
1094+
return a + b + c
1095+
1096+
results = []
1097+
try:
1098+
func(1, 2, 3) # Positional argument after keyword-only argument
1099+
except TypeError as e:
1100+
results.append(str(e))
1101+
1102+
try:
1103+
func(1, b=2) # Missing required keyword-only argument
1104+
except TypeError as e:
1105+
results.append(str(e))
1106+
1107+
try:
1108+
func(1, 2, d=3) # Unknown keyword argument
1109+
except TypeError as e:
1110+
results.append(str(e))
1111+
1112+
results
1113+
"""
1114+
tree = parser.parse(code)
1115+
result = interpreter.execute(tree)
1116+
assert result == [
1117+
"func() takes 2 positional arguments but 3 were given",
1118+
"func() missing 1 required keyword-only argument: 'c'",
1119+
"func() got an unexpected keyword argument 'd'",
1120+
]
1121+
1122+
# Test method call with invalid arguments
1123+
code = """
1124+
class Test:
1125+
def method(self, a, b=2):
1126+
return a + b
1127+
1128+
@classmethod
1129+
def class_method(cls, x):
1130+
return x * 2
1131+
1132+
@staticmethod
1133+
def static_method(y):
1134+
return y + 1
1135+
1136+
obj = Test()
1137+
results = []
1138+
1139+
# Test instance method
1140+
results.append(obj.method(1))
1141+
results.append(obj.method(1, 3))
1142+
1143+
# Test classmethod
1144+
results.append(Test.class_method(5))
1145+
results.append(obj.class_method(5))
1146+
1147+
# Test staticmethod
1148+
results.append(Test.static_method(10))
1149+
results.append(obj.static_method(10))
1150+
1151+
try:
1152+
obj.method() # Missing required argument
1153+
except TypeError as e:
1154+
results.append(str(e))
1155+
1156+
try:
1157+
obj.method(1, 2, 3) # Too many arguments
1158+
except TypeError as e:
1159+
results.append(str(e))
1160+
1161+
results
1162+
"""
1163+
tree = parser.parse(code)
1164+
result = interpreter.execute(tree)
1165+
assert result == [
1166+
3,
1167+
4,
1168+
10,
1169+
10,
1170+
11,
1171+
11,
1172+
"method() missing 1 required positional argument: 'a'",
1173+
"method() takes from 2 to 3 positional arguments but 4 were given",
1174+
]
1175+
1176+
1177+
def test_generator_advanced_features():
1178+
"""Test advanced generator features."""
1179+
parser = ExpressionsParser()
1180+
interpreter = ExpressionsInterpreter()
1181+
1182+
# Test generator with try/finally
1183+
code = """
1184+
def gen():
1185+
yield 1
1186+
yield 2
1187+
1188+
results = []
1189+
g = gen()
1190+
results.append(next(g))
1191+
results.append(next(g))
1192+
try:
1193+
next(g)
1194+
except StopIteration:
1195+
results.append('stopped')
1196+
results
1197+
"""
1198+
tree = parser.parse(code)
1199+
result = interpreter.execute(tree)
1200+
assert result == [1, 2, "stopped"]
1201+
1202+
# Test generator with throw
1203+
code = """
1204+
def gen_with_throw():
1205+
yield 1
1206+
yield 2
1207+
yield 3
1208+
yield 'end'
1209+
1210+
results = []
1211+
g = gen_with_throw()
1212+
results.append(next(g))
1213+
results.append(next(g))
1214+
try:
1215+
g.throw(ValueError)
1216+
except ValueError:
1217+
results.append('caught')
1218+
except StopIteration:
1219+
results.append('stopped')
1220+
results
1221+
"""
1222+
tree = parser.parse(code)
1223+
result = interpreter.execute(tree)
1224+
assert result == [1, 2, "caught"]
1225+
1226+
1227+
def test_comprehension_advanced_features():
1228+
"""Test advanced comprehension features."""
1229+
parser = ExpressionsParser()
1230+
interpreter = ExpressionsInterpreter()
1231+
1232+
# Test nested comprehensions with complex conditions
1233+
code = """
1234+
def get_data():
1235+
return [[j for j in range(i + 1)] for i in range(3)]
1236+
1237+
results = []
1238+
# List comprehension
1239+
results.append([sum(row) for row in get_data()])
1240+
1241+
# Set comprehension with tuple unpacking
1242+
points = [(1, 2), (3, 4), (1, 2), (5, 6)]
1243+
results.append({(y, x) for x, y in points})
1244+
1245+
# Dict comprehension with complex key generation
1246+
words = ['hello', 'world', 'python']
1247+
results.append({word: {c: word.count(c) for c in set(word)}
1248+
for word in words if len(word) > 4})
1249+
1250+
results
1251+
"""
1252+
tree = parser.parse(code)
1253+
result = interpreter.execute(tree)
1254+
assert result == [
1255+
[0, 1, 3], # Sum of each row
1256+
{(2, 1), (4, 3), (6, 5)}, # Swapped coordinates
1257+
{
1258+
"hello": {"h": 1, "o": 1, "e": 1, "l": 2},
1259+
"world": {"o": 1, "l": 1, "r": 1, "d": 1, "w": 1},
1260+
"python": {"o": 1, "t": 1, "p": 1, "y": 1, "n": 1, "h": 1},
1261+
},
1262+
]
1263+
1264+
# Test comprehension with error handling
1265+
code = """
1266+
def problematic_data():
1267+
yield 1
1268+
yield 'not a number'
1269+
yield 3
1270+
1271+
results = []
1272+
try:
1273+
results.append([x * 2 for x in problematic_data()])
1274+
except TypeError as e:
1275+
results.append(str(e))
1276+
1277+
# Generator expression with error
1278+
def gen_expr():
1279+
return (x * 2 for x in problematic_data())
1280+
1281+
g = gen_expr()
1282+
results.append(next(g))
1283+
try:
1284+
next(g)
1285+
except TypeError as e:
1286+
results.append(str(e))
1287+
1288+
results
1289+
"""
1290+
tree = parser.parse(code)
1291+
result = interpreter.execute(tree)
1292+
assert result == [[2, "not a numbernot a number", 6], 2]
1293+
1294+
1295+
def test_match_pattern_advanced():
1296+
"""Test advanced pattern matching features."""
1297+
parser = ExpressionsParser()
1298+
interpreter = ExpressionsInterpreter()
1299+
1300+
# Test match with custom class patterns
1301+
code = """
1302+
class Point:
1303+
def __init__(self, x, y):
1304+
self.x = x
1305+
self.y = y
1306+
__match_args__ = ('x', 'y')
1307+
1308+
class Line:
1309+
def __init__(self, start, end):
1310+
self.start = start
1311+
self.end = end
1312+
__match_args__ = ('start', 'end')
1313+
1314+
def classify(shape):
1315+
match shape:
1316+
case Point(0, y):
1317+
return f"Point on y-axis at y={y}"
1318+
case Point(x, 0):
1319+
return f"Point on x-axis at x={x}"
1320+
case Point(x, y) if x == y:
1321+
return f"Point on diagonal at {x}"
1322+
case Line(Point(x1, y1), Point(x2, y2)) if x1 == x2:
1323+
return f"Vertical line at x={x1}"
1324+
case Line(Point(x1, y1), Point(x2, y2)) if y1 == y2:
1325+
return f"Horizontal line at y={y1}"
1326+
case _:
1327+
return "Other shape"
1328+
1329+
results = []
1330+
results.append(classify(Point(0, 5)))
1331+
results.append(classify(Point(3, 0)))
1332+
results.append(classify(Point(4, 4)))
1333+
results.append(classify(Line(Point(2, 1), Point(2, 5))))
1334+
results.append(classify(Line(Point(1, 3), Point(5, 3))))
1335+
results.append(classify(Line(Point(1, 1), Point(2, 2))))
1336+
results
1337+
"""
1338+
tree = parser.parse(code)
1339+
result = interpreter.execute(tree)
1340+
assert result == [
1341+
"Point on y-axis at y=5",
1342+
"Point on x-axis at x=3",
1343+
"Point on diagonal at 4",
1344+
"Vertical line at x=2",
1345+
"Horizontal line at y=3",
1346+
"Other shape",
1347+
]
1348+
1349+
1350+
def test_async_function_advanced():
1351+
"""Test advanced async function features."""
1352+
parser = ExpressionsParser()
1353+
interpreter = ExpressionsInterpreter()
1354+
1355+
# Test async function with error handling
1356+
code = """
1357+
async def the_answer():
1358+
return 42
1359+
1360+
async def async_with_error():
1361+
try:
1362+
await the_answer()
1363+
raise ValueError('test error')
1364+
except ValueError as e:
1365+
return str(e)
1366+
1367+
async def run_async():
1368+
return await async_with_error()
1369+
1370+
result = await run_async()
1371+
result
1372+
"""
1373+
tree = parser.parse(code)
1374+
result = interpreter.execute(tree)
1375+
assert result == "test error"

tests/expressions/test_interpreter_coverage4.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -821,9 +821,7 @@ def inner():
821821
with pytest.raises(SyntaxError) as exc_info:
822822
interpreter.execute(parser.parse(code))
823823

824-
assert "No binding for nonlocal 'x' found in outer scopes" in str(
825-
exc_info.value
826-
)
824+
assert "no binding for nonlocal 'x' found" in str(exc_info.value)
827825

828826
# Test nonlocal declaration at module level
829827
code = """
@@ -926,7 +924,7 @@ def func(a, b):
926924

927925
error1 = interpreter.get_name_value("error1")
928926
error2 = interpreter.get_name_value("error2")
929-
assert "missing required positional argument" in error1
927+
assert "missing 1 required positional argument" in error1
930928
assert "takes 2 positional arguments but 3 were given" in error2
931929

932930

@@ -1015,7 +1013,7 @@ def inner():
10151013
with pytest.raises(SyntaxError) as exc_info:
10161014
interpreter.execute(parser.parse(code))
10171015

1018-
assert "No binding for nonlocal 'x' found" in str(exc_info.value)
1016+
assert "no binding for nonlocal 'x' found" in str(exc_info.value)
10191017

10201018

10211019
def test_name_deletion_complex():

tests/expressions/test_interpreter_coverage5.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,9 @@ def method_with_args(self, a, b=2, *args, c=3):
382382
== "a=1, b=3, args=(4, 5), c=6, kwargs={'d': 7}"
383383
)
384384
assert "has no attribute" in interpreter.get_name_value("error1")
385-
assert "missing required positional argument" in interpreter.get_name_value(
386-
"error2"
385+
assert (
386+
"missing 1 required positional argument"
387+
in interpreter.get_name_value("error2")
387388
)
388389
assert "got an unexpected keyword argument" in interpreter.get_name_value(
389390
"error3"

0 commit comments

Comments
 (0)