One of the major features of Python packaging on Debian systems is that pure Python modules are byte compiled for all officially supported versions of Python that are available, and are actually supported by the module itself. There are several utilities available to aid in this task. Two of the most popular (and mutually exclusive -- select one or the other for use in your packages) (python-central and python-support, for example). However, these utilities need information about modules in the package (for example, whether a pure Python module supports all versions of Python or not).
The XS-Python-Version field in debian/control specifies the versions of Python supported by the package [1]. While this is a requirement only if using the utility package python-central (python-support, for example, prefers debian/pyversions), setting this is "appreciated" in any case, according to the new policy wiki[2]. This is used to track packages during Python transitions.
This can be a single version, or one or more of a list of non-overlapping ranges. The lowest range may optionally omit a low end, and the highest range may optionally omit an upper end. In other words, the overall range may be open ended. The ranges are often matched to the set of all known Python version that have existed, and the supported set is the intersection of the known versions of python and the range specification.
If the current version of Python is supported by the package, then:
For packages with private modules or private extensions compiled for the current python version and for applications using /usr/bin/python, this should be set to the string "all" (or "-", in the case of debian/pyversions). [3] If the module doesn't work with all Python version, the range of versions supported should be used [4]
For packages with public modules, this should be set to the string "all" (or "-", in the case of debian/pyversions), unless not all versions of Python are supported (in which case the setting should specify the versions or range of versions actually supported, like ">= 2.4" or ">= 2.2, << 2.y".
If the current version is not supported, or if the application uses /usr/bin/pythonX.Y explicitly, then this should be set to the (list of) version(s) supported.
Currently, the string "current" in the field XS-Python-Version is used by python-central to indicate that the package contains private modules, and explicitly state that the package is only built for the current Python version, and not for any other version supported in Debian. This is flawed, for the following reasons:
The value corresponds to the version of Python the package is currently built for; but in all other cases the semantics of the XS-Python-Version field is to indicate which versions of Python are supported by the package, and indicates compatibility, not the version it is currently built against. So this special case breaks the semantics of the field.
By hijacking the XS-Python-Version field to indicate the version of Python it is currently compiled against, it hinder s the propagation of compatibility information, so the ability of the maintainer to indicate the range of Python versions this package is compatible with.
The information conveyed by this field is redundant; it should be clear that the package contains private modules, based on the directories the modules are shipped in, and also the fact that it ought to build depend on python-dev and not on python-all-dev.
The semantics of "current" are not fixed, since they depend on the contents of the package python-defaults, and are ill suited for the debian/control file.
The rules for calculating the dependencies a package has are simple.
If a script invokes /usr/bin/pythonX.Y, than the package must depend on pythonX.Y. This is because no amount of automatic byte compiling would ever get rid of the requirement that /usr/bin/pythonX.Y has to be present for the script to function.
For package that contains extensions, the range of Python versions required has to be restricted to Python versions for which the extensions have been built and shipped in the package. For packages with private extension modules, this means that the range of python versions it depends on has to be set to whatever version of Python was used during the build process (since private extension module packages can only be compiled for one version of Python at any time).
If any version of python can be supported, there are two [5] sub cases:
For pure Python modules, the package just depends on python. This includes pure Python private modules (as long as they do not depend on any private extensions -- in which case the extensions shall restrict the dependency).
Private extension modules can only be compiled for one version of Python at a time, so even if they have no restrictions on the versions of python supported, they must depend on just the current version (which is the version they are likely to be compiled for).
To do this, one determines the stop version: the stop version is next minor version after the current version (found by incrementing the minor version), whether or not it exists, and is form of Major.Minor.
In this case, the package must depend on: python (>= $current_version), python (<< $stop_version)
If there is a range of values of versions of Python supported, there are two sub cases:
The current version is supported. In this case, select the larger interval in the range of Python versions supported that contains the current version, and determine the lower and upper bounds.
If the lower bound to the range exists, then add a dependency on python (>= $min_version)
If the upper bound to the range exists, then the stop version is the next minor version after the upper bound (found by incrementing the minor version), whether or not it exists, and is form of Major.Minor. If the upper bound to the range exists, then depend on python (<< $stop_version)
The package does not support the current version of Python, again, there are again two sub cases:
The range of Python versions supported is higher than the current version. In this case, the package should depend upon: python (>= $min_version) | python$min_version)
If the upper bound to the range exists, then the stop version is the next minor version after the upper bound (found by incrementing the minor version), whether or not it exists, and is form of Major.Minor. If the upper bound to the range exists, then depend on python (<< $stop_version)
The range of Python versions supported is lower than the current version. This implies that the package is obsolete, and should either be updated to support the current Python version, or be dropped from the archive.
Packaged modules that require other modules to work, must depend on the corresponding python-foo packages. They must not depend on any pythonX.Y-foo package directly.
Packaged modules available for only one particular version of Python that need other modules (say, "bar"), must depend on the corresponding pythonX.Y-bar packages, and must not depend on any python-bar. For consistency, if the package ("foo") provides several pythonX.Y-foo packages, and it needs the module "bar", it must also depend on pythonX.Y-bar corresponding to each version "X.Y" for the virtual packages pythonX.Y-foo that it provides.
Packages with public modules and extensions should be named, or should provide, python-foo. Pure Python public modules that support all Python versions need not have a Provides field.
For package that contains public extensions, the range of versions supported has to be restricted to Python versions for which the extensions have been built and shipped in the package.
Public pure Python modules that have a subset of all python versions supported, or for public extensions, the Provides field indicates which versions of Python are supported (for which one may import the module). For every version of python supported the package should provide pythonX.Y-foo packages. This assumes that the package correctly depends on all the appropriate versions of any version specific module that it itself requires.
If the package provides public extension modules, then build depending on "python-all-dev (>= 2.3.5-11)" shall ensure that all the >pythonX.Y-dev packages are available during building.
On the other hand, if the package provides private modules, then build depending on "python-dev", or one specific "pythonX.Y-dev" (if there are restrictions on the version of Python supported) is sufficient, since only one version of Python is ever supported in any package.
If you are using helper packages (CDBS, yada, debhelper, etc) you should build depend on the appropriate version. This also applies if your build process uses either python-central or python-support.
| [1] | python-central also uses XB-Python-Version field in the control file, which is substituted in the binary package using the values from the XS-Python-Version field, filtered according to various rules. |
| [2] | For compatibility, each of the tools (python-central and python-support) are able to use each others data. |
| [3] | Note that pycentral uses the special string "current" here. |
| [4] | For pycentral, one may specify something like "current, >= 2.4" or even "current, >= 2.2, << 2.5". |
| [5] | Public extensions are restricted to the list of Python versions for which the extensions have been compiled, and thus are covered in the section below. |