我正在为通过表单上传的文件编写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模块,所以我相信可能会有更聪明的方法来实现这一目标。
有什么建议吗?
答案 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)
我会使用类似访客的图案遍历树