Gestión de dependencias y versionado en Python

Cuando programas una de las cosas más importantes para asegurar la compatibilidad y el soporte de una librería, herramienta o programa, es el versionado del mismo.

El versionado sirve para que a nivel interno, el equipo de desarrolladores pueda llevar un control de hitos dentro del desarrollo y a su vez sirve para que otros desarrolladores o usuarios, que usan estas librerías, herramientas o programas, puedan tener un control a la hora de integrarlas o actualizarlas.

Ahora bien, el problema viene a la hora de establecer la significación de dicho número de versión. En Python es normal usar el sistema SemVer, el cual establece tres grupos de números separados por puntos de la forma MAJOR.MINOR.PATCH

  • MAJOR: Se incrementa cuando cuando se realizan cambios incompatibles a nivel de API.
  • MINOR: Se incrementa cuando se añaden funcionalidad de manera retrocompatible.
  • PATCH: Se incrementa cuando se corrigen 🐛 fallos de manera retrocompotible

Es posible que estuvieras familiarizado con este sistema de versionado, pero aún así te recomiendo su lectura completa en https://semver.org.

Teniendo esto claro, vamos a pasar a ver la aplicación práctica que que tiene esto en la gestión de dependencias, donde la generación de paquetes para su distribución en Pipy es donde se marca la diferencia. Podemos ajustar que nuestro paquete maneje las dependencias de acuerdo a criterios de versión de Python, debido a casos como que una librería específica deje de dar soporte a ciertas versiones de Python a partir de cierta versión.

En el caso citado, hay dos opciones directas que son, o retirar soporte a ciertas versiones de Python propagando la restricción de alguna de nuestras dependencias, o controlar las versiones de las dependencias dependiendo de la versión de Python a utilizar. Veamos cómo:

colorama==0.3.7; python_version < '3.4.*'
colorama>=0.3.7; python_version >= '3.4.*'

En este caso definimos en nuestro requirements.txt la condición de que para versiones de Python menores a 3.4.* es necesario usar la versión de colorama 0.3.7, ya que dicha dependencia retira el soporte a versiones inferiores desde esa versión. Para versiones iguales o mayores a 3.4.*, simplemente se exige una versión mayor o igual a 0.3.7. Atención a que siempre se citan los tres grupos de números.

Otras veces puede pasar que cierta versión de una dependencia nos dé problemas y queramos convertirla en una excepción al requerimiento

fake_library>1.6.2,!=1.7.2

En este caso de la librería inventada fake_library exigiría una versión superior a 1.6.2, pero que no sea 1.7.2.

Por último es posible instalar dependencias que sean necesarias para ciertos sistemas operativos. Veamos un ejemplo:

pywin32 >=1.0.*; sys_platform == 'win32'
SistemaValor platform
AIX'aix'
GNU/Linux'linux'
Windows'win32'
Windows/Cygwin'cygwin'
macOS'darwin'

https://docs.python.org/3/library/sys.html#sys.platform

Para el ejemplo se especifica una versión superior o igual a 1.0.* de pywin32 en el caso de encontrarnos en un sistema Windows.

Finalmente es posible que en el setup.py de una librería, herramienta o aplicación, se obligue a contar con unas versión especificas de Python y/o evitar otras:

from setuptools import setup
 
setup(
    name='mypackage',
    packages=['mypackage'],
    version='0.1',
    license='LGPL v3',
    description='A random test lib',
    author='RDCH106',
    author_email='contact@rdch106.hol.es',
    url='https://github.com/RDCH106/mypackage',
    download_url='https://github.com/RDCH106/parallel_foreach_submodule/archive/v0.1.tar.gz',
    keywords='test example develop', 
    python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', # requerimientos de versión de Python
    classifiers = ['Programming Language :: Python',
                   'Programming Language :: Python :: 2.7',
                   'Programming Language :: Python :: 3.4',
                   'Programming Language :: Python :: 3.5',
                   'Programming Language :: Python :: 3.6',
                   'Programming Language :: Python :: 3.7',
                   'Programming Language :: Python :: 3.8'],
)

En la línea 14 se puede ver que se especifica que se requiere versiones de Python mayores a 2.7, pero que no sean ni 3.0.*, 3.1.*, 3.2.* o 3.3.*.

Todas estas reglas condicionales para la gestión de dependencias quedan reflejadas en las PEP (Python Enhancement Proposal) 345, 440, 496 y 508 principalmente.

Espero que todo esto sirva para evitar caer en el llamado “infierno de las dependencias”, mientras crece tu librería, herramienta o aplicación.





4280 Visitas Totales 1 Visitas para Hoy

Deja un comentario