Re: The Python Registrar
On Sat, Feb 23, 2002 at 10:38:17AM +1100, Donovan Baarda wrote:
> On Tue, Feb 12, 2002 at 12:05:22AM +0100, Bastian Kleineidam wrote:
> > Hello.
> >
> > The first version of the python-central package is online at
> > http://people.debian.org/~calvin/python-central/
> >
> > It provides support for installing pure Python modules independent
> > of the Python version (see Python Policy 2.2.3).
[...]
> Did you see my analysis and modified "register-python-package" script? I
> posted it under a misleading subject by mistake (responded to another thread
> that migrated onto it).
OK, I got creative and figured out a way the python-central could work
without using an emac's style registry, instead just using the existing dpkg
"Depends:" information.
This new version of register-python-package has shrunk to under 180 lines,
and is much simplified over the original. The usage has been reduced to;
usage: ./register-python-package {configure|remove} <package name>
It will determine if it is configure/removing a python version or python
module from the package name. Any package that contains *.py files in
/usr/lib/python/site-packages is assumed to be multi-version python module.
The versions of python that a multi-version python module supports is
determined by the "pythonX.Y" entries in the package's "Depends:".
An example for a python-foo module that works for python version 1.5->2.1
would have the following dependancies;
Depends: python1.5 | python1.6 | python2.0 | python2.1, python-central
Any python package with python-central support, including pythonX.Y
packages, would call in it's postinst;
register-python-package configure <package-name>
and in its prerm would call;
register-python-package remove <package-name>
For a pythonX.Y package, installing will symlink and compile all modules
with files in /usr/lib/python/site-packages that have compable dependancies.
For a python-foo package, installing will symlink and compile the module for
all installed and compatible python versions. Removing will do the correct
inverse.
Comments welcome. This one is a bit more tested than the last.
--
----------------------------------------------------------------------
ABO: finger abo@minkirri.apana.org.au for more info, including pgp key
----------------------------------------------------------------------
#!/bin/sh
# the python registrar
# directory with registered packages
CENTRAL=/var/lib/python-central
# python command to byte-compile a file
BYTECOMP="import sys,py_compile;py_compile.compile(sys.argv[1],sys.argv[2])"
# directory for installed .py files
IN=/usr/lib/python/site-packages
# get_modules <pythonX.Y package>
# return installed multi-version python packages that work for the
# specified python package
get_modules() {
PYTHONXY=$1
RET=""
for p in `dpkg -S /usr/lib/python/site-packages 2>/dev/null | sed 's#,\|:.*$##g'`; do
if dpkg -s $p | egrep "^Depends:.* $PYTHONXY([ ,]|$)" >/dev/null 2>&1; then
RET="$RET $p"
fi
done
}
# get_versions <package name>
# return installed versions of python supported by the python package
get_versions () {
DEPENDS=`dpkg -s $1 | grep "^Depends:" | cut -d: -f2`
RET=""
for PYTHONXY in `ls /usr/bin/python?.? | cut -c 10-`; do
if echo "$DEPENDS" | egrep " $PYTHONXY([ ,]|$)" >/dev/null 2>&1; then
RET="$RET $PYTHONXY"
fi
done
}
# module_compile <package name> <pythonX.Y package>
# symlinks and compiles a package for the specified python version
module_compile () {
PACKAGE=$1
PYTHONXY=$2
PYTHON=/usr/bin/$PYTHONXY
OUT=/usr/lib/$PYTHONXY/site-packages
# look for .py files in the package
for i in `dpkg --listfiles $PACKAGE | grep "^$IN/.*\.py$" | sed "s#^$IN/##"`; do
# install potentially missing (sub)directories
DIRNAME=`dirname $OUT/$i`
install -d -o root -g root -m 0755 $DIRNAME
# make relative link
REL="../.."
while [ $DIRNAME != $OUT ]; do
REL=../$REL
DIRNAME=`dirname $DIRNAME`
# prevent infinite loops
if [ "$DIRNAME" = "/" -o "$DIRNAME" = "." ]; then
exit 1
fi
done
# REL points to /usr/lib now
ln -sf $REL/python/site-packages/$i $OUT/$i
# byte-compile package .py files
$PYTHON -O -c "$BYTECOMP" $OUT/$i $OUT/${i}o
$PYTHON -c "$BYTECOMP" $OUT/$i $OUT/${i}c
# fix output file mode
chmod 0644 $OUT/${i}[co] || true
done
}
# module_clean <package name> <pythonX.Y package>
# removes symlinks and bytecode of a package for the specified python version
module_clean() {
# remove symlink and byte-compiled files
PACKAGE=$1
PYTHONXY=$2
OUT=/usr/lib/$PYTHONXY/site-packages
for i in `dpkg --listfiles $PACKAGE | grep "^$IN/.*\.py$" | sed "s#^$IN/##"`; do
rm -f $OUT/$i $OUT/${i}c $OUT/${i}o
done
# remove directories
for i in `dpkg --listfiles $PACKAGE | grep "^$IN/" | sort -r | sed "s#^$IN/##"`; do
if [ -d $OUT/$i ]; then
rmdir $OUT/$i || true
fi
done
}
# module_configure <package name>
# configure a module for all supported installed python versions
module_configure () {
PACKAGE=$1
get_versions $PACKAGE
versions=$RET
for pyver in $versions; do
module_compile $PACKAGE $pyver
done
}
# module_remove <package name>
# remove a configured module for all supported installed python versions
module_remove () {
PACKAGE=$1
get_versions $PACKAGE
versions=$RET
for pyver in $versions; do
module_clean $PACKAGE $pyver
done
}
# python_configure <pythonX.Y package>
# byte-compile this python version plus all supported packages
python_configure () {
PYTHONXY=$1
PYTHON=/usr/bin/$PYTHONXY
PYLIBS=/usr/lib/$PYTHONXY
# byte-compile all python files
$PYTHON -O $PYLIBS/compileall.py -q $PYLIBS
$PYTHON $PYLIBS/compileall.py -q $PYLIBS
# byte-compile registered packages
get_modules $PYTHONXY
modules=$RET
for p in $modules; do
module_compile $p $PYTHONXY
done
}
# python_remove <pythonX.Y package>
# remove byte-compiled files for this python version and for all
# supported python packages
python_remove () {
PYTHONXY=$1
PYTHON=/usr/bin/$PYTHONXY
# remove byte-compiled files for this python version
dpkg --listfiles $PYTHONXY |
awk '$0~/\.py$/ {print $0"c\n" $0"o"}' |
xargs rm -f >&2
# remove registered packages
get_modules $PYTHONXY
modules=$RET
for p in $modules; do
module_clean $p $PYTHONXY
done
}
usage () {
echo "usage: $0 {configure|remove} <package name>"
exit 1
}
###############################################################
################ main ##########################
###############################################################
action=$1
if echo $2 | egrep '^python[0-9]\.[0-9]$' >/dev/null 2>&1; then
mode="python"
else
mode="module"
fi
if [ "$action" = "configure" ]; then
${mode}_configure $2
elif [ "$action" = "remove" ]; then
${mode}_remove $2
else
usage
fi
Reply to: