APKBUILD examples:Python: Difference between revisions

From Alpine Linux
(Add py-setuptools to makedepends)
(Add more examples and considerations)
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''.
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''.
== Considerations ==
=== Python 2 vs. Python 3 ===
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.
You may omit ''py2'' variant, but never omit ''py3'' variant if it's supported by the project.
=== pkgname ===
Package name for a Python ''library'' must be prefixed with ''py-'', ''py2-'', or ''py3-''.
; 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.
=== arch ===
; noarch : Use for pure Python packages (i.e. without compiled code). Also add python2, or python3 to <tt>depends=</tt>.
; 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 ===
Basically all Python 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:
<pre>
https://files.pythonhosted.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz
</pre>
where <tt>_pkgname</tt> is a real name of the Python package.
== Examples ==
Comments marked with <tt>##</tt> should not be copied into final APKBUILD!
=== 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"
_pkgname="foo"
...
...
depends="python3"
depends="python3"
Line 19: Line 65:
</pre>
</pre>


If Python package support both Python 2 and Python 3, then the Alpine package should provide both variants as ''py2-'' and ''py3-'' subpackages.
 
=== 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>
<pre>
Line 25: Line 75:
_pkgname="PyFoo"
_pkgname="PyFoo"
...
...
arch="noarch"
depends="py-bar py-baz"
depends="py-bar"
makedepends="python2-dev python3-dev py-setuptools"
makedepends="python2-dev python3-dev py-setuptools"
subpackages="py2-${pkgname#py-}:_py2 py3-${pkgname#py-}:_py3"
subpackages="py2-${pkgname#py-}:_py2 py3-${pkgname#py-}:_py3"
Line 43: Line 92:
_py2() {
_py2() {
replaces="$pkgname"
replaces="$pkgname"
depends="${depends//py-/py2-}"
depends="${depends//py-/py2-}" ## remove if there are no common Python dependencies
_py python2
_py python2
}
}


_py3() {
_py3() {
depends="${depends//py-/py3-}"
depends="${depends//py-/py3-}" ## remove if there are no common Python dependencies
_py python3
_py python3
}
}
Line 55: Line 104:
local python="$1"
local python="$1"
pkgdesc="$pkgdesc (for $python)"
pkgdesc="$pkgdesc (for $python)"
depends="$depends $python"
depends="$depends $python" ## remove if arch isn't noarch
install_if="$pkgname=$pkgver-r$pkgrel $python"
install_if="$pkgname=$pkgver-r$pkgrel $python"


Line 63: Line 112:
</pre>
</pre>


* If the package doesn’t have any dependencies, then omit <tt>depends=""</tt> in the <tt>_py2()</tt> and <tt>_py3()</tt> functions.
* If the package contains some compiled code (native extensions), then replace the <tt>subpackages=</tt> line with: <pre>subpackages="py2-${pkgname#py-}:_py2:all py3-${pkgname#py-}:_py3:all"</pre>


Source located at [http://pypi.python.org PyPi]
=== 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!
 
<pre>
<pre>
_pkgname=ShortName
pkgname="py-foo"
_pkgname="PyFoo"
...
...
source="https://files.pythonhosted.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz"
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 || return 1
python3 setup.py build || return 1
}
 
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 || return 1
done
}
 
_py2() {
replaces="$pkgname"
depends="${depends//py-/py2-}"  ## remove if there are no common Python dependencies
_py python2
}
 
_py3() {
depends="${depends//py-/py3-}"  ## remove if there are no common Python dependencies
_py python3
}
 
