@@ -591,6 +591,28 @@ Node("a: int = 1").find_variable("a").is_equivalent("a: int = 1")
591591Node (" 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
10131035explorer .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\n except ZeroDivisionError:\n print('division by zero')\n else:\n print('no error')\n finally:\n print('cleanup')" ) # True
1061+ node .find_trys ()[1 ].is_equivalent (" try:\n y = int('abc')\n except:\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')\n x = 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')\n x = 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)\n print('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))")
11141360explorer .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