Tag: Testing

Integración de PyLint

Habitualmente se genera código que funciona, y que no por ello quiere decir que esté bien codificado. Cuando me refiero a bien codificado, me refiero a que no existan secciones de código que no se usan, que los comportamientos del código sean deterministas, que se codifique evitando generar brechas de seguridad, que cumpla unas reglas de codificación que aseguren una buena comprensión del código, que se genere documentación del código... Por ello, algo que funcione no es sinónimo de que esté bien codificado (simplemente funciona).

En mi día a día suelo utilizar habitualmente Python y el estupendo IDE PyCharm para desarrollar mi trabajo. También tengo que orientar a otras personas que se están formando en este lenguaje, y eso conlleva una supervisión del código generado, no en el sentido de revisión que asegure la funcionalidad, sino el de asegurar una serie de buenas praxis en la codificación. Se trata del paso anterior a cualquier tipo de Testing.

Hablando con un compañero surgió el tema de asegurar unas buenas praxis para el lenguaje Python de personas interinas en la empresa que acaban de empezar, que desarrollan sus prácticas, su proyecto PFG (Proyecto Fin de Grado) o PFM (Proyecto Fin de Master). Estas buenas praxis no son otra cosa que la extensión del Zen de Python promulgado por Tim Peters:


  • Bello es mejor que feo.
  • Explícito es mejor que implícito.
  • Simple es mejor que complejo.
  • Complejo es mejor que complicado.
  • Plano es mejor que anidado.
  • Disperso es mejor que denso.
  • La legibilidad cuenta.
  • Los casos especiales no son tan especiales como para quebrantar las reglas.
  • Aunque lo práctico gana a la pureza.
  • Los errores nunca deberían dejarse pasar silenciosamente.
  • A menos que hayan sido silenciados explícitamente.
  • Frente a la ambigüedad, rechaza la tentación de adivinar.
  • Debería haber una -y preferiblemente sólo una- manera obvia de hacerlo.
  • Aunque esa manera puede no ser obvia al principio a menos que usted sea holandés.
  • Ahora es mejor que nunca.
  • Aunque nunca es a menudo mejor que ya mismo.
  • Si la implementación es difícil de explicar, es una mala idea.
  • Si la implementación es fácil de explicar, puede que sea una buena idea.
  • Los espacios de nombres (namespaces) son una gran idea ¡Hagamos más de esas cosas!

zen_symbol

Si el código cumple con estas directrices se dice que es código "pythonico". Esta filosofía ha hecho que Python lleve en su ADN esa características de legibilidad y transparencia.

Toda esta introducción nos lleva a las Python Enhancement Proposal (PEP) como formalismo de estas buenas praxis, siendo el Zen de Python la PEP20. Pero la pregunta es: ¿cómo me aseguro cumplir estas buenas praxis?, ¿y qué otros las cumplan?, ¿y qué además la forma de evaluarlas sea la misma? La respuesta es un revisor automático como es el caso de PyLint, que asegura una codificación estandarizada alineada con lo que se entiende con un código pythonico, la corrección de errores, la detección de código duplicado o que no se usa... en definitiva asegurar la buena praxis durante la codificación.

PyLint es un revisor automático ampliamente usado e integrado en otros servicios de mayor envergadura como es el caso de Codacy. Sitio de donde tomé la idea de coger un revisor local que se pudiese ejecutar desde el propio equipo, pero que a la vez se pudiese configurar de manera sencilla en el proyecto, y por supuesto integrarlo en mi IDE PyCharm.

Como primer paso, lo que hice fue instalarlo de manera sencilla con el comando "pip":

pip install pylint

Lo primero tras instalarlo fue hacer la prueba de ejecutarlo contra código que ya tenía evaluado por Codacy para poder comprobar lo estricto que era el revisor por defecto. Para mi mayor pena, el proyecto que arrojaba una calificación de B en Codacy, se quedaba en un 2.5 sobre 10. Inmediatamente me dí cuenta de que la vara de medir era extremadamente estricta por defecto, con lo que exporté los parámetros de revisión con los que Codacy revisaba mi código, ya que entendía que era una revisión más coherente.

Acto seguido revisé aquellas parametrizaciones que correspondían a PyLint y las migré a un fichero "pylintrc" que puede albergar la información de configuración de PyLint. Para ello ejecuté el siguiente comando, obteniendo la plantilla del "pylintrc":

pylint --generate-rcfile > .pylintrc

Una vez obtenida la plantilla del fichero de configuración, posteriormente modifiqué la sección "MESSAGES CONTROL" para deshabilitar todas las reglas de revisión por defecto y añadir las que yo deseaba, y que además coincidían con las de revisión en Codacy.

disable=all
enable= E0001,E0100,E0101,E0102,E0103,E0104,E0105,E0106,E0107,E0110,
        E0113,E0114,E0115,E0116,E0117,E0108,E0202,E0203,E0211,E0236,
        E0238,E0239,E0240,E0241,E0301,E0302,E0601,E0603,E0604,E0701,
        E0702,E0703,E0704,E0710,E0711,E0712,E1003,E1102,E1111,E0112,
        E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1132,E1200,E1201,
        E1205,E1206,E1300,E1301,E1302,E1303,E1304,E1305,E1306,
        C0123,C0200,C0303,C1001,
        W0101,W0102,W0104,W0105,W0106,W0107,W0108,W0109,W0110,W0120,
        W0122,W0124,W0150,W0199,W0221,W0222,W0233,W0404,W0410,W0601,
        W0602,W0604,W0611,W0612,W0622,W0623,W0702,W0705,W0711,W1300,
        W1301,W1302,W1303,,W1305,W1306,W1307
        R0102,R0201,R0202,R0203

La serie de códigos que añado son una normalización de distintas reglas aplicables en PyLint para revisar el código. Podéis disponer del fichero completo con las reglas desde el siguiente Gist:

Con ese fichero "pylintrc" ya es posible portar la configuración para el revisor PyLint en cualquier proyecto. Sólo debemos añadirlo a la raíz de cualquier proyecto Python.

Anteriormente he comentado que uso PyCharm como IDE, y claro está, que ejecutar esta herramienta por línea de comandos, no resulta lo ideal. No os preocupéis porque existe una integración bastante directa de PyLint en PyCharm. Para ello solo tenéis que ir a File --> Settings --> Tools --> External Tools en vuestro PyCharm y añadir la siguiente configuración haciendo click en el símbolo + de color verde:

pycharm_external-tool_pylint

Poned el nombre y una descripción para la herramienta y desmarcad "Synchronize files after execution". En "Program" buscad dentro de la carpeta de instalación de Python en el subdirectorio Scripts el ejecutable "pylint.exe", si sois usuarios Windows,  y en el directorio "/usr/bin" si sois usuarios de Linux.

Los parámetros que se introducen son la ubicación del fichero de configuración de PyLint (que debiera estar en la raíz del proyecto) y la macro que corresponde al fichero o carpeta que analizaríamos con PyLint. En "Working directory" ponemos la macro que apunta al directorio del proyecto correspondiente al fichero o carpeta que analicemos. Guardamos y para probarlo basta con ir a la raíz del proyecto y ejecutar PyLint con el botón derecho External Tools --> PyLint.

pylint_linkero_review

Como podéis ver, con esta integración tenéis una excelente herramienta que mejorará (si hacéis caso a sus reportes) vuestro código, generando un código mucho más pythonico.