From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id BF4BC15808B for ; Fri, 1 Apr 2022 20:30:53 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 93875E0839; Fri, 1 Apr 2022 20:30:52 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 63985E0839 for ; Fri, 1 Apr 2022 20:30:51 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 93FED34172D for ; Fri, 1 Apr 2022 20:30:48 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 01DF1AF for ; Fri, 1 Apr 2022 20:30:47 +0000 (UTC) From: "Matt Turner" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Matt Turner" Message-ID: <1648844940.1b1c4323d73d095f5ee2816201b5780f6a7ea14b.mattst88@gentoo> Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/ X-VCS-Repository: proj/portage X-VCS-Files: lib/portage/eapi.py X-VCS-Directories: lib/portage/ X-VCS-Committer: mattst88 X-VCS-Committer-Name: Matt Turner X-VCS-Revision: 1b1c4323d73d095f5ee2816201b5780f6a7ea14b X-VCS-Branch: master Date: Fri, 1 Apr 2022 20:30:47 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 8e813c52-e5ad-4338-99e6-400d8cf7c957 X-Archives-Hash: ea87cb830bd8f7298fa3b6dcc3d3c981 commit: 1b1c4323d73d095f5ee2816201b5780f6a7ea14b Author: Wolfgang E. Sanyer gmail com> AuthorDate: Thu Feb 24 02:30:24 2022 +0000 Commit: Matt Turner gentoo org> CommitDate: Fri Apr 1 20:29:00 2022 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=1b1c4323 portage.eapi: use functools @lru_cache decorator Also, refactor logic in order to improve readability. Closes: https://github.com/gentoo/portage/pull/754 Signed-off-by: Wolfgang E. Sanyer gmail.com> Signed-off-by: Matt Turner gentoo.org> lib/portage/eapi.py | 458 +++++++++++++++++++--------------------------------- 1 file changed, 169 insertions(+), 289 deletions(-) diff --git a/lib/portage/eapi.py b/lib/portage/eapi.py index 18069b04b..f8e8573ed 100644 --- a/lib/portage/eapi.py +++ b/lib/portage/eapi.py @@ -2,288 +2,167 @@ # Distributed under the terms of the GNU General Public License v2 import collections -import operator -import types +import logging +from functools import lru_cache +from typing import Optional from portage import eapi_is_supported -def eapi_has_iuse_defaults(eapi): - return eapi != "0" +def eapi_has_iuse_defaults(eapi: str) -> bool: + return _get_eapi_attrs(eapi).iuse_defaults -def eapi_has_iuse_effective(eapi): - return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi") +def eapi_has_iuse_effective(eapi: str) -> bool: + return _get_eapi_attrs(eapi).iuse_effective -def eapi_has_slot_deps(eapi): - return eapi != "0" +def eapi_has_slot_deps(eapi: str) -> bool: + return _get_eapi_attrs(eapi).slot_deps -def eapi_has_slot_operator(eapi): - return eapi not in ("0", "1", "2", "3", "4", "4-python") +def eapi_has_slot_operator(eapi: str) -> bool: + return _get_eapi_attrs(eapi).slot_operator -def eapi_has_src_uri_arrows(eapi): - return eapi not in ("0", "1") +def eapi_has_src_uri_arrows(eapi: str) -> bool: + return _get_eapi_attrs(eapi).src_uri_arrows -def eapi_has_selective_src_uri_restriction(eapi): - return eapi not in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - "7", - ) +def eapi_has_selective_src_uri_restriction(eapi: str) -> bool: + return _get_eapi_attrs(eapi).selective_src_uri_restriction -def eapi_has_use_deps(eapi): - return eapi not in ("0", "1") +def eapi_has_use_deps(eapi: str) -> bool: + return _get_eapi_attrs(eapi).use_deps -def eapi_has_strong_blocks(eapi): - return eapi not in ("0", "1") +def eapi_has_strong_blocks(eapi: str) -> bool: + return _get_eapi_attrs(eapi).strong_blocks -def eapi_has_src_prepare_and_src_configure(eapi): +def eapi_has_src_prepare_and_src_configure(eapi: str) -> bool: return eapi not in ("0", "1") -def eapi_supports_prefix(eapi): - return eapi not in ("0", "1", "2") +def eapi_supports_prefix(eapi: str) -> bool: + return _get_eapi_attrs(eapi).prefix -def eapi_exports_AA(eapi): - return eapi in ("0", "1", "2", "3") +def eapi_exports_AA(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_AA -def eapi_exports_KV(eapi): - return eapi in ("0", "1", "2", "3") +def eapi_exports_KV(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_KV -def eapi_exports_merge_type(eapi): - return eapi not in ("0", "1", "2", "3") +def eapi_exports_merge_type(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_merge_type -def eapi_exports_replace_vars(eapi): - return eapi not in ("0", "1", "2", "3") +def eapi_exports_replace_vars(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_replace_vars -def eapi_exports_EBUILD_PHASE_FUNC(eapi): - return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi") +def eapi_exports_EBUILD_PHASE_FUNC(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_EBUILD_PHASE_FUNC -def eapi_exports_PORTDIR(eapi): - return eapi in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_exports_PORTDIR(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_PORTDIR -def eapi_exports_ECLASSDIR(eapi): - return eapi in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_exports_ECLASSDIR(eapi: str) -> bool: + return _get_eapi_attrs(eapi).exports_ECLASSDIR -def eapi_exports_REPOSITORY(eapi): +def eapi_exports_REPOSITORY(eapi: str) -> bool: return eapi in ("4-python", "5-progress") -def eapi_has_pkg_pretend(eapi): +def eapi_has_pkg_pretend(eapi: str) -> bool: return eapi not in ("0", "1", "2", "3") -def eapi_has_implicit_rdepend(eapi): +def eapi_has_implicit_rdepend(eapi: str) -> bool: return eapi in ("0", "1", "2", "3") -def eapi_has_dosed_dohard(eapi): +def eapi_has_dosed_dohard(eapi: str) -> bool: return eapi in ("0", "1", "2", "3") -def eapi_has_required_use(eapi): - return eapi not in ("0", "1", "2", "3") +def eapi_has_required_use(eapi: str) -> bool: + return _get_eapi_attrs(eapi).required_use -def eapi_has_required_use_at_most_one_of(eapi): - return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi") +def eapi_has_required_use_at_most_one_of(eapi: str) -> bool: + return _get_eapi_attrs(eapi).required_use_at_most_one_of -def eapi_has_use_dep_defaults(eapi): - return eapi not in ("0", "1", "2", "3") +def eapi_has_use_dep_defaults(eapi: str) -> bool: + return _get_eapi_attrs(eapi).use_dep_defaults -def eapi_requires_posixish_locale(eapi): - return eapi not in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - ) +def eapi_requires_posixish_locale(eapi: str) -> bool: + return _get_eapi_attrs(eapi).posixish_locale -def eapi_has_repo_deps(eapi): - return eapi in ("4-python", "5-progress") +def eapi_has_repo_deps(eapi: str) -> bool: + return _get_eapi_attrs(eapi).repo_deps -def eapi_allows_dots_in_PN(eapi): - return eapi in ("4-python", "5-progress") +def eapi_allows_dots_in_PN(eapi: str) -> bool: + return _get_eapi_attrs(eapi).dots_in_PN -def eapi_allows_dots_in_use_flags(eapi): - return eapi in ("4-python", "5-progress") +def eapi_allows_dots_in_use_flags(eapi: str) -> bool: + return _get_eapi_attrs(eapi).dots_in_use_flags -def eapi_supports_stable_use_forcing_and_masking(eapi): +def eapi_supports_stable_use_forcing_and_masking(eapi: str) -> bool: return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi") -def eapi_allows_directories_on_profile_level_and_repository_level(eapi): +def eapi_allows_directories_on_profile_level_and_repository_level(eapi: str) -> bool: return eapi not in ("0", "1", "2", "3", "4", "4-slot-abi", "5", "6") -def eapi_has_use_aliases(eapi): +def eapi_has_use_aliases(eapi: str) -> bool: return eapi in ("4-python", "5-progress") -def eapi_has_automatic_unpack_dependencies(eapi): +def eapi_has_automatic_unpack_dependencies(eapi: str) -> bool: return eapi in ("5-progress",) -def eapi_allows_package_provided(eapi): - return eapi in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_allows_package_provided(eapi: str) -> bool: + return _get_eapi_attrs(eapi).allows_package_provided -def eapi_has_bdepend(eapi): - return eapi not in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_has_bdepend(eapi: str) -> bool: + return _get_eapi_attrs(eapi).bdepend -def eapi_has_idepend(eapi): - return eapi not in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - "7", - ) +def eapi_has_idepend(eapi: str) -> bool: + return _get_eapi_attrs(eapi).idepend -def eapi_empty_groups_always_true(eapi): - return eapi in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_empty_groups_always_true(eapi: str) -> bool: + return _get_eapi_attrs(eapi).empty_groups_always_true -def eapi_path_variables_end_with_trailing_slash(eapi): - return eapi in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_path_variables_end_with_trailing_slash(eapi: str) -> bool: + return _get_eapi_attrs(eapi).path_variables_end_with_trailing_slash -def eapi_has_broot(eapi): - return eapi not in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_has_broot(eapi: str) -> bool: + return _get_eapi_attrs(eapi).broot -def eapi_has_sysroot(eapi): - return eapi not in ( - "0", - "1", - "2", - "3", - "4", - "4-python", - "4-slot-abi", - "5", - "5-progress", - "6", - ) +def eapi_has_sysroot(eapi: str) -> bool: + return _get_eapi_attrs(eapi).sysroot _eapi_attrs = collections.namedtuple( @@ -324,53 +203,39 @@ _eapi_attrs = collections.namedtuple( ) -_eapi_attr_func_prefixes = ( - "eapi_allows_", - "eapi_has_", - "eapi_requires_", - "eapi_supports_", - "eapi_", -) - - -def _eapi_func_decorator(func, attr_getter): - def wrapper(eapi): - return attr_getter(_get_eapi_attrs(eapi)) - - wrapper.func = func - wrapper.__doc__ = func.__doc__ - return wrapper - +class Eapi: + ALL_EAPIS = ( + "0", + "1", + "2", + "3", + "4", + "4-python", + "4-slot-abi", + "5", + "5-progress", + "6", + "7", + "8", + ) -def _decorate_eapi_funcs(): - """ - Decorate eapi_* functions so that they use _get_eapi_attrs(eapi) - to cache results. - """ - decorated = {} - for k, v in globals().items(): - if not ( - isinstance(v, types.FunctionType) and k.startswith(_eapi_attr_func_prefixes) - ): - continue - for prefix in _eapi_attr_func_prefixes: - if k.startswith(prefix): - attr_name = k[len(prefix) :] - if hasattr(_eapi_attrs, attr_name): - decorated[k] = _eapi_func_decorator( - v, operator.attrgetter(attr_name) - ) - break - globals().update(decorated) + _eapi_val: int = -1 + def __init__(self, eapi_string: str): + if not eapi_string in self.ALL_EAPIS: + raise ValueError(f"'{eapi_string}' not recognized as a valid EAPI") -_decorate_eapi_funcs() + self._eapi_val = int(eapi_string.partition("-")[0]) + def __ge__(self, other: "Eapi") -> bool: + return self._eapi_val >= other._eapi_val -_eapi_attrs_cache = {} + def __le__(self, other: "Eapi") -> bool: + return self._eapi_val <= other._eapi_val -def _get_eapi_attrs(eapi): +@lru_cache(32) +def _get_eapi_attrs(eapi_str: Optional[str]) -> _eapi_attrs: """ When eapi is None then validation is not as strict, since we want the same to work for multiple EAPIs that may have slightly different rules. @@ -378,59 +243,74 @@ def _get_eapi_attrs(eapi): be helpful for handling of corrupt EAPI metadata in essential functions such as pkgsplit. """ - eapi_attrs = _eapi_attrs_cache.get(eapi) - if eapi_attrs is not None: - return eapi_attrs - - orig_eapi = eapi - if eapi is not None and not eapi_is_supported(eapi): - eapi = None - - eapi_attrs = _eapi_attrs( - allows_package_provided=( - eapi is None or eapi_allows_package_provided.func(eapi) - ), - bdepend=(eapi is not None and eapi_has_bdepend.func(eapi)), - broot=(eapi is None or eapi_has_broot.func(eapi)), - dots_in_PN=(eapi is None or eapi_allows_dots_in_PN.func(eapi)), - dots_in_use_flags=(eapi is None or eapi_allows_dots_in_use_flags.func(eapi)), - empty_groups_always_true=( - eapi is not None and eapi_empty_groups_always_true.func(eapi) - ), - exports_AA=(eapi is not None and eapi_exports_AA.func(eapi)), - exports_EBUILD_PHASE_FUNC=( - eapi is None or eapi_exports_EBUILD_PHASE_FUNC.func(eapi) - ), - exports_ECLASSDIR=(eapi is not None and eapi_exports_ECLASSDIR.func(eapi)), - exports_KV=(eapi is not None and eapi_exports_KV.func(eapi)), - exports_merge_type=(eapi is None or eapi_exports_merge_type.func(eapi)), - exports_PORTDIR=(eapi is None or eapi_exports_PORTDIR.func(eapi)), - exports_replace_vars=(eapi is None or eapi_exports_replace_vars.func(eapi)), - feature_flag_test=False, - idepend=(eapi is not None and eapi_has_idepend.func(eapi)), - iuse_defaults=(eapi is None or eapi_has_iuse_defaults.func(eapi)), - iuse_effective=(eapi is not None and eapi_has_iuse_effective.func(eapi)), - path_variables_end_with_trailing_slash=( - eapi is not None and eapi_path_variables_end_with_trailing_slash.func(eapi) - ), - posixish_locale=(eapi is not None and eapi_requires_posixish_locale.func(eapi)), - prefix=(eapi is None or eapi_supports_prefix.func(eapi)), - repo_deps=(eapi is None or eapi_has_repo_deps.func(eapi)), - required_use=(eapi is None or eapi_has_required_use.func(eapi)), - required_use_at_most_one_of=( - eapi is None or eapi_has_required_use_at_most_one_of.func(eapi) - ), - selective_src_uri_restriction=( - eapi is None or eapi_has_selective_src_uri_restriction.func(eapi) - ), - slot_deps=(eapi is None or eapi_has_slot_deps.func(eapi)), - slot_operator=(eapi is None or eapi_has_slot_operator.func(eapi)), - src_uri_arrows=(eapi is None or eapi_has_src_uri_arrows.func(eapi)), - strong_blocks=(eapi is None or eapi_has_strong_blocks.func(eapi)), - sysroot=(eapi is None or eapi_has_sysroot.func(eapi)), - use_deps=(eapi is None or eapi_has_use_deps.func(eapi)), - use_dep_defaults=(eapi is None or eapi_has_use_dep_defaults.func(eapi)), - ) - - _eapi_attrs_cache[orig_eapi] = eapi_attrs - return eapi_attrs + logging.info("cache info: {}".format(_get_eapi_attrs.cache_info())) + if eapi_str is None or not eapi_is_supported(eapi_str): + return _eapi_attrs( + allows_package_provided=True, + bdepend=False, + broot=True, + dots_in_PN=True, + dots_in_use_flags=True, + empty_groups_always_true=False, + exports_AA=False, + exports_EBUILD_PHASE_FUNC=True, + exports_ECLASSDIR=False, + exports_KV=False, + exports_merge_type=True, + exports_PORTDIR=True, + exports_replace_vars=True, + feature_flag_test=False, + idepend=False, + iuse_defaults=True, + iuse_effective=False, + path_variables_end_with_trailing_slash=False, + posixish_locale=False, + prefix=True, + repo_deps=True, + required_use=True, + required_use_at_most_one_of=True, + selective_src_uri_restriction=True, + slot_deps=True, + slot_operator=True, + src_uri_arrows=True, + strong_blocks=True, + sysroot=True, + use_deps=True, + use_dep_defaults=True, + ) + else: + eapi_special = ("4-python", "5-progress") + eapi = Eapi(eapi_str) + return _eapi_attrs( + allows_package_provided=eapi <= Eapi("6"), + bdepend=eapi >= Eapi("7"), + broot=eapi >= Eapi("7"), + dots_in_PN=eapi_str in eapi_special, + dots_in_use_flags=eapi_str in eapi_special, + empty_groups_always_true=eapi <= Eapi("6"), + exports_AA=eapi <= Eapi("3"), + exports_EBUILD_PHASE_FUNC=eapi >= Eapi("5"), + exports_ECLASSDIR=eapi <= Eapi("6"), + exports_KV=eapi <= Eapi("3"), + exports_merge_type=eapi >= Eapi("4"), + exports_PORTDIR=eapi <= Eapi("6"), + exports_replace_vars=eapi >= Eapi("4"), + feature_flag_test=False, + idepend=eapi >= Eapi("8"), + iuse_defaults=eapi >= Eapi("1"), + iuse_effective=eapi >= Eapi("5"), + path_variables_end_with_trailing_slash=eapi <= Eapi("6"), + posixish_locale=eapi >= Eapi("6"), + prefix=eapi >= Eapi("3"), + repo_deps=eapi_str in eapi_special, + required_use=eapi >= Eapi("4"), + required_use_at_most_one_of=eapi >= Eapi("5"), + selective_src_uri_restriction=eapi >= Eapi("8"), + slot_deps=eapi >= Eapi("1"), + slot_operator=eapi >= Eapi("5"), + src_uri_arrows=eapi >= Eapi("2"), + strong_blocks=eapi >= Eapi("2"), + sysroot=eapi >= Eapi("7"), + use_deps=eapi >= Eapi("2"), + use_dep_defaults=eapi >= Eapi("4"), + )