给 Arch 打一个包 – Python 模块篇

这是一篇简化的教程,如果你有一个喜爱的 Python 模块不在 Arch 仓库里,AUR 里也没有,可以尝试读下去。

准备

对 Python 模块来说,一般仅仅一个 PKGBUILD 文件就足以完成所有的事情。现在你可以打开你最喜欢的文本编辑器,把下面这一个简单的 PKGBUILD 模板复制进去:

# $Id$
# Maintainer: Felix Yan <felixonmars@archlinux.org>

pkgbase=python-whatever
pkgname=('python-whatever' 'python2-whatever')
pkgver=0.4.3
pkgrel=1
pkgdesc='Easy way to make anonymous functions by partial application of operators'
arch=('any')
license=('BSD')
url='https://github.com/Suor/whatever'
makedepends=('python-setuptools' 'python2-setuptools')
checkdepends=('python-pytest-runner' 'python2-pytest-runner')
source=("$pkgbase-$pkgver.tar.gz::https://github.com/Suor/whatever/archive/$pkgver.tar.gz")
sha512sums=('162d66753ef4fb15279150b7fa953b4ecf086e2b36cc77531dac099ff4a25b3458af627bdf52e168b7b4b2163a1445f35c2c656b1c10c0c73502d2357ba42dd8')

prepare() {
  cp -a whatever-$pkgver{,-py2}
}

build() {
  cd "$srcdir"/whatever-$pkgver
  python setup.py build

  cd "$srcdir"/whatever-$pkgver-py2
  python2 setup.py build
}

check() {
  cd "$srcdir"/whatever-$pkgver
  python setup.py pytest

  cd "$srcdir"/whatever-$pkgver-py2
  python2 setup.py pytest
}

package_python-whatever() {
  depends=('python')

  cd whatever-$pkgver
  python setup.py install --root="$pkgdir" --optimize=1
  install -D -m644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
}

package_python2-whatever() {
  depends=('python2')

  cd whatever-$pkgver-py2
  python2 setup.py install --root="$pkgdir" --optimize=1
  install -D -m644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
}

# vim:set ts=2 sw=2 et:

因为距离 Python 2 的废弃时间(2020年)还早,Arch 仓库中的 Python 模块包通常同时提供 Python 2/3 模块。上面例子里的 Python 软件包名叫 whatever,这也同样是它在 PyPI 中的名字。如果原来的包名中包含大写字母,在制作软件包时需要改成小写。

名字和源代码位置

现在你可以开始修改了。首先替换名字,一个简单的方法是首先找到你要处理的软件包的仓库,然后全局查找替换 GitHub URL 和软件包名(如果不在 GitHub 上,就稍微找一下吧)。

注:PyPI 的下载地址一般格式为:

"https://pypi.io/packages/source/喵/名字/名字-$pkgver.tar.gz"

注意把中间的“喵”换成包名的首字母。

依赖、介绍、授权

现在可以打开代码中的 setup.py 了。如果你看到了 install_requires=,那恭喜你,基本可以参照这个文件的内容(或者它打开的文件)来找到依赖列表。对每一个依赖,先检查一下是否在 Arch 仓库或 AUR 中(大部分都在),如果在的话,更新一下上面的 makedepends 列表和下方 python 2/3 对应的 package_*() 函数中的 depends 列表,加入这些依赖。接下来,在附近你可以找到模块介绍和授权,分别填入 pkgdesc 和 license 即可。

如果你看到的是一个只有包括 pbr=True 的很短的 setup.py 文件,说明这个项目使用了 pbr。这时候你需要打开 requirements.txt 查找依赖,并把 python{,2}-pbr 加入 makedepends。模块介绍和授权则会在同目录的 setup.cfg 文件中。

测试

下面是一个比较麻烦的步骤:确定测试如何运行。当然如果你对你的包已经信心满满根本不想跑测试,可以直接去掉 check() 和 checkdepends() (咳咳)然后完工。

一般来说项目自己跑着的持续集成会把测试工具定义在 .travis.yml 或者 tox.ini 这样的文件里,可以在这些地方找到一些线索。一般来说,如果测试使用的是 pytest/py.test 这样的命令,说明测试工具是 pytest,上面的模板已经是这个工具的用法了。模板里定义的 pytest-runner 是一个可以用来解决 PYTHONPATH、2to3、以及依赖等问题的 pytest 运行工具。

如果你看到了 nosetests,说明测试工具是 nose。把上面模板中的 pytest-runner 替换成 nose,并把下面的 setup.py pytest 替换为 setup.py nosetests 一般可以解决问题。

如果你看到的是普通的 setup.py test,则可以去掉 checkdepends,直接修改 check() 为一样的语句。

还有一些其他情况,可以试试在官方仓库里找找我对类似情况的处理进行参考 🙂

最后把定义在 setup.py 中 tests_requires 里,或者 tox.ini、.travis.yml 中的依赖加入 checkdepends 列表,大功告成!

现在你可以运行 makepkg 进行打包尝试了。如果上面的步骤都正确完成了,这里应该可以顺利完成(flag)。

疑难解答

  • 有些项目的测试需要 X 环境,而我的服务器上不一定启动了 X。

在 checkdepends 中加入 xorg-server-xvfb,然后在 check() 中两个运行测试的语句前面加上 xvfb-run 即可。

  • 打包过程中因为 UnicodeDecodeError 挂掉了。

在不同的条件下,这个问题的原因可能是多种多样的,但解决方法通常比较一致:在出问题的语句前面加上 LC_CTYPE=en_US.UTF-8。

  • pbr 提示无法找到版本。

在 prepare() 里加上:export PBR_VERSION=$pkgver

  • setuptools_scm 提示无法找到版本。

在 prepare() 里加上:export SETUPTOOLS_SCM_PRETEND_VERSION=$pkgver

  • 测试中用到了 entry_point 功能,因此在未安装的情况下测试软件会失败。

这种情况确实需要更多的 hack,我常用的一个简单方法是安装到临时目录,然后修改 PYTHONPATH:

check() {
  # Hack entry points by installing it

  cd "$srcdir"/whatever-$pkgver
  python setup.py install --root="$PWD/tmp_install" --optimize=1
  PYTHONPATH="$PWD/tmp_install/usr/lib/python3.6/site-packages:$PYTHONPATH" py.test

  cd "$srcdir"/whatever-$pkgver-py2
  python2 setup.py install --root="$PWD/tmp_install" --optimize=1
  PYTHONPATH="$PWD/tmp_install/usr/lib/python2.7/site-packages:$PYTHONPATH" py.test2
}
  • 我实在调不过测试了,但我确定这个包没问题;或者上游已经知道这个问题了,确定不是因为我打包方面的问题引起。

把这个测试跳过吧!(咳咳)

2 thoughts on “给 Arch 打一个包 – Python 模块篇”

    1. 后一个域名缺失很多库的新版,所以后来基本都迁移到 pypi.io 了。包名里有点的问题目前没有一致解,有一部分 Arch 包保留了点,一部分把点换成了短横线 –

Leave a Reply

Your email address will not be published. Required fields are marked *

QR Code Business Card