|
|
| (15 intermediate revisions by 2 users not shown) |
| Line 1: |
Line 1: |
| A lot of Python packages use the ''setuptools'' or ''distutils'' framework. This mean that the build() and the package() section looks a bit different compared to an application which uses ''make''.
| | Typical Python packages use Python-specific build systems, making their <code>build()</code> and <code>package()</code> functions different compared to an application which uses ''make''. |
| | |
|
| |
|
| == Considerations == | | == Considerations == |
|
| |
|
| === Python 2 vs. Python 3 === | | === pkgname === |
|
| |
|
| '''Python 3 should be the default option.''' If the project support both Python 2 and Python 3, then the Alpine package may provide both variants as ''py2-'' and ''py3-'' subpackages.
| | Package name for a Python ''library'' must be prefixed with ''py3-''. |
| However, add ''py2'' variant only when you really need it.
| |
| Python 2 is legacy and will be deprecated soon.
| |
| You may omit ''py2'' variant, but never omit ''py3'' variant if it's supported by the project.
| |
|
| |
|
| === pkgname ===
| | For an 'executable' (for example, <code>black</code>, <code>binwalk</code>), you generally don't need to prefix it. |
|
| |
|
| Package name for a Python ''library'' must be prefixed with ''py-'', ''py2-'', or ''py3-''.
| | === arch === |
| | |
| ; py- : Use if the project supports both Python 2 and Python 3, even if it does not support Python 3 yet, but may in future.
| |
| ; py2- : TODO
| |
| ; py3- : Use if the project does not support Python 2.
| |
|
| |
|
| There’s no exact rule if the prefix should be used for tools and applications written in Python, it varies.
| | ; noarch : Use for pure Python packages (i.e. without compiled code). |
| | ; all (and others) : Use for packages with native extensions (i.e. with compiled code). |
|
| |
|
| === arch === | | === depends === |
|
| |
|
| ; noarch : Use for pure Python packages (i.e. without compiled code). Also add python2, or python3 to <tt>depends=</tt>.
| | '''Do not''' add python3 to <tt>depends=</tt> (it's auto-detected via dynamic linking to python library). |
| ; all (and others) : Use for packages with native extensions (i.e. with compiled code). '''Do not''' add python2/python3 to <tt>depends=</tt> (it's auto-detected via dynamic linking to python library).
| |
|
| |
|
| === source === | | === source === |
|
| |
|
| Basically all Python are published in [https://pypi.python.org/pypi PyPI] (the Python Package Index).
| | Most Python packages are published in [https://pypi.python.org/pypi PyPI](the Python Package Index). |
| If the package has a source tarball available in PyPI (that’s true for most packages), you should reference it in <tt>source=</tt> as: | | If the package has a source tarball available in PyPI (that’s true for most packages), and it contains tests (some explicitly remove them from PyPI), you should reference it in <tt>source=</tt> as: |
|
| |
|
| <pre> | | <pre> |
| Line 35: |
Line 27: |
| </pre> | | </pre> |
|
| |
|
| where <tt>_pyname</tt> is a real name of the Python package. | | where <tt>_pyname</tt> is the real name of the Python package. |
|
| |
|
| | Otherwise, use the normal upstream git tarballs. |
|
| |
|
| == Examples == | | == Examples == |
|
| |
|
| Comments marked with <tt>##</tt> should not be copied into final APKBUILD!
| | === pep517 invocation === |
| | |
| | |
| === Package for single Python version === | |
| | |
| If the project supports only Python 3 (or 2), then the APKBUILD is very simple:
| |
|
| |
|
| <pre> | | <pre> |
| pkgname="py3-foo" | | pkgname="py3-foo" |
| _pyname="foo" | | _pyname=foo |
| ... | | ... |
| depends="python3" | | depends="py3-bar py3-baz" |
| makedepends="python3-dev" | | makedepends="py3-gpep517 py3-setuptools py3-wheel python3-dev" |
| | checkdepends="py3-pytest" |
| | subpackages="$pkgname-pyc" |
| | source="$pkgname-$pkgver.tar.gz::https://github.com/xyz/foo/archive/refs/tags/v$pkgver.tar.gz" |
| | builddir="$srcdir/$_pyname-$pkgver" |
| ... | | ... |
|
| |
|
| build() { | | build() { |
| cd "$builddir" | | gpep517 build-wheel --wheel-dir .dist --output-fd 3 3>&1 |
| python3 setup.py build
| |
| } | | } |
|
| |
|
| check() { | | check() { |
| cd "$builddir" | | python3 -m venv --clear --system-site-packages testenv |
| python3 setup.py test | | testenv/bin/python3 -m installer .dist/*.whl |
| | testenv/bin/python3 -m pytest |
| } | | } |
|
| |
|
| package() { | | package() { |
| cd "$builddir"
| | python3 -m installer -d "$pkgdir" \ |
| python3 setup.py install --prefix=/usr --root="$pkgdir" | | dist/*.whl |
| } | | } |
| </pre> | | </pre> |
|
| |
|
| | | Depending on the <code>build-backend</code> in the pyproject.toml, the package should depend on py3-setuptools, py3-flit-core, py3-poetry-core or py3-hatchling at build time. If a project specifies literally <code>flit</code> or <code>poetry</code>, patch it to use the <code>-core</code> variant. |
| === Multiversion package without executables ===
| |
| | |
| Use this variant if the package does not install any files outside of <tt>/usr/lib/pythonX.Y/site-packages</tt>.
| |
| If the build modifies source code, e.g. using 2to3, read the last section!
| |
| | |
| <pre>
| |
| pkgname="py-foo"
| |
| _pyname="PyFoo"
| |
| ...
| |
| _py2deps="python2 py2-bar py2-baz"
| |
| _py3deps="python3 py3-bar py3-baz"
| |
| makedepends="python2-dev python3-dev"
| |
| subpackages="py2-${pkgname#py-}:_py2 py3-${pkgname#py-}:_py3"
| |
| ...
| |
| | |
| build() { | |
| cd "$builddir"
| |
| python2 setup.py build
| |
| python3 setup.py build
| |
| }
| |
| | |
| check() {
| |
| cd "$builddir"
| |
| python2 setup.py test
| |
| python3 setup.py test
| |
| }
| |
| | |
| package() {
| |
| cd "$builddir"
| |
| python2 setup.py install --prefix=/usr --root="$pkgdir"
| |
| python3 setup.py install --prefix=/usr --root="$pkgdir"
| |
| }
| |
| | |
| _py() {
| |
| local _python="$1"
| |
| pkgdesc="$pkgdesc (for $_python)"
| |
| install_if="$pkgname=$pkgver-r$pkgrel $_python"
| |
| | |
| mkdir -p "$subpkgdir"/usr/lib/
| |
| mv "$pkgdir"/usr/lib/$_python* "$subpkgdir"/usr/lib/
| |
| }
| |
| | |
| _py2() {
| |
| depends="$_py2deps"
| |
| _py python2
| |
| }
| |
| | |
| _py3() {
| |
| depends="$_py3deps"
| |
| _py python3
| |
| }
| |
| </pre> | |
| | |
| === Multiversion package with executables ===
| |
| | |
| Use this variant if the packages installs some executables into <tt>/usr/bin</tt>.
| |
| If the build modifies source code, e.g. using 2to3, read the last section!
| |
| | |
| '''Note:''' This is just mere workaround that will not be needed in future once we add needed features to apk.
| |
| | |
| <pre>
| |
| pkgname="py-foo"
| |
| _pyname="PyFoo"
| |
| ...
| |
| depends="py-bar py-baz"
| |
| makedepends="python2-dev python3-dev py-setuptools"
| |
| subpackages="py2-${pkgname#py-}:_py2 py3-${pkgname#py-}:_py3"
| |
| ...
| |
| | |
| build() {
| |
| cd "$builddir"
| |
| python2 setup.py build
| |
| python3 setup.py build
| |
| }
| |
| | |
| package() {
| |
| mkdir -p "$pkgdir"/usr/bin
| |
| | |
| # Create unsuffixed symlinks for executables from py3 subpackage.
| |
| local name; for name in foo bar baz; do
| |
| ln -s $name-3 "$pkgdir"/usr/bin/$name
| |
| done
| |
| }
| |
| | |
| _py2() {
| |
| replaces="$pkgname" ## remove if you're writing a new aport (and always remove this comment!)
| |
| depends="${depends//py-/py2-}" ## remove if there are no common Python dependencies, i.e. above depends= is empty/undefined (and always remove this comment!)
| |
| _py python2
| |
| }
| |
| | |
| _py3() {
| |
| depends="${depends//py-/py3-}" ## remove if there are no common Python dependencies, i.e. above depends= is empty/undefined (and always remove this comment!)
| |
| _py python3
| |
| }
| |
| | |
| _py() {
| |
| local python="$1"
| |
| local pyver="${1:6:1}"
| |
| pkgdesc="$pkgdesc (for $python)"
| |
| depends="$depends $python" ## remove if arch isn't noarch (and always remove this comment!)
| |
| install_if="$pkgname=$pkgver-r$pkgrel $python"
| |
| | |
| cd "$builddir"
| |
| $python setup.py install --prefix=/usr --root="$subpkgdir"
| |
| | |
| # Add version suffix to executable files.
| |
| local path; for path in "$subpkgdir"/usr/bin/*; do
| |
| mv "$path" "$path-$pyver"
| |
| done
| |
| }
| |
| </pre> | |
| | |
| | |
| === Multiversion package for project using 2to3 ===
| |
| | |
| Some Python projects use 2to3 (or similar tools) during build phase to make the code-base compatible with Python 3.
| |
| Since it modifies sources during build, you cannot run <tt>setup.py build</tt> with python2 and python3 one after another with the same source files.
| |
| You must duplicate the buildir and run them separately.
| |
| | |
| <pre>
| |
| prepare() {
| |
| default_prepare
| |
| | |
| # Soure files are modified during build with 2to3 tool, so we cannot
| |
| # build it for both Python versions in the same location.
| |
| local python; for python in python2 python3; do
| |
| cp -r "$builddir" "$builddir-$python"
| |
| done
| |
| }
| |
| | |
| build() {
| |
| local python; for python in python2 python3; do
| |
| cd "$builddir"-$python
| |
| $python setup.py build
| |
| done
| |
| }
| |
| | |
| _py() {
| |
| ...
| |
| | |
| cd "$builddir"-$python
| |
| $python setup.py install --prefix=/usr --root="$subpkgdir"
| |
| }
| |
| </pre> | |
| | |
| === Generating documentation ===
| |
| | |
| To generate documentation:
| |
| | |
| <pre>
| |
| makedepends="py-sphinx"
| |
| subpackages="$pkgname-doc"
| |
| | |
| package() {
| |
| ...
| |
| cd "$builddir"/doc
| |
| install -d "$pkgdir"/usr/share/html/$pkgname "$pkgdir"/usr/share/man/man1
| |
| PYTHONPATH="$builddir/src:$PYTHONPATH" make html man
| |
| install -t "$pkgdir"/usr/share/man/man1 build/man/*
| |
| mv build/html/* "$pkgdir"/usr/share/html/$pkgname
| |
| }
| |
| </pre> | |
|
| |
|
| [[Category:Development]] [[Category:Python]] | | [[Category:Development]] [[Category:Python]] |
Typical Python packages use Python-specific build systems, making their build() and package() functions different compared to an application which uses make.
Considerations
pkgname
Package name for a Python library must be prefixed with py3-.
For an 'executable' (for example, black, binwalk), you generally don't need to prefix it.
arch
- noarch
- Use for pure Python packages (i.e. without compiled code).
- all (and others)
- Use for packages with native extensions (i.e. with compiled code).
depends
Do not add python3 to depends= (it's auto-detected via dynamic linking to python library).
source
Most Python packages are published in PyPI(the Python Package Index).
If the package has a source tarball available in PyPI (that’s true for most packages), and it contains tests (some explicitly remove them from PyPI), you should reference it in source= as:
https://files.pythonhosted.org/packages/source/${_pyname%${_pyname#?}}/$_pyname/$_pyname-$pkgver.tar.gz
where _pyname is the real name of the Python package.
Otherwise, use the normal upstream git tarballs.
Examples
pep517 invocation
pkgname="py3-foo"
_pyname=foo
...
depends="py3-bar py3-baz"
makedepends="py3-gpep517 py3-setuptools py3-wheel python3-dev"
checkdepends="py3-pytest"
subpackages="$pkgname-pyc"
source="$pkgname-$pkgver.tar.gz::https://github.com/xyz/foo/archive/refs/tags/v$pkgver.tar.gz"
builddir="$srcdir/$_pyname-$pkgver"
...
build() {
gpep517 build-wheel --wheel-dir .dist --output-fd 3 3>&1
}
check() {
python3 -m venv --clear --system-site-packages testenv
testenv/bin/python3 -m installer .dist/*.whl
testenv/bin/python3 -m pytest
}
package() {
python3 -m installer -d "$pkgdir" \
dist/*.whl
}
Depending on the build-backend in the pyproject.toml, the package should depend on py3-setuptools, py3-flit-core, py3-poetry-core or py3-hatchling at build time. If a project specifies literally flit or poetry, patch it to use the -core variant.