python-utils-r1.eclass: python_moduleinto, allow package dot-notation
[gentoo.git] / eclass / python-utils-r1.eclass
index bf833eb990074c910fc7a027ab11bad6b7a62285..863051337f0b1e12a779834229e36a7d7fbbe810 100644 (file)
@@ -1,6 +1,5 @@
-# Copyright 1999-2016 Gentoo Foundation
+# Copyright 1999-2017 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
-# $Id$
 
 # @ECLASS: python-utils-r1.eclass
 # @MAINTAINER:
@@ -44,7 +43,7 @@ _PYTHON_ALL_IMPLS=(
        jython2_7
        pypy pypy3
        python2_7
-       python3_3 python3_4 python3_5
+       python3_4 python3_5 python3_6
 )
 readonly _PYTHON_ALL_IMPLS
 
@@ -68,10 +67,10 @@ _python_impl_supported() {
        # keep in sync with _PYTHON_ALL_IMPLS!
        # (not using that list because inline patterns shall be faster)
        case "${impl}" in
-               python2_7|python3_[345]|jython2_7)
+               python2_7|python3_[456]|jython2_7)
                        return 0
                        ;;
-               pypy1_[89]|pypy2_0|python2_[56]|python3_[12])
+               pypy1_[89]|pypy2_0|python2_[56]|python3_[123])
                        return 1
                        ;;
                pypy|pypy3)
@@ -115,22 +114,39 @@ _python_set_impls() {
                _python_impl_supported "${i}"
        done
 
-       _PYTHON_SUPPORTED_IMPLS=()
-       _PYTHON_UNSUPPORTED_IMPLS=()
+       local supp=() unsupp=()
 
        for i in "${_PYTHON_ALL_IMPLS[@]}"; do
                if has "${i}" "${PYTHON_COMPAT[@]}"; then
-                       _PYTHON_SUPPORTED_IMPLS+=( "${i}" )
+                       supp+=( "${i}" )
                else
-                       _PYTHON_UNSUPPORTED_IMPLS+=( "${i}" )
+                       unsupp+=( "${i}" )
                fi
        done
 
-       if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 0 ]]; then
+       if [[ ! ${supp[@]} ]]; then
                die "No supported implementation in PYTHON_COMPAT."
        fi
 
-       readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
+       if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} ]]; then
+               # set once already, verify integrity
+               if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
+                       eerror "Supported impls (PYTHON_COMPAT) changed between inherits!"
+                       eerror "Before: ${_PYTHON_SUPPORTED_IMPLS[*]}"
+                       eerror "Now   : ${supp[*]}"
+                       die "_PYTHON_SUPPORTED_IMPLS integrity check failed"
+               fi
+               if [[ ${_PYTHON_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
+                       eerror "Unsupported impls changed between inherits!"
+                       eerror "Before: ${_PYTHON_UNSUPPORTED_IMPLS[*]}"
+                       eerror "Now   : ${unsupp[*]}"
+                       die "_PYTHON_UNSUPPORTED_IMPLS integrity check failed"
+               fi
+       else
+               _PYTHON_SUPPORTED_IMPLS=( "${supp[@]}" )
+               _PYTHON_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
+               readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
+       fi
 }
 
 # @ECLASS-VARIABLE: PYTHON
@@ -415,9 +431,9 @@ python_export() {
                                        python*)
                                                PYTHON_PKG_DEP="dev-lang/python:${impl#python}";;
                                        pypy)
-                                               PYTHON_PKG_DEP='virtual/pypy:0=';;
+                                               PYTHON_PKG_DEP='>=virtual/pypy-5:0=';;
                                        pypy3)
-                                               PYTHON_PKG_DEP='virtual/pypy3:0=';;
+                                               PYTHON_PKG_DEP='>=virtual/pypy3-5:0=';;
                                        jython2.7)
                                                PYTHON_PKG_DEP='dev-java/jython:2.7';;
                                        *)
@@ -644,7 +660,7 @@ python_optimize() {
                                "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
                                "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
                                ;;
-                       python*)
+                       python*|pypy3)
                                # both levels of optimization are separate since 3.5
                                "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
                                "${PYTHON}" -O -m compileall -q -f -d "${instpath}" "${d}"
@@ -794,11 +810,19 @@ python_newscript() {
 # The <new-path> can either be an absolute target system path (in which
 # case it needs to start with a slash, and ${ED} will be prepended to
 # it) or relative to the implementation's site-packages directory
-# (then it must not start with a slash).
+# (then it must not start with a slash). The relative path can be
+# specified either using the Python package notation (separated by dots)
+# or the directory notation (using slashes).
 #
 # When not set explicitly, the modules are installed to the top
 # site-packages directory.
 #
+# In the relative case, the exact path is determined directly
+# by each python_doscript/python_newscript function. Therefore,
+# python_moduleinto can be safely called before establishing the Python
+# interpreter and/or a single call can be used to set the path correctly
+# for multiple implementations, as can be seen in the following example.
+#
 # Example:
 # @CODE
 # src_install() {
@@ -807,12 +831,6 @@ python_newscript() {
 #   python_foreach_impl python_domodule baz.py
 # }
 # @CODE
-
-# Set the current module root. The new value will be stored
-# in the 'python_moduleroot' environment variable. The new value need
-# be relative to the site-packages root.
-#
-# Alternatively, you can set the variable directly.
 python_moduleinto() {
        debug-print-function ${FUNCNAME} "${@}"
 
@@ -851,7 +869,7 @@ python_domodule() {
                local PYTHON_SITEDIR=${PYTHON_SITEDIR}
                [[ ${PYTHON_SITEDIR} ]] || python_export PYTHON_SITEDIR
 
-               d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot}
+               d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot//.//}
        fi
 
        (
@@ -927,7 +945,7 @@ python_wrapper_setup() {
                rm -f "${workdir}"/bin/2to3 || die
                rm -f "${workdir}"/pkgconfig/python{,2,3}.pc || die
 
-               local EPYTHON PYTHON PYTHON_CONFIG
+               local EPYTHON PYTHON
                python_export "${impl}" EPYTHON PYTHON
 
                local pyver pyother
@@ -954,11 +972,9 @@ python_wrapper_setup() {
 
                # CPython-specific
                if [[ ${EPYTHON} == python* ]]; then
-                       python_export "${impl}" PYTHON_CONFIG
-
                        cat > "${workdir}/bin/python-config" <<-_EOF_ || die
                                #!/bin/sh
-                               exec "${PYTHON_CONFIG}" "\${@}"
+                               exec "${PYTHON}-config" "\${@}"
                        _EOF_
                        cp "${workdir}/bin/python-config" \
                                "${workdir}/bin/python${pyver}-config" || die
@@ -985,18 +1001,18 @@ python_wrapper_setup() {
                        _EOF_
                        chmod +x "${workdir}"/bin/${x} || die
                done
+       fi
 
-               # Now, set the environment.
-               # But note that ${workdir} may be shared with something else,
-               # and thus already on top of PATH.
-               if [[ ${PATH##:*} != ${workdir}/bin ]]; then
-                       PATH=${workdir}/bin${PATH:+:${PATH}}
-               fi
-               if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
-                       PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
-               fi
-               export PATH PKG_CONFIG_PATH
+       # Now, set the environment.
+       # But note that ${workdir} may be shared with something else,
+       # and thus already on top of PATH.
+       if [[ ${PATH##:*} != ${workdir}/bin ]]; then
+               PATH=${workdir}/bin${PATH:+:${PATH}}
        fi
+       if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
+               PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
+       fi
+       export PATH PKG_CONFIG_PATH
 }
 
 # @FUNCTION: python_is_python3
@@ -1232,7 +1248,7 @@ python_export_utf8_locale() {
 
        if [[ $(locale charmap) != UTF-8 ]]; then
                # Try English first, then everything else.
-               local lang locales="en_US.UTF-8 $(locale -a)"
+               local lang locales="C.UTF-8 en_US.UTF-8 en_GB.UTF-8 $(locale -a)"
 
                for lang in ${locales}; do
                        if [[ $(LC_ALL=${lang} locale charmap 2>/dev/null) == UTF-8 ]]; then
@@ -1254,14 +1270,14 @@ python_export_utf8_locale() {
                                        fi
                                        return 0
                                fi
-                       fi  
+                       fi
                done
 
                ewarn "Could not find a UTF-8 locale. This may trigger build failures in"
                ewarn "some python packages. Please ensure that a UTF-8 locale is listed in"
                ewarn "/etc/locale.gen and run locale-gen."
                return 1
-       fi  
+       fi
 
        return 0
 }