Versión del programa

¡Buenas!

Algo que no tengo del todo resuelto en mis proyectos es como manejar la versión de lo que se está ejecutando/instalando/empaquetando.

No me refiero a qué número usar, para esta post es lo mismo si la versión es “42” o “5.2.1-alpha”, me refiero a cómo obtener ese valor en las distintas instancias.

Tampoco me refiero a “cómo calcular la versión”, lo cual puede ser un valor constante (version = "17") o calculada a partir de parámetros como el commit de git o whatever.

El problema base, claro, es tener la información de versión en un único lugar, que la fuente de verdad sea una sola, y usar ese valor tanto del setup.py (o cómo sea que empaqueten e instalen el proyecto) y desde el mismo proyecto (cuando corren al programa con --version o van a “Acerca de…” en el menú).

¿Ideas? ¿Experiencias? ¿Soluciones?

Se agradece.

Es una muy buena pregunta. La última vez que vi cómo resolverlo encontré que en un codebase moderno se puede usar importlib.metadata Using importlib.metadata — Python 3.11.3 documentation . Algo tipo esto setuptools/version.py at main · pypa/setuptools · GitHub
Creo que no hay una solución que abarca todos los casos de uso.

Buenas!
En el laburo nos chocamos varias veces con este tema, y lo que solemos usar es pgk_resources.

Estoy viendo que la documentación no es muy feliz, pero basicamente hacemos:

import pkg_resources

lib_version = pkg_resources.get_distribution(lib_name).version

Lo único que es medio meta es que el código tiene que “tener conciencia” del nombre de la lib que lo instala :stuck_out_tongue:
Pero bueno, a fines prácticos, solo tenes que tener hardcodeado en algún lado el nombre de tu lib :slight_smile:

Igual por lo que estoy chusmeando, lo que compartió San, pinta mejor que el pkg_resources (y de hecho dice literal " this package can eliminate the need to use the older and less efficient pkg_resources package." jajaa :smiley:

@SAn @sofide gracias por la info!

Pero, si no entiendo mal, las soluciones que uds indican me dan la versión del paquete instalado. Si vamos por ese lado, con hardcodear la versión en el setup.py alcanza.

Yo, además de eso, quiero que esa versión sea accesible cuando el programa se ejecuta desde el proyecto. Y en ese caso no es tan fácil acceder a la info de setup.py

@facundo no me queda claro eso de ejecutar el programa desde el proyecto, a que te referis? Entiendo que te referis a ejecutarlo desde el código fuente directamente, sin tenerlo instalado?

No me queda claro que versión te serviría mostrar en esos casos, si es que no tenes realmente una versión instalada.

Claro, por eso decia que no se ajustaba a todos los casos de uso y no hay una forma que sea genial para todo creo.

Si lo estas ejecutando desde “el proyecto” sin instalarlo supongo que es en “modo desarrollo”, si es así en realidad vas a querer que te muestre el git hash por ejemplo en vez del numero de versión porque sino va a ser siempre 0.-dev y no vas a saber que commit e inclusive vas a querer que te diga si esta dirty el repo o no, o todo eso combinado, y mas detalles que empiezan a ser importantes para tu uso especifico. Y ahi ya es muy especifico del ciclo de trabajo del repo me parece y hay varias formas.
Lo mas facil para mi es mostrar esa versión de qué esta instalado (si está) y ademas mostrar un git hash si está en un repo, y no mezclar ambas cosas.

@sofide sí, “desde el proyecto” es clonarlo y ejecutarlo, sin instalar; incluso habiendo tocado el código, y eso se tiene que reflejar en la versión.

@SAn exacto, hash del último commit, idealmente cantidad de commits luego del release y versión de ese release. Para Charmcraft Chipaca había armado algo que tiene esas consideraciones pero depende de que tagees el branch correctamente y la integración con el setup.py no es trivial.

Vos necesitas que se relacione lo del git hash con el setup.py? Porque eso le agrega una complejidad extra importante que para mi (salvo proyectos puntuales) puede solucionarse justamente con no relacionar el setup.py con el git hash.
Una forma podria ser que mostras ambas cosas: installed_version y executed_from_repo_version. installed_version lo sacas del setup.py (y puede no corresponder a lo que esta corriendo, porque puede estar instalado version X pero vos estas corriendo del repo version Y). executed_from_repo_version lo sacas del githash si existe. Si, no es lo mas feliz del mundo pero todo lo otro en mi experiencia es peor. Si a vos alguien te da installed_version y executed_from_repo_version vos podes saber que es realmente lo que esta corriendo, no?

1 me gusta

Sí, más o menos. A ver, resumiendo tu propuesta:

  • si está instalado (lo normal): sacás la info de metadata.version() y usás eso; a nivel “implementación”, tenés la versión hardcodeada en setup.py, se usa solamente para empaquetar/releasear, y listo

  • corriendo desde el proyecto (raro, o no tanto, ver detalle abajo): mostrás directamente el hash del commit donde estás parado y listo; a nivel implementación no hay que hacer nada

Eso funciona, pero…

  • Detalle 1: para cuando corre del proyecto, si yo te digo “version ffcb8220d7” eso no te dice nada; si yo te digo “version 2.0+5@ffcb8220d7” (“estás parado en ffcb8220d7, que son cinco commits luego de 2.0”) te da un montón de info sin tener que andar buscando nada

  • Detalle 2: justamente algo como “version 2.0+5@ffcb8220d7” es genial para “nightly releases”, que lo puede estar usando un montón de gente, más allá que la versión estable es 2.0…

Le podes pedir a git que te de esa info, me parece, pidiendole “el tag mas cercano” y otros detalles, no tengo a mano cómo era pero esta por ahi la info de como hacerlo ya que alguna vez lo hice.

Y se me ocurre que el setup.py valide que haya un tag con la versión que tiene hardcodeada… seguimos teniendo la versión “en dos lados”, pero al menos es validable que coincidan.

Me intriga saber para que proyecto estás tramando esto :smile:

Sobre esto:

Me parece que lo ideal debería ser tener esos “nightly releases” directamente en pypi, usando versiones con el sufijo dev, por ejemplo 1.0.1-dev1). Así es más fácil para tus users tener acceso a los early releases sin tener que tener tu repo clonado y actualizado… Pero obvio que esto igual depende del proyecto.

Para ninguno en particular. Pero en cada proyecto que arranco (y arranqué dos en estas semanas, ahora que estoy desempleado y tengo tiempo) me enfrento al mismo problema y me “molesta” que no haya nada resuelto de manera que sea fácil tener una solución completa…