Skip to content

Commit 7e823e6

Browse files
authored
docs: update ast-based helpers docs (#756)
1 parent 705de2e commit 7e823e6

File tree

1 file changed

+275
-1
lines changed

1 file changed

+275
-1
lines changed

src/content/docs/curriculum-help.mdx

Lines changed: 275 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,28 @@ Node("a: int = 1").find_variable("a").is_equivalent("a: int = 1")
591591
Node("self.spam = spam").find_variable("self.spam").is_equivalent("self.spam = spam")
592592
```
593593
594+
#### `find_variables()`
595+
596+
Returns a list of all variable assignments with the given name (unlike `find_variable` which returns only the first match).
597+
598+
```python
599+
code_str = """
600+
x: int = 0
601+
a.b = 0
602+
x = 5
603+
a.b = 2
604+
x = 10
605+
"""
606+
node = Node(code_str)
607+
len(node.find_variables("x")) # 3
608+
node.find_variables("x")[0].is_equivalent("x: int = 0") # True
609+
node.find_variables("x")[1].is_equivalent("x = 5") # True
610+
node.find_variables("x")[2].is_equivalent("x = 10") # True
611+
len(node.find_variables("a.b")) # 2
612+
node.find_variables("a.b")[0].is_equivalent("a.b = 0") # True
613+
node.find_variables("a.b")[1].is_equivalent("a.b = 2") # True
614+
```
615+
594616
#### `find_aug_variable()`
595617
596618
```python
@@ -1013,7 +1035,231 @@ explorer.find_function("foo").find_return().find_comp_ifs()[0].is_equivalent("i
10131035
explorer.find_function("foo").find_return().find_comp_ifs()[1].is_equivalent("j != 6")
10141036
```
10151037
1016-
#### Getting values
1038+
#### `find_trys()`
1039+
1040+
Returns a list of all try statements.
1041+
1042+
```python
1043+
code_str = """
1044+
try:
1045+
x = 1 / 0
1046+
except ZeroDivisionError:
1047+
print("division by zero")
1048+
else:
1049+
print("no error")
1050+
finally:
1051+
print("cleanup")
1052+
1053+
try:
1054+
y = int("abc")
1055+
except:
1056+
pass
1057+
"""
1058+
node = Node(code_str)
1059+
len(node.find_trys()) # 2
1060+
node.find_trys()[0].is_equivalent("try:\n x = 1 / 0\nexcept ZeroDivisionError:\n print('division by zero')\nelse:\n print('no error')\nfinally:\n print('cleanup')") # True
1061+
node.find_trys()[1].is_equivalent("try:\n y = int('abc')\nexcept:\n pass") # True
1062+
```
1063+
1064+
#### `find_excepts()`
1065+
1066+
Returns a list of all except handlers in a try statement.
1067+
1068+
```python
1069+
code_str = """
1070+
try:
1071+
x = 1 / 0
1072+
except ZeroDivisionError:
1073+
print("division by zero")
1074+
except ValueError as e:
1075+
print(f"value error: {e}")
1076+
except:
1077+
print("other error")
1078+
"""
1079+
node = Node(code_str)
1080+
try_stmt = node.find_trys()[0]
1081+
len(try_stmt.find_excepts()) # 3
1082+
```
1083+
1084+
`is_equivalent()` cannot be used on the items found by `find_excepts()` because a standalone `except` raises a `SyntaxError`.
1085+
1086+
#### `find_except()`
1087+
1088+
Returns a specific except handler matching the exception type and optional variable name.
1089+
1090+
```python
1091+
code_str = """
1092+
try:
1093+
x = 1 / 0
1094+
except ZeroDivisionError:
1095+
print("division by zero")
1096+
except ValueError as e:
1097+
print(f"value error: {e}")
1098+
except:
1099+
print("other error")
1100+
"""
1101+
node = Node(code_str)
1102+
try_stmt = node.find_trys()[0]
1103+
try_stmt.find_except("ZeroDivisionError").find_body().is_equivalent("print('division by zero')") # True
1104+
try_stmt.find_except("ValueError", "e").find_body().is_equivalent("print(f'value error: {e}')") # True
1105+
try_stmt.find_except().find_body().is_equivalent("print('other error')") # True (bare except)
1106+
```
1107+
1108+
#### `has_except()`
1109+
1110+
Returns True if a try statement has an except handler for the given exception type and variable name.
1111+
1112+
```python
1113+
code_str = """
1114+
try:
1115+
x = 1 / 0
1116+
except ZeroDivisionError:
1117+
print("division by zero")
1118+
except ValueError as e:
1119+
print(f"value error: {e}")
1120+
"""
1121+
node = Node(code_str)
1122+
try_stmt = node.find_trys()[0]
1123+
try_stmt.has_except("ZeroDivisionError") # True
1124+
try_stmt.has_except("ValueError", "e") # True
1125+
try_stmt.has_except("ValueError") # False
1126+
```
1127+
1128+
#### `find_try_else()`
1129+
1130+
Returns the else block of a try statement.
1131+
1132+
```python
1133+
code_str = """
1134+
try:
1135+
x = 1
1136+
except ValueError:
1137+
print("error")
1138+
else:
1139+
print("success")
1140+
x = 2
1141+
"""
1142+
node = Node(code_str)
1143+
try_stmt = node.find_trys()[0]
1144+
try_stmt.find_try_else().is_equivalent("print('success')\nx = 2") # True
1145+
```
1146+
1147+
#### `find_finally()`
1148+
1149+
Returns the finally block of a try statement.
1150+
1151+
```python
1152+
code_str = """
1153+
try:
1154+
x = 1
1155+
except ValueError:
1156+
print("error")
1157+
finally:
1158+
print("cleanup")
1159+
x = None
1160+
"""
1161+
node = Node(code_str)
1162+
try_stmt = node.find_trys()[0]
1163+
try_stmt.find_finally().is_equivalent("print('cleanup')\nx = None") # True
1164+
```
1165+
1166+
#### `find_matches()`
1167+
1168+
Returns a list of match statements.
1169+
1170+
```python
1171+
code_str = """
1172+
match x:
1173+
case 0:
1174+
pass
1175+
case _:
1176+
pass
1177+
1178+
match y:
1179+
case 1:
1180+
pass
1181+
"""
1182+
node = Node(code_str)
1183+
len(node.find_matches()) # 2
1184+
node.find_matches()[0].is_equivalent("match x:\n case 0:\n pass\n case _:\n pass") # True
1185+
```
1186+
1187+
#### `find_match_subject()`
1188+
1189+
Returns the subject of a match statement.
1190+
1191+
```python
1192+
code_str = """
1193+
match x:
1194+
case 0:
1195+
pass
1196+
"""
1197+
node = Node(code_str)
1198+
node.find_matches()[0].find_match_subject().is_equivalent("x") # True
1199+
```
1200+
1201+
#### `find_match_cases()`
1202+
1203+
Returns a list of case blocks in a match statement.
1204+
1205+
```python
1206+
code_str = """
1207+
match x:
1208+
case 0:
1209+
print(0)
1210+
print('spam')
1211+
case _:
1212+
pass
1213+
"""
1214+
node = Node(code_str)
1215+
len(node.find_matches()[0].find_match_cases()) # 2
1216+
node.find_matches()[0].find_match_cases()[0].find_body().is_equivalent("print(0)\nprint('spam')") # True
1217+
node.find_matches()[0].find_match_cases()[1].find_body().is_equivalent("pass") # True
1218+
```
1219+
1220+
`is_equivalent()` cannot be used on the items found by `find_match_cases()` because a standalone `case` raises a `SyntaxError`.
1221+
1222+
#### `find_case_pattern()`
1223+
1224+
Returns the pattern of a case block.
1225+
1226+
```python
1227+
code_str = """
1228+
match x:
1229+
case 0:
1230+
pass
1231+
case [a, b]:
1232+
pass
1233+
case _:
1234+
pass
1235+
"""
1236+
node = Node(code_str)
1237+
node.find_matches()[0].find_match_cases()[0].find_case_pattern().is_equivalent("0") # True
1238+
node.find_matches()[0].find_match_cases()[1].find_case_pattern().is_equivalent("[a, b]") # True
1239+
node.find_matches()[0].find_match_cases()[2].find_case_pattern().is_equivalent("_") # True
1240+
```
1241+
1242+
#### `find_case_guard()`
1243+
1244+
Returns the guard condition of a case block.
1245+
1246+
```python
1247+
code_str = """
1248+
match x:
1249+
case 0 if y > 0:
1250+
pass
1251+
case [a, b] if y == -1:
1252+
pass
1253+
case _:
1254+
pass
1255+
"""
1256+
node = Node(code_str)
1257+
node.find_matches()[0].find_match_cases()[0].find_case_guard().is_equivalent("y > 0") # True
1258+
node.find_matches()[0].find_match_cases()[1].find_case_guard().is_equivalent("y == -1") # True
1259+
node.find_matches()[0].find_match_cases()[2].find_case_guard().is_empty() # True (no guard)
1260+
```
1261+
1262+
### Getting values
10171263
10181264
`get_` functions return the value of the node, not the node itself.
10191265
@@ -1114,6 +1360,34 @@ explorer.has_call("print(math.sqrt(25))")
11141360
explorer.find_ifs()[0].find_bodies()[0].has_call("spam()")
11151361
```
11161362
1363+
#### `block_has_call()`
1364+
1365+
Checks if a function/method call exists within a specific function or the entire code.
1366+
1367+
```python
1368+
code_str = """
1369+
srt = sorted([5, 1, 9])
1370+
1371+
def foo(lst):
1372+
return sorted(lst)
1373+
1374+
def spam(lst):
1375+
return lst.sort()
1376+
1377+
def eggs(dictionary):
1378+
if True:
1379+
k = dictionary.get(key)
1380+
"""
1381+
node = Node(code_str)
1382+
1383+
node.block_has_call("sorted", "foo") # True
1384+
node.block_has_call("sorted") # True
1385+
node.block_has_call("sort", "spam") # True
1386+
node.block_has_call("get", "eggs") # True
1387+
node.block_has_call("get") # True
1388+
node.block_has_call("split") # False
1389+
```
1390+
11171391
#### `has_import()`
11181392
11191393
```python

0 commit comments

Comments
 (0)