web-dev-qa-db-ja.com

setup.py(setuptools)とソースコードの両方の自動バージョン番号?

状況:

pythonライブラリ、gitによって制御され、distutils/setuptoolsにバンドルされています。また、setup.py sdistと同様に、gitタグに基づいてバージョン番号を自動的に生成したいコマンド、およびライブラリ自体。

最初のタスクでは、git describeまたは同様のソリューションを使用できます( を参照してください)パッケージのsetup.py(setuptools)で定義されているバージョンを取得するにはどうすればよいですか )。

たとえば、「0.1」というタグの中にいて「setup.py sdist」を呼び出すと、「mylib-0.1.tar.gz」が表示されます。タグ付け後にコードを変更した場合は「mylib-0.1-3-abcd.tar.gz」。これで結構です。

問題は:

ライブラリ自体でこのバージョン番号を使用できるようにしたいときに問題が発生するため、User-Agent HTTPヘッダーで「mylib/0.1-3-adcd」として送信できます。

のようにsetup.py versionコマンドを追加した場合、パッケージのsetup.py(setuptools)で定義されているバージョンを取得するにはどうすればよいですか 、このversion.pyは後に生成されますタグを値として使用するため、タグが作成されます。ただし、この場合、コードに一貫性を持たせるために、バージョンタグが作成された後にもう一度コミットする必要があります。次に、さらにバンドルするために新しいタグが必要になります。

質問は:

この依存関係の輪を壊す方法(generate-commit-tag-generate-commit-tag -...)?

37
Sergey Vasilyev

依存関係を逆にすることもできます。バージョンをmylib/__init__.py、setup.pyでそのファイルを解析してバージョンパラメータを取得し、コマンドラインでgitタグ$(setup.py --version)を使用してタグを作成します。

git tag -a v$(python setup.py --version) -m 'description of version'

私が理解していない、あなたがしたいもっと複雑なことはありますか?

32
Éric Araujo

キーワード展開 ;)でいじるときの古典的な問題

重要なのは、タグがリリース管理プロセスの一部であり、開発(およびそのバージョン管理)プロセスの一部ではないことを認識することです。

つまり、質問で示したループが原因で、リリース管理データを開発リポジトリに含めることはできません。

パッケージ(「リリース管理パート」)を生成するときに、ライブラリが検索し、User-Agent HTTPヘッダー用に(上記のファイルが存在する場合)使用するファイルにその情報を書き込む必要があります。

23
VonC

このトピックはまだ存続しており、検索結果に到達することもあるため、2012年に最初に登場し、多かれ少なかれ使用できる別のソリューションについて触れておきたいと思います。

https://github.com/warner/python-versioneer

これは、前述のすべてのソリューションとは異なる方法で機能します。gitタグを手動で追加すると、ライブラリ(およびsetup.py)がタグを読み取り、バージョン文字列を動的に構築します。

バージョン文字列には、最新のタグ、そのタグからの距離、現在のコミットハッシュ、「ダーティネス」、その他の情報が含まれています。いくつかの異なるバージョン形式があります。

しかし、いわゆる「カスタムビルド」のブランチ名はまだありません。また、2つのブランチが同じコミットに基づいている場合、コミット距離が混乱することがあります。そのため、選択した1つのブランチ(マスター)のみにタグを付けて解放することをお勧めします。

8
Sergey Vasilyev

エリックのアイデアは、ここで私が使用したコードがここで役立つ場合に備えて、簡単な方法でした(Flaskのチームはこの方法で行いました)。

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,
 .....
)
5
dim_user

similar SO question でOGHazaのソリューションを実行した後、setup.pyで解析するファイル_version.pyを保持します。そこからのバージョン文字列を使用して、タグをgitでsetup.py。次に、セットアップバージョン変数をバージョン文字列とgit commitハッシュの組み合わせに設定します。したがって、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,
    ....
4
Sven