Python3函数调用、字符串插值和变量跟踪的静态代码分析器
pystrict3的Python项目详细描述
肾盂狭窄
pyrestrict3静态地检查Python3代码中的简单错误,例如
- 使用错误数量的参数调用函数
- 访问从未定义的属性和方法
- 跟踪和重用变量
这补充了其他静态分析仪,如pyflakes,以及 可与linter和代码格式检查程序(如pylint和flake8)一起使用。在
假设
pystrict3假设Python代码并不奇怪,因此
- 没有猴子修补
- 没有可以改变类和变量的魔术属性(u dict_uqu,uu local_uu)
- 禁止改动建筑等
需要Python3.5及更高版本。在
规则
Pyrist3强制变量只分配一次。 这避免了变量语义的隐藏和更改,并导致更干净、更惯用的代码 副作用少。它还可以防止重写python内置函数
parse = parse(foo) ## bad node = get_node() node.foo() ## ok, modification node += 3 ## ok, modification def format(...): ## bad, format is a python keyword import requests, html html = requests.get(url) ## bad: overwrites imported package name
pystrict3检查函数是否使用 正确的参数数。例如,这会在执行之前捕获bug 当调用签名更改为包含附加参数时:
^{pr2}$pystrict3检查类是否使用正确数量的参数实例化, 方法使用正确数量的参数调用,并且 只有在某处分配的属性才被访问。 例如,这会在执行之前捕获bug 当调用签名更改为包含附加参数时:
class Foo(): def __init__(self, a): self.a = a def foo(self): self.b = 3 print(self.a) ## OK def bar(self, c): print(self.b) ## OK return self.c ## error, because never assigned Foo(1, 2) ## error: wrong number of arguments for __init__ foo = Foo(1) ## OK # real example: class Ellipse: def __init__(self,center,radius_x,radius_y,fill_color,line_color,line_width): self.center = center self.radiusx = radius_x self.radiusy = radius_y self.fill_color = fill_color self.line_color = line_color self.line_width = line_width def strarray(self): return [" <ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\"\n" %\ (self.center[0],self.center[1],self.radius_x,self.radius_y), " style=\"fill:%s;stroke:%s;stroke-width:%d\"/>\n" % (colorstr(self.fill_color),colorstr(self.line_color),self.line_width)] # error above: self.radius_x vs self.radiusx
贡献
欢迎投稿。在
pystrict3可能无法捕获所有角落的情况。 它努力避免无意的误报,并且 集成测试的高代码覆盖率(请参见运行测试.sh和测试/目录)。在
在activestate食谱上测试,大约有一半的有效Python3 程序符合pystrict3,这表明它的指导方针 已经被遵守了。在
安装
$ pip3 install pystrict3
使用
运行方式:
$ python3 pystrict3.py <filenames> $ python3 pystrict3.py --import-builtin <filenames> $ python3 pystrict3.py --import-any <filenames>
使用多个文件名运行的好处是 首先记录并验证所有文件中的函数签名。在
使用运行–import builtin检查对builtin的函数调用 模块。在
使用运行–import any检查对任何模块的函数调用, 但这需要pystrict3来导入它们,这可能是任意运行的 模块代码。在
标准输出示例:
tests/expect-fail/recipe-412717.py:32: ERROR: Variable reuse: "Test" tests/expect-fail/recipe-425043.py:13: ERROR: Function "pow" (3..3 arguments) called with 2 arguments tests/expect-fail/recipe-578135.py:184: ERROR: Function "encode" (3..3 arguments) called with 2 arguments
否则,如果检测到错误代码为1,则返回。 对于非冗余/冗余的管道,则为空。在
许可证
BSD 2-条款。在
蒂普斯
不符合超磁致伸缩3是可以的。它可以作为指导 更清洁的代码。在
如何写入Pyristic3 compliance:
使用del主动删除未使用的变量:
answer = input("Do you want to play? (yes/no)") if answer == "no": sys.exit() del answer answer = int(input("first value")) print(answer * 10):
在明确地命名计算部分:
# bad: magicnumber = sys.argv[1] magicnumber = int(magicnumber) # better: magicnumberstr = sys.argv[1] magicnumber = int(magicnumberstr) filename = 'foo.pdf' if condition: filename = 'foo.png' # bad # better: if condition: filename = 'foo.png' else: filename = 'foo.pdf' # bad: path = os.path.basename(sys.argv[1]) path = path + filename # bad: variable changes meaning path = path + extension # better: components = [] components.append(os.path.basename(sys.argv[1])) components.append(filename) components.append(extension) path = ''.join(components)
在重构为函数:
# original: "changes" is being reused. USE_JYTHON = False try: # ... code detecting something, which throws an exception USE_JYTHON = True ## re-assigning: not allowed # could use instead: # USE_JYTHON |= True except: pass # or define a function USE_JYTHON = check_jython() # original: a sorting construct changes = True while changes: changes = False for a in ...: if ...: changes = True break if not changes: break # new: function returns when no further changes are needed def mysort(objs): while True: changes = False for a in ...: if ...: changes = True break if not changes: return objs
在将docstring移到文件的开头,而不是指定给uu doc_uu。在
在
发行说明
0.1.0(2020-03-07)
- 第一版
- 项目
标签: