Comment puis-je obtenir la version définie dans setup.py (setuptools) dans mon package?

Réponses:

246

Interroger la chaîne de version de la distribution déjà installée

Pour récupérer la version de l'intérieur de votre package au moment de l'exécution (ce que votre question semble réellement demander), vous pouvez utiliser:

import pkg_resources  # part of setuptools
version = pkg_resources.require("MyProject")[0].version

Stocker la chaîne de version à utiliser lors de l'installation

Si vous voulez aller dans l'autre sens (ce qui semble être ce que les autres auteurs de réponses semblent avoir pensé que vous demandiez ici), mettez la chaîne de version dans un fichier séparé et lisez le contenu de ce fichier setup.py.

Vous pouvez créer un version.py dans votre package avec une __version__ligne, puis le lire à partir de setup.py en utilisant execfile('mypackage/version.py'), de sorte qu'il soit __version__défini dans l'espace de noms setup.py.

Si vous voulez un moyen beaucoup plus simple qui fonctionnera avec toutes les versions de Python et même les langages non Python qui peuvent avoir besoin d'accéder à la chaîne de version:

Stockez la chaîne de version comme le seul contenu d'un fichier texte brut, nommé par exemple VERSION, et lisez ce fichier pendant setup.py.

version_file = open(os.path.join(mypackage_root_dir, 'VERSION'))
version = version_file.read().strip()

Le même VERSIONfichier fonctionnera alors exactement aussi bien dans n'importe quel autre programme, même non Python, et il vous suffit de changer la chaîne de version en un seul endroit pour tous les programmes.

Avertissement sur les conditions de concurrence lors de l'installation

À propos, N'importez PAS votre package depuis votre setup.py comme suggéré dans une autre réponse ici: cela semblera fonctionner pour vous (car vous avez déjà installé les dépendances de votre package), mais cela fera des ravages sur les nouveaux utilisateurs de votre package , car ils ne pourront pas installer votre package sans d'abord installer manuellement les dépendances.

PJ Eby
la source
1
C'est simplement la meilleure réponse ici: le meilleur moyen est d'utiliser execfile si vous avez besoin de setup.py pour obtenir la version de votre package.
trinth
2
execfilefonctionne vraiment bien ... mais (malheureusement) ne fonctionne pas avec Python 3.
medmunds
9
... OK, pour Python 2 et 3, utilisez with open('mypackage/version.py') as f: exec(f.read())à la place de execfile('mypackage/version.py'). (De stackoverflow.com/a/437857/647002 )
Medmunds
5
La partie des ravages n'est pas nécessairement vraie ... elle ne fera des ravages que si votre fichier init .py dans le package a des dépendances d'importation de code (directement ou indirectement).
Pykler
2
Il semble intéressant de mentionner que django effectue un appel __import__ dans leur setup.py . Est-ce que «__import__» vs «import» rend cela sûr? Cela ne semble pas leur causer de problèmes.
user1978019
33

exemple d'étude: mymodule

Imaginez cette configuration:

setup.py
mymodule/
        / __init__.py
        / version.py
        / myclasses.py

Ensuite, imaginez un scénario habituel où vous avez des dépendances et setup.pyressemble à:

setup(...
    install_requires=['dep1','dep2', ...]
    ...)

Et un exemple __init__.py:

from mymodule.myclasses import *
from mymodule.version import __version__

Et par exemple myclasses.py:

# these are not installed on your system.
# importing mymodule.myclasses would give ImportError
import dep1
import dep2

problème n ° 1: importation mymodulelors de la configuration

Si vos setup.pyimportations mymodulepuis lors de l' installation , vous obtiendraient probablement un ImportError. Il s'agit d'une erreur très courante lorsque votre package a des dépendances. Si votre package n'a pas d'autres dépendances que les fonctions intégrées, vous pouvez être en sécurité; cependant ce n'est pas une bonne pratique. La raison en est que ce n'est pas à l'épreuve du temps; disons que demain, votre code doit consommer une autre dépendance.

problème n ° 2: où est mon __version__?

