Я делаю парсинг исходного кода Python с GitHub, используя модуль AST, чтобы увидеть, как часто используются различные функции и библиотеки. Мне удалось успешно проанализировать вызовы функций и импорт библиотек, так что я могу перехватывать такие вещи, как import numpy as np
и np.array([1, 2, 3])
, и документировать, что был вызван numpy.array (я также могу обрабатывать операции импорта).
Проблема, с которой я сталкиваюсь, заключается в перехвате таких вызовов, как
x = [1, 1, 2, 1, 3]
x.count(1)
Я могу извлечь x.count(1)
, но поскольку я не знаю тип x (списки и строки имеют метод подсчета), я не могу полностью проанализировать и записать эти вызовы функций.
Есть идеи, как к этому подойти? Должен ли я попытаться сохранить рабочее пространство имен переменных и их содержимое / типы, а затем попытаться выяснить, какой библиотеке соответствует функция? Просто кажется, что здесь слишком много сложности, так как вы можете иметь такие выражения, как x, y = (len (a), str (b)), поэтому я надеюсь, что есть более простой способ. Спасибо!
Вот как я подошел к нему для других частей. Код адаптирован из другого поста StackOverflow.
class ParseCall(ast.NodeVisitor):
def __init__(self):
self.ls = []
def visit_Attribute(self, node):
ast.NodeVisitor.generic_visit(self, node)
self.ls.append(node.attr)
def visit_Name(self, node):
self.ls.append(node.id)
class FindFuncs(ast.NodeVisitor):
def __init__(self):
self.funcs = []
def visit_Call(self, node):
p = ParseCall()
p.visit(node.func)
self.funcs.append(".".join(p.ls))
ast.NodeVisitor.generic_visit(self, node)
class FindImports(ast.NodeVisitor):
def __init__(self):
self.imports = {}
def visit_Import(self, node):
for x in node.names:
if(x.asname): self.imports[x.asname] = x.name
else: self.imports[x.name] = x.name
def visit_ImportFrom(self, node):
for x in node.names:
if(x.asname): self.imports[x.asname] = f"{node.module}.{x.name}"
else: self.imports[x.name] = f"{node.module}.{x.name}"