summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2025-09-15 14:26:28 -0700
committerDylan Baker <dylan@pnwbakers.com>2025-10-20 15:15:53 -0700
commitf4fbb17301d87e4c774ed50a449051511a3982c2 (patch)
treee3cabe1df3aeab472ffbc2a20cc0191c05004a9b
parent229ed1c9d467227da36eb0cafa84bbe15d92370e (diff)
downloadmeson-f4fbb17301d87e4c774ed50a449051511a3982c2.tar.gz
interpreter/dependencyfallbacks: use DependencyObjectKWs
This allows for a lot of type safety to be introduced, and almost all casting to be removed.
-rw-r--r--mesonbuild/interpreter/dependencyfallbacks.py56
-rwxr-xr-xrun_mypy.py1
2 files changed, 28 insertions, 29 deletions
diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py
index b85e09e7a..baf5ea39e 100644
--- a/mesonbuild/interpreter/dependencyfallbacks.py
+++ b/mesonbuild/interpreter/dependencyfallbacks.py
@@ -8,7 +8,7 @@ from .. import mlog
from .. import dependencies
from .. import build
from ..wrap import WrapMode
-from ..mesonlib import stringlistify, version_compare_many
+from ..mesonlib import stringlistify, version_compare_many, MachineChoice
from ..options import OptionKey
from ..dependencies import Dependency, DependencyException, NotFoundDependency
from ..interpreterbase import (MesonInterpreterObject, FeatureNew,
@@ -19,12 +19,11 @@ if T.TYPE_CHECKING:
from typing_extensions import TypeAlias
from .interpreter import Interpreter
from .kwargs import DoSubproject
- from ..interpreterbase import TYPE_nkwargs, TYPE_nvar
- from ..mesonlib import MachineChoice
- from ..options import ElementaryOptionValues
+ from ..dependencies.base import DependencyObjectKWs
+ from ..options import ElementaryOptionValues, OptionDict
from .interpreterobjects import SubprojectHolder
- CandidateType: TypeAlias = T.Tuple[T.Callable[[TYPE_nkwargs, TYPE_nvar, DoSubproject], T.Optional[Dependency]], TYPE_nvar]
+ CandidateType: TypeAlias = T.Tuple[T.Callable[[DependencyObjectKWs, str, DoSubproject], T.Optional[Dependency]], str]
class DependencyFallbacksHolder(MesonInterpreterObject):
@@ -83,36 +82,33 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
self.subproject_name = subp_name
self.subproject_varname = varname
- def _do_dependency_cache(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
- name = func_args[0]
+ def _do_dependency_cache(self, kwargs: DependencyObjectKWs, name: str, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
cached_dep = self._get_cached_dep(name, kwargs)
if cached_dep:
self._verify_fallback_consistency(cached_dep)
return cached_dep
- def _do_dependency(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
+ def _do_dependency(self, kwargs: DependencyObjectKWs, name: str, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
# Note that there is no df.dependency() method, this is called for names
# given as positional arguments to dependency_fallbacks(name1, ...).
# We use kwargs from the dependency() function, for things like version,
# module, etc.
- name = func_args[0]
self._handle_featurenew_dependencies(name)
dep = dependencies.find_external_dependency(name, self.environment, kwargs)
if dep.found():
- for_machine = T.cast('MachineChoice', kwargs['native'])
+ for_machine = kwargs.get('native', MachineChoice.HOST)
identifier = dependencies.get_dep_identifier(name, kwargs)
self.coredata.deps[for_machine].put(identifier, dep)
return dep
return None
- def _do_existing_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
- subp_name = func_args[0]
+ def _do_existing_subproject(self, kwargs: DependencyObjectKWs, subp_name: str, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
varname = self.subproject_varname
if subp_name and self._get_subproject(subp_name):
return self._get_subproject_dep(subp_name, varname, kwargs)
return None
- def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
+ def _do_subproject(self, kwargs: DependencyObjectKWs, name: str, func_kwargs: DoSubproject) -> T.Optional[Dependency]:
if self.forcefallback:
mlog.log('Looking for a fallback subproject for the dependency',
mlog.bold(self._display_name), 'because:\nUse of fallback dependencies is forced.')
@@ -127,7 +123,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# dependency('foo', static: true) should implicitly add
# default_options: ['default_library=static']
static = kwargs.get('static')
- forced_options = {}
+ forced_options: OptionDict = {}
if static is not None:
default_library = 'static' if static else 'shared'
mlog.log(f'Building fallback subproject with default_library={default_library}')
@@ -145,7 +141,7 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
return sub
return None
- def _get_subproject_dep(self, subp_name: str, varname: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+ def _get_subproject_dep(self, subp_name: str, varname: str, kwargs: DependencyObjectKWs) -> T.Optional[Dependency]:
# Verify the subproject is found
subproject = self._get_subproject(subp_name)
if not subproject:
@@ -208,12 +204,12 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
mlog.normal_cyan(found) if found else None)
return var_dep
- def _get_cached_dep(self, name: str, kwargs: TYPE_nkwargs) -> T.Optional[Dependency]:
+ def _get_cached_dep(self, name: str, kwargs: DependencyObjectKWs) -> T.Optional[Dependency]:
# Unlike other methods, this one returns not-found dependency instead
# of None in the case the dependency is cached as not-found, or if cached
# version does not match. In that case we don't want to continue with
# other candidates.
- for_machine = T.cast('MachineChoice', kwargs['native'])
+ for_machine = kwargs.get('native', MachineChoice.HOST)
identifier = dependencies.get_dep_identifier(name, kwargs)
wanted_vers = stringlistify(kwargs.get('version', []))
@@ -300,28 +296,30 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
candidates: T.List[CandidateType] = []
# 1. check if any of the names is cached already.
for name in self.names:
- candidates.append((self._do_dependency_cache, [name]))
+ candidates.append((self._do_dependency_cache, name))
# 2. check if the subproject fallback has already been configured.
if self.subproject_name:
- candidates.append((self._do_existing_subproject, [self.subproject_name]))
+ candidates.append((self._do_existing_subproject, self.subproject_name))
# 3. check external dependency if we are not forced to use subproject
if not self.forcefallback or not self.subproject_name:
for name in self.names:
- candidates.append((self._do_dependency, [name]))
+ candidates.append((self._do_dependency, name))
# 4. configure the subproject
if self.subproject_name:
- candidates.append((self._do_subproject, [self.subproject_name]))
+ candidates.append((self._do_subproject, self.subproject_name))
return candidates
- def lookup(self, kwargs: TYPE_nkwargs, force_fallback: bool = False) -> Dependency:
+ def lookup(self, kwargs: DependencyObjectKWs, force_fallback: bool = False) -> Dependency:
mods = kwargs.get('modules', [])
if mods:
self._display_name += ' (modules: {})'.format(', '.join(str(i) for i in mods))
- required = T.cast('bool', kwargs.get('required', True))
+ required = kwargs.get('required', True)
# Check if usage of the subproject fallback is forced
- wrap_mode = WrapMode.from_string(self.coredata.optstore.get_value_for(OptionKey('wrap_mode')))
+ _wm = self.coredata.optstore.get_value_for(OptionKey('wrap_mode'))
+ assert isinstance(_wm, str), 'for mypy'
+ wrap_mode = WrapMode.from_string(_wm)
force_fallback_for = self.coredata.optstore.get_value_for(OptionKey('force_fallback_for'))
assert isinstance(force_fallback_for, list), 'for mypy'
self.nofallback = wrap_mode == WrapMode.nofallback
@@ -354,21 +352,21 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
# Try all candidates, only the last one is really required.
last = len(candidates) - 1
for i, item in enumerate(candidates):
- func, func_args = item
+ func, name = item
+ kwargs['required'] = required and (i == last)
func_kwargs: DoSubproject = {
- 'required': required and (i == last),
+ 'required': kwargs['required'],
'cmake_options': [],
'default_options': self.default_options,
'options': None,
'version': [],
}
- kwargs['required'] = required and (i == last)
- dep = func(kwargs, func_args, func_kwargs)
+ dep = func(kwargs, name, func_kwargs)
if dep and dep.found():
# Override this dependency to have consistent results in subsequent
# dependency lookups.
for name in self.names:
- for_machine = T.cast('MachineChoice', kwargs['native'])
+ for_machine = kwargs.get('native', MachineChoice.HOST)
identifier = dependencies.get_dep_identifier(name, kwargs)
if identifier not in self.build.dependency_overrides[for_machine]:
self.build.dependency_overrides[for_machine][identifier] = \
diff --git a/run_mypy.py b/run_mypy.py
index 08d579113..18c46f1f7 100755
--- a/run_mypy.py
+++ b/run_mypy.py
@@ -35,6 +35,7 @@ modules = [
'mesonbuild/envconfig.py',
'mesonbuild/environment.py',
'mesonbuild/interpreter/compiler.py',
+ 'mesonbuild/interpreter/dependencyfallbacks.py',
'mesonbuild/interpreter/mesonmain.py',
'mesonbuild/interpreter/interpreterobjects.py',
'mesonbuild/interpreter/type_checking.py',