public inbox for gentoo-python@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Michał Górny" <mgorny@gentoo.org>
To: gentoo-python@lists.gentoo.org
Cc: python@gentoo.org, dolsen@gentoo.org
Subject: [gentoo-python] Minimal technical demo for alternate bindir scheme
Date: Sat, 7 Sep 2013 10:44:19 +0200	[thread overview]
Message-ID: <20130907104419.6de8ecf2@gentoo.org> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 1140 bytes --]

Hello, all.

I've wrapped up a first patch to demonstrate the concept of keeping
Python scripts outta bindir.

Steps to do:

1. create /etc/env.d/NNpythonpath like:

PATH="/usr/lib64/python3.3/bin:/usr/lib64/python3.2/bin:/usr/lib64/python2.7/bin:/usr/lib64/python2.6/bin:/usr/lib64/pypy2.0/bin"

(this will be most likely done by eselect-python)

2. env-update, source /etc/profile

3. apply the attached patch to the eclasses

TADAAM!

Expect new levels of screwup. Things that definitely don't work:

1. python_scriptinto() since we install all the scripts to dedicated
location. I have no idea how to support it without forking paths like
crazy.

2. things that rely on /usr/bin path. We will need new wrappers for
that. If we really want that.

3. systems with screwed up $PATH. That is, you won't find Python stuff
if you don't have proper path in PATH :).

4. python_wrapper_setup() enforces only current impl in PATH. Remaining
impls need to be provided by caller env. If they aren't, some deps with
mis-matched impls may not work.

Enjoy, test and comment.

-- 
Best regards,
Michał Górny

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Support-PYTHON_SCRIPTDIR-in-eclass.patch --]
[-- Type: text/x-patch, Size: 8257 bytes --]

From 69b07358c07379e741fb01b0520ea7652012b89d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@gentoo.org>
Date: Sat, 7 Sep 2013 10:04:51 +0200
Subject: [PATCH] Support PYTHON_SCRIPTDIR in eclass.

---
 gx86/eclass/distutils-r1.eclass    | 41 +++-------------------
 gx86/eclass/python-r1.eclass       | 35 ++++++-------------
 gx86/eclass/python-utils-r1.eclass | 70 +++++++++++++++++++++++++++++++-------
 3 files changed, 71 insertions(+), 75 deletions(-)

diff --git a/gx86/eclass/distutils-r1.eclass b/gx86/eclass/distutils-r1.eclass
index c2872b3..4a29fa7 100644
--- a/gx86/eclass/distutils-r1.eclass
+++ b/gx86/eclass/distutils-r1.eclass
@@ -409,41 +409,6 @@ distutils-r1_python_test() {
 	:
 }
 
-# @FUNCTION: _distutils-r1_rename_scripts
-# @USAGE: <path>
-# @INTERNAL
-# @DESCRIPTION:
-# Renames installed Python scripts to be implementation-suffixed.
-# ${EPYTHON} needs to be set to the implementation name.
-#
-# All executable scripts having shebang referencing ${EPYTHON}
-# in given path will be renamed.
-_distutils-r1_rename_scripts() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	local path=${1}
-	[[ ${path} ]] || die "${FUNCNAME}: no path given"
-
-	local f
-	while IFS= read -r -d '' f; do
-		debug-print "${FUNCNAME}: found executable at ${f#${D}/}"
-
-		local shebang
-		read -r shebang < "${f}"
-		if [[ ${shebang} == '#!'*${EPYTHON}* ]]
-		then
-			debug-print "${FUNCNAME}: matching shebang: ${shebang}"
-
-			local newf=${f}-${EPYTHON}
-			debug-print "${FUNCNAME}: renaming to ${newf#${D}/}"
-			mv "${f}" "${newf}" || die
-
-			debug-print "${FUNCNAME}: installing wrapper at ${f#${D}/}"
-			_python_ln_rel "${path}${EPREFIX}"/usr/bin/python-exec "${f}" || die
-		fi
-	done < <(find "${path}" -type f -executable -print0)
-}
-
 # @FUNCTION: distutils-r1_python_install
 # @USAGE: [additional-args...]
 # @DESCRIPTION:
@@ -475,14 +440,16 @@ distutils-r1_python_install() {
 	local root=${D}/_${EPYTHON}
 	[[ ${DISTUTILS_SINGLE_IMPL} ]] && root=${D}
 
-	esetup.py install "${flags[@]}" --root="${root}" "${@}"
+	esetup.py install "${flags[@]}" \
+		--root="${root}" \
+		--install-scripts="$(python_get_scriptdir)" \
+		"${@}"
 
 	if [[ -d ${root}$(python_get_sitedir)/tests ]]; then
 		die "Package installs 'tests' package, file collisions likely."
 	fi
 
 	if [[ ! ${DISTUTILS_SINGLE_IMPL} ]]; then
-		_distutils-r1_rename_scripts "${root}"
 		multibuild_merge_root "${root}" "${D}"
 	fi
 }
diff --git a/gx86/eclass/python-r1.eclass b/gx86/eclass/python-r1.eclass
index 5c5b33c..7c7469f 100644
--- a/gx86/eclass/python-r1.eclass
+++ b/gx86/eclass/python-r1.eclass
@@ -122,7 +122,6 @@ fi
 #
 # Example value:
 # @CODE
-# dev-python/python-exec
 # python_targets_python2_6? ( dev-lang/python:2.6[gdbm] )
 # python_targets_python2_7? ( dev-lang/python:2.7[gdbm] )
 # @CODE
@@ -198,12 +197,6 @@ _python_set_globals() {
 	IUSE=${flags[*]}
 	PYTHON_REQUIRED_USE="|| ( ${flags[*]} )"
 	PYTHON_USEDEP=${optflags// /,}
-
-	# 1) well, python-exec would suffice as an RDEP
-	# but no point in making this overcomplex, BDEP doesn't hurt anyone
-	# 2) python-exec should be built with all targets forced anyway
-	# but if new targets were added, we may need to force a rebuild
-	PYTHON_DEPS+="dev-python/python-exec[${PYTHON_USEDEP}]"
 }
 _python_set_globals
 
@@ -741,28 +734,20 @@ python_export_best() {
 python_replicate_script() {
 	debug-print-function ${FUNCNAME} "${@}"
 
-	local suffixes=()
+	local scriptdirs=()
 
-	_add_suffix() {
-		suffixes+=( "${EPYTHON}" )
+	_add_scriptdir() {
+		scriptdirs+=( "$(python_get_scriptdir)" )
 	}
-	python_foreach_impl _add_suffix
-	debug-print "${FUNCNAME}: suffixes = ( ${suffixes[@]} )"
-
-	local f suffix
-	for suffix in "${suffixes[@]}"; do
-		for f; do
-			local newf=${f}-${suffix}
+	python_foreach_impl _add_scriptdir
+	debug-print "${FUNCNAME}: scriptdirs = ( ${scriptdirs[@]} )"
 
-			debug-print "${FUNCNAME}: ${f} -> ${newf}"
-			cp "${f}" "${newf}" || die
-		done
-
-		_python_rewrite_shebang "${suffix}" "${@/%/-${suffix}}"
-	done
+	local f d
+	for d in "${scriptdirs[@]}"; do
+		mkdir -p "${D%/}/${d}" || die
+		cp "${@}" "${D%/}/${d}"/ || die
 
-	for f; do
-		_python_ln_rel "${ED}"/usr/bin/python-exec "${f}" || die
+		_python_rewrite_shebang "${suffix}" "${@/#/${D%/}/${d}/}"
 	done
 }
 
diff --git a/gx86/eclass/python-utils-r1.eclass b/gx86/eclass/python-utils-r1.eclass
index 1a136f4..119030a 100644
--- a/gx86/eclass/python-utils-r1.eclass
+++ b/gx86/eclass/python-utils-r1.eclass
@@ -195,6 +195,18 @@ _python_impl_supported() {
 # dev-lang/python:2.7[xml]
 # @CODE
 
+# @ECLASS-VARIABLE: PYTHON_SCRIPTDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The location where Python scripts must be installed for current impl.
+#
+# Set and exported on request using python_export().
+#
+# Example value:
+# @CODE
+# /usr/lib64/python2.7/bin
+# @CODE
+
 # @FUNCTION: python_export
 # @USAGE: [<impl>] <variables>...
 # @DESCRIPTION:
@@ -359,6 +371,23 @@ python_export() {
 				export PYTHON_PKG_DEP
 				debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
 				;;
+			PYTHON_SCRIPTDIR)
+				local dir
+				case "${impl}" in
+					python*)
+						dir=/usr/$(get_libdir)/${impl}
+						;;
+					jython*)
+						dir=/usr/share/${impl}
+						;;
+					pypy*)
+						dir=/usr/$(get_libdir)/${impl/-c/}
+						;;
+				esac
+
+				export PYTHON_SCRIPTDIR=${EPREFIX}${dir}/bin
+				debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
+				;;
 			*)
 				die "python_export: unknown variable ${var}"
 		esac
@@ -475,6 +504,19 @@ python_get_LIBS() {
 	echo "${PYTHON_LIBS}"
 }
 
+# @FUNCTION: python_get_scriptdir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the script install path for the given
+# implementation. If no implementation is provided, ${EPYTHON} will
+# be used.
+python_get_scriptdir() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	python_export "${@}" PYTHON_SCRIPTDIR
+	echo "${PYTHON_SCRIPTDIR}"
+}
+
 # @FUNCTION: _python_rewrite_shebang
 # @USAGE: [<EPYTHON>] <path>...
 # @INTERNAL
@@ -725,23 +767,24 @@ python_newscript() {
 	[[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
 	[[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <path> <new-name>"
 
-	local d=${python_scriptroot:-${DESTTREE}/bin}
+	if [[ ${python_scriptroot} ]]; then
+		ewarn "Installing Python scripts in non-standard location is not supported"
+		ewarn "in this technical demo. It might be solved in the future."
+	fi
+
 	local INSDESTTREE INSOPTIONS
+	local PYTHON_SCRIPTDIR=${PYTHON_SCRIPTDIR}
+	[[ ${PYTHON_SCRIPTDIR} ]] || python_export PYTHON_SCRIPTDIR
 
-	insinto "${d}"
+	insinto "${PYTHON_SCRIPTDIR#${EPREFIX}}"
 	insopts -m755
 
 	local f=${1}
-	local barefn=${2}
-
-	local newfn=${barefn}-${EPYTHON}
+	local newfn=${2}
 
 	debug-print "${FUNCNAME}: ${f} -> ${d}/${newfn}"
 	newins "${f}" "${newfn}" || die
 	_python_rewrite_shebang "${ED}/${d}/${newfn}"
-
-	# install the wrapper
-	_python_ln_rel "${ED}"/usr/bin/python-exec "${ED}/${d}/${barefn}" || die
 }
 
 # @ECLASS-VARIABLE: python_moduleroot
@@ -879,8 +922,8 @@ python_wrapper_setup() {
 		rm -f "${workdir}"/bin/2to3
 		rm -f "${workdir}"/pkgconfig/python{,2,3}.pc
 
-		local EPYTHON PYTHON
-		python_export "${impl}" EPYTHON PYTHON
+		local EPYTHON PYTHON PYTHON_SCRIPTDIR
+		python_export "${impl}" EPYTHON PYTHON PYTHON_SCRIPTDIR
 
 		local pyver
 		if python_is_python3; then
@@ -932,9 +975,10 @@ __EOF__
 		# 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 [[ ${PATH##:*} != ${workdir}/bin ]]; then
+			PATH=${workdir}/bin:${PYTHON_SCRIPTDIR}${PATH:+:${PATH}}
+#		fi
+		# TODO: ^ clean this up, add other impl scriptdirs to PATH?
 		if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
 			PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
 		fi
-- 
1.8.3.2


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 966 bytes --]

             reply	other threads:[~2013-09-07  8:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-07  8:44 Michał Górny [this message]
2013-09-07 16:00 ` [gentoo-python] Re: Minimal technical demo for alternate bindir scheme Mike Gilbert
2013-09-07 17:50   ` Mike Gilbert
2013-09-07 20:11 ` Mike Gilbert
2013-09-08 17:56 ` [gentoo-python] " Michał Górny

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130907104419.6de8ecf2@gentoo.org \
    --to=mgorny@gentoo.org \
    --cc=dolsen@gentoo.org \
    --cc=gentoo-python@lists.gentoo.org \
    --cc=python@gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox