メソッドで使用される標準関数によってエラーを出す方法
学生向けにプログラミング能力を試験するテストを作りました。
https://github.com/ernix/quiz/blob/master/q1.py
python2で書かれており、指定の機能もったメソッドをクラスに実装するテストなのですが、実行することでクラス自身が自己採点できるような作りになっています。
その中でevalのような一部のビルトイン関数を使われる事が無いよう制限をかけたいのですが、tokenize
を使ってメソッドの字面だけをパースする方法だとデコレータが使われりプライベートメソッドを呼び出した時に対応できません。
一部抜粋:
""" test 3: keywords """
from cStringIO import StringIO
import inspect
import tokenize
code = StringIO(''.join(inspect.getsourcelines(method)[0][1:]))
tokens = tokenize.generate_tokens(code.readline)
name_tokens = []
for toknum, tokval, _, _, _ in tokens:
if toknum == tokenize.NAME and tokval in used_keyword.keys():
name_tokens.append(tokval)
for t in set(name_tokens):
if t in kw_not_allowed:
errors.append(['`%s` is not allowed' % (t)])
elif used_keyword[t] is not None:
errors.append([
'`%s` is already used in %s' % (t, used_keyword[t]),
])
else:
used_keyword[t] = f
特にinspect.getsourcelines(method)[0][1:]
のあたりです。defから始まる最初の行はスキップするようになっています。
このようにメソッドの中身を単純にパースするのではなく、動的にビルトイン関数を上書きしてエラーを出すように変更することは可能でしょうか?