aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter/interpreter.py
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2021-06-17 00:07:04 +0200
committerDaniel Mensinger <daniel@mensinger-ka.de>2021-06-18 23:48:33 +0200
commitc2c7f7c9d7b05dddb1cee028b1b685c7f2bd424c (patch)
tree7392e6220ddede2781662bcf0851080b4f0aa1ff /mesonbuild/interpreter/interpreter.py
parent6879e84c48632bcd0f6c277e81b4032a00bb1d5c (diff)
downloadmeson-c2c7f7c9d7b05dddb1cee028b1b685c7f2bd424c.zip
meson-c2c7f7c9d7b05dddb1cee028b1b685c7f2bd424c.tar.gz
meson-c2c7f7c9d7b05dddb1cee028b1b685c7f2bd424c.tar.bz2
holders: Ensure that InterpreterBase is the sole instance for (un)holderifying
Diffstat (limited to 'mesonbuild/interpreter/interpreter.py')
-rw-r--r--mesonbuild/interpreter/interpreter.py128
1 files changed, 78 insertions, 50 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index ea36288..13be8e4 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -21,33 +21,35 @@ from .. import optinterpreter
from .. import compilers
from ..wrap import wrap, WrapMode
from .. import mesonlib
-from ..mesonlib import FileMode, MachineChoice, OptionKey, listify, extract_as_list, has_path_sep, unholder
+from ..mesonlib import HoldableObject, FileMode, MachineChoice, OptionKey, listify, extract_as_list, has_path_sep
from ..programs import ExternalProgram, NonExistingExternalProgram
from ..dependencies import Dependency
from ..depfile import DepFile
from ..interpreterbase import ContainerTypeInfo, InterpreterBase, KwargInfo, typed_kwargs, typed_pos_args
-from ..interpreterbase import noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
+from ..interpreterbase import noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening, unholder_return
from ..interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from ..interpreterbase import InterpreterObject, Disabler, disablerIfNotFound
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs
from ..interpreterbase import ObjectHolder, RangeHolder
+from ..interpreterbase import TYPE_nkwargs, TYPE_nvar, TYPE_var
from ..modules import ModuleObject, MutableModuleObject
from ..cmake import CMakeInterpreter
from ..backend.backends import Backend, ExecutableSerialisation
+from . import interpreterobjects as OBJ
+from . import compiler as compilerOBJ
from .mesonmain import MesonMain
-from .compiler import CompilerHolder
-from .interpreterobjects import (SubprojectHolder, MachineHolder, EnvironmentVariablesHolder,
- FeatureOptionHolder, ExternalProgramHolder, CustomTargetHolder,
- RunTargetHolder, IncludeDirsHolder, ConfigurationDataHolder,
- DependencyHolder, ModuleObjectHolder, GeneratedListHolder,
- TargetHolder, CustomTargetIndexHolder, GeneratedObjectsHolder,
- StaticLibraryHolder, ExecutableHolder, SharedLibraryHolder,
- SharedModuleHolder, HeadersHolder, BothLibrariesHolder,
- BuildTargetHolder, DataHolder, JarHolder, Test, RunProcess,
- ManHolder, GeneratorHolder, InstallDirHolder, extract_required_kwarg,
- extract_search_dirs, MutableModuleObjectHolder, FileHolder)
from .dependencyfallbacks import DependencyFallbacksHolder
+from .interpreterobjects import (
+ SubprojectHolder,
+ EnvironmentVariablesObject,
+ ConfigurationDataObject,
+ Test,
+ RunProcess,
+ extract_required_kwarg,
+ extract_search_dirs,
+ NullSubprojectInterpreter,
+)
from pathlib import Path
import os
@@ -386,45 +388,70 @@ class Interpreter(InterpreterBase, HoldableObject):
if 'MESON_UNIT_TEST' in os.environ:
self.funcs.update({'exception': self.func_exception})
- def holderify(self, item):
- if isinstance(item, list):
- return [self.holderify(x) for x in item]
- if isinstance(item, dict):
- return {k: self.holderify(v) for k, v in item.items()}
-
- if isinstance(item, build.CustomTarget):
- return CustomTargetHolder(item, self)
- elif isinstance(item, (int, str, bool, InterpreterObject)) or item is None:
- return item
- elif isinstance(item, build.Executable):
- return ExecutableHolder(item, self)
- elif isinstance(item, build.GeneratedList):
- return GeneratedListHolder(item)
- elif isinstance(item, build.RunTarget):
- raise RuntimeError('This is not a pipe.')
- elif isinstance(item, ExecutableSerialisation):
- raise RuntimeError('Do not do this.')
- elif isinstance(item, build.Data):
- return DataHolder(item)
- elif isinstance(item, dependencies.Dependency):
- return DependencyHolder(item, self.subproject)
- elif isinstance(item, ExternalProgram):
- return ExternalProgramHolder(item, self.subproject)
- elif isinstance(item, MutableModuleObject):
- return MutableModuleObjectHolder(item, self)
- elif isinstance(item, ModuleObject):
- return ModuleObjectHolder(item, self)
- elif isinstance(item, mesonlib.File):
- return FileHolder(item)
- else:
- raise InterpreterException('Module returned a value of unknown type.')
-
- def process_new_values(self, invalues):
+ def build_holder_map(self) -> None:
+ '''
+ Build a mapping of `HoldableObject` types to their corresponding
+ `ObjectHolder`s. This mapping is used in `InterpreterBase` to automatically
+ holderify all returned values from methods and functions.
+ '''
+ self.holder_map.update({
+ mesonlib.File: OBJ.FileHolder,
+ build.SharedLibrary: OBJ.SharedLibraryHolder,
+ build.StaticLibrary: OBJ.StaticLibraryHolder,
+ build.BothLibraries: OBJ.BothLibrariesHolder,
+ build.SharedModule: OBJ.SharedModuleHolder,
+ build.Executable: OBJ.ExecutableHolder,
+ build.Jar: OBJ.JarHolder,
+ build.CustomTarget: OBJ.CustomTargetHolder,
+ build.CustomTargetIndex: OBJ.CustomTargetIndexHolder,
+ build.Generator: OBJ.GeneratorHolder,
+ build.GeneratedList: OBJ.GeneratedListHolder,
+ build.ExtractedObjects: OBJ.GeneratedObjectsHolder,
+ build.RunTarget: OBJ.RunTargetHolder,
+ build.AliasTarget: OBJ.AliasTargetHolder,
+ build.Headers: OBJ.HeadersHolder,
+ build.Man: OBJ.ManHolder,
+ build.Data: OBJ.DataHolder,
+ build.InstallDir: OBJ.InstallDirHolder,
+ build.IncludeDirs: OBJ.IncludeDirsHolder,
+ compilers.RunResult: compilerOBJ.TryRunResultHolder,
+ dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder,
+ coredata.UserFeatureOption: OBJ.FeatureOptionHolder,
+ })
+
+ '''
+ Build a mapping of `HoldableObject` base classes to their
+ corresponding `ObjectHolder`s. The difference to `self.holder_map`
+ is that the keys here define an upper bound instead of requireing an
+ exact match.
+
+ The mappings defined here are only used when there was no direct hit
+ found in `self.holder_map`.
+ '''
+ self.bound_holder_map.update({
+ dependencies.Dependency: OBJ.DependencyHolder,
+ ExternalProgram: OBJ.ExternalProgramHolder,
+ compilers.Compiler: compilerOBJ.CompilerHolder,
+ ModuleObject: OBJ.ModuleObjectHolder,
+ MutableModuleObject: OBJ.MutableModuleObjectHolder,
+ })
+
+ def append_holder_map(self, held_type: T.Type[mesonlib.HoldableObject], holder_type: T.Type[ObjectHolder]) -> None:
+ '''
+ Adds one additional mapping to the `holder_map`.
+
+ The intended use for this function is in the `initialize` method of
+ modules to register custom object holders.
+ '''
+ self.holder_map.update({
+ held_type: holder_type
+ })
+
+ def process_new_values(self, invalues: T.List[TYPE_var]) -> None:
invalues = listify(invalues)
for v in invalues:
- if isinstance(v, (RunTargetHolder, CustomTargetHolder, BuildTargetHolder)):
- v = v.held_object
-
+ if isinstance(v, ObjectHolder):
+ raise InterpreterException('Modules must not return ObjectHolders')
if isinstance(v, (build.BuildTarget, build.CustomTarget, build.RunTarget)):
self.add_target(v.name, v)
elif isinstance(v, list):
@@ -2647,6 +2674,7 @@ This will become a hard error in the future.''', location=self.current_node)
@noKwargs
@noArgsFlattening
+ @unholder_return
def func_get_variable(self, node, args, kwargs):
if len(args) < 1 or len(args) > 2:
raise InvalidCode('Get_variable takes one or two arguments.')