プロジェクトバージョンの単一ソース化¶
Page Status: | Complete |
---|---|
Last Reviewed: | 2015-12-03 |
プロジェクトのバージョン番号について、単一ソースの原則を維持する多くの手法がある:
setup.py
を正規表現でパースしてバージョンを得る。例えば(pip の setup.py より):def read(*names, **kwargs): with io.open( os.path.join(os.path.dirname(__file__), *names), encoding=kwargs.get("encoding", "utf8") ) as fp: return fp.read() def find_version(*file_paths): version_file = read(*file_paths) 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.") setup( ... version=find_version("package", "__init__.py") ... )
注釈
この手法は複雑な正規表現を扱わなければならない欠点がある。
両方の場所で更新管理ができるか、もしくは両方の場所で使える API を持つ外部ビルドツールを使う。
そんなツールはほとんどないが、挙げるとすれば bumpversion, changes, zest.releaser だ。この順序に特定の意図はないし、これで全てだとも限らない。
プロジェクト内の専用モジュール(例えば
version.py
) でグローバル変数__version__
の値を設定し、setup.py
がそれを読んでexec
した値を変数に格納する。execfile
を使う例:execfile('...sample/version.py') # now we have a `__version__` variable # later on we use: __version__
exec
を使う例:version = {} with open("...sample/version.py") as fp: exec(fp.read(), version) # later on we use: version['__version__']
この手法を使っている例: warehouse
単純な
VERSION
というテキストファイルに値を格納し、setup.py
とプロジェクトコードの両方でそれを読む。with open(os.path.join(mypackage_root_dir, 'VERSION')) as version_file: version = version_file.read().strip()
この手法の利点は Python に特化していないことだ。どのツールでもバージョンを読み取れる。
警告
この手法をとる場合、
VERSION
ファイルが全ての source / binary distributions に含まれていることを確認しなければならない(例えば、MANIFEST.in
にinclude VERSION
を追加するなど)。setup.py
で値を設定し、プロジェクトコードではpkg_resources
API を使う。import pkg_resources assert pkg_resources.get_distribution('pip').version == '1.2.0'
注意:
pkg_resources
API が認識するのはインストール環境のメタデータだけであり、これは必ずしも現在インポートされているコードとは限らない。sample/__init__.py
で__version__
の値を設定し、setup.py
でsample
をインポートする。import sample setup( ... version=sample.__version__ ... )
この手法はよく使われているが、
sample/__init__.py
がinstall_requires
依存関係からパッケージをインポートしていると失敗しうる。setup.py
の実行時点では、その依存関係はまだインストールされていない可能性が高いからだ。コードではなくバージョン管理システム (Git, Mercurial など)のタグにバージョン番号を保管し、 setuptools_scm を使って自動抽出する。