python - run - ¿Número de versión automática tanto en setup.py(setuptools) Y código fuente?
pyton setup py (5)
Como este tema aún está vivo y, a veces, llega a los resultados de búsqueda, me gustaría mencionar otra solución que apareció por primera vez en 2012 y ahora es más o menos utilizable:
https://github.com/warner/python-versioneer
Funciona de manera diferente a todas las soluciones mencionadas: agrega etiquetas git manualmente, y la biblioteca (y setup.py) lee las etiquetas y construye la cadena de la versión dinámicamente.
La cadena de la versión incluye la etiqueta más reciente, la distancia desde esa etiqueta, el hash de confirmación actual, la "suciedad" y otra información. Tiene pocos formatos de versión diferentes.
Pero todavía no tiene un nombre de rama para las llamadas "compilaciones personalizadas"; y la distancia de compromiso puede ser confusa a veces cuando dos ramas se basan en el mismo compromiso, por lo que es mejor etiquetar y liberar solo una rama seleccionada (maestra).
SITUACIÓN:
Tengo una biblioteca de python, que está controlada por git, y se incluye con distutils / setuptools. Y quiero generar automáticamente un número de versión basado en etiquetas git, tanto para setup.py sdist
y comandos similares, como para la propia biblioteca.
Para la primera tarea puedo usar git describe
o soluciones similares (consulte ¿Cómo puedo obtener la versión definida en setup.py (setuptools) en mi paquete? ).
Y cuando, por ejemplo, estoy en una etiqueta ''0.1'' y pido ''setup.py sdist'', obtengo ''mylib-0.1.tar.gz''; o ''mylib-0.1-3-abcd.tar.gz'' si alteré el código después del etiquetado. Esto esta bien.
EL PROBLEMA ES:
El problema surge cuando quiero que este número de versión esté disponible para la propia biblioteca, por lo que podría enviarlo en el encabezado HTTP de User-Agent como ''mylib / 0.1-3-adcd''.
Si setup.py version
comando setup.py version
como en ¿Cómo puedo obtener la versión definida en setup.py (setuptools) en mi paquete? , entonces este version.py se genera DESPUÉS de que se haga la etiqueta, ya que usa la etiqueta como un valor. Pero en este caso, necesito hacer una confirmación más después de que la etiqueta de versión se haga para que el código sea consistente. Lo que, a su vez, requiere una nueva etiqueta para un paquete adicional.
LA PREGUNTA ES:
¿Cómo romper este círculo de dependencias (generar-cometer-etiquetar-generar-cometer-etiquetar -...)?
La idea de Eric era la manera más simple de ir, en caso de que sea útil, aquí está el código que usé (el equipo de Flask lo hizo de esta manera):
import re
import ast
_version_re = re.compile(r''__version__/s+=/s+(.*)'')
with open(''app_name/__init__.py'', ''rb'') as f:
version = str(ast.literal_eval(_version_re.search(
f.read().decode(''utf-8'')).group(1)))
setup(
name=''app-name'',
version=version,
.....
)
Siguiendo la solución de OGHaza en una pregunta similar de SO, conservo un archivo _version.py que analizo en setup.py. Con la cadena de versión desde allí, git tag en setup.py. Luego configuro la variable de versión de configuración para una combinación de cadena de versión más el hash de confirmación de git. Así que aquí está la parte relevante de setup.py:
from setuptools import setup, find_packages
from codecs import open
from os import path
import subprocess
here = path.abspath(path.dirname(__file__))
import re, os
VERSIONFILE=os.path.join(here,"_version.py")
verstrline = open(VERSIONFILE, "rt").read()
VSRE = r"^__version__ = [''/"]([^''/"]*)[''/"]"
mo = re.search(VSRE, verstrline, re.M)
if mo:
verstr = mo.group(1)
else:
raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
if os.path.exists(os.path.join(here, ''.git'')):
cmd = ''git rev-parse --verify --short HEAD''
git_hash = subprocess.check_output(cmd)
# tag git
gitverstr = ''v'' + verstr
tags = subprocess.check_output(''git tag'')
if not gitverstr in tags:
cmd = ''git tag -a %s %s -m "tagged by setup.py to %s"'' % (gitverstr, git_hash, verstr)
subprocess.check_output(cmd)
# use the git hash in the setup
verstr += '', git hash: %s'' % git_hash
setup(
name=''a_package'',
version = verstr,
....
También puede revertir la dependencia: ponga la versión en mylib/__init__.py
, mylib/__init__.py
ese archivo en setup.py para obtener el parámetro de la versión y use git tag $ (setup.py --version) en la línea de comandos para crear su etiqueta.
git tag -a v$(python setup.py --version) -m ''description of version''
¿Hay algo más complicado que quieras hacer que no haya entendido?
Un problema clásico cuando se juega con la expansión de palabras clave ;)
La clave es darse cuenta de que su etiqueta es parte del proceso de administración de la versión, no parte del proceso de desarrollo (y su control de versión).
En otras palabras, no puede incluir datos de administración de la versión en un repositorio de desarrollo, debido al bucle que ilustra en su pregunta.
Necesita, al generar el paquete (que es la "parte de administración de la versión"), escribir esa información en un archivo que su biblioteca buscará y usará (si dicho archivo existe) para su encabezado HTTP de Usuario-Agente.