読者です 読者をやめる 読者になる 読者になる

今川館

都内勤務の地味OLです

setup.pyのdependency_linksの書き方

Python setuptools

前回の続き


前回の記事
でpipコマンドにGithubリポジトリsshで接続するURLを指定する方法を紹介した。

今度はsetup.pyで非公開プロジェクトを依存パッケージに指定する方法をここにメモしておく。

なお、わたしはwheelパッケージの仕様を知らないのでここでは旧式のeggパッケージを作ることを想定して話を進める。

依存パッケージをPyPI以外から取得するときはdependency_links

setup.pyのsetup関数にはdependency_linksという引数を渡せる。

これを使って依存パッケージの所在を指定できる。

ところがURLの指定方法に込み入ったルールがあり、pipのときと違って何かと不都合が多く注意を要する。

試しにpython-dateutilをsshのURLで入れてみる

試しにdateutilモジュールをdependency_linksを使って入れてみる。

リポジトリの名前はdateutil、しかしパッケージの名前はpython-dateutil

まず、ダメな例を示す。これだとうまくいかないので注意。

setup(...
    install_requires=['python-dateutil'],
    dependency_links=['git+ssh://git@github.com/dateutil/dateutil.git'],
    ...
)

コンソール出力を見ると、

Searching for python-dateutil
Reading git+ssh://git@github.com/dateutil/dateutil.git
Download error on git+ssh://git@github.com/dateutil/dateutil.git: unknown url type: git+ssh -- Some packages may not be found!
Reading https://pypi.python.org/simple/python-dateutil/
Reading http://labix.org/python-dateutil
Reading https://dateutil.readthedocs.org
Best match: python-dateutil 2.4.0
Downloading https://pypi.python.org/packages/source/p/python-dateutil/python-dateutil-2.4.0.tar.gz#md5=75714163bb96bedd07685cdb2071b8bc

はい、赤字部分の通り、Githubからパッケージを取得しようとして失敗したので結局PyPIから取得している。

原因は、dateutilは正式にはpython-dateutilというパッケージ名で、Githubリポジトリの名前 "dateutil" と違うから。

#egg=なんちゃら の部分が大事

dependency_linksのURLに#egg=python_dateutilというフラグメント識別子をつけるとこの問題が解決する(以下)。

setup(...
    install_requires=['python-dateutil'],
    dependency_links=['git+ssh://git@github.com/dateutil/dateutil.git#egg=python_dateutil'],
    ...
)

install_requiresには "python-dateutil" とハイフン区切りにするが、dependency_linksのゲタは "python_dateutil" とアンダースコア区切りになる。
(後述するが、これには理由がある)

コンソール出力を見ると、

Searching for python-dateutil
Best match: python-dateutil [unknown version]
Doing git clone from ssh://git@github.com/dateutil/dateutil.git to /tmp/easy_install-1Y4QDO/dateutil.git
Processing dateutil.git
Writing /tmp/easy_install-1Y4QDO/dateutil.git/setup.cfg
Running setup.py -q bdist_egg --dist-dir /tmp/easy_install-1Y4QDO/dateutil.git/egg-dist-tmp-VUkHXx
Adding python-dateutil 2.4.0 to easy-install.pth file

Installed /home/echizen/foolish/lib/python2.7/site-packages/python_dateutil-2.4.0-py2.7.egg

今度はPyPIに問い合わせに行かなくなり、期待通りの結果となる。

ね、簡単でしょ?

ここまでは簡単。
では、dateutilの2.4.0バージョンを指定してインストールするときはどうだろうか。

バージョンを指定すると??

その場合は以下となる。

setup(...
    install_requires=['python-dateutil==2.4.0'],
    dependency_links=['git+ssh://git@github.com/dateutil/dateutil.git@2.4.0#egg=python_dateutil-2.4.0'],
    ...
)

dateutil.gitというリポジトリ名の後ろの部分が複雑になる。

@2.4.0#egg=python_dateutil-2.4.0

ゲタに加えてアットマークまで出てくるので余計混乱する。

アットマークの後ろはGitのブランチやタグの名前を書く

アットマークの後ろはなぬものだ?と。生まれてこの方見だこだぁねぇ、と。
おら東京さ行ぐだと、銀座に山買うだぇと。

アットマークの後ろはGitのブランチやタグの名前である。

https://github.com/dateutil/dateutil/tree/2.4.0
https://github.com/dateutil/dateutil/releases/tag/2.4.0

この通り、python-dateutilプロジェクトには2.4.0というタグが存在する。
もしブランチを指定するなら @master とか @t2015 などと書く。

ゲタの後ろはPythonパッケージの名前とバージョン名をハイフン区切りで書く

次に、ゲタの後ろの部分だが、python_dateutilはパッケージの名前、2.4.0がバージョンの名前となる。
(パッケージ名とバージョン名をハイフンで区切るから、パッケージ名の中の区切り文字はアンダースコアに置き換えられる)

つまり、

git+ssh://git@github.com/dateutil/dateutil.git@2.4.0#egg=python_dateutil-2.4.0

これはpython-dateutilの2.4.0バージョンが欲しければ、そのリポジトリの2.4.0のタグを見に行けばあるよ、と教えているのである。

参考リンク

python-dateutil==2.4.0とか>2.0, <=2.3とか、バージョンを指定する式
https://pythonhosted.org/setuptools/setuptools.html#declaring-dependencies

pipのパッケージURL指定方法(git向け)
https://pip.pypa.io/en/latest/reference/pip_install.html#git