Python3函数调用、字符串插值和变量跟踪的静态代码分析器

pystrict3的Python项目详细描述


肾盂狭窄

pyrestrict3静态地检查Python3代码中的简单错误,例如

  • 使用错误数量的参数调用函数
  • 访问从未定义的属性和方法
  • 跟踪和重用变量

这补充了其他静态分析仪,如pyflakes,以及 可与linter和代码格式检查程序(如pylint和flake8)一起使用。在

https://travis-ci.org/JohannesBuchner/pystrict3.svg?branch=masterhttps://coveralls.io/repos/github/JohannesBuchner/pystrict3/badge.svg?branch=master

假设

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)

  • 第一版

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
JAVAutil。整数java的扫描器键盘输入   java通知运行后立即崩溃   java如何在一个只能由类修改而不能由其实例修改的类中生成静态变量?   数据库Java字段猜测   返回值周围的java括号为什么?   java Android更新通讯录中的联系人   一个消费者正在读取数据   java是否可以通过编程方式为蓝牙配对设置pin?   java Spring引导和buildResponseEntity()   java为什么序列化可以在没有实现可序列化的情况下工作   Java同步无助于相互排斥   twitter Java Twitter4J未在推文下显示源标签   为什么Javasocket不支持中断处理?