Pyanalyze est un vérificateur de type semi-statique pour le code Python. Comme un vérificateur de type statique (par exemple, mypy ou pyright), il détecte des erreurs de type dans votre code afin que les bogues puissent être trouvés avant d'atteindre la production. Contrairement à ces outils, cependant, il importe les modules que le type de type vérifie, permettant à Pyanalyze de comprendre de nombreuses constructions dynamiques que d'autres vérificateurs de type rejeteront. Cette propriété permet également d'étendre Pyanalyze avec des plugins qui interagissent directement avec votre code.
Vous pouvez installer Pyanalyze avec:
$ pip install pyanalyzeUne fois installé, vous pouvez exécuter pyanalyze sur un fichier ou un package Python comme suit:
$ python -m pyanalyze file.py
$ python -m pyanalyze package/ Mais notez que cela essaiera d'importer tous les fichiers Python qu'il est passé. Si vous avez des scripts qui effectuent des opérations sans if __name__ == "__main__": les blocs, Pyanalyze peut finir par les exécuter.
Afin de s'exécuter avec succès, Pyanalyze doit être en mesure d'importer le code qu'il vérifie. Pour faire ce travail, vous devrez peut-être ajuster manuellement le chemin d'importation de Python à l'aide de la variable d'environnement $PYTHONPATH .
Pour une expérimentation rapide, vous pouvez également utiliser l'option -c pour taper directement un morceau de code:
$ python -m pyanalyze -c 'import typing; typing.reveal_type(1)'
Runtime type is 'int'
Revealed type is 'Literal[1]' (code: reveal_type)
In <code> at line 1
1: import typing; typing.reveal_type(1)
^
Pyanalyze a un certain nombre d'options de ligne de commande, que vous pouvez voir en exécutant python -m pyanalyze --help . Les importants incluent -f , qui exécute une invite interactive qui vous permet d'examiner et de corriger chaque erreur trouvée par Pyanalyze, et --enable / --disable , qui permettent et désactivent des codes d'erreur spécifiques.
La configuration via un fichier pyproject.toml est également prise en charge. Voir la documentation pour plus de détails.
L'une des principales façons d'étendre Pyanalyze est de fournir une spécification pour une fonction particulière. Cela vous permet d'exécuter un code arbitraire qui inspecte les arguments à la fonction et soulève des erreurs si quelque chose ne va pas.
À titre d'exemple, supposons que votre base de code contient une database.run_query() qui prend en tant qu'argument une chaîne SQL, comme ceci:
database . run_query ( "SELECT answer, question FROM content" ) Vous souhaitez détecter quand un appel à run_query() contient SQL syntaxiquement non valide ou fait référence à une table ou une colonne inexistante. Vous pouvez configurer cela avec du code comme ceci:
from pyanalyze . error_code import ErrorCode
from pyanalyze . signature import CallContext , Signature , SigParameter
from pyanalyze . value import KnownValue , TypedValue , AnyValue , AnySource , Value
from database import run_query , parse_sql
def run_query_impl ( ctx : CallContext ) -> Value :
sql = ctx . vars [ "sql" ]
if not isinstance ( sql , KnownValue ) or not isinstance ( sql . val , str ):
ctx . show_error (
"Argument to run_query() must be a string literal" ,
ErrorCode . incompatible_call ,
)
return AnyValue ( AnySource . error )
try :
parsed = parse_sql ( sql )
except ValueError as e :
ctx . show_error (
f"Invalid sql passed to run_query(): { e } " ,
ErrorCode . incompatible_call ,
)
return AnyValue ( AnySource . error )
# check that the parsed SQL is valid...
# pyanalyze will use this as the inferred return type for the function
return TypedValue ( list )
# in pyproject.toml, set:
# known_signatures = ["<module>.get_known_argspecs"]
def get_known_argspecs ( arg_spec_cache ):
return {
# This infers the parameter types and names from the function signature
run_query : arg_spec_cache . get_argspec (
run_query , impl = run_query_impl
),
# You can also write the signature manually
run_query : Signature . make (
[ SigParameter ( "sql" , annotation = TypedValue ( str ))],
callable = run_query ,
impl = run_query_impl ,
),
}Pyanalyze vise généralement à implémenter la spécification de typage Python, mais la prise en charge de certaines fonctionnalités est incomplète. Voir la documentation pour plus de détails.
Parfois, Pyanalyze se trompe et vous devez ignorer une erreur qu'il émet. Cela peut être fait comme suit:
# static analysis: ignore sur une ligne par elle-même avant la ligne qui génère l'erreur.# static analysis: ignore à la fin de la ligne qui génère l'erreur.# static analysis: ignore en haut du fichier; Cela ignorera les erreurs dans l'ensemble du fichier. Vous pouvez ajouter un code d'erreur, comme # static analysis: ignore[undefined_name] , pour ignorer uniquement un code d'erreur spécifique. Cela ne fonctionne pas pour les ignores de fichiers entiers. Si le code d'erreur bare_ignore est activé, Pyanalyze émettra une erreur si vous ne spécifiez pas de code d'erreur sur un commentaire Ignore.
Pyanalyze ne prend pas actuellement en charge le type norme # type: ignore la syntaxe des commentaires.
Pyanalyze prend en charge toutes les versions de Python qui n'ont pas atteint la fin de vie. Parce qu'il importe le code qu'il vérifie, vous devez l'exécuter en utilisant la même version de Python que vous utilisez pour exécuter votre code.
Nous accueillons vos contributions. Voir contribution.md pour comment commencer.
La documentation est disponible sur ReadTheDocs ou sur GitHub.