diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2021-08-18 14:13:17 -0700 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2021-08-30 18:05:02 -0700 |
commit | 3731e1d8f38be0ba3360d6badae789b1078e5b5a (patch) | |
tree | f1995ced3659c5cd7de27f6d771f2c5a2c719819 | |
parent | d6a1f85248e80650d628d969212a06992d1b8f4c (diff) | |
download | meson-3731e1d8f38be0ba3360d6badae789b1078e5b5a.zip meson-3731e1d8f38be0ba3360d6badae789b1078e5b5a.tar.gz meson-3731e1d8f38be0ba3360d6badae789b1078e5b5a.tar.bz2 |
make EnvironmentVariablesObject a proper holder
Currently, EnvironmentVariablesObject is a strange
holder-that's-not-a-holder. This has implicaitons for things that expect
to get an EnvironmentVariables object, as we can't automatically
unholder it, and instead have to to manually do so. Now we can
automatically unholder it, which makes everything much nicer.
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 43 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreterobjects.py | 44 | ||||
-rw-r--r-- | mesonbuild/interpreter/kwargs.py | 3 | ||||
-rw-r--r-- | mesonbuild/interpreter/mesonmain.py | 15 |
4 files changed, 42 insertions, 63 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index ec5c75c..d640e65 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -42,7 +42,6 @@ from .mesonmain import MesonMain from .dependencyfallbacks import DependencyFallbacksHolder from .interpreterobjects import ( SubprojectHolder, - EnvironmentVariablesObject, ConfigurationDataObject, Test, RunProcess, @@ -396,6 +395,7 @@ class Interpreter(InterpreterBase, HoldableObject): build.Data: OBJ.DataHolder, build.InstallDir: OBJ.InstallDirHolder, build.IncludeDirs: OBJ.IncludeDirsHolder, + build.EnvironmentVariables: OBJ.EnvironmentVariablesObject, compilers.RunResult: compilerOBJ.TryRunResultHolder, dependencies.ExternalLibrary: OBJ.ExternalLibraryHolder, coredata.UserFeatureOption: OBJ.FeatureOptionHolder, @@ -1723,19 +1723,14 @@ This will become a hard error in the future.''' % kwargs['input'], location=self kwargs: 'kwargs.FuncTest') -> None: self.add_test(node, args, kwargs, True) - def unpack_env_kwarg(self, kwargs: T.Union[EnvironmentVariablesObject, T.Dict[str, str], T.List[str]]) -> build.EnvironmentVariables: - envlist = kwargs.get('env', EnvironmentVariablesObject()) - if isinstance(envlist, EnvironmentVariablesObject): - env = envlist.vars - elif isinstance(envlist, dict): - FeatureNew.single_use('environment dictionary', '0.52.0', self.subproject) - env = EnvironmentVariablesObject(envlist) - env = env.vars - else: - # Convert from array to environment object - env = EnvironmentVariablesObject(envlist) - env = env.vars - return env + def unpack_env_kwarg(self, kwargs: T.Union[build.EnvironmentVariables, T.Dict[str, 'TYPE_var'], T.List['TYPE_var'], str]) -> build.EnvironmentVariables: + envlist = kwargs.get('env') + if envlist is None: + return build.EnvironmentVariables() + msg = ENV_KW.validator(envlist) + if msg: + raise InvalidArguments(f'"env": {msg}') + return ENV_KW.convertor(envlist) def make_test(self, node: mparser.BaseNode, args: T.Tuple[str, T.Union[build.Executable, build.Jar, ExternalProgram, mesonlib.File]], @@ -2361,17 +2356,17 @@ This will become a hard error in the future.''' % kwargs['input'], location=self @noKwargs @noArgsFlattening - def func_environment(self, node, args, kwargs): - if len(args) > 1: - raise InterpreterException('environment takes only one optional positional arguments') - elif len(args) == 1: + @typed_pos_args('environment', optargs=[(str, list, dict)]) + def func_environment(self, node: mparser.FunctionNode, args: T.Tuple[T.Union[None, str, T.List['TYPE_var'], T.Dict[str, 'TYPE_var']]], + kwargs: 'TYPE_kwargs') -> build.EnvironmentVariables: + init = args[0] + if init is not None: FeatureNew.single_use('environment positional arguments', '0.52.0', self.subproject) - initial_values = args[0] - if not isinstance(initial_values, dict) and not isinstance(initial_values, list): - raise InterpreterException('environment first argument must be a dictionary or a list') - else: - initial_values = {} - return EnvironmentVariablesObject(initial_values, self.subproject) + msg = ENV_KW.validator(init) + if msg: + raise InvalidArguments(f'"environment": {msg}') + return ENV_KW.convertor(init) + return build.EnvironmentVariables() @typed_pos_args('join_paths', varargs=str, min_varargs=1) @noKwargs diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index c614f09..53a0666 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -229,39 +229,19 @@ class RunProcess(MesonInterpreterObject): def stderr_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str: return self.stderr -# TODO: Parsing the initial values should be either done directly in the -# `Interpreter` or in `build.EnvironmentVariables`. This way, this class -# can be converted into a pure object holder. -class EnvironmentVariablesObject(MutableInterpreterObject, MesonInterpreterObject): - # TODO: Move the type cheking for initial_values out of this class and replace T.Any - def __init__(self, initial_values: T.Optional[T.Any] = None, subproject: str = ''): - super().__init__(subproject=subproject) - self.vars = build.EnvironmentVariables() + +class EnvironmentVariablesObject(ObjectHolder[build.EnvironmentVariables], MutableInterpreterObject): + + def __init__(self, obj: build.EnvironmentVariables, interpreter: 'Interpreter'): + super().__init__(obj, interpreter) self.methods.update({'set': self.set_method, 'append': self.append_method, 'prepend': self.prepend_method, }) - if isinstance(initial_values, build.EnvironmentVariables): - self.vars = initial_values - elif isinstance(initial_values, dict): - for k, v in initial_values.items(): - self.set_method([k, v], {}) - elif initial_values is not None: - for e in mesonlib.listify(initial_values): - if not isinstance(e, str): - raise InterpreterException('Env var definition must be a list of strings.') - if '=' not in e: - raise InterpreterException('Env var definition must be of type key=val.') - (k, val) = e.split('=', 1) - k = k.strip() - val = val.strip() - if ' ' in k: - raise InterpreterException('Env var key must not have spaces in it.') - self.set_method([k, val], {}) def __repr__(self) -> str: repr_str = "<{0}: {1}>" - return repr_str.format(self.__class__.__name__, self.vars.envvars) + return repr_str.format(self.__class__.__name__, self.held_object.envvars) def unpack_separator(self, kwargs: T.Dict[str, T.Any]) -> str: separator = kwargs.get('separator', os.pathsep) @@ -270,9 +250,13 @@ class EnvironmentVariablesObject(MutableInterpreterObject, MesonInterpreterObjec " argument needs to be a string.") return separator + def __deepcopy__(self, memo: T.Dict[str, object]) -> 'EnvironmentVariablesObject': + # Avoid trying to copy the intepreter + return EnvironmentVariablesObject(copy.deepcopy(self.held_object), self.interpreter) + def warn_if_has_name(self, name: str) -> None: # Multiple append/prepend operations was not supported until 0.58.0. - if self.vars.has_name(name): + if self.held_object.has_name(name): m = f'Overriding previous value of environment variable {name!r} with a new one' FeatureNew('0.58.0', m).use(self.subproject) @@ -282,7 +266,7 @@ class EnvironmentVariablesObject(MutableInterpreterObject, MesonInterpreterObjec def set_method(self, args: T.Tuple[str, T.List[str]], kwargs: T.Dict[str, T.Any]) -> None: name, values = args separator = self.unpack_separator(kwargs) - self.vars.set(name, values, separator) + self.held_object.set(name, values, separator) @stringArgs @permittedKwargs({'separator'}) @@ -291,7 +275,7 @@ class EnvironmentVariablesObject(MutableInterpreterObject, MesonInterpreterObjec name, values = args separator = self.unpack_separator(kwargs) self.warn_if_has_name(name) - self.vars.append(name, values, separator) + self.held_object.append(name, values, separator) @stringArgs @permittedKwargs({'separator'}) @@ -300,7 +284,7 @@ class EnvironmentVariablesObject(MutableInterpreterObject, MesonInterpreterObjec name, values = args separator = self.unpack_separator(kwargs) self.warn_if_has_name(name) - self.vars.prepend(name, values, separator) + self.held_object.prepend(name, values, separator) class ConfigurationDataObject(MutableInterpreterObject, MesonInterpreterObject): diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py index 9eb02be..317f7c6 100644 --- a/mesonbuild/interpreter/kwargs.py +++ b/mesonbuild/interpreter/kwargs.py @@ -11,7 +11,6 @@ from typing_extensions import TypedDict, Literal from .. import build from .. import coredata from ..mesonlib import MachineChoice, File, FileMode, FileOrString -from .interpreterobjects import EnvironmentVariablesObject class FuncAddProjectArgs(TypedDict): @@ -39,7 +38,7 @@ class BaseTest(TypedDict): workdir: T.Optional[str] depends: T.List[T.Union[build.CustomTarget, build.BuildTarget]] priority: int - env: EnvironmentVariablesObject + env: build.EnvironmentVariables suite: T.List[str] diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index 5355c47..9c4f50a 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -7,13 +7,13 @@ from .. import mlog from ..mesonlib import MachineChoice, OptionKey from ..programs import OverrideProgram, ExternalProgram +from ..interpreter.type_checking import ENV_KW from ..interpreterbase import (MesonInterpreterObject, FeatureNew, FeatureDeprecated, typed_pos_args, permittedKwargs, noArgsFlattening, noPosargs, noKwargs, typed_kwargs, KwargInfo, MesonVersionString, InterpreterException) from .interpreterobjects import (ExecutableHolder, ExternalProgramHolder, - CustomTargetHolder, CustomTargetIndexHolder, - EnvironmentVariablesObject) + CustomTargetHolder, CustomTargetIndexHolder) from .type_checking import NATIVE_KW, NoneType import typing as T @@ -415,9 +415,10 @@ class MesonMain(MesonInterpreterObject): @FeatureNew('add_devenv', '0.58.0') @noKwargs - @typed_pos_args('add_devenv', (str, list, dict, EnvironmentVariablesObject)) - def add_devenv_method(self, args: T.Union[str, list, dict, EnvironmentVariablesObject], kwargs: T.Dict[str, T.Any]) -> None: + @typed_pos_args('add_devenv', (str, list, dict, build.EnvironmentVariables)) + def add_devenv_method(self, args: T.Tuple[T.Union[str, list, dict, build.EnvironmentVariables]], kwargs: T.Dict[str, T.Any]) -> None: env = args[0] - if isinstance(env, (str, list, dict)): - env = EnvironmentVariablesObject(env) - self.build.devenv.append(env.vars) + msg = ENV_KW.validator(env) + if msg: + raise build.InvalidArguments(f'"add_devenv": {msg}') + self.build.devenv.append(ENV_KW.convertor(env)) |