如何解析python编译代码的方法

时间:2019-02-05 10:46:21

标签: python parsing methods

我正在为通过表单上传的文件编写noted by Andreas。这些文件是python脚本,可能存在错误和/或不安全,因此在完全验证之前,请勿执行它们。

一项检查是确保同时存在“运行”和“回滚”两种方法,再次不执行代码

所有上传的python脚本具有相同的结构:

$name = array("ravi", "ram", "rani", 87); 


if (in_array("ravi", $name, TRUE)){

}

if (@in_array("ravi", $name, TRUE)){

}

我找到了以下解决方案,可以使用AST进行此操作:

class Action(ActionGlobal):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def run(self, args):
        print("custom code here")
        ...

    def rollback(self,args):
        print("custom code here")
        ...

它工作正常,但是不是很优雅(body Django validator ...),并且因为我以前从未使用过AST模块,所以我相信可能会有更聪明的方法来实现这一目标。

有什么建议吗?

4 个答案:

答案 0 :(得分:1)

您应该使用dir()

class MyClass:
    def methodA(self):
        print("Method-A")
    def methodB(self):
        print("Method-B")

print(dir(MyClass))

输出:

  

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'methodA' 'methodB' ]

或者,就您而言

print(all(elem in dir(Action) for elem in ['run', 'rollback']))

输出:

  

True

Python 2 Python 3

中均可工作

答案 1 :(得分:0)

在代码中设置一组名称,然后遍历所有必需的名称,将使您的代码少一点copy-paste-y:

code_names = {x.name for x in codetoanalyze.body[1].body}
for reqd_name in ['run', 'rollback']:
    if reqd_name not in code_names:
        raise ValidationError( _('Package error : module must contain a {!r} method'.format(reqd_name)), code='compilation_error', )

答案 2 :(得分:0)

好吧,看来AST是满足我的需要的绝佳解决方案,因此我创建了一篇说明它的here

对于我的问题,这是我已实施的解决方案:

codetoanalyze = ast.parse( open('/path/to/script_to_analyse.py','r').read())

# AST checks
if True not in [ [ y for y in x.bases if y.id == 'ActionGlobal' ] != [] for x in codetoanalyze.body if type(x) is ast.ClassDef and x.name == "Action" ] :
    raise ValidationError( _('Package error : module must provide an Action class which inherits from ActionGlobal'), code='compilation_error', )

methods = [ z.name for x in codetoanalyze.body if type(x) is ast.ClassDef and x.name == "Action" for y in x.bases if y.id == 'ActionGlobal' for z in x.body ]
for reqd_name in ['run', 'rollback']:
    if reqd_name not in methods:
        raise ValidationError( _('Package error : module must contain a "{}" method').format(reqd_name), code='compilation_error', )

如果有人找到了通过其他模块(也许是parser来实现这一目标的更好方法),我将等待其他帖子并投票,然后再选择接受的答案。

谢谢您的帮助

答案 3 :(得分:-1)

我会使用类似访客的图案遍历树