Si vous codez __version__en dur, setup.pycela peut ne pas correspondre à la version que vous enverriez dans votre module. Pour être cohérent, vous le mettriez au même endroit et le liriez à partir du même endroit lorsque vous en avez besoin. En utilisant importvous pouvez obtenir le problème n ° 1.

solution: à la setuptools

Vous utiliseriez une combinaison de open, execet fourniriez un dict pour execajouter des variables:

# setup.py
from setuptools import setup, find_packages
from distutils.util import convert_path

main_ns = {}
ver_path = convert_path('mymodule/version.py')
with open(ver_path) as ver_file:
    exec(ver_file.read(), main_ns)

setup(...,
    version=main_ns['__version__'],
    ...)

Et en mymodule/version.pyexposer la version:

__version__ = 'some.semantic.version'

De cette façon, la version est livrée avec le module et vous ne rencontrez pas de problèmes lors de l'installation en essayant d'importer un module qui a des dépendances manquantes (encore à installer).

Dnozay
la source
2
Cela semble être la solution la plus raisonnable car elle ne repose que sur les dépendances autorisées.
Dogweather
Le concept de version du package défini dans le fichier setup.py est-il différent de la version ?
variable du
16

La meilleure technique consiste à définir __version__dans votre code produit, puis à l'importer dans setup.py à partir de là. Cela vous donne une valeur que vous pouvez lire dans votre module en cours d'exécution, et n'avez qu'un seul endroit pour la définir.

Les valeurs de setup.py ne sont pas installées et setup.py ne reste pas après l'installation.

Ce que j'ai fait (par exemple) dans coverage.py:

# coverage/__init__.py
__version__ = "3.2"


# setup.py
from coverage import __version__

setup(
    name = 'coverage',
    version = __version__,
    ...
    )

UPDATE (2017): coverage.py ne s'importe plus pour obtenir la version. L'importation de votre propre code peut le rendre désinstallable, car le code de votre produit essaiera d'importer des dépendances, qui ne sont pas encore installées, car setup.py est ce qui les installe.

Ned Batchelder
la source
4
@Evan: Je ne suis pas sûr de ce que vous voulez dire à propos de "extraire uniquement cette valeur de la source". Si le fichier __version__qu'il contient est cassé d'une manière ou d'une autre, votre importation sera également interrompue. Python ne sait pas interpréter uniquement les instructions que vous souhaitez. @pjeby a raison: si votre module a besoin d'importer d'autres modules, il se peut qu'ils ne soient pas encore installés et ce sera chaotique. Cette technique fonctionne si vous faites attention à ce que l'importation ne provoque pas une longue chaîne d'autres importations.
Ned Batchelder
1
@Ned Batchelder Je suis à peu près sûr que si vous placez la version avant toute importation dans le fichier source et uniquement dans une «version d'importation du module», elle ne lexera pas plus du fichier source qu'il n'en a besoin. De plus, qui va publier du code cassé? Si le paquet a besoin de dépendances, utilisez setuptools ou attendez la sortie de distutils2 plus tard dans l'année.
Evan Plaice
15
@Evan, je suis désolé, mais vous vous trompez sur l'importation de fichiers partiels. Essayez de mettre une instruction d'impression à la fin d'un long module et importez la première variable définie dans le fichier. L'instruction d'impression s'exécutera.
Ned Batchelder
23
J'ai craqué pour ça, mais @pjeby a tout à fait raison: "Au fait, N'importez PAS votre package depuis votre setup.py comme suggéré dans une autre réponse ici: cela semblera fonctionner pour vous (car vous avez déjà installé les dépendances de votre package ), mais cela fera des ravages sur les nouveaux utilisateurs de votre paquet, car ils ne pourront pas installer votre paquet sans installer manuellement les dépendances au préalable. " Ned, cela vous dérangerait-il d'ajouter un avertissement à votre réponse?
Dr.Jan-Philip Gehrcke
1
Comme @ Jan-PhilipGehrcke quand je télécharge un fichier setup.py comme celui - ci à PyPI puis pip install <packagename>, je reçois l'erreur suivante: ImportError: No module named <packagename>. Veuillez avertir vos lecteurs que vous ne pouvez pas exécuter de fichiers setup.py comme celui-ci sur des environnements où le package n'est pas déjà installé!
plaques de cuisson du
14

