2010-01-08 5 views
28

Je voudrais appeler le vérificateur pylint, limité à la partie de signalisation d'erreur, dans le cadre de mes tests unitaires. donc j'ai vérifié le script exécutable de pylint, arrivé à la classe d'assistance pylint.lint.Run et là je me suis perdu dans une fonction assez longue __init__, se terminant par un appel à sys.exit().invocation de pylint par programme

quelqu'un a-t-il déjà essayé et réussi à le faire?

le plan de rêve serait:

if __name__ == '__main__': 
    import pylint.lint 
    pylint.lint.something(__file__, justerrors=True) 
    # now continue with unit testing 

des conseils? autre que "copier la méthode __init__ et passer le sys.exit()", je veux dire?

Je ne besoin les tests à exécuter par pylint, il pourrait aussi bien être pyflakes ou tout autre logiciel: ne hésitez pas à proposer des alternatives. Merci!

Répondre

20

Jetez un oeil à la pylint/epylint.py qui contient deux différentes façons de démarrer pylint par programmation.

Vous pouvez aussi simplement appeler:

from pylint.lint import Run 
Run(['--errors-only', 'myfile.py']) 

par exemple.

+0

combiné avec la réponse précédente. et avec une légère modification: 'pylint.lint.Run (['- errors-only', filename])' – mariotomo

+0

est-il un moyen d'analyser plusieurs fichiers lors de l'appel de pylint par programmation? – Gobliins

+0

@gobliins: oui, ajoutez simplement d'autres noms de fichiers à la liste donnée en tant qu'argument Run. – sthenault

3

Je suis content de l'avoir rencontré. Je quelques-unes des réponses ici et une initiative de venir avec:

# a simple class with a write method 
class WritableObject: 
    def __init__(self): 
     self.content = [] 
    def write(self, string): 
     self.content.append(string) 
pylint_output = WritableObject() 

pylint = lint.Run(args, reporter=ParseableTextReporter(pylint_output), exit=False) 

Args dans ce qui précède est une liste de chaînes, par exemple. ["-r", "n", "myfile.py"]

+2

J'ai mis une solution ci-dessus, mais j'ai depuis trouvé que l'appel de Pylint par programmation de cette façon est mauvais car Pylint utilise des imports qui sont mis en cache. Donc, si vous éditiez le fichier que vous étiez en train de planter, les modifications ne seraient pas visibles. Si vous exécutez uniquement Pylint par programmation une fois contre un seul script, alors c'est probablement correct. – mcarans

14

J'ai eu le même problème récemment. syt a raison, pylint.epylint a obtenu plusieurs méthodes là-bas. Cependant, ils appellent tous un sous-processus dans lequel python est à nouveau lancé. Dans mon cas, cela devenait assez lent.

bâtiment de mcarans réponse, et de trouver qu'il ya une sortie de drapeau, je l'ai fait ce qui suit

class WritableObject(object): 
    "dummy output stream for pylint" 
    def __init__(self): 
     self.content = [] 
    def write(self, st): 
     "dummy write" 
     self.content.append(st) 
    def read(self): 
     "dummy read" 
     return self.content 
def run_pylint(filename): 
    "run pylint on the given file" 
    from pylint import lint 
    from pylint.reporters.text import TextReporter 
    ARGS = ["-r","n", "--rcfile=rcpylint"] # put your own here 
    pylint_output = WritableObject() 
    lint.Run([filename]+ARGS, reporter=TextReporter(pylint_output), exit=False) 
    for l in pylint_output.read(): 
     do what ever you want with l... 

qui est environ 3 fois plus rapide dans mon cas. Avec cela, j'ai traversé un projet entier, en utilisant la sortie complète pour vérifier chaque fichier source, pointer les erreurs, et classer tous les fichiers de leur note.

+1

Pouvez-vous s'il vous plaît pinte moi à la source où je peux lire à ce sujet. –

+0

Merci, ça marche! Voici le code qui analyse la sortie et renvoie la note (n'hésitez pas à ajouter à la réponse, si vous le souhaitez): https://pastebin.com/Lta2cCB8 –

+0

Vous utilisez également: pylint_output = pylint.testutils.TestReporter() puis obtenez les résultats avec test_reporter.finalize(). strip(). Ou encore mieux, regardez l'implémentation de 'TestReporter' et mettez en place la vôtre pour gérer les messages structurels. –

1

Au lieu de créer une classe WritableObject, nous pouvons utiliser StringIO. StringIO contient la méthode write.

import sys 
try: 
    from io import StringIO 
except: 
    from StringIO import StringIO 

stdout = sys.stdout 
sys.stdout = StringIO() 

ARGS = ["-r","n", "--rcfile=rcpylint"] 
r = lint.Run(['../test.py']+ARGS, exit=False) 

test = sys.stdout.getvalue() 
sys.stdout.close() 
sys.stdout = stdout 

print (test.split('\n')) 

Source:

0

Un autre point d'entrée pour pylint est la fonction epylint.py_run, qui mettent en œuvre la stdout et l'interception stderr.Cependant, comme indiqué dans le code suivant, pylint semble ne pas écrire ses rapports dans stdout:

from pylint import epylint 

pylint_stdout, pylint_stderr = epylint.py_run(__file__, return_std=True) 
print(pylint_stdout.getvalue()) # -> there is just the final rank, no report nor message 
print(pylint_stderr.getvalue()) 

Maintenant, je trouve que pylint de CLI et pylint de CLI ne pas utiliser les mêmes paramètres par défaut. Donc, il vous suffit de fournir les paramètres dont vous avez besoin pour pylint.

from pylint import epylint 
options = '--enable=all' # all messages will be shown 
options += '--reports=y' # also print the reports (ascii tables at the end) 

pylint_stdout, pylint_stderr = epylint.py_run(__file__ + ' ' + options, return_std=True) 
print(pylint_stdout.getvalue()) 
print(pylint_stderr.getvalue()) 

Comme décrit here, pylint effectuera lui-même l'analyse, et ce que les résultats attendus en sortie stdout correctement.