In a recent update of the uzbl port I had to specify that a script is to be executed by some 2.x version of python (it would break with python 3). Any old python2 would be good enough. At upstream the assumption was that python2 in the search path would be the preferred 2.x version of python. In the FreeBSD ports collection, this works slightly different.
By stating
USE_PYTHON= 2.4-2.7
post-patch: # [...] @${REINPLACE_CMD} -e "s|/usr/bin/env python2|/usr/bin/env ${PYTHON_VERSION}|" \ ${WRKSRC}/bin/uzbl-event-manager
The whole magic happens in ${PORTSDIR}/bsd.python.mk which is .include'd if you USE_PYTHON. Looking at it is quite interesting. It is one of those typical ports-Makefiles that do a lot of business logic. I quote a few of the relevant passages. (Copyright The FreeBSD Project, BSD-License.)
It starts by specifying the FreeBSD-wide defaults.
_PYTHON_PORTBRANCH= 2.7 _PYTHON_ALLBRANCHES= 2.7 2.6 2.5 2.4 3.2 3.1 # preferred first
However, the actual default version is either what is explicity specified (in the port or /etc/make.conf) or, in absence of that, what is currently installed as ${LOCALBASE}/bin/python. Only if neither gives a clue, we use the FreeBSD-wide default.
# Determine version number of Python to use .if !defined(PYTHON_DEFAULT_VERSION) . if exists(${LOCALBASE}/bin/python) _PYTHON_DEFAULT_VERSION!= (${LOCALBASE}/bin/python -c \ 'import sys; print sys.version[:3]' 2> /dev/null \ || ${ECHO_CMD} ${_PYTHON_PORTBRANCH}) | ${TAIL} -1 . else _PYTHON_DEFAULT_VERSION= ${_PYTHON_PORTBRANCH} . endif PYTHON_DEFAULT_VERSION= python${_PYTHON_DEFAULT_VERSION} .endif .if defined(PYTHON_VERSION) _PYTHON_VERSION:= ${PYTHON_VERSION:S/^python//} _PYTHON_CMD= ${LOCALBASE}/bin/${PYTHON_VERSION} .else _PYTHON_VERSION:= ${PYTHON_DEFAULT_VERSION:S/^python//} _PYTHON_CMD= ${LOCALBASE}/bin/${PYTHON_DEFAULT_VERSION} .endif
This version is compared against the constraints specified, if any. A simple YES does not match the shape of a range specification.
# Validate Python version whether it meets USE_PYTHON version restriction. _PYTHON_VERSION_CHECK:= ${USE_PYTHON:C/^([1-9]\.[0-9])$/\1-\1/} _PYTHON_VERSION_MINIMUM_TMP:= ${_PYTHON_VERSION_CHECK:C/([1-9]\.[0-9])[-+].*/\1/} _PYTHON_VERSION_MINIMUM:= ${_PYTHON_VERSION_MINIMUM_TMP:M[1-9].[0-9]} _PYTHON_VERSION_MAXIMUM_TMP:= ${_PYTHON_VERSION_CHECK:C/.*-([1-9]\.[0-9])/\1/} _PYTHON_VERSION_MAXIMUM:= ${_PYTHON_VERSION_MAXIMUM_TMP:M[1-9].[0-9]} .if !empty(_PYTHON_VERSION_MINIMUM) && ( \ ${_PYTHON_VERSION} < ${_PYTHON_VERSION_MINIMUM}) _PYTHON_VERSION_NONSUPPORTED= ${_PYTHON_VERSION_MINIMUM} at least .elif !empty(_PYTHON_VERSION_MAXIMUM) && ( \ ${_PYTHON_VERSION} > ${_PYTHON_VERSION_MAXIMUM}) _PYTHON_VERSION_NONSUPPORTED= ${_PYTHON_VERSION_MAXIMUM} at most .endif
# If we have an unsupported version of Python, try another. .if defined(_PYTHON_VERSION_NONSUPPORTED) .if defined(PYTHON_VERSION) || defined(PYTHON_CMD) IGNORE= needs Python ${_PYTHON_VERSION_NONSUPPORTED}.\ But you specified ${_PYTHON_VERSION} .else .undef _PYTHON_VERSION .for ver in ${_PYTHON_ALLBRANCHES} __VER= ${ver} .if !defined(_PYTHON_VERSION) && \ !(!empty(_PYTHON_VERSION_MINIMUM) && ( \ ${__VER} < ${_PYTHON_VERSION_MINIMUM})) && \ !(!empty(_PYTHON_VERSION_MAXIMUM) && ( \ ${__VER} > ${_PYTHON_VERSION_MAXIMUM})) _PYTHON_VERSION= ${ver} _PYTHON_CMD= ${LOCALBASE}/bin/python${ver} .endif .endfor .if !defined(_PYTHON_VERSION) IGNORE= needs an unsupported version of Python _PYTHON_VERSION= ${_PYTHON_PORTBRANCH} # just to avoid version sanity checking. .endif .endif # defined(PYTHON_VERSION) || defined(PYTHON_CMD) .endif # defined(_PYTHON_VERSION_NONSUPPORTED) PYTHON_VERSION?= python${_PYTHON_VERSION} PYTHON_CMD?= ${_PYTHON_CMD}