Votre question est un peu vague, mais je pense que vous demandez comment la préciser.

Vous devez définir __version__comme ceci:

__version__ = '1.4.4'

Et puis vous pouvez confirmer que setup.py connaît la version que vous venez de spécifier:

% ./setup.py --version
1.4.4
jathanisme
la source
9

Je n'étais pas satisfait de ces réponses ... je ne voulais pas exiger setuptools, ni créer un module séparé complet pour une seule variable, alors je les ai trouvés.

Pour quand vous êtes sûr que le module principal est dans le style pep8 et le restera:

version = '0.30.unknown'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            _, _, version = line.replace("'", '').split()
            break

Si vous souhaitez être très prudent et utiliser un véritable analyseur:

import ast
version = '0.30.unknown2'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            version = ast.parse(line).body[0].value.s
            break

setup.py est en quelque sorte un module jetable, donc pas de problème s'il est un peu moche.


Mise à jour: assez drôle, je me suis éloigné de cela ces dernières années et j'ai commencé à utiliser un fichier séparé dans le package appelé meta.py. J'ai mis beaucoup de méta-données là-dedans que je pourrais vouloir changer fréquemment. Donc, pas seulement pour une valeur.

Gringo Suave
la source
+1. C'est relativement simple, conserve le numéro de version au même endroit, ne nécessite pas de fichier séparé pour le contenir et n'impose pas les dépendances d'importation du module python sur setup.py. Je ne me soucierais même pas du gestionnaire de contexte dans un programme aussi éphémère que setup.py.
ʇsәɹoɈ
Beaucoup plus agréable que d'utiliser regex, merci. Vous pouvez également utiliser ast.get_docstring()avec certains .split('\n')[0].strip()etc pour remplir automatiquement à descriptionpartir de la source. Une chose de moins à synchroniser
perdu
4

Créez un fichier dans votre arborescence source, par exemple dans yourbasedir / yourpackage / _version.py. Laissez ce fichier ne contenir qu'une seule ligne de code, comme ceci:

__version__ = "1.1.0-r4704"

Ensuite, dans votre setup.py, ouvrez ce fichier et analysez le numéro de version comme ceci:

verstr = "inconnu"
essayer:
    verstrline = open ('votre paquet / _version.py', "rt"). read ()
sauf EnvironmentError:
    pass # Ok, il n'y a pas de fichier de version.
