[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: new dh_python proposal



Here's updated dh_python proposal. Main change since my last mail:
pycompile/pyclean will no longer search for files to compile/remove
in public directories as Matthias will fix #552595 using triggers so I don't
have to care about pycentral bugs anymore and dpkg -L seems to be fast enough
to be used in maintainer scripts (BTW: my previous proposal had a typo: "prerm"
should be replaced with "postrm", I guess everyone figured that out from the
context…). 

Again, the main idea is to ship files in official site/dist-packages location
or symlink files from /usr/share/py{,3}shared directory there (if files can be
shared).

This means Architecture:all packages will need sourceful uploads once list of
supported Python versions will change (binNMUs do not touch architecture
independent packages and even if they'd do, that still leaves the
"=${source:Version}" problem).

Advantages:
* dpkg is aware of all .py files (including symlinks) and their locations (it
  isn't true for pysupport/pycentral),
* no need for helper in Depends and Build-Depends - I want dh_python and
  pycompile/pyclean to be shipped in python packages,
* broken modules that use __file__ incorrectly will work without problems,
* less opportunities to break a system while installing / upgrading Python
  packages:
  - problems with creating/removing symlinks in pycentral (see f.e. #552595),
  - starting/stopping daemons problems (very long downtimes due to byte
    compilation via triggers) in pysupport,
* no more compile errors at install time in public directories, all Python
  versions tested at build time,
* Python modules available out of the box (think about daemons and upgrades)


Short overview of how things will work with new dh_python:
==========================================================

build time:
^^^^^^^^^^^
* files installed into the standard location[1] or into private directory.
  It's up to maintainer which files will be installed for which Python version,
  by default every package providing public module should build/install for all
  `pyversions -vs` versions.
* dh_python will:
  - move files to /usr/lib/pythonX.Y/*-packages if /usr/local or 
    /usr/lib/python2.X/site-packages (for X >= 6) is used
    (i.e. --install-layout or --prefix can be skipped in most cases),
  - copy all files that can be shared to /usr/share/py{,3}shared and replace
    the ones in *-packages with a symlink (if package supports only one Python
    version, there's no need to use pyshared),
  - create simple maintainer scripts with pycompile and pyclean
    commands and (if needed) rtupdate script (for private directories that
    use default Python version and will most probably work with next default
    version). Private modules that cannot be used with default Python version
    will get additional pycompile command with all needed arguments, like
    minimum required Python version or hardcoded version in both, maintainer
    and rtupdate scripts,
  - add substvar for ${python:Versions} (used in XB-Python-Version, i.e. the
    "make release managers happy" field (this field will be used by RMs to
    track transitions)
  - add substvar for ${python:Provides}

[1] SL = standard distutils/setuptools/distribute location:
    /usr/{,local}/lib/pythonX.Y/{site,dist}-packages/

installation time:
^^^^^^^^^^^^^^^^^^
* maintainer script will byte compile .pyc files for all provided
  symlinks / private directories if given Python version is installed
  (dpkg -L output will be used to detect which files need byte compilation,
  directories without __init__.py file will be skipped),
* user installs new pythonX.Y package:
  - bytecompile related symlinks (pycompile -V X.Y) - no need for a list of
    files to compile at this point - all .py files in
    /usr/lib/pythonX.Y/{site,dist}-packages will have to be byte-compiled,
    byte compilation will not fail as it was already tested at build time,
* user removes pythonX.Y package:
  - remove all pythonX.Y's .pyc files (pyclean -V X.Y)
  - all packages with private directories that use this Python version will be
    removed by dpkg (Depends field will do its job) so prerm will remove all
    remaining .pyc files in private directories
* default Python version changes:
  - rtupdate scripts for packages with private modules that support it (i.e.
    the ones without hardcoded Python version and without private extensions)
    will be invoked


examples:
=========

example 1 - public modules/extensions only
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
$ python2.4 ./setup.py install --root=debian/python-foo/
 debian/python-foo/usr/lib/python2.4/site-packages/foo/__init__.py
 debian/python-foo/usr/lib/python2.4/site-packages/foo/_foo.so
 debian/python-foo/usr/lib/python2.4/site-packages/foo/bar.py
 debian/python-foo/usr/lib/python2.4/site-packages/spam.py

$ python2.5 ./setup.py install --root=debian/python-foo/
 debian/python-foo/usr/lib/python2.5/site-packages/foo/__init__.py
 debian/python-foo/usr/lib/python2.5/site-packages/foo/_foo.so
 debian/python-foo/usr/lib/python2.5/site-packages/foo/bar.py
 debian/python-foo/usr/lib/python2.5/site-packages/spam.py

$ python2.6 ./setup.py install --root=debian/python-foo/
 debian/python-foo/usr/local/lib/python2.6/dist-packages/foo/__init__.py
 debian/python-foo/usr/local/lib/python2.6/dist-packages/foo/_foo.so
 debian/python-foo/usr/local/lib/python2.6/dist-packages/foo/bar.py
 debian/python-foo/usr/local/lib/python2.6/dist-packages/spam.py

$ python3.1 ./3.x/setup.py install --root=debian/python3-foo/
 debian/python3-foo/usr/local/lib/python3.1/dist-packages/foo/__init__.py
 debian/python3-foo/usr/local/lib/python3.1/dist-packages/foo/_foo.so
 debian/python3-foo/usr/local/lib/python3.1/dist-packages/foo/bar.py

$ dh_python
 # doesn't have to use debian/pyversions or XS-Python-Version as Debian
 # packages now have to build/test files for all supported Python versions;
 # ignores private dirs
 debian/python-foo/usr/lib/python2.4/site-packages/foo/_foo.so
 debian/python-foo/usr/lib/python2.4/site-packages/foo/__init__.py -> /usr/share/pyshared/foo/__init__.py
 debian/python-foo/usr/lib/python2.4/site-packages/foo/bar.py -> /usr/share/pyshared/foo/bar.py
 debian/python-foo/usr/lib/python2.4/site-packages/foo/spam.py -> /usr/share/pyshared/foo/spam.py
 debian/python-foo/usr/lib/python2.5/site-packages/foo/_foo.so
 debian/python-foo/usr/lib/python2.5/site-packages/foo/__init__.py -> /usr/share/pyshared/foo/__init__.py
 debian/python-foo/usr/lib/python2.5/site-packages/foo/bar.py -> /usr/share/pyshared/foo/bar.py
 debian/python-foo/usr/lib/python2.5/site-packages/foo/spam.py -> /usr/share/pyshared/foo/spam.py
 debian/python-foo/usr/lib/python2.6/dist-packages/foo/_foo.so
 debian/python-foo/usr/lib/python2.6/dist-packages/foo/__init__.py -> /usr/share/pyshared/foo/__init__.py
 debian/python-foo/usr/lib/python2.6/dist-packages/foo/bar.py -> /usr/share/pyshared/foo/bar.py
 debian/python-foo/usr/lib/python2.6/dist-packages/foo/spam.py # not a symlink as it differs from Python2.4 and 2.5's version
 debian/python-foo/usr/share/pyshared/foo/__init__.py
 debian/python-foo/usr/share/pyshared/foo/bar.py
 debian/python-foo/usr/share/pyshared/spam.py
 debian/python3-foo/usr/lib/python3.1/dist-packages/foo/_foo.so
 debian/python3-foo/usr/lib/python3.1/dist-packages/foo/__init__.py
 debian/python3-foo/usr/lib/python3.1/dist-packages/foo/bar.py
 debian/python3-foo/usr/lib/python3.1/dist-packages/foo/spam.py
 # note that debian/python3-foo/usr/share/py3shared/ is not used here as
 # there's only one 3.X version supported by this package

$ grep foo debian/python-foo.postinst
 dpkg -L python-foo | pycompile

$ grep foo debian/python3-foo.postinst
 dpkg -L python3-foo | pycompile

$ grep foo debian/python-foo.prerm
 dpkg -L python-foo | pyclean

$ grep foo debian/python3-foo.prerm
 dpkg -L python3-foo | pyclean


example 2 - private modules/scripts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# bar uses default Python version
$ python ./setup.py install --root=debian/mypackage/ --install-lib=/usr/share/privatedir1/ --install-scripts=/usr/share/privatedir1
 debian/mypackage/usr/share/privatedir1/bar/__init__.py
 debian/mypackage/usr/share/privatedir1/run.py

# spam uses Python 2.4 only
$ python ./setup.py install --root=debian/mypackage/ --install-lib=/usr/share/privatedir2/ --install-scripts=/usr/share/privatedir2
 debian/mypackage/usr/share/privatedir2/spam/__init__.py
 debian/mypackage/usr/share/privatedir2/run.py

# egg uses Python >= 2.6
$ python ./setup.py install --root=debian/mypackage/ --install-lib=/usr/share/privatedir3/ --install-scripts=/usr/share/privatedir3
 debian/mypackage/usr/lib/privatedir3/egg/__init__.py
 debian/mypackage/usr/lib/privatedir3/run.py

# baz uses Python >= 2.5 and has private extension
$ python ./setup.py install --root=debian/mypackage/ --install-lib=/usr/lib/privatedir4/ --install-scripts=/usr/lib/privatedir4
 debian/mypackage/usr/lib/privatedir4/baz/__init__.py
 debian/mypackage/usr/lib/privatedir4/baz/baz.so
 debian/mypackage/usr/lib/privatedir4/run.py

$ dh_python /usr/share/privatedir1 # ignores SL
 debian/mypackage/usr/share/privatedir1/bar/__init__.py
 debian/mypackage/usr/share/privatedir1/run.py
 # Python not hardcoded in shebang and -V not used so recompile once default
 # Python version will change, minimum required version hardcoded in the script
 debian/mypackage/usr/share/python/runtime.d/mypackage.rtupdate

$ grep python:Depends debian/mypackage.substvars
 python:Depends=python

$ dh_python /usr/share/privatedir2 -V 2.4
 debian/mypackage/usr/share/privatedir2/bar/__init__.py
 debian/mypackage/usr/share/privatedir2/run.py
 # note that rtupdate script is not touched, python2.4 is added to the Depends
 # instead and maintainer script contains hardcoded python2.4
 debian/mypackage/usr/share/python/data/mypackage

$ grep python:Depends debian/mypackage.substvars
 python:Depends=python, python2.4

$ grep privatedir debian/mypackage.postinst
 dpkg -L mypackage | pycompile /usr/share/privatedir1
 dpkg -L mypackage | pycompile /usr/share/privatedir2 -V 2.4

$ grep privatedir debian/mypackage.prerm
 dpkg -L mypackage | pyclean /usr/share/privatedir1
 dpkg -L mypackage | pyclean /usr/share/privatedir2

$ dh_python /usr/share/privatedir3 -V 2.6+
 debian/mypackage/usr/share/privatedir3/egg/__init__.py
 debian/mypackage/usr/share/privatedir3/run.py
 debian/mypackage/usr/share/python/runtime.d/mypackage.rtupdate

$ grep python:Depends debian/mypackage.substvars
 python:Depends=python, python2.4, python (>=2.6) | python2.6

$ grep privatedir debian/mypackage.postinst
 dpkg -L mypackage | pycompile /usr/share/privatedir1
 dpkg -L mypackage | pycompile /usr/share/privatedir2 -V 2.4
 dpkg -L mypackage | pycompile /usr/share/privatedir3 -V 2.6+

$ grep privatedir debian/mypackage.prerm
 dpkg -L mypackage | pyclean /usr/share/privatedir1
 dpkg -L mypackage | pyclean /usr/share/privatedir2
 dpkg -L mypackage | pyclean /usr/share/privatedir3

$ dh_python /usr/share/privatedir4 -V 2.5+ # note the "+" here and lack of it later
 debian/mypackage/usr/lib/privatedir4/baz/__init__.py
 debian/mypackage/usr/lib/privatedir4/baz/baz.so
 debian/mypackage/usr/lib/privatedir4/run.py

$ grep python:Depends debian/mypackage.substvars
 python:Depends=python, python2.4, python (>=2.6) | python2.6, python2.5

$ grep privatedir debian/mypackage.postinst
 dpkg -L mypackage | pycompile /usr/share/privatedir1
 dpkg -L mypackage | pycompile /usr/share/privatedir2 -V 2.4
 dpkg -L mypackage | pycompile /usr/share/privatedir3 -V 2.6+
 dpkg -L mypackage | pycompile /usr/lib/privatedir4 -V 2.5 # note that there's no "+" here (due to private extension)

$ grep privatedir debian/mypackage.prerm
 dpkg -L mypackage | pyclean /usr/share/privatedir1
 dpkg -L mypackage | pyclean /usr/share/privatedir2
 dpkg -L mypackage | pyclean /usr/share/privatedir3
 dpkg -L mypackage | pyclean /usr/lib/privatedir4
-- 
Piotr Ożarowski                         Debian GNU/Linux Developer
www.ozarowski.pl          www.griffith.cc           www.debian.org
GPG Fingerprint: 1D2F A898 58DA AF62 1786 2DF7 AEF6 F1A2 A745 7645

Attachment: signature.asc
Description: Digital signature


Reply to: