From 351a1e9ec93fecee8923356c5647fa526524c54d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 30 Jun 2021 12:46:33 -0700 Subject: interpreter: use typed_pos_args for func_import and make the helper method private --- mesonbuild/interpreter/interpreter.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'mesonbuild/interpreter/interpreter.py') diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 693924f..dc2fd1a 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -601,35 +601,33 @@ class Interpreter(InterpreterBase, HoldableObject): dep = df.lookup(kwargs, force_fallback=True) self.build.stdlibs[for_machine][l] = dep - def import_module(self, modname): - if modname in self.modules: - return - try: - module = importlib.import_module('mesonbuild.modules.' + modname) - except ImportError: - raise InvalidArguments(f'Module "{modname}" does not exist') - ext_module = module.initialize(self) - assert isinstance(ext_module, ModuleObject) - self.modules[modname] = ext_module - - @stringArgs + @typed_pos_args('import', str) @noKwargs - def func_import(self, node, args, kwargs): - if len(args) != 1: - raise InvalidCode('Import takes one argument.') + def func_import(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs) -> ModuleObject: modname = args[0] if modname.startswith('unstable-'): plainname = modname.split('-', 1)[1] try: # check if stable module exists - self.import_module(plainname) + self._import_module(plainname) mlog.warning(f'Module {modname} is now stable, please use the {plainname} module instead.') modname = plainname except InvalidArguments: 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 self.modules[modname] + + if modname in self.modules: + return self.modules[modname] + + try: + module = importlib.import_module('mesonbuild.modules.' + modname) + except ImportError: + raise InvalidArguments(f'Module "{modname}" does not exist') + ext_module = module.initialize(self) + assert isinstance(ext_module, ModuleObject) + self.modules[modname] = ext_module + + return ext_module @stringArgs @noKwargs -- cgit v1.1 From 4a0a6a80837af1b75db3b3b57a5b8f41386e5c0b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 30 Jun 2021 13:01:41 -0700 Subject: modules: modules need to return either an ExtensionModlue or a NewExtensionModule object So that we get the found() method. --- mesonbuild/interpreter/interpreter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild/interpreter/interpreter.py') diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index dc2fd1a..c103f7e 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -32,7 +32,7 @@ from ..interpreterbase import 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 ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule from ..cmake import CMakeInterpreter from ..backend.backends import Backend, ExecutableSerialisation @@ -304,7 +304,7 @@ class Interpreter(InterpreterBase, HoldableObject): subproject: str = '', subdir: str = '', subproject_dir: str = 'subprojects', - modules: T.Optional[T.Dict[str, ModuleObject]] = None, + modules: T.Optional[T.Dict[str, T.Union[ExtensionModule, NewExtensionModule]]] = None, default_project_options: T.Optional[T.Dict[str, str]] = None, mock: bool = False, ast: T.Optional[mparser.CodeBlockNode] = None, -- cgit v1.1 From bc4201a7f1e93d6afb62caa8ce81bb1b0211b70c Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 30 Jun 2021 13:03:54 -0700 Subject: interpreter: add required and disabled to import This is useful both from the perspective of optional functionality that requires a module, and also as I continue to progress with Meson++, which will probably not implement all of the modules that Meson itself does. --- mesonbuild/interpreter/interpreter.py | 59 ++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 19 deletions(-) (limited to 'mesonbuild/interpreter/interpreter.py') diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c103f7e..9bc7bd5 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -32,7 +32,7 @@ from ..interpreterbase import 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 ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule +from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule from ..cmake import CMakeInterpreter from ..backend.backends import Backend, ExecutableSerialisation @@ -161,6 +161,13 @@ _INSTALL_MODE_KW = KwargInfo( convertor=_install_mode_convertor, ) +_REQUIRED_KW = KwargInfo( + 'required', + (bool, coredata.UserFeatureOption), + default=True, + # TODO: extract_required_kwarg could be converted to a convertor +) + def stringifyUserArguments(args, quote=False): if isinstance(args, list): @@ -304,7 +311,7 @@ class Interpreter(InterpreterBase, HoldableObject): subproject: str = '', subdir: str = '', subproject_dir: str = 'subprojects', - modules: T.Optional[T.Dict[str, T.Union[ExtensionModule, NewExtensionModule]]] = None, + modules: T.Optional[T.Dict[str, T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]]] = None, default_project_options: T.Optional[T.Dict[str, str]] = None, mock: bool = False, ast: T.Optional[mparser.CodeBlockNode] = None, @@ -601,33 +608,47 @@ class Interpreter(InterpreterBase, HoldableObject): dep = df.lookup(kwargs, force_fallback=True) self.build.stdlibs[for_machine][l] = dep + def _import_module(self, modname: str, required: bool) -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]: + if modname in self.modules: + return self.modules[modname] + try: + module = importlib.import_module('mesonbuild.modules.' + modname) + except ImportError: + if required: + raise InvalidArguments(f'Module "{modname}" does not exist') + ext_module = NotFoundExtensionModule() + else: + ext_module = module.initialize(self) + assert isinstance(ext_module, (ExtensionModule, NewExtensionModule)) + self.modules[modname] = ext_module + return ext_module + @typed_pos_args('import', str) - @noKwargs - def func_import(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs) -> ModuleObject: + @typed_kwargs( + 'import', + _REQUIRED_KW.evolve(since='0.59.0'), + KwargInfo('disabler', bool, default=False, since='0.59.0'), + ) + @disablerIfNotFound + def func_import(self, node: mparser.BaseNode, args: T.Tuple[str], + kwargs: 'kwargs.FuncImportModule') -> T.Union[ExtensionModule, NewExtensionModule, NotFoundExtensionModule]: modname = args[0] + disabled, required, _ = extract_required_kwarg(kwargs, self.subproject) + if disabled: + return NotFoundExtensionModule() + if modname.startswith('unstable-'): plainname = modname.split('-', 1)[1] try: # check if stable module exists - self._import_module(plainname) + mod = self._import_module(plainname, required) + # XXX: this is acutally not helpful, since it doesn't do a version check mlog.warning(f'Module {modname} is now stable, please use the {plainname} module instead.') - modname = plainname + return mod except InvalidArguments: mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node) modname = 'unstable_' + plainname - - if modname in self.modules: - return self.modules[modname] - - try: - module = importlib.import_module('mesonbuild.modules.' + modname) - except ImportError: - raise InvalidArguments(f'Module "{modname}" does not exist') - ext_module = module.initialize(self) - assert isinstance(ext_module, ModuleObject) - self.modules[modname] = ext_module - - return ext_module + return self._import_module(modname, required) @stringArgs @noKwargs -- cgit v1.1