autre:
    VSRE = r "^ __ version__ = ['\"] ([^' \ "] *) ['\"] "
    mo = re.search (VSRE, verstrline, re.M)
    si mo:
        verstr = groupe mo (1)
    autre:
        lever RuntimeError ("impossible de trouver la version dans votre package / _version.py")

Enfin, dans yourbasedir/yourpackage/__init__.pyimport _version comme ceci:

__version__ = "inconnu"
essayer:
    depuis _version import __version__
sauf ImportError:
    # Nous fonctionnons dans un arbre qui n'a pas de _version.py, donc nous ne savons pas quelle est notre version.
    passer

Un exemple de code qui fait cela est le package "pyutil" que je gère. (Voir PyPI ou recherche Google - stackoverflow ne me permet pas d'inclure un lien hypertexte vers celui-ci dans cette réponse.)

@pjeby a raison de ne pas importer votre package depuis son propre setup.py. Cela fonctionnera lorsque vous le testerez en créant un nouvel interpréteur Python et en exécutant setup.py en premier lieu:, python setup.pymais il y a des cas où cela ne fonctionnera pas. C'est parce import youpackageque ne veut pas dire lire le répertoire de travail courant pour un répertoire nommé "yourpackage", cela signifie chercher dans le courant sys.modulesune clé "yourpackage" et ensuite faire diverses choses si elle n'est pas là. Donc, cela fonctionne toujours lorsque vous le faites python setup.pyparce que vous avez un frais, vide sys.modules, mais cela ne fonctionne pas en général.

Par exemple, que se passe-t-il si py2exe exécute votre setup.py dans le cadre du processus d'empaquetage d'une application? J'ai vu un cas comme celui-ci où py2exe mettrait le mauvais numéro de version sur un package parce que le package obtenait son numéro de version deimport myownthingdans son setup.py, mais une version différente de ce package avait déjà été importée lors de l'exécution de py2exe. De même, que se passe-t-il si setuptools, easy_install, distribuer ou distutils2 essaie de créer votre package dans le cadre d'un processus d'installation d'un package différent qui dépend du vôtre? Ensuite, si votre package est importable au moment où son setup.py est évalué, ou s'il existe déjà une version de votre package qui a été importée au cours de la vie de cet interpréteur Python, ou si l'importation de votre package nécessite l'installation préalable d'autres packages , ou a des effets secondaires, peuvent changer les résultats. J'ai eu plusieurs difficultés à essayer de réutiliser les packages Python, ce qui a causé des problèmes pour des outils tels que py2exe et setuptools car leur setup.py importe le package lui-même afin de trouver son numéro de version.

En passant, cette technique joue bien avec des outils pour créer automatiquement le yourpackage/_version.pyfichier pour vous, par exemple en lisant votre historique de contrôle de révision et en écrivant un numéro de version basé sur la balise la plus récente dans l'historique de contrôle de révision. Voici un outil qui fait cela pour darcs: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst et voici un extrait de code qui fait la même chose pour git: http: // github .com / warner / python-ecdsa / blob / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34

Zooko
la source
3

Cela devrait également fonctionner, en utilisant des expressions régulières et en fonction des champs de métadonnées pour avoir un format comme celui-ci:

__fieldname__ = 'value'

Utilisez ce qui suit au début de votre setup.py:

import re
main_py = open('yourmodule.py').read()
metadata = dict(re.findall("__([a-z]+)__ = '([^']+)'", main_py))

Après cela, vous pouvez utiliser les métadonnées dans votre script comme ceci:

print 'Author is:', metadata['author']
print 'Version is:', metadata['version']
thp
la source
Comme je l'ai dit plus haut, il suffit d'utiliser str.split :)
Éric Araujo
Oh mon dieu non. Vous analysez Python en Python? À tout le moins, utilisez eval (), child.
slacy
3
Mauvais conseil slacy, l'évaluation doit être évitée lorsqu'elle est si facile.
Gringo Suave
3

Avec une structure comme celle-ci:

setup.py
mymodule/
        / __init__.py
        / version.py
        / myclasses.py

version.py contient:

__version__ = 'version_string'

Vous pouvez le faire dans setup.py :

import sys

sys.path[0:0] = ['mymodule']

from version import __version__

Cela ne posera aucun problème avec les dépendances que vous avez dans votre mymodule / __ init__.py

Jahid
la source
2

Pour éviter d'importer un fichier (et donc d'exécuter son code), on pourrait l'analyser et récupérer l' versionattribut à partir de l'arbre de syntaxe:

# assuming 'path' holds the path to the file

import ast

with open(path, 'rU') as file:
    t = compile(file.read(), path, 'exec', ast.PyCF_ONLY_AST)
    for node in (n for n in t.body if isinstance(n, ast.Assign)):
        if len(node.targets) == 1:
            name = node.targets[0]
            if isinstance(name, ast.Name) and \
                    name.id in ('__version__', '__version_info__', 'VERSION'):
                v = node.value
                if isinstance(v, ast.Str):
                    version = v.s
                    break
                if isinstance(v, ast.Tuple):
                    r = []
                    for e in v.elts:
                        if isinstance(e, ast.Str):
                            r.append(e.s)
                        elif isinstance(e, ast.Num):
                            r.append(str(e.n))
                    version = '.'.join(r)
                    break

Ce code tente de trouver l' affectation __version__ou VERSIONau niveau supérieur du module return is string value. Le côté droit peut être une chaîne ou un tuple.

Mikhail Edoshin
la source
3
Cela semble intelligent et compliqué :) Il serait plus simple d'avoir un fichier _version.py contenant une affectation et de l'analyser avec open-read-str.split.
Éric Araujo
Merci d'avoir publié ceci. Je pense que c'est trop complexe pour cette situation, mais très utile pour comprendre comment on pourrait aborder le problème. J'aime le fait qu'il garde le numéro de version au même endroit, ne nécessite pas de fichier séparé pour le contenir et n'impose pas les dépendances d'importation du module python sur le script de configuration.
ʇsәɹoɈ
2

