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 > }
> 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?
What would be the exact difference between calling it in global scope vs via this method?
(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.
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.
(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.