将 Pylint 与 Django 结合使用

发布于 2024-07-05 11:33:06 字数 1427 浏览 8 评论 0原文

我非常想将 pylint 集成到构建过程中 我的 python 项目,但我遇到了一个阻碍:其中之一 我发现非常有用的错误类型--:E1101: *%s %r 没有 %r member*--使用常见的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 源,请指出具体细节:)

请参阅 此处总结了我在使用 pycheckerpyflakes 时遇到的问题 - 事实证明,它们对于一般情况来说非常不稳定使用。 (在 pychecker 的例子中,崩溃源自 pychecker 代码——而不是加载/调用的源代码。)

I would very much like to integrate pylint into the build process for
my python projects, but I have run into one show-stopper: One of the
error types that I find extremely useful--:E1101: *%s %r has no %r
member*
--constantly reports errors when using common django fields,
for example:

E1101:125:get_user_tags: Class 'Tag' has no 'objects' member

which is caused by this code:

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

How can I tune Pylint to properly take fields such as objects into account? (I've also looked into the Django source, and I have been unable to find the implementation of objects, so I suspect it is not "just" a class field. On the other hand, I'm fairly new to python, so I may very well have overlooked something.)

Edit: The only way I've found to tell pylint to not warn about these warnings is by blocking all errors of the type (E1101) which is not an acceptable solution, since that is (in my opinion) an extremely useful error. If there is another way, without augmenting the pylint source, please point me to specifics :)

See here for a summary of the problems I've had with pychecker and pyflakes -- they've proven to be far to unstable for general use. (In pychecker's case, the crashes originated in the pychecker code -- not source it was loading/invoking.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

杀お生予夺 2024-07-12 11:33:06

由于 pylint 的工作方式(它检查源本身,而不让 Python 实际执行它), pylint 很难弄清楚元类和复杂基类实际上如何影响类及其实例。 “pychecker”工具在这方面要好一些,因为它确实让 Python 执行代码; 它导入模块并检查生成的对象。 然而,这种方法还有其他问题,因为它实际上让 Python 执行代码:-)

您可以扩展 pylint 来教它有关 Django 使用的神奇功能,或者让它更好地理解元类或复杂的基类,或者忽略这种情况在检测到一个或多个特征后,它不太理解。 我认为这不会特别容易。 您还可以通过源代码、命令行选项或 .pylintrc 文件中的特殊注释告诉 pylint 不要警告这些事情。

Because of how pylint works (it examines the source itself, without letting Python actually execute it) it's very hard for pylint to figure out how metaclasses and complex baseclasses actually affect a class and its instances. The 'pychecker' tool is a bit better in this regard, because it does actually let Python execute the code; it imports the modules and examines the resulting objects. However, that approach has other problems, because it does actually let Python execute the code :-)

You could extend pylint to teach it about the magic Django uses, or to make it understand metaclasses or complex baseclasses better, or to just ignore such cases after detecting one or more features it doesn't quite understand. I don't think it would be particularly easy. You can also just tell pylint to not warn about these things, through special comments in the source, command-line options or a .pylintrc file.

幽梦紫曦~ 2024-07-12 11:33:06

django-lint 是一个很好的工具,它使用 django 特定设置包装 pylint : http:// chris-lamb.co.uk/projects/django-lint/

github 项目:https:/ /github.com/lamby/django-lint

django-lint is a nice tool which wraps pylint with django specific settings : http://chris-lamb.co.uk/projects/django-lint/

github project: https://github.com/lamby/django-lint

扮仙女 2024-07-12 11:33:06

请勿通过添加 ignoresgenerated-members 来禁用或削弱 Pylint 功能。
使用积极开发的 Pylint 插件,该插件理解 Django。
Django 的 Pylint 插件 工作得很好:

pip install pylint-django

运行 pylint 时将以下标志添加到命令中:

--load-plugins pylint_django

详细的博客文章此处

Do not disable or weaken Pylint functionality by adding ignores or generated-members.
Use an actively developed Pylint plugin that understands Django.
This Pylint plugin for Django works quite well:

pip install pylint-django

and when running pylint add the following flag to the command:

--load-plugins pylint_django

Detailed blog post here.

孤单情人 2024-07-12 11:33:06

我使用以下内容:pylint -- generated-members=objects

I use the following: pylint --generated-members=objects

别把无礼当个性 2024-07-12 11:33:06

如果您使用 Visual Studio Code,请执行以下操作:

pip install pylint-django

并添加到 VSC 配置:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],

If you use Visual Studio Code do this:

pip install pylint-django

And add to VSC config:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
巡山小妖精 2024-07-12 11:33:06

我的 ~/.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 行)。

快乐的时光!

My ~/.pylintrc contains