_py() {
local python="$1"
local pyver="${1:6:1}"
pkgdesc="$pkgdesc (for $python)"
depends="$depends $python"  ## remove if arch isn't noarch
install_if="$pkgname=$pkgver-r$pkgrel $python"
 
cd "$builddir"
$python setup.py install --prefix=/usr --root="$subpkgdir" || return 1
 
# Add version suffix to executable files.
local path; for path in "$subpkgdir"/usr/bin/*; do
mv "$path" "$path-$pyver" || return 1
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 || return 1
 
# 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" || return 1
done
}
 
build() {
local python; for python in python2 python3; do
cd "$builddir"-$python
$python setup.py build || return 1
done
}
 
_py() {
...
 
cd "$builddir"-$python
$python setup.py install --prefix=/usr --root="$subpkgdir" || return 1
}
</pre>
</pre>


[[Category:Development]] [[Category:Python]]
[[Category:Development]] [[Category:Python]]

Revision as of 20:08, 29 November 2016

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.


Considerations

Python 2 vs. Python 3

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. You may omit py2 variant, but never omit py3 variant if it's supported by the project.

pkgname

Package name for a Python library must be prefixed with py-, py2-, or py3-.

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.

arch

noarch
Use for pure Python packages (i.e. without compiled code). Also add python2, or python3 to depends=.
all (and others)
Use for packages with native extensions (i.e. with compiled code). Do not add python2/python3 to depends= (it's auto-detected via dynamic linking to python library).

source

Basically all Python are published in 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 source= as:

https://files.pythonhosted.org/packages/source/${_pkgname:0:1}/$_pkgname/$_pkgname-$pkgver.tar.gz

where _pkgname is a real name of the Python package.


Examples

Comments marked with ## should not be copied into final APKBUILD!


Package for single Python version

If the project supports only Python 3 (or 2), then the APKBUILD is very simple:

pkgname="py3-foo"
_pkgname="foo"
...
depends="python3"
makedepends="python3-dev"
...

build() {
	cd "$builddir"
	python3 setup.py build
}

package() {
	cd "$builddir"
	python3 setup.py install --prefix=/usr --root="$pkgdir"
}


Multiversion package without executables

Use this variant if the package does not install any files outside of /usr/lib/pythonX.Y/site-packages. If the build modifies source code, e.g. using 2to3, read the last section!

pkgname="py-foo"
_pkgname="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 || return 1
	python3 setup.py build || return 1
}

package() {
	mkdir -p "$pkgdir"
}

_py2() {
	replaces="$pkgname"
	depends="${depends//py-/py2-}"  ## remove if there are no common Python dependencies
	_py python2
}

_py3() {
	depends="${depends//py-/py3-}"  ## remove if there are no common Python dependencies
	_py python3
}

_py() {
	local python="$1"
	pkgdesc="$pkgdesc (for $python)"
	depends="$depends $python"  ## remove if arch isn't noarch
	install_if="$pkgname=$pkgver-r$pkgrel $python"

	cd "$builddir"
	$python setup.py install --prefix=/usr --root="$subpkgdir"
}


Multiversion package with executables

Use this variant if the packages installs some executables into /usr/bin. If the build modifies source code, e.g. using 2to3, read the last section!

pkgname="py-foo"
_pkgname="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 || return 1
	python3 setup.py build || return 1
}

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 || return 1
	done
}

_py2() {
	replaces="$pkgname"
	depends="${depends//py-/py2-}"  ## remove if there are no common Python dependencies
	_py python2
}

_py3() {
	depends="${depends//py-/py3-}"  ## remove if there are no common Python dependencies
	_py python3
}

_py() {
	local python="$1"
	local pyver="${1:6:1}"
	pkgdesc="$pkgdesc (for $python)"
	depends="$depends $python"  ## remove if arch isn't noarch
	install_if="$pkgname=$pkgver-r$pkgrel $python"

	cd "$builddir"
	$python setup.py install --prefix=/usr --root="$subpkgdir" || return 1

	# Add version suffix to executable files.
	local path; for path in "$subpkgdir"/usr/bin/*; do
		mv "$path" "$path-$pyver" || return 1
	done
}


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 setup.py build with python2 and python3 one after another with the same source files. You must duplicate the buildir and run them separately.

prepare() {
	default_prepare || return 1

	# 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" || return 1
	done
}

build() {
	local python; for python in python2 python3; do
		cd "$builddir"-$python
		$python setup.py build || return 1
	done
}

_py() {
	...

	cd "$builddir"-$python
	$python setup.py install --prefix=/usr --root="$subpkgdir" || return 1
}