Skip to content

Commit

Permalink
docs: update python helpers docs (#184)
Browse files Browse the repository at this point in the history
* update examples

* add new helpers

* add comments
  • Loading branch information
Dario-DC authored Apr 19, 2024
1 parent d68454c commit ce4f889
Showing 1 changed file with 258 additions and 1 deletion.
259 changes: 258 additions & 1 deletion docs/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def b(d, e):

### `__pyodide.runPython`

Running the code of a singluar function to get the output:
Running the code of a singular function to get the output:

```javascript,mdbook-runnable,hidelines=#
# {{#rustdoc_include tools/helpers.js:1}}
Expand Down Expand Up @@ -154,10 +154,34 @@ The output and source string compile to the same AST, but the output is indented
Node('def foo():\n x = "1"').find_function("foo").has_variable("x") # True
```

#### `find_async_function`

```python
Node('async def foo():\n await bar()').find_async_function("foo").is_equivalent("async def foo():\n await bar()") # True
```

#### `find_awaits`

```python
code_str = """
async def foo(spam):
if spam:
await spam()
await bar()
await func()
"""
explorer = Node(code_str)
explorer.find_async_function("foo").find_awaits()[0].is_equivalent("await bar()") # True
explorer.find_async_function("foo").find_awaits()[1].is_equivalent("await func()") # True
explorer.find_async_function("foo").find_ifs()[0].find_awaits()[0].is_equivalent("await spam()") # True
```

#### `find_variable`

```python
Node("y = 2\nx = 1").find_variable("x").is_equivalent("x = 1")
Node("a: int = 1").find_variable("a").is_equivalent("a: int = 1")
Node("self.spam = spam").find_variable("self.spam").is_equivalent("self.spam = spam")
```

#### `find_aug_variable`
Expand All @@ -182,6 +206,48 @@ def foo():
Node(func_str).find_function("foo").find_body().is_equivalent("x = 1") # True
```

#### `find_return`

```python
code_str = """
def foo():
if x == 1:
return False
return True
"""
Node(code_str).find_function("foo").find_return().is_equivalent("return True") # True
Node(code_str).find_function("foo").find_ifs()[0].find_return().is_equivalent("return False") # True
```

#### `find_calls`

```python
code_str = """
print(1)
print(2)
foo("spam")
obj.foo("spam")
obj.bar.foo("spam")
"""
explorer = Node(code_str)
len(explorer.find_calls("print")) # 2
explorer.find_calls("print")[0].is_equivalent("print(1)")
explorer.find_calls("print")[1].is_equivalent("print(2)")
len(explorer.find_calls("foo")) # 3
explorer.find_calls("foo")[0].is_equivalent("foo('spam')")
explorer.find_calls("foo")[1].is_equivalent("obj.foo('spam')")
explorer.find_calls("foo")[2].is_equivalent("obj.bar.foo('spam')")
```

#### `find_call_args`

```python
explorer = Node("print(1, 2)")
len(explorer.find_calls("print")[0].find_call_args()) # 2
explorer.find_calls("print")[0].find_call_args()[0].is_equivalent("1")
explorer.find_calls("print")[0].find_call_args()[1].is_equivalent("2")
```

#### `find_class`

```python
Expand Down Expand Up @@ -413,6 +479,133 @@ explorer3.find_for_loops()[0].find_bodies()[1].is_equivalent("print(x)") # True
explorer3.find_for_loops()[1].find_bodies()[0].is_equivalent("pass") # True
```

#### `find_imports`

```python
code_str = """
import ast, sys
from math import factorial as f
"""

explorer = Node(code_str)
len(explorer.find_imports()) # 2
explorer.find_imports()[0].is_equivalent("import ast, sys")
explorer.find_imports()[1].is_equivalent("from math import factorial as f")
```

#### `find_comps`

Returns a list of list comprehensions, set comprehensions, dictionary comprehensions and generator expressions nodes not assigned to a variable or part of other statements.

```python
code_str = """
[i**2 for i in lst]
(i for i in lst)
{i * j for i in spam for j in lst}
{k: v for k,v in dict}
comp = [i for i in lst]
"""
explorer = Node(code_str)
len(explorer.find_comps()) # 4
explorer.find_comps()[0].is_equivalent("[i**2 for i in lst]")
explorer.find_comps()[1].is_equivalent("(i for i in lst)")
explorer.find_comps()[2].is_equivalent("{i * j for i in spam for j in lst}")
explorer.find_comps()[3].is_equivalent("{k: v for k,v in dict}")
```

#### `find_comp_iters`

Returns a list of comprehension/generator expression iterables. It can be chained to `find_variable`, `find_return`, `find_call_args()[n]`.

```python
code_str = """
x = [i**2 for i in lst]
def foo(spam):
return [i * j for i in spam for j in lst]
"""
explorer = Node(code_str)
len(explorer.find_variable("x").find_comp_iters()) # 1
explorer.find_variable("x").find_comp_iters()[0].is_equivalent("lst")

len(explorer.find_function("foo").find_return().find_comp_iters()) # 2
explorer.find_function("foo").find_return().find_comp_iters()[0].is_equivalent("spam")
explorer.find_function("foo").find_return().find_comp_iters()[1].is_equivalent("lst")
```

#### `find_comp_targets`

Returns a list of comprhension/generator expression targets (i.e. the iteration variables).

```python
code_str = """
x = [i**2 for i in lst]
def foo(spam):
return [i * j for i in spam for j in lst]
"""
explorer = Node(code_str)
len(explorer.find_variable("x").find_comp_targets()) # 1
explorer.find_variable("x").find_comp_targets()[0].is_equivalent("i")

len(explorer.find_function("foo").find_return().find_comp_targets()) # 2
explorer.find_function("foo").find_return().find_comp_targets()[0].is_equivalent("i")
explorer.find_function("foo").find_return().find_comp_targets()[1].is_equivalent("j")
```

#### `find_comp_key`

Returns the dictionary comprehension key.

```python
code_str = """
x = {k: v for k,v in dict}
def foo(spam):
return {k: v for k in spam for v in lst}
"""
explorer = Node(code_str)
explorer.find_variable("x").find_comp_key().is_equivalent("k")

explorer.find_function("foo").find_return().find_comp_key().is_equivalent("k")
```

#### `find_comp_expr`

Returns the expression evaluated at each iteration of comprehensions/generator expressions. It includes the `if`/`else` portion. In case only the `if` is present, use `find_comp_ifs`.

```python
code_str = """
x = [i**2 if i else -1 for i in lst]
def foo(spam):
return [i * j for i in spam for j in lst]
"""
explorer = Node(code_str)
explorer.find_variable("x").find_comp_expr().is_equivalent("i**2 if i else -1")

explorer.find_function("foo").find_return().find_comp_expr().is_equivalent("i * j")
```

#### `find_comp_ifs`

Returns a list of comprehension/generator expression `if` conditions. The `if`/`else` construct instead is part of the expression and is found with `find_comp_expr`.

```python
code_str = """
x = [i**2 if i else -1 for i in lst]
def foo(spam):
return [i * j for i in spam if i > 0 for j in lst if j != 6]
"""
explorer = Node(code_str)
len(explorer.find_variable("x").find_comp_ifs()) # 0

len(explorer.find_function("foo").find_return().find_comp_ifs()) # 2
explorer.find_function("foo").find_return().find_comp_ifs()[0].is_equivalent("i > 0")
explorer.find_function("foo").find_return().find_comp_ifs()[1].is_equivalent("j != 6")
```

### Getting values

`get_` functions return the value of the node, not the node itself.
Expand All @@ -439,6 +632,14 @@ Node("x = 1").has_variable("x") # True
Node("def foo():\n pass").has_function("foo") # True
```

#### `has_stmt`

Returns a boolean indicating if the specified statement is found.

```python
Node("name = input('hi')\nself.matrix[1][5] = 3").has_stmt("self.matrix[1][5] = 3") # True
```

#### `has_args`

```python
Expand All @@ -452,8 +653,26 @@ Node("def foo():\n pass").find_function("foo").has_pass() # True
Node("if x==1:\n x+=1\nelse: pass").find_ifs()[0].find_bodies()[1].has_pass() # True
```

#### `has_return`

Returns a boolean indicating if the function returns the specified expression/object.

```python
code_str = """
def foo():
if x == 1:
return False
return True
"""
explorer = Node(code_str)
explorer.find_function("foo").has_return("True") # True
explorer.find_function("foo").find_ifs()[0].has_return("False") # True
```

#### `has_returns`

Returns a boolean indicating if the function has the specified return annotation.

```python
Node("def foo() -> int:\n return 0").find_function("foo").has_returns("int") # True
Node("def foo() -> 'spam':\n pass").find_function("foo").has_returns("spam") # True
Expand All @@ -473,6 +692,44 @@ Node(code_str).find_class("A").find_function("foo").has_decorators("property") #
Node(code_str).find_class("A").find_function("foo").has_decorators("property", "staticmethod") # True
```

#### `has_call`

```python
code_str = """
print(math.sqrt(25))
if True:
spam()
"""

explorer = Node(code_str)
explorer.has_call("print(math.sqrt(25))")
explorer.find_ifs()[0].find_bodies()[0].has_call("spam()")
```

#### `has_import`

```python
code_str = """
import ast, sys
from math import factorial as f
"""

explorer = Node(code_str)
explorer.has_import("import ast, sys")
explorer.has_import("from math import factorial as f")
```

#### `has_class`

```python
code_str = """
class spam:
pass
"""

Node(code_str).has_class("spam")
```

### Misc

#### `is_equivalent`
Expand Down

0 comments on commit ce4f889

Please sign in to comment.