Skip to content

Commit f50819f

Browse files
authored
docs: add missing python helper methods (#363)
* update docs * remove find_case_body references * Update docs/python.md
1 parent d588fd9 commit f50819f

1 file changed

Lines changed: 274 additions & 0 deletions

File tree

docs/python.md

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,28 @@ Node("a: int = 1").find_variable("a").is_equivalent("a: int = 1")
205205
Node("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
627649
explorer.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\nexcept ZeroDivisionError:\n print('division by zero')\nelse:\n print('no error')\nfinally:\n print('cleanup')") # True
675+
node.find_trys()[1].is_equivalent("try:\n y = int('abc')\nexcept:\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')\nx = 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')\nx = 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)\nprint('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))")
728974
explorer.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

Comments
 (0)