aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/interpreter.py')
-rw-r--r--mesonbuild/interpreter.py118
1 files changed, 31 insertions, 87 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 570b34f..2cc4f44 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -33,7 +33,7 @@ from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, Fe
from .interpreterbase import ObjectHolder, MesonVersionString
from .interpreterbase import TYPE_var, TYPE_nkwargs
from .interpreterbase import typed_pos_args
-from .modules import ModuleReturnValue, ExtensionModule
+from .modules import ModuleReturnValue, ModuleObject, ModuleState
from .cmake import CMakeInterpreter
from .backend.backends import TestProtocol, Backend, ExecutableSerialisation
@@ -55,7 +55,6 @@ if T.TYPE_CHECKING:
from .compilers import Compiler
from .envconfig import MachineInfo
from .environment import Environment
- from .modules import ExtensionModule
permitted_method_kwargs = {
'partial_dependency': {'compile_args', 'link_args', 'links', 'includes',
@@ -1765,93 +1764,43 @@ class CompilerHolder(InterpreterObject):
return self.compiler.get_argument_syntax()
-class ModuleState(T.NamedTuple):
-
- """Object passed to a module when it a method is called.
-
- holds the current state of the meson process at a given method call in
- the interpreter.
- """
-
- source_root: str
- build_to_src: str
- subproject: str
- subdir: str
- current_lineno: str
- environment: 'Environment'
- project_name: str
- project_version: str
- backend: str
- targets: T.Dict[str, build.Target]
- data: T.List[build.Data]
- headers: T.List[build.Headers]
- man: T.List[build.Man]
- global_args: T.Dict[str, T.List[str]]
- project_args: T.Dict[str, T.List[str]]
- build_machine: 'MachineInfo'
- host_machine: 'MachineInfo'
- target_machine: 'MachineInfo'
- current_node: mparser.BaseNode
-
-
-class ModuleHolder(InterpreterObject, ObjectHolder['ExtensionModule']):
- def __init__(self, modname: str, module: 'ExtensionModule', interpreter: 'Interpreter'):
+class ModuleObjectHolder(InterpreterObject, ObjectHolder['ModuleObject']):
+ def __init__(self, modobj: 'ModuleObject', interpreter: 'Interpreter'):
InterpreterObject.__init__(self)
- ObjectHolder.__init__(self, module)
- self.modname = modname
+ ObjectHolder.__init__(self, modobj)
self.interpreter = interpreter
def method_call(self, method_name, args, kwargs):
- try:
- fn = getattr(self.held_object, method_name)
- except AttributeError:
- raise InvalidArguments('Module %s does not have method %s.' % (self.modname, method_name))
- if method_name.startswith('_'):
- raise InvalidArguments('Function {!r} in module {!r} is private.'.format(method_name, self.modname))
- if not getattr(fn, 'no-args-flattening', False):
+ modobj = self.held_object
+ method = modobj.methods.get(method_name)
+ if not method and not modobj.methods:
+ # FIXME: Port all modules to use the methods dict.
+ method = getattr(modobj, method_name, None)
+ if method_name.startswith('_'):
+ raise InvalidArguments('Method {!r} is private.'.format(method_name))
+ if not method:
+ raise InvalidCode('Unknown method "%s" in object.' % method_name)
+ if not getattr(method, 'no-args-flattening', False):
args = flatten(args)
- # This is not 100% reliable but we can't use hash()
- # because the Build object contains dicts and lists.
- num_targets = len(self.interpreter.build.targets)
- state = ModuleState(
- source_root = self.interpreter.environment.get_source_dir(),
- build_to_src=mesonlib.relpath(self.interpreter.environment.get_source_dir(),
- self.interpreter.environment.get_build_dir()),
- subproject=self.interpreter.subproject,
- subdir=self.interpreter.subdir,
- current_lineno=self.interpreter.current_lineno,
- environment=self.interpreter.environment,
- project_name=self.interpreter.build.project_name,
- project_version=self.interpreter.build.dep_manifest[self.interpreter.active_projectname],
- # The backend object is under-used right now, but we will need it:
- # https://github.com/mesonbuild/meson/issues/1419
- backend=self.interpreter.backend,
- targets=self.interpreter.build.targets,
- data=self.interpreter.build.data,
- headers=self.interpreter.build.get_headers(),
- man=self.interpreter.build.get_man(),
- #global_args_for_build = self.interpreter.build.global_args.build,
- global_args = self.interpreter.build.global_args.host,
- #project_args_for_build = self.interpreter.build.projects_args.build.get(self.interpreter.subproject, {}),
- project_args = self.interpreter.build.projects_args.host.get(self.interpreter.subproject, {}),
- build_machine=self.interpreter.builtin['build_machine'].held_object,
- host_machine=self.interpreter.builtin['host_machine'].held_object,
- target_machine=self.interpreter.builtin['target_machine'].held_object,
- current_node=self.current_node
- )
+ state = ModuleState(self.interpreter)
# Many modules do for example self.interpreter.find_program_impl(),
# so we have to ensure they use the current interpreter and not the one
# that first imported that module, otherwise it will use outdated
# overrides.
- self.held_object.interpreter = self.interpreter
- if self.held_object.is_snippet(method_name):
- value = fn(self.interpreter, state, args, kwargs)
- return self.interpreter.holderify(value)
+ modobj.interpreter = self.interpreter
+ if method_name in modobj.snippets:
+ ret = method(self.interpreter, state, args, kwargs)
else:
- value = fn(state, args, kwargs)
+ # This is not 100% reliable but we can't use hash()
+ # because the Build object contains dicts and lists.
+ num_targets = len(self.interpreter.build.targets)
+ ret = method(state, args, kwargs)
if num_targets != len(self.interpreter.build.targets):
raise InterpreterException('Extension module altered internal state illegally.')
- return self.interpreter.module_method_callback(value)
+ if isinstance(ret, ModuleReturnValue):
+ self.interpreter.process_new_values(ret.new_objects)
+ ret = ret.return_value
+ return self.interpreter.holderify(ret)
class Summary:
@@ -2401,7 +2350,7 @@ class Interpreter(InterpreterBase):
subproject: str = '',
subdir: str = '',
subproject_dir: str = 'subprojects',
- modules: T.Optional[T.Dict[str, ExtensionModule]] = None,
+ modules: T.Optional[T.Dict[str, ModuleObject]] = None,
default_project_options: T.Optional[T.Dict[str, str]] = None,
mock: bool = False,
ast: T.Optional[mparser.CodeBlockNode] = None,
@@ -2566,6 +2515,8 @@ class Interpreter(InterpreterBase):
return DependencyHolder(item, self.subproject)
elif isinstance(item, dependencies.ExternalProgram):
return ExternalProgramHolder(item, self.subproject)
+ elif isinstance(item, ModuleObject):
+ return ModuleObjectHolder(item, self)
elif isinstance(item, (InterpreterObject, ObjectHolder)):
return item
else:
@@ -2600,13 +2551,6 @@ class Interpreter(InterpreterBase):
else:
raise InterpreterException('Module returned a value of unknown type.')
- def module_method_callback(self, return_object):
- if not isinstance(return_object, ModuleReturnValue):
- raise InterpreterException('Bug in module, it returned an invalid object')
- invalues = return_object.new_objects
- self.process_new_values(invalues)
- return self.holderify(return_object.return_value)
-
def get_build_def_files(self) -> T.List[str]:
return self.build_def_files
@@ -2676,7 +2620,7 @@ class Interpreter(InterpreterBase):
except ImportError:
raise InvalidArguments('Module "%s" does not exist' % (modname, ))
ext_module = module.initialize(self)
- assert isinstance(ext_module, ExtensionModule)
+ assert isinstance(ext_module, ModuleObject)
self.modules[modname] = ext_module
@stringArgs
@@ -2696,7 +2640,7 @@ class Interpreter(InterpreterBase):
mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node)
modname = 'unstable_' + plainname
self.import_module(modname)
- return ModuleHolder(modname, self.modules[modname], self)
+ return ModuleObjectHolder(self.modules[modname], self)
@stringArgs
@noKwargs