@@ -205,6 +205,28 @@ Node("a: int = 1").find_variable("a").is_equivalent("a: int = 1")
205205Node(" self.spam = spam" ).find_variable(" self.spam" ).is_equivalent(" self.spam = spam" )
206206```
207207
208+ #### ` find_variables `
209+
210+ Returns a list of all variable assignments with the given name (unlike ` find_variable ` which returns only the first match).
211+
212+ ``` python
213+ code_str = """
214+ x: int = 0
215+ a.b = 0
216+ x = 5
217+ a.b = 2
218+ x = 10
219+ """
220+ node = Node(code_str)
221+ len (node.find_variables(" x" )) # 3
222+ node.find_variables(" x" )[0 ].is_equivalent(" x: int = 0" ) # True
223+ node.find_variables(" x" )[1 ].is_equivalent(" x = 5" ) # True
224+ node.find_variables(" x" )[2 ].is_equivalent(" x = 10" ) # True
225+ len (node.find_variables(" a.b" )) # 2
226+ node.find_variables(" a.b" )[0 ].is_equivalent(" a.b = 0" ) # True
227+ node.find_variables(" a.b" )[1 ].is_equivalent(" a.b = 2" ) # True
228+ ```
229+
208230#### ` find_aug_variable `
209231
210232``` python
@@ -627,6 +649,230 @@ explorer.find_function("foo").find_return().find_comp_ifs()[0].is_equivalent("i
627649explorer.find_function(" foo" ).find_return().find_comp_ifs()[1 ].is_equivalent(" j != 6" )
628650```
629651
652+ #### ` find_trys `
653+
654+ Returns a list of all try statements.
655+
656+ ``` python
657+ code_str = """
658+ try:
659+ x = 1 / 0
660+ except ZeroDivisionError:
661+ print("division by zero")
662+ else:
663+ print("no error")
664+ finally:
665+ print("cleanup")
666+
667+ try:
668+ y = int("abc")
669+ except:
670+ pass
671+ """
672+ node = Node(code_str)
673+ len (node.find_trys()) # 2
674+ 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
675+ node.find_trys()[1 ].is_equivalent(" try:\n y = int('abc')\n except:\n pass" ) # True
676+ ```
677+
678+ #### ` find_excepts `
679+
680+ Returns a list of all except handlers in a try statement.
681+
682+ ``` python
683+ code_str = """
684+ try:
685+ x = 1 / 0
686+ except ZeroDivisionError:
687+ print("division by zero")
688+ except ValueError as e:
689+ print(f"value error: {e} ")
690+ except:
691+ print("other error")
692+ """
693+ node = Node(code_str)
694+ try_stmt = node.find_trys()[0 ]
695+ len (try_stmt.find_excepts()) # 3
696+ ```
697+
698+ ` is_equivalent() ` cannot be used on the items found by ` find_excepts() ` because a standalone ` except ` raises a ` SyntaxError ` .
699+
700+ #### ` find_except `
701+
702+ Returns a specific except handler matching the exception type and optional variable name.
703+
704+ ``` python
705+ code_str = """
706+ try:
707+ x = 1 / 0
708+ except ZeroDivisionError:
709+ print("division by zero")
710+ except ValueError as e:
711+ print(f"value error: {e} ")
712+ except:
713+ print("other error")
714+ """
715+ node = Node(code_str)
716+ try_stmt = node.find_trys()[0 ]
717+ try_stmt.find_except(" ZeroDivisionError" ).find_body().is_equivalent(" print('division by zero')" ) # True
718+ try_stmt.find_except(" ValueError" , " e" ).find_body().is_equivalent(" print(f'value error: {e} ')" ) # True
719+ try_stmt.find_except().find_body().is_equivalent(" print('other error')" ) # True (bare except)
720+ ```
721+
722+ #### ` has_except `
723+
724+ Returns True if a try statement has an except handler for the given exception type and variable name.
725+
726+ ``` python
727+ code_str = """
728+ try:
729+ x = 1 / 0
730+ except ZeroDivisionError:
731+ print("division by zero")
732+ except ValueError as e:
733+ print(f"value error: {e} ")
734+ """
735+ node = Node(code_str)
736+ try_stmt = node.find_trys()[0 ]
737+ try_stmt.has_except(" ZeroDivisionError" ) # True
738+ try_stmt.has_except(" ValueError" , " e" ) # True
739+ try_stmt.has_except(" ValueError" ) # False
740+ ```
741+
742+ #### ` find_try_else `
743+
744+ Returns the else block of a try statement.
745+
746+ ``` python
747+ code_str = """
748+ try:
749+ x = 1
750+ except ValueError:
751+ print("error")
752+ else:
753+ print("success")
754+ x = 2
755+ """
756+ node = Node(code_str)
757+ try_stmt = node.find_trys()[0 ]
758+ try_stmt.find_try_else().is_equivalent(" print('success')\n x = 2" ) # True
759+ ```
760+
761+ #### ` find_finally `
762+
763+ Returns the finally block of a try statement.
764+
765+ ``` python
766+ code_str = """
767+ try:
768+ x = 1
769+ except ValueError:
770+ print("error")
771+ finally:
772+ print("cleanup")
773+ x = None
774+ """
775+ node = Node(code_str)
776+ try_stmt = node.find_trys()[0 ]
777+ try_stmt.find_finally().is_equivalent(" print('cleanup')\n x = None" ) # True
778+ ```
779+
780+ #### ` find_matches `
781+
782+ Returns a list of match statements.
783+
784+ ``` python
785+ code_str = """
786+ match x:
787+ case 0:
788+ pass
789+ case _:
790+ pass
791+
792+ match y:
793+ case 1:
794+ pass
795+ """
796+ node = Node(code_str)
797+ len (node.find_matches()) # 2
798+ node.find_matches()[0 ].is_equivalent(" match x:\n case 0:\n pass\n case _:\n pass" ) # True
799+ ```
800+
801+ #### ` find_match_subject `
802+
803+ Returns the subject of a match statement.
804+
805+ ``` python
806+ code_str = """
807+ match x:
808+ case 0:
809+ pass
810+ """
811+ node = Node(code_str)
812+ node.find_matches()[0 ].find_match_subject().is_equivalent(" x" ) # True
813+ ```
814+
815+ #### ` find_match_cases `
816+
817+ Returns a list of case blocks in a match statement.
818+
819+ ``` python
820+ code_str = """
821+ match x:
822+ case 0:
823+ print(0)
824+ print('spam')
825+ case _:
826+ pass
827+ """
828+ node = Node(code_str)
829+ len (node.find_matches()[0 ].find_match_cases()) # 2
830+ node.find_matches()[0 ].find_match_cases()[0 ].find_body().is_equivalent(" print(0)\n print('spam')" ) # True
831+ node.find_matches()[0 ].find_match_cases()[1 ].find_body().is_equivalent(" pass" ) # True
832+ ```
833+
834+ ` is_equivalent() ` cannot be used on the items found by ` find_match_cases() ` because a standalone ` case ` raises a ` SyntaxError ` .
835+
836+ #### ` find_case_pattern `
837+
838+ Returns the pattern of a case block.
839+
840+ ``` python
841+ code_str = """
842+ match x:
843+ case 0:
844+ pass
845+ case [a, b]:
846+ pass
847+ case _:
848+ pass
849+ """
850+ node = Node(code_str)
851+ node.find_matches()[0 ].find_match_cases()[0 ].find_case_pattern().is_equivalent(" 0" ) # True
852+ node.find_matches()[0 ].find_match_cases()[1 ].find_case_pattern().is_equivalent(" [a, b]" ) # True
853+ node.find_matches()[0 ].find_match_cases()[2 ].find_case_pattern().is_equivalent(" _" ) # True
854+ ```
855+
856+ #### ` find_case_guard `
857+
858+ Returns the guard condition of a case block.
859+
860+ ``` python
861+ code_str = """
862+ match x:
863+ case 0 if y > 0:
864+ pass
865+ case [a, b] if y == -1:
866+ pass
867+ case _:
868+ pass
869+ """
870+ node = Node(code_str)
871+ node.find_matches()[0 ].find_match_cases()[0 ].find_case_guard().is_equivalent(" y > 0" ) # True
872+ node.find_matches()[0 ].find_match_cases()[1 ].find_case_guard().is_equivalent(" y == -1" ) # True
873+ node.find_matches()[0 ].find_match_cases()[2 ].find_case_guard().is_empty() # True (no guard)
874+ ```
875+
630876### Getting values
631877
632878` get_ ` functions return the value of the node, not the node itself.
@@ -728,6 +974,34 @@ explorer.has_call("print(math.sqrt(25))")
728974explorer.find_ifs()[0 ].find_bodies()[0 ].has_call(" spam()" )
729975```
730976
977+ #### ` block_has_call `
978+
979+ Checks if a function/method call exists within a specific function (specified as the second argument) or the entire code (if the second argument is not provided).
980+
981+ ``` python
982+ code_str = """
983+ srt = sorted([5, 1, 9])
984+
985+ def foo(lst):
986+ return sorted(lst)
987+
988+ def spam(lst):
989+ return lst.sort()
990+
991+ def eggs(dictionary):
992+ if True:
993+ k = dictionary.get(key)
994+ """
995+ node = Node(code_str)
996+
997+ node.block_has_call(" sorted" , " foo" ) # True
998+ node.block_has_call(" sorted" ) # True
999+ node.block_has_call(" sort" , " spam" ) # True
1000+ node.block_has_call(" get" , " eggs" ) # True
1001+ node.block_has_call(" get" ) # True
1002+ node.block_has_call(" split" ) # False
1003+ ```
1004+
7311005#### ` has_import `
7321006
7331007``` python
0 commit comments