Il y a mille façons d'écorcher un chat - voici la mienne:

# Copied from (and hacked):
# https://github.com/pypa/virtualenv/blob/develop/setup.py#L42
def get_version(filename):
    import os
    import re

    here = os.path.dirname(os.path.abspath(__file__))
    f = open(os.path.join(here, filename))
    version_file = f.read()
    f.close()
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                              version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")
Marc Abramowitz
la source
2

Nettoyage de https://stackoverflow.com/a/12413800 de @ gringo-suave:

from itertools import ifilter
from os import path
from ast import parse

with open(path.join('package_name', '__init__.py')) as f:
    __version__ = parse(next(ifilter(lambda line: line.startswith('__version__'),
                                     f))).body[0].value.s
À
la source
2

Maintenant, c'est dégoûtant et a besoin d'être affiné (il peut même y avoir un appel de membre découvert dans pkg_resources que j'ai manqué), mais je ne vois tout simplement pas pourquoi cela ne fonctionne pas, ni pourquoi personne ne l'a suggéré à ce jour (googler autour a n'a pas augmenté cela) ... notez qu'il s'agit de Python 2.x, et nécessiterait d'exiger pkg_resources (soupir):

import pkg_resources

version_string = None
try:
    if pkg_resources.working_set is not None:
        disto_obj = pkg_resources.working_set.by_key.get('<my pkg name>', None)
        # (I like adding ", None" to gets)
        if disto_obj is not None:
            version_string = disto_obj.version
except Exception:
    # Do something
    pass
Mark Gerolimatos
la source
2

Nous voulions mettre les méta - informations sur notre package pypackagerydans __init__.py, mais ne pouvait pas car il a des dépendances tiers comme PJ Eby a déjà indiqué (voir sa réponse et la mise en garde concernant l'état de la course).

Nous l'avons résolu en créant un module séparé pypackagery_meta.pyqui ne contient que les méta-informations:

"""Define meta information about pypackagery package."""

__title__ = 'pypackagery'
__description__ = ('Package a subset of a monorepo and '
                   'determine the dependent packages.')
__url__ = 'https://github.com/Parquery/pypackagery'
__version__ = '1.0.0'
__author__ = 'Marko Ristin'
__author_email__ = '[email protected]'
__license__ = 'MIT'
__copyright__ = 'Copyright 2018 Parquery AG'

puis importé les méta-informations dans packagery/__init__.py:

# ...

from pypackagery_meta import __title__, __description__, __url__, \
    __version__, __author__, __author_email__, \
    __license__, __copyright__

# ...

et finalement utilisé dans setup.py:

import pypackagery_meta

setup(
    name=pypackagery_meta.__title__,
    version=pypackagery_meta.__version__,
    description=pypackagery_meta.__description__,
    long_description=long_description,
    url=pypackagery_meta.__url__,
    author=pypackagery_meta.__author__,
    author_email=pypackagery_meta.__author_email__,
    # ...
    py_modules=['packagery', 'pypackagery_meta'],
 )

Vous devez inclure pypackagery_metadans votre package avec l' py_modulesargument setup. Sinon, vous ne pouvez pas l'importer lors de l'installation car la distribution packagée en manquerait.

marko.ristin
la source
1

Simple et direct, créez un fichier appelé source/package_name/version.pyavec le contenu suivant:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
__version__ = "2.6.9"

Ensuite, sur votre fichier source/package_name/__init__.py, vous importez la version que d'autres personnes pourront utiliser:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from .version import __version__

Maintenant, tu peux mettre ça setup.py

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys

try:
    filepath = 'source/package_name/version.py'
    version_file = open( filepath )
    __version__ ,= re.findall( '__version__ = "(.*)"', version_file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

finally:
    version_file.close()

Testé avec Python 2.7, 3.3, 3.4, 3.5, 3.6et 3.7sous Linux, Windows et Mac OS. J'ai utilisé sur mon package qui a l'intégration et les tests unitaires pour toutes ces plates-formes. Vous pouvez voir les résultats de .travis.ymlet appveyor.ymlici:

  1. https://travis-ci.org/evandrocoan/debugtools/builds/527110800
  2. https://ci.appveyor.com/project/evandrocoan/pythondebugtools/builds/24245446

Une autre version utilise le gestionnaire de contexte:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys

try:
    filepath = 'source/package_name/version.py'

    with open( filepath ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

Vous pouvez également utiliser le codecsmodule pour gérer les erreurs Unicode à la fois sur Python 2.7et3.6

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys
import codecs

try:
    filepath = 'source/package_name/version.py'

    with codecs.open( filepath, 'r', errors='ignore' ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

Si vous écrivez un module Python à 100% en C / C ++ en utilisant les extensions C Python, vous pouvez faire la même chose, mais en utilisant C / C ++ au lieu de Python.

Dans ce cas, créez ce qui suit setup.py:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys
import codecs
from setuptools import setup, Extension

try:
    filepath = 'source/version.h'

    with codecs.open( filepath, 'r', errors='ignore' ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

setup(
        name = 'package_name',
        version = __version__,

        package_data = {
                '': [ '**.txt', '**.md', '**.py', '**.h', '**.hpp', '**.c', '**.cpp' ],
            },

        ext_modules = [
            Extension(
                name = 'package_name',
                sources = [
                    'source/file.cpp',
                ],
                include_dirs = ['source'],
            )
        ],
    )

Qui lit la version du fichier version.h:

const char* __version__ = "1.0.12";

Mais n'oubliez pas de créer le MANIFEST.inpour inclure le version.hfichier:

include README.md
include LICENSE.txt

recursive-include source *.h

Et il est intégré à l'application principale avec:

#include <Python.h>
#include "version.h"

// create the module
PyMODINIT_FUNC PyInit_package_name(void)
{
    PyObject* thismodule;
    ...

    // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
    PyObject_SetAttrString( thismodule, "__version__", Py_BuildValue( "s", __version__ ) );

    ...
}

Références:

  1. erreur de fichier ouvert python
  2. Définir un global dans un module Python à partir d'une API C
  3. Comment inclure des données de package avec setuptools / distribuer?
  4. https://github.com/lark-parser/lark/blob/master/setup.py#L4
  5. Comment utiliser les packages setuptools et les ext_modules du même nom?
  6. Est-il possible d'inclure des sous-répertoires en utilisant dist utils (setup.py) dans le cadre des données du package?
utilisateur
la source
1

Déployez le package sur le serveur et la convention de dénomination des fichiers pour les packages d'index:

exemple de conversion de version dynamique pip:

  • gagner:

    • test_pkg-1.0.0-cp36-cp36m-win_amd64.whl
    • test_pkg-1.0.0-py3.6-win-amd64.egg
  • Mac:

    • test_pkg-1.0.0-py3.7-macosx-10.12-x86_64.egg
    • test_pkg-1.0.0-py3.7-macosx-10.12-x86_64.whl
  • linux:
    • test_pkg-1.0.0-cp36-cp36m-linux_x86_64.whl
from setuptools_scm import get_version

def _get_version():

     dev_version = str(".".join(map(str, str(get_version()).split("+")[0]\
            .split('.')[:-1])))

    return dev_version

Trouvez l'exemple setup.py appelle la version de pip dynamique correspondant à partir de git commit

setup(
    version=_get_version(),
    name=NAME,
    description=DESCRIPTION,
    long_description=LONG_DESCRIPTION,
    classifiers=CLASSIFIERS,

# add few more for wheel wheel package ...conversion

)
Narayana Reddy
la source
0

J'utilise une variable d'environnement comme ci-dessous

VERSION = 0.0.0 python setup.py sdist bdist_wheel

Dans setup.py


import os

setup(
    version=os.environ['VERSION'],
    ...
)

Pour vérifier la cohérence avec la version du packer, j'utilise le script ci-dessous.

PKG_VERSION=`python -c "import pkg; print(pkg.__version__)"`
if [ $PKG_VERSION == $VERSION ]; then
    python setup.py sdist bdist_wheel
else
    echo "Package version differs from set env variable"
fi
Seongjoo
la source