[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id

the last two are specifically for Django.

Note that there is a bug in PyLint 0.21.1 which needs patching to make this work.

Edit: After messing around with this a little more, I decided to hack PyLint just a tiny bit to allow me to expand the above into:

[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id,[a-zA-Z]+_set

I simply added:

    import re
    for pattern in self.config.generated_members:
        if re.match(pattern, node.attrname):
            return

after the fix mentioned in the bug report (i.e., at line 129).

Happy days!

我也只是我 2024-07-12 11:33:06

这不是一个解决方案,但您可以将 objects = models.Manager() 添加到您的 Django 模型中,而无需更改任何行为。

我自己只使用 pyflakes,主要是由于 pylint 中的一些愚蠢的默认值和我的懒惰(不想查找如何更改默认值)。

This is not a solution, but you can add objects = models.Manager() to your Django models without changing any behavior.

I myself only use pyflakes, primarily due to some dumb defaults in pylint and laziness on my part (not wanting to look up how to change the defaults).

氛圍 2024-07-12 11:33:06

我放弃使用 pylint/pychecker,转而使用 pyflakes 和 Django 代码 - 它只是尝试导入模块并报告它发现的任何问题,例如未使用的导入或未初始化的本地名称。

I resigned from using pylint/pychecker in favor of using pyflakes with Django code - it just tries to import module and reports any problem it finds, like unused imports or uninitialized local names.

清引 2024-07-12 11:33:06

对于 Neovim 和 vim8 使用 w0rp's ale 插件。 如果您已正确安装所有内容,包括 w0rp's alepylintpylint-django。 在您的 vimrc 中添加以下行 & 享受使用 django 开发 Web 应用程序的乐趣。
谢谢。

let g:ale_python_pylint_options = '--load-plugins pylint_django'

For neovim & vim8 use w0rp's ale plugin. If you have installed everything correctly including w0rp's ale, pylint & pylint-django. In your vimrc add the following line & have fun developing web apps using django.
Thanks.

let g:ale_python_pylint_options = '--load-plugins pylint_django'
北斗星光 2024-07-12 11:33:06

尝试运行 pylint

pylint --ignored-classes=Tags

如果有效,请添加所有其他 Django 类 - 可能使用脚本,例如 python :P

--ignore-classes 的文档是:

--ignored-classes=<成员名称>
其成员的类名称列表
不应检查属性
(对于具有属性的类很有用
动态设置)。 [当前:%默认]

我应该补充一点,在我看来,这不是一个特别优雅的解决方案,但它应该可行。

Try running pylint with

pylint --ignored-classes=Tags

If that works, add all the other Django classes - possibly using a script, in say, python :P

The documentation for --ignore-classes is:

--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]

I should add this is not a particular elegant solution in my view, but it should work.

穿透光 2024-07-12 11:33:06

到目前为止,我还没有找到真正的解决方案,但可以解决:

  • 在我们公司,我们需要一个 pylint
    分数> 8. 这允许编码
    pylint 不明白的做法
    同时确保代码不是
    太“不寻常”了。 到目前为止我们还没有看到
    E1101 留下我们的任何实例
    达到 8 分或
    更高。
  • 我们的“检查”目标
    过滤掉“因为没有‘对象’
    成员”消息删除大部分
    pylint 造成的干扰不是
    了解姜戈。

So far I have found no real solution to that but work around:

  • In our company we require a pylint
    score > 8. This allows coding
    practices pylint doesn't understand
    while ensuring that the code isn't
    too "unusual". So far we havn't seen
    any instance where E1101 kept us
    from reaching a score of 8 or
    higher.
  • Our 'make check' targets
    filter out "for has no 'objects'
    member" messages to remove most of
    the distraction caused by pylint not
    understanding Django.
错爱 2024-07-12 11:33:06

对于heroku用户,您还可以使用Tal Weiss对此问题的回答,使用以下语法使用 pylint-django 运行 pylint插件(将 timekeeping 替换为您的应用程序/包):

# run on the entire timekeeping app/package
heroku local:run pylint --load-plugins pylint_django timekeeping

# run on the module timekeeping/report.py
heroku local:run pylint --load-plugins pylint_django timekeeping/report.py

# With temporary command line disables
heroku local:run pylint --disable=invalid-name,missing-function-docstring --load-plugins pylint_django timekeeping/report.py

注意:如果不指定项目/包目录,我将无法运行。

如果您遇到 E5110:Django 未配置。 问题,您还可以按如下方式调用来尝试解决该问题(再次将 timekeeping 更改为您的应用/包) :

heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "timekeeping"])'

# With temporary command line disables, specific module
heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "--disable=invalid-name,missing-function-docstring", "timekeeping/report.py"])'

For heroku users, you can also use Tal Weiss's answer to this question using the following syntax to run pylint with the pylint-django plugin (replace timekeeping with your app/package):

# run on the entire timekeeping app/package
heroku local:run pylint --load-plugins pylint_django timekeeping

# run on the module timekeeping/report.py
heroku local:run pylint --load-plugins pylint_django timekeeping/report.py

# With temporary command line disables
heroku local:run pylint --disable=invalid-name,missing-function-docstring --load-plugins pylint_django timekeeping/report.py

Note: I was unable to run without specifying project/package directories.

If you have issues with E5110: Django was not configured., you can also invoke as follows to try to work around that (again, change timekeeping to your app/package):

heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "timekeeping"])'

# With temporary command line disables, specific module
heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "--disable=invalid-name,missing-function-docstring", "timekeeping/report.py"])'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文