Evaluate AST node in provided context. Applies evaluation restrictions defined in the context. Currently does not support evaluation of functions with keyword arguments. Does not evaluate actions that always have side effects: - class definitions (``class sth: ...``) - function de
(node: Union[ast.AST, None], context: EvaluationContext)
| 763 | |
| 764 | |
| 765 | def eval_node(node: Union[ast.AST, None], context: EvaluationContext): |
| 766 | """Evaluate AST node in provided context. |
| 767 | |
| 768 | Applies evaluation restrictions defined in the context. Currently does not support evaluation of functions with keyword arguments. |
| 769 | |
| 770 | Does not evaluate actions that always have side effects: |
| 771 | |
| 772 | - class definitions (``class sth: ...``) |
| 773 | - function definitions (``def sth: ...``) |
| 774 | - variable assignments (``x = 1``) |
| 775 | - augmented assignments (``x += 1``) |
| 776 | - deletions (``del x``) |
| 777 | |
| 778 | Does not evaluate operations which do not return values: |
| 779 | |
| 780 | - assertions (``assert x``) |
| 781 | - pass (``pass``) |
| 782 | - imports (``import x``) |
| 783 | - control flow: |
| 784 | |
| 785 | - conditionals (``if x:``) except for ternary IfExp (``a if x else b``) |
| 786 | - loops (``for`` and ``while``) |
| 787 | - exception handling |
| 788 | |
| 789 | The purpose of this function is to guard against unwanted side-effects; |
| 790 | it does not give guarantees on protection from malicious code execution. |
| 791 | """ |
| 792 | policy = get_policy(context) |
| 793 | |
| 794 | if node is None: |
| 795 | return None |
| 796 | if isinstance(node, (ast.Interactive, ast.Module)): |
| 797 | result = None |
| 798 | for child_node in node.body: |
| 799 | result = eval_node(child_node, context) |
| 800 | return result |
| 801 | if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
| 802 | is_async = isinstance(node, ast.AsyncFunctionDef) |
| 803 | func_locals = context.transient_locals.copy() |
| 804 | func_context = context.replace(transient_locals=func_locals) |
| 805 | is_property = False |
| 806 | is_static = False |
| 807 | is_classmethod = False |
| 808 | for decorator_node in node.decorator_list: |
| 809 | try: |
| 810 | decorator = eval_node(decorator_node, context) |
| 811 | except NameError: |
| 812 | # if the decorator is not yet defined this is fine |
| 813 | # especialy because we don't handle imports yet |
| 814 | continue |
| 815 | if decorator is property: |
| 816 | is_property = True |
| 817 | elif decorator is staticmethod: |
| 818 | is_static = True |
| 819 | elif decorator is classmethod: |
| 820 | is_classmethod = True |
| 821 | |
| 822 | if func_context.class_transients is not None: |
no test coverage detected
searching dependent graphs…