Usando o Pylint com o Django

140

Gostaria muito de integrar o pylint ao processo de compilação dos meus projetos python, mas encontrei um show-stopper: um dos tipos de erro que considero extremamente E1101: *%s %r has no %r member*úteis-- : - relata constantemente erros ao usar campos django comuns , por exemplo:

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

que é causado por este código:

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

Como posso ajustar o Pylint para levar em consideração campos como objetos? (Eu também procurei na fonte do Django e não consegui encontrar a implementação de objects, então suspeito que não seja "apenas" um campo de classe. Por outro lado, sou bastante novo em python, então pode muito bem ter esquecido alguma coisa.)

Edit: A única maneira que eu descobri para dizer ao pylint para não avisar sobre esses avisos é bloqueando todos os erros do tipo (E1101) que não são uma solução aceitável, já que esse é (na minha opinião) um erro extremamente útil. Se houver outra maneira, sem aumentar a fonte pylint, aponte-me para detalhes :)

Veja aqui um resumo dos problemas que tive pycheckere pyflakes- eles provaram ser muito instáveis ​​para uso geral. (No caso do psicólogo, as falhas foram originadas no código do psicólogo - não na fonte que estava carregando / invocando.)

rcreswick
fonte
4
veja a publicação de @ talweiss para obter uma resposta atualizada!
Brendan
Encontrei uma boa solução em stackoverflow.com/a/31000713/78234
shahjapan
1
Você pode aceitar a resposta de @talweiss? É a solução mais atualizada e correta.
Vijay Varadan

Respostas:

155

Não desative ou enfraqueça a funcionalidade Pylint adicionando ignoresou generated-members.
Use um plugin Pylint desenvolvido ativamente que entenda o Django.
Este plugin Pylint para Django funciona muito bem:

pip install pylint-django

e ao executar o pylint, adicione o seguinte sinalizador ao comando:

--load-plugins pylint_django

Postagem detalhada no blog aqui .

Tal Weiss
fonte
2
O link para a postagem do blog está morto (em breve). Aqui estão alguns links arquivados do Internet Archive e de archive.is
Christian Long
3
Para fazê-lo funcionar com o plug-in SublimeLinter do Sublime Text, tive que adicionar --load-plugins=pylint_djangoà configuração linters / pylint / args. Observe o sinal '=', ele não funcionou sem ele.
Dennis Golomazov
não funciona. Eu recebo este erro: E: 8, 0: Nenhum nome 'modelos' no módulo 'django.db' (sem nome no módulo)
max
6
Você também pode adicionar isso no seu pylintrc:[MASTER] load-plugins=pylint_django
azmeuk
3
Em vs código É dose não trabalho para mim até que eu ponha na seguinte nas configurações do usuário: {"python.linting.pylintArgs": [ "--load-plugins=pylint_django" ],} a resposta de tieuminh2510
ali-myousefi
63

Eu uso o seguinte: pylint --generated-members=objects

Shai
fonte
man pylint (1) em TYPECHECK --generated-members=<members names>Lista de membros que são configurados dinamicamente e perdidos pelo sistema de inferência pylint e, portanto, não devem acionar E0201 e E1101 quando acessados. [atual: REQUEST, acl_users, aq_parent]
Mark Mikofski
Eu adiciono isso no PyDev no eclipse sob preferências na seção PyDev / PyLint .
Mark Mikofski
2
O uso de membros gerados apenas oculta esses erros, ainda pode haver erros ao tentar acessar o campo de objetos no objeto errado. Use o plugin pylint-django.
Vajk Hermecz
5
Esta é a maneira errada de corrigir o Pylint - desativando algumas de suas funcionalidades. Tudo que você precisa fazer é instalar um plugin Pylint que entenda o Django. Veja stackoverflow.com/a/31000713/78234
Tal Weiss
31

Meu ~ / .pylintrc contém

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

os dois últimos são especificamente para o Django.

Observe que há um bug no PyLint 0.21.1 que precisa de correções para fazer isso funcionar.

Edit: Depois de brincar um pouco mais com isso, decidi hackear o PyLint um pouquinho para permitir que eu expandisse o exposto acima para:

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

Eu simplesmente adicionei:

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

após a correção mencionada no relatório de erros (ou seja, na linha 129).

Dias felizes!

simon
fonte
Você deve enviar seu patch para pilotar de volta aos mantenedores.
slacy
na verdade, eles incluíram esse patch na versão 0.24, mas começaram a usar o shlexpacote e quebraram outra coisa agora. Eu tive que adicionar gen.wordchars += "[]-+"na linha 135 para obtê-lo para o trabalho ...
simon
4
O uso de membros gerados apenas oculta esses erros, ainda pode haver erros ao tentar acessar o campo 'objetos' no objeto errado. Use o plugin pylint-django.
Vajk Hermecz
4
Esta é a maneira errada de corrigir o Pylint - desativando algumas de suas funcionalidades. Tudo que você precisa fazer é instalar um plugin Pylint que entenda o Django. Veja stackoverflow.com/a/31000713/78234
Tal Weiss
3
@TalWeiss - Para ser justo, esta resposta é três anos mais velho que pylint-django, assim que o downvote é um pouco dura ...
simon
27

Se você usa o Código do Visual Studio, faça o seguinte:

pip install pylint-django

E adicione à configuração do VSC:

"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
Thiago Falcao
fonte
2
Melhor resposta de longe: D
serfer2 10/10/19
19

O django-lint é uma boa ferramenta que envolve o pylint com configurações específicas do django: http://chris-lamb.co.uk/projects/django-lint/

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

maca alex
fonte
1
Eu gosto da idéia de um pylint específico do Django, mas parece um grande buggy da última vez que tentei.
Wernight
3
Também não está disponível via PyPI e o site não parece fornecer informações suficientes, como: Qual é a versão atual?
Wernight
1
Eu gosto do conceito, mas essa implementação é apenas incompleta e quebra em qualquer base de código de tamanho moderado. Ainda há um longo caminho a percorrer antes de ser realmente útil.
Cerin
1
@ alex gurney, Link está morto.
usar o seguinte comando
2
Parece que o pylint-django está mais ativo agora, essa deve ser a solução recomendada.
Vajk Hermecz
16

Por causa de como o pylint funciona (ele examina a fonte em si, sem permitir que o Python realmente o execute), é muito difícil para o pylint descobrir como metaclasses e classes básicas complexas realmente afetam uma classe e suas instâncias. A ferramenta 'pychecker' é um pouco melhor nesse sentido, porque faz realmente deixar Python executar o código; importa os módulos e examina os objetos resultantes. No entanto, essa abordagem tem outros problemas, porque na verdade permite que o Python execute o código :-)

Você pode estender o pylint para ensiná-lo sobre a mágica que o Django usa, ou para entender melhor as metaclasses ou classes básicas complexas, ou simplesmente ignorar esses casos depois de detectar um ou mais recursos que ele não entende. Eu não acho que seria particularmente fácil. Você também pode dizer ao pylint para não avisar sobre isso, através de comentários especiais na fonte, opções de linha de comando ou um arquivo .pylintrc.

Thomas Wouters
fonte
3
Não é fácil ensinar o Pylint sobre o Django, mas já foi feito: tudo o que você precisa fazer é instalar um plugin do Pylint que entenda o Django. Veja stackoverflow.com/a/31000713/78234
Tal Weiss
Bem, eu o instalei, mas ele ainda compensa sobre coisas como o QuerySet não remove ...
Eino Mäkitalo
7

Eu renunciei ao uso do pylint / pychecker em favor do uso de pyflakes com código Django - ele apenas tenta importar o módulo e relata qualquer problema encontrado, como importações não utilizadas ou nomes locais não inicializados.

zgoda
fonte
interessante - vou dar outra olhada aos flocos de neve.
rcreswick 22/09/08
2
O PyChecker captura muito menos que o pylint. doughellmann.com/articles/CompletelyDifferent-2008-03-linters/...
Justin Abrahms
1
Não é necessário desistir do Pylint - Tudo o que você precisa fazer é instalar um plug-in do Pylint que entenda o Django. Veja stackoverflow.com/a/31000713/78234
Tal Weiss
7

Esta não é uma solução, mas você pode adicionar objects = models.Manager()aos seus modelos de Django sem alterar nenhum comportamento.

Eu mesmo uso apenas flocos de neve, principalmente devido a alguns padrões estúpidos de pylint e preguiça da minha parte (não querendo saber como alterar os padrões).

AdamKG
fonte
Ah ... obrigado pela dica. Eu posso tentar apenas adicionar isso ao Model.models na cópia local da fonte do django e ver se isso acontece.
Rcreswick 23/09/08
Eu acho que essa é uma ótima solução, pois não compromete os avisos.
Tom Leys
1
Esta é uma solução ruim . Repetir a si mesmo e substituir algo que for possível mudará mais tarde (introduzindo um problema de controle de qualidade), apenas para corrigir uma ferramenta incompleta de controle de qualidade?
21812 Chris Morgan
2
Eu não chamaria isso de uma solução ruim: explícito é melhor que implícito. Talvez objectsnão deva ser adicionado magicamente de qualquer maneira.
Will Hardy
1
Eu acho que esta é a maneira errada de consertar o Pylint - corrigindo o Django em certo sentido. Tudo que você precisa fazer é instalar um plugin Pylint que entenda o Django. Veja stackoverflow.com/a/31000713/78234
Tal Weiss
5

Tente executar o pylint com

pylint --ignored-classes=Tags

Se isso funcionar, adicione todas as outras classes do Django - possivelmente usando um script, por exemplo, python: P

A documentação para --ignore-classesé:

--ignored-classes=<members names>
Lista de nomes de classes para os quais os atributos de membro não devem ser verificados (útil para classes com atributos definidos dinamicamente). [atual:% padrão]

Devo acrescentar que essa não é uma solução elegante em particular, mas deve funcionar.

espaço livre
fonte
Só funciona se eu nunca cometer erros nessas classes;). Quero evitar ignorar o código, se possível - acho que é uma péssima idéia ter diferentes partes da base de código analisadas em diferentes graus de análise. Eu vou esquecer qual é qual, e fazer suposições falsas quando a depuração
rcreswick
1
Esta é a maneira errada de corrigir o Pylint - desativando algumas de suas funcionalidades. Tudo que você precisa fazer é instalar um plugin Pylint que entenda o Django. Veja stackoverflow.com/a/31000713/78234
Tal Weiss
3

A solução proposta nesta outra questão é simplesmente adicionar get_attr à sua classe Tag. Feio, mas funciona.

Eric
fonte
1

Até agora, não encontrei uma solução real para isso, mas contornar:

  • Em nossa empresa, exigimos uma pontuação pylint> 8. Isso permite práticas de codificação que o pylint não entende, garantindo que o código não seja "incomum" demais. Até agora, não vimos nenhum caso em que o E1101 nos impedisse de atingir uma pontuação de 8 ou superior.
  • Nossos destinos 'make check' filtram as mensagens "para não tem 'objetos' membro" para remover a maior parte da distração causada pelo pylint não entender o Django.
max
fonte
0

Para neovim & vim8usar o w0rp's aleplugin. Se você instalou tudo corretamente w0rp's ale, incluindo , pylint& pylint-django. vimrcAdicione sua seguinte linha e divirta-se desenvolvendo aplicativos da Web usando o django. Obrigado.

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