在Django中使用Pylint
我非常想将pylint集成到
我的python项目,但遇到了一个显示停止器:
我认为非常有用的错误类型-:E1101:%s%r没有%r
成员`-使用常见的django字段时始终报告错误,
例如:
E1101:125:get_user_tags: Class 'Tag' has no 'objects' member
这是由以下代码引起的:
def get_user_tags(username): """ Gets all the tags that username has used. Returns a query set. """ return Tag.objects.filter( ## This line triggers the error. tagownership__users__username__exact=username).distinct() # Here is the Tag class, models.Model is provided by Django: class Tag(models.Model): """ Model for user-defined strings that help categorize Events on on a per-user basis. """ name = models.CharField(max_length=500, null=False, unique=True) def __unicode__(self): return self.name
如何调整Pylint以适当考虑诸如对象之类的字段? (我也研究了Django的源代码,但我一直无法找到`objects'的实现,因此我怀疑它不是"仅仅"一个类字段。另一方面,我对python还是相当陌生的,所以我很可能已经忽略了一些东西。)
编辑:我发现告诉pylint不要警告这些警告的唯一方法是阻止所有类型的错误(E1101),这是不可接受的解决方案,因为(在我看来)这是一个非常有用的错误。如果还有另一种方法,而又不增加pylint的来源,请给我指出细节:)
有关我使用pychecker和pyflakes遇到的问题的摘要,请参见此处,事实证明它们对于一般用途而言非常不稳定。 (在pychecker的情况下,崩溃源于pychecker代码-而不是它正在加载/调用的源。)
解决方案
由于pylint的工作方式(它在不让Python实际执行的情况下检查源代码本身)使pylint很难弄清楚元类和复杂的基类如何实际上影响一个类及其实例。在这方面," pychecker"工具要好一些,因为它确实允许Python执行代码。它导入模块并检查生成的对象。但是,该方法还有其他问题,因为它确实允许Python执行代码:-)
我们可以扩展pylint来教它有关Django所使用的魔术的知识,或者使它更好地理解元类或者复杂的基类,或者在检测到一个或者多个它不太了解的功能之后忽略这些情况。我认为这不会特别容易。我们还可以通过源代码中的特殊注释,命令行选项或者.pylintrc文件,告诉pylint不要警告这些事情。
尝试与运行pylint
pylint --ignored-classes=Tags
如果可行,请使用脚本添加所有其他Django类,例如python:P
--ignore-classes的文档是:
--ignored-classes=<members names> List of classes names for which member attributes should not be checked (useful for classes with attributes dynamicaly set). [current: %default]
我认为这并不是一个特别优雅的解决方案,但它应该可以工作。
我从使用pylint / pychecker辞职,转而将pyflakes与Django代码一起使用,它只是尝试导入模块并报告发现的任何问题,例如未使用的导入或者未初始化的本地名称。
这不是解决方案,但是我们可以在不更改任何行为的情况下将objects = models.Manager()
添加至Django模型。
我自己只使用pyflakes,主要是因为我的部分pylint和懒惰有一些愚蠢的默认设置(不想查看如何更改默认设置)。
到目前为止,我没有找到真正的解决方案,但是可以解决:
- 在我们公司,我们要求pylint分数>8. 这允许pylint无法理解编码实践,同时确保代码不太"异常"。到目前为止,我们还没有看到E1101阻止我们达到8分或者更高分数的情况。
- 我们的" make check"目标过滤掉" for has no'objects member"消息,以消除由于pylint不了解Django引起的大部分干扰。
我使用以下命令:pylint --generation-members = objects
django-lint是一个不错的工具,它使用django特定的设置包装pylint:http://chris-lamb.co.uk/projects/django-lint/
github项目:https://github.com/lamby/django-lint
我的〜/ .pylintrc包含
[TYPECHECK] generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id
最后两个是专门针对Django的。
请注意,PyLint 0.21.1中存在一个错误,需要对其进行修补才能使其正常工作。
编辑:弄乱了一点之后,我决定对PyLint进行一点修改,以允许我将以上内容扩展为:
[TYPECHECK] generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id,[a-zA-Z]+_set
我只是添加:
import re for pattern in self.config.generated_members: if re.match(pattern, node.attrname): return
在错误报告中提到的修复程序之后(即在第129行)。
快乐的时光!