| # Copyright 2013-2021 The Meson development team |
| |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from .. import mparser, mlog |
| from .exceptions import InvalidArguments, InterpreterException |
| |
| import collections.abc |
| import typing as T |
| |
| if T.TYPE_CHECKING: |
| from .baseobjects import TYPE_nvar, TV_fw_args, TV_fw_kwargs |
| |
| def flatten(args: T.Union['TYPE_nvar', T.List['TYPE_nvar']]) -> T.List['TYPE_nvar']: |
| if isinstance(args, mparser.StringNode): |
| assert isinstance(args.value, str) |
| return [args.value] |
| if not isinstance(args, collections.abc.Sequence): |
| return [args] |
| result: T.List['TYPE_nvar'] = [] |
| for a in args: |
| if isinstance(a, list): |
| rest = flatten(a) |
| result = result + rest |
| elif isinstance(a, mparser.StringNode): |
| result.append(a.value) |
| else: |
| result.append(a) |
| return result |
| |
| def check_stringlist(a: T.Any, msg: str = 'Arguments must be strings.') -> None: |
| if not isinstance(a, list): |
| mlog.debug('Not a list:', str(a)) |
| raise InvalidArguments('Argument not a list.') |
| if not all(isinstance(s, str) for s in a): |
| mlog.debug('Element not a string:', str(a)) |
| raise InvalidArguments(msg) |
| |
| def default_resolve_key(key: mparser.BaseNode) -> str: |
| if not isinstance(key, mparser.IdNode): |
| raise InterpreterException('Invalid kwargs format.') |
| return key.value |
| |
| def get_callee_args(wrapped_args: T.Sequence[T.Any], want_subproject: bool = False) -> T.Tuple[T.Any, mparser.BaseNode, 'TV_fw_args', 'TV_fw_kwargs', T.Optional[str]]: |
| s = wrapped_args[0] |
| n = len(wrapped_args) |
| # Raise an error if the codepaths are not there |
| subproject = None # type: T.Optional[str] |
| if want_subproject and n == 2: |
| if hasattr(s, 'subproject'): |
| # Interpreter base types have 2 args: self, node |
| node = wrapped_args[1] |
| # args and kwargs are inside the node |
| args = None |
| kwargs = None |
| subproject = s.subproject |
| elif hasattr(wrapped_args[1], 'subproject'): |
| # Module objects have 2 args: self, interpreter |
| node = wrapped_args[1].current_node |
| # args and kwargs are inside the node |
| args = None |
| kwargs = None |
| subproject = wrapped_args[1].subproject |
| else: |
| raise AssertionError(f'Unknown args: {wrapped_args!r}') |
| elif n == 3: |
| # Methods on objects (*Holder, MesonMain, etc) have 3 args: self, args, kwargs |
| node = s.current_node |
| args = wrapped_args[1] |
| kwargs = wrapped_args[2] |
| if want_subproject: |
| if hasattr(s, 'subproject'): |
| subproject = s.subproject |
| elif hasattr(s, 'interpreter'): |
| subproject = s.interpreter.subproject |
| elif n == 4: |
| # Meson functions have 4 args: self, node, args, kwargs |
| # Module functions have 4 args: self, state, args, kwargs |
| from .interpreterbase import InterpreterBase # TODO: refactor to avoid this import |
| if isinstance(s, InterpreterBase): |
| node = wrapped_args[1] |
| else: |
| node = wrapped_args[1].current_node |
| args = wrapped_args[2] |
| kwargs = wrapped_args[3] |
| if want_subproject: |
| if isinstance(s, InterpreterBase): |
| subproject = s.subproject |
| else: |
| subproject = wrapped_args[1].subproject |
| else: |
| raise AssertionError(f'Unknown args: {wrapped_args!r}') |
| # Sometimes interpreter methods are called internally with None instead of |
| # empty list/dict |
| args = args if args is not None else [] |
| kwargs = kwargs if kwargs is not None else {} |
| return s, node, args, kwargs, subproject |