如何自动化测试以强制 Python 2.x 代码主体不包含字符串实例(仅 unicode 实例)?
例如。
我可以从代码中做到这一点吗?
有没有具有此功能的静态分析工具?
编辑:
我希望将它用于 Python 2.5 中的应用程序,但事实证明这是不可能的,因为:
- 2.5不支持
unicode_literals
- kwargs 字典键不能是 unicode 对象,只能是字符串
因此,我接受了不可能的答案,即使出于不同的原因:)
如何自动化测试以强制 Python 2.x 代码主体不包含字符串实例(仅 unicode 实例)?
例如。
我可以从代码中做到这一点吗?
有没有具有此功能的静态分析工具?
编辑:
我希望将它用于 Python 2.5 中的应用程序,但事实证明这是不可能的,因为:
unicode_literals
因此,我接受了不可能的答案,即使出于不同的原因:)
在我看来,您确实需要使用诚实的 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 字符串不是 unicode 但应该被允许,因此您可能需要做一些更复杂的事情,例如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())
您不能强制所有字符串都是 Unicode;即使from __future__ import unicode_literals
在模块中,字节字符串也可以写成b'...'
,就像在 Python 3 中一样。
有一个选项可以用来获得与全局相同的效果:unicode_literals
命令行选项-U
。然而,它在 2.x 系列的早期就被放弃了,因为它基本上破坏了所有脚本。
你这样做的目的是什么?不希望废除字节串。它们不是“坏”的,Unicode 字符串也不是普遍“更好”的;它们是两种不同的动物,你将需要它们。与二进制文件和网络服务通信肯定需要字节字符串。
如果您想为过渡到 Python 3 做好准备,最好的方法是编写b'...'
所有您真正想成为字节u'...'
的字符串,以及本质上是 Unicode 的字符串。默认字符串'...'
格式可用于其他所有内容、您不关心的地方和/或 Python 3 是否更改默认字符串类型。
我们的SD 源代码搜索引擎 (SCSE)可以直接提供此结果。
SCSE 提供了一种使用某些语言结构在大量文件中快速搜索的方法,以实现精确查询并最大限度地减少误报。它甚至可以同时处理多种语言,包括 Python。GUI 显示搜索命中和包含选定命中的文件中的实际文本页面。
它使用来自源语言的词汇信息作为查询的基础,由各种语言关键字和匹配不同内容语言元素的模式标记组成。SCSE 知道语言中可用的词位类型。可以搜索通用标识符(使用查询标记 I)或匹配某个正则表达式的标识符。类似地,on 可以搜索通用字符串(使用查询标记“S”来表示“任何类型的字符串文字”)或特定类型的字符串(对于 Python,包括“UnicodeStrings”、非 unicode 字符串等,它们共同使组成“S”的一组 Python 事物)。
于是一搜:
'for' ... I=ij*
在(“...”)前缀为“ij”的标识符附近找到关键字“for”,并向您显示所有匹配项。(包括换行符和注释在内的特定于语言的空格将被忽略。
一个简单的搜索:
S
查找所有字符串文字。这通常是一个很大的集合:-}
搜索
UnicodeStrings
查找在词法上定义为 Unicode 字符串 (u"...") 的所有字符串文字
你想要的是所有不是 UnicodeStrings 的字符串。SCSE 提供了一个“减法”运算符,用于减去与另一种命中重叠的一种命中。因此,您的问题“哪些字符串不是 unicode”简洁地表达为:
S-UnicodeStrings
显示的所有命中都将是不是 unicode 字符串的字符串,这是您的确切问题。
SCSE 提供了日志功能,以便您可以记录命中。您可以从命令行运行 SCSE,为您的答案启用脚本查询。将其放入命令脚本将提供一个工具,直接给出您的答案。