How to use ast to evaluate built-in function using python?

Issue

>>> list("abc")
['a', 'b', 'c']
>>> list = 42
>>> list("xyz")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

How do i find such bugs if one has accidentally assigned values to class-names and function definitions? I wanted to use AST but not really sure how do i do it?

Solution

One approach is to extract ast nodes for constructs that could contain builtin shadowing; for example, assignments, function signatures, for-loops, and comprehensions, and then check if any target names belonging to these ast objects are builtins:

import warnings
import builtins, ast
def extract_names(node):
  if isinstance(node, ast.Name):
     yield node.id
  elif isinstance(node, ast.arg):
     yield node.arg
  elif isinstance(node, list):
     for i in node: yield from extract_names(i)
  else:
     for i in getattr(node, '_fields', []): yield from extract_names(getattr(node, i))

def log_shadowing(node, names):
   for i in names:
      if i in dir(builtins):
         warnings.warn(f"On line {node.lineno}: shadowing of '{i}'")

def check_node(node):
   if isinstance(node, ast.Assign):
      log_shadowing(node, extract_names(node.targets))
   if isinstance(node, ast.FunctionDef):
      log_shadowing(node, [node.name, *extract_names(node.args)])
   if isinstance(node, ast.For):
      log_shadowing(node, extract_names(node.target))
   if isinstance(node, (ast.ListComp, ast.SetComp, ast.DictComp)):
      for i in node.generators:
         log_shadowing(node, extract_names(i.target)) 

sample = """ 
list = 10
def f(a, b, dict, c):
   pass

for set in range(10):
   pass

r = [next for next in range(10)]
"""
for i in ast.walk(ast.parse(sample)):
   check_node(i)

Output:

<stdin>:4: UserWarning: On line 2: shadowing of 'list'
<stdin>:4: UserWarning: On line 3: shadowing of 'dict'
<stdin>:4: UserWarning: On line 6: shadowing of 'set'
<stdin>:4: UserWarning: On line 9: shadowing of 'next'

Answered By – Ajax1234

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published