summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2025-09-16 13:23:19 -0700
committerDylan Baker <dylan@pnwbakers.com>2025-10-20 15:15:53 -0700
commite005e9a459f3847a9d30861ec0a5f5653b4df0e4 (patch)
treeb77bde943801c0b0d83538413c6e1b51e14aeee1
parent87dac856b61dbd98e922aa159f08bce4852941d9 (diff)
downloadmeson-e005e9a459f3847a9d30861ec0a5f5653b4df0e4.tar.gz
interpreter: Rework extract_required_kwarg to have better typing
This allows us to avoid making `feature` a union, therefore if we write code like: ```python disabled, required, feature = extract_required_kwarg(...) if disabled: ... ``` and now mypy knows that feature is a `str` inside the `if disabled` block
-rw-r--r--mesonbuild/interpreter/interpreter.py3
-rw-r--r--mesonbuild/interpreter/interpreterobjects.py30
2 files changed, 24 insertions, 9 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 69d04bd61..43433d591 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -868,7 +868,6 @@ class Interpreter(InterpreterBase, HoldableObject):
pass
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
if disabled:
- assert feature, 'for mypy'
mlog.log('Subproject', mlog.bold(subp_name), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
return self.disabled_subproject(subp_name, disabled_feature=feature)
@@ -1299,7 +1298,6 @@ class Interpreter(InterpreterBase, HoldableObject):
native = kwargs['native']
if disabled:
- assert feature, 'for mypy'
for lang in sorted(langs, key=compilers.sort_clink):
mlog.log('Compiler for language', mlog.bold(lang), 'skipped: feature', mlog.bold(feature), 'disabled')
return False
@@ -1754,7 +1752,6 @@ class Interpreter(InterpreterBase, HoldableObject):
) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']:
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
if disabled:
- assert feature, 'for mypy'
mlog.log('Program', mlog.bold(' '.join(args[0])), 'skipped: feature', mlog.bold(feature), 'disabled')
return self.notfound_program(args[0])
diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py
index b6137d175..697c4a0f0 100644
--- a/mesonbuild/interpreter/interpreterobjects.py
+++ b/mesonbuild/interpreter/interpreterobjects.py
@@ -36,7 +36,7 @@ if T.TYPE_CHECKING:
from ..interpreterbase import FeatureCheckBase, SubProject, TYPE_var, TYPE_kwargs, TYPE_nvar, TYPE_nkwargs
from .interpreter import Interpreter
- from typing_extensions import TypedDict
+ from typing_extensions import Literal, TypedDict
class EnvironmentSeparatorKW(TypedDict):
@@ -52,18 +52,36 @@ _ERROR_MSG_KW: KwargInfo[T.Optional[str]] = KwargInfo('error_message', (str, Non
def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired',
subproject: 'SubProject',
feature_check: T.Optional[FeatureCheckBase] = None,
- default: bool = True) -> T.Tuple[bool, bool, T.Optional[str]]:
+ default: bool = True
+ ) -> T.Union[T.Tuple[Literal[True], bool, str],
+ T.Tuple[Literal[False], bool, None]]:
+ """Check common keyword arguments for required status.
+
+ This handles booleans vs feature option.
+
+ :param kwargs:
+ keyword arguments from the Interpreter, containing a `required` argument
+ :param subproject: The subproject this is
+ :param feature_check:
+ A custom feature check for this use of `required` with a
+ `UserFeatureOption`, defaults to None.
+ :param default:
+ The default value is `required` is not set in `kwargs`, defaults to
+ True
+ :raises InterpreterException: If the type of `kwargs['required']` is invalid
+ :return:
+ a tuple of `disabled, required, feature_name`. If `disabled` is `True`
+ `feature_name` will be a string, otherwise it is `None`
+ """
val = kwargs.get('required', default)
- disabled = False
required = False
- feature: T.Optional[str] = None
if isinstance(val, options.UserFeatureOption):
if not feature_check:
feature_check = FeatureNew('User option "feature"', '0.47.0')
feature_check.use(subproject)
feature = val.name
if val.is_disabled():
- disabled = True
+ return True, required, feature
elif val.is_enabled():
required = True
elif isinstance(val, bool):
@@ -76,7 +94,7 @@ def extract_required_kwarg(kwargs: 'kwargs.ExtractRequired',
# TODO: this should be removed, and those callers should learn about FeatureOptions
kwargs['required'] = required
- return disabled, required, feature
+ return False, required, None
def extract_search_dirs(kwargs: 'kwargs.ExtractSearchDirs') -> T.List[str]:
search_dirs_str = mesonlib.stringlistify(kwargs.get('dirs', []))