正直なところのPythonパーサーでコードを解析する必要があるように思えます。次に、パーサーが生成する AST を掘り下げて、文字列リテラルが含まれているかどうかを確認する必要があります。
Python には、すぐに使用できるパーサーが付属しているようです。このドキュメントから、このコードサンプルが機能するようになりました:
import parser
from token import tok_name
def checkForNonUnicode(codeString):
return checkForNonUnicodeHelper(parser.suite(codeString).tolist())
def checkForNonUnicodeHelper(lst):
returnValue = True
nodeType = lst[0]
if nodeType in tok_name and tok_name[nodeType] == 'STRING':
stringValue = lst[1]
if stringValue[0] != "u": # Kind of hacky. Does this always work?
print "%s is not unicode!" % stringValue
returnValue = False
else:
for subNode in [lst[n] for n in range(1, len(lst))]:
if isinstance(subNode, list):
returnValue = returnValue and checkForNonUnicodeHelper(subNode)
return returnValue
print checkForNonUnicode("""
def foo():
a = 'This should blow up!'
""")
print checkForNonUnicode("""
def bar():
b = u'although this is ok.'
""")
印刷する
'This should blow up!' is not unicode!
False
True
現在、doc 文字列はユニコードではありませんが、許可する必要がfrom symbol import sym_nameあるため、クラスと関数の定義に使用するノード タイプを検索できる場所など、より複雑なことを行う必要がある場合があります。次に、単純な文字列である最初のサブノード、つまり割り当てなどの一部ではない最初のサブノードは、Unicode ではないことを許可する必要があります。
良い質問!
編集
ただの補足コメントです。便利なことに、parser.suite実際には python コードを評価しません。これは、命名エラーやインポート エラーを心配することなく、Python ファイルに対してこのパーサーを実行できることを意味します。たとえば、次のものmyObscureUtilityFile.pyが含まれているとします。
from ..obscure.relative.path import whatever
あなたはできる
checkForNonUnicode(open('/whoah/softlink/myObscureUtilityFile.py').read())