Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 795006

Summary: [Future EAPI] call eclass_init functions for all inherited eclasses, which resembles constructor usage in any other language
Product: Gentoo Hosted Projects Reporter: Zac Medico <zmedico>
Component: PMS/EAPIAssignee: PMS/EAPI <pms>
Status: CONFIRMED ---    
Severity: enhancement CC: mgorny
Priority: Normal    
Version: unspecified   
Hardware: All   
OS: All   
URL: https://github.com/zmedico/filebus/blob/master/lib/bash/bash-import.bash
See Also: https://bugs.gentoo.org/show_bug.cgi?id=241442
https://bugs.gentoo.org/show_bug.cgi?id=516014
Whiteboard:
Package list:
Runtime testing required: ---
Bug Depends on:    
Bug Blocks: 174380    

Description Zac Medico gentoo-dev 2021-06-08 23:03:00 UTC
If we add support for an eclass_init function which is always called when an eclass is inherited, then it provides an very organized way to group global scope code and variable assignments, in a way the resembles constructor usage in any other language.

For example, global scope code and variables from python-utils-r1.eclass can be migrated into an eclass init function like this:

> EXPORT_FUNCTIONS eclass_init
> 
> distutils-r1_eclass_init() {
> 	# NOTE: When dropping support for EAPIs here, we need to update
> 	# metadata/install-qa-check.d/60python-pyc
> 	# See bug #704286, bug #781878
> 	case "${EAPI:-0}" in
> 		[0-5]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
> 		[6-7]) ;;
> 		*)     die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
> 	esac
> 
> 	if [[ ${_PYTHON_ECLASS_INHERITED} ]]; then
> 		die 'python-r1 suite eclasses can not be used with python.eclass.'
> 	fi
> 
> 	if [[ ! ${_PYTHON_UTILS_R1} ]]; then
> 
> 	inherit toolchain-funcs
> 
> 	# @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS
> 	# @INTERNAL
> 	# @DESCRIPTION:
> 	# All supported Python implementations, most preferred last.
> 	_PYTHON_ALL_IMPLS=(
> 		pypy3
> 		python3_{8..10}
> 	)
> 	readonly _PYTHON_ALL_IMPLS
> 
> 	# @ECLASS-VARIABLE: _PYTHON_HISTORICAL_IMPLS
> 	# @INTERNAL
> 	# @DESCRIPTION:
> 	# All historical Python implementations that are no longer supported.
> 	_PYTHON_HISTORICAL_IMPLS=(
> 		jython2_7
> 		pypy pypy1_{8,9} pypy2_0
> 		python2_{5..7}
> 		python3_{1..7}
> 	)
> 	readonly _PYTHON_HISTORICAL_IMPLS
> }
Comment 1 Ulrich Müller gentoo-dev 2021-06-09 07:03:03 UTC
> EXPORT_FUNCTIONS eclass_init

So conceptually, eclass_init would be a new phase function? That seems to follow from its being used as a parameter of EXPORT_FUNCTIONS?

> 	if [[ ! ${_PYTHON_UTILS_R1} ]]; then
> 
> 	inherit toolchain-funcs

What would be the consequences of allowing inherit() to be called from within a phase function, or from within an if-conditional? Wouldn't that break metadata invariance, e.g., if the inherited eclass defines *DEPEND?
Comment 2 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2021-06-09 07:22:19 UTC
What would be the exact difference between calling it in global scope vs via this method?
Comment 3 Zac Medico gentoo-dev 2021-06-09 07:24:43 UTC
(In reply to Ulrich Müller from comment #1)
> > EXPORT_FUNCTIONS eclass_init
> 
> So conceptually, eclass_init would be a new phase function? That seems to
> follow from its being used as a parameter of EXPORT_FUNCTIONS?

Yeah, this is one possible way to implement it.

> > 	if [[ ! ${_PYTHON_UTILS_R1} ]]; then
> > 
> > 	inherit toolchain-funcs
> 
> What would be the consequences of allowing inherit() to be called from
> within a phase function, or from within an if-conditional? Wouldn't that
> break metadata invariance, e.g., if the inherited eclass defines *DEPEND?

The eclass_init function is special in the sense that it's invoked *during* inherit, so the effect is very similar to the global scope code that we have now. In effect, the main difference is only that the global scope code and variable assignments have migrated from global scope to a function that has been given a similar role.

(In reply to Michał Górny from comment #2)
> What would be the exact difference between calling it in global scope vs via
> this method?

The intention is for the exact difference to be nil. However, I think the visual benefit is obvious, since it resembles constructor usage in any other language.
Comment 4 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2021-06-09 07:48:42 UTC
I don't see any gain from it, compared to just calling the just-declared function in global scope.  You will have to do it anyway for older EAPI support.

Besides you should note that doing global stuff in function is tricky.  Particularly, 'declare' defaults to creating local variables.
Comment 5 Zac Medico gentoo-dev 2021-06-09 07:54:02 UTC
(In reply to Michał Górny from comment #4)
> I don't see any gain from it, compared to just calling the just-declared
> function in global scope.  You will have to do it anyway for older EAPI
> support.

It establishes a unified practice that we can apply to any eclass with EXPORT_FUNCTIONS eclass_init. It's valuable to have a practice that can be applied consistently.

> Besides you should note that doing global stuff in function is tricky. 
> Particularly, 'declare' defaults to creating local variables.

That's a valid point, but since valid syntax exists, I do see it as a show stopper. It's always possible to write incorrect code.