types: Use import typing as T

pull/6316/head
Daniel Mensinger 5 years ago
parent ab988198c7
commit 0302a697b8
No known key found for this signature in database
GPG Key ID: 54DD94C131E277D4
  1. 48
      mesonbuild/ast/introspection.py
  2. 4
      mesonbuild/ast/postprocess.py
  3. 102
      mesonbuild/interpreterbase.py
  4. 39
      mesonbuild/mparser.py

@ -23,7 +23,7 @@ from ..mesonlib import MachineChoice
from ..interpreterbase import InvalidArguments, TYPE_nvar from ..interpreterbase import InvalidArguments, TYPE_nvar
from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary from ..build import Executable, Jar, SharedLibrary, SharedModule, StaticLibrary
from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode
from typing import Any, Dict, List, Optional import typing as T
import os import os
build_target_functions = ['executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries'] build_target_functions = ['executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries']
@ -33,7 +33,7 @@ class IntrospectionHelper:
def __init__(self, cross_file: str) -> None: def __init__(self, cross_file: str) -> None:
self.cross_file = cross_file # type: str self.cross_file = cross_file # type: str
self.native_file = None # type: str self.native_file = None # type: str
self.cmd_line_options = {} # type: Dict[str, str] self.cmd_line_options = {} # type: T.Dict[str, str]
class IntrospectionInterpreter(AstInterpreter): class IntrospectionInterpreter(AstInterpreter):
# Interpreter to detect the options without a build directory # Interpreter to detect the options without a build directory
@ -42,11 +42,11 @@ class IntrospectionInterpreter(AstInterpreter):
source_root: str, source_root: str,
subdir: str, subdir: str,
backend: str, backend: str,
visitors: Optional[List[AstVisitor]] = None, visitors: T.Optional[T.List[AstVisitor]] = None,
cross_file: Optional[str] = None, cross_file: T.Optional[str] = None,
subproject: str = '', subproject: str = '',
subproject_dir: str = 'subprojects', subproject_dir: str = 'subprojects',
env: Optional[environment.Environment] = None) -> None: env: T.Optional[environment.Environment] = None) -> None:
visitors = visitors if visitors is not None else [] visitors = visitors if visitors is not None else []
super().__init__(source_root, subdir, subproject, visitors=visitors) super().__init__(source_root, subdir, subproject, visitors=visitors)
@ -61,9 +61,9 @@ class IntrospectionInterpreter(AstInterpreter):
self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
self.backend = backend self.backend = backend
self.default_options = {'backend': self.backend} self.default_options = {'backend': self.backend}
self.project_data = {} # type: Dict[str, Any] self.project_data = {} # type: T.Dict[str, T.Any]
self.targets = [] # type: List[Dict[str, Any]] self.targets = [] # type: T.List[T.Dict[str, T.Any]]
self.dependencies = [] # type: List[Dict[str, Any]] self.dependencies = [] # type: T.List[T.Dict[str, T.Any]]
self.project_node = None # type: BaseNode self.project_node = None # type: BaseNode
self.funcs.update({ self.funcs.update({
@ -79,7 +79,7 @@ class IntrospectionInterpreter(AstInterpreter):
'both_libraries': self.func_both_lib, 'both_libraries': self.func_both_lib,
}) })
def func_project(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> None: def func_project(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None:
if self.project_node: if self.project_node:
raise InvalidArguments('Second call to project()') raise InvalidArguments('Second call to project()')
self.project_node = node self.project_node = node
@ -136,7 +136,7 @@ class IntrospectionInterpreter(AstInterpreter):
except (mesonlib.MesonException, RuntimeError): except (mesonlib.MesonException, RuntimeError):
return return
def func_add_languages(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> None: def func_add_languages(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None:
args = self.flatten_args(args) args = self.flatten_args(args)
for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]: for for_machine in [MachineChoice.BUILD, MachineChoice.HOST]:
for lang in sorted(args, key=compilers.sort_clink): for lang in sorted(args, key=compilers.sort_clink):
@ -149,7 +149,7 @@ class IntrospectionInterpreter(AstInterpreter):
if lang not in self.coredata.compilers[for_machine]: if lang not in self.coredata.compilers[for_machine]:
self.environment.detect_compiler_for(lang, for_machine) self.environment.detect_compiler_for(lang, for_machine)
def func_dependency(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> None: def func_dependency(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> None:
args = self.flatten_args(args) args = self.flatten_args(args)
kwargs = self.flatten_kwargs(kwargs) kwargs = self.flatten_kwargs(kwargs)
if not args: if not args:
@ -173,7 +173,7 @@ class IntrospectionInterpreter(AstInterpreter):
'node': node 'node': node
}] }]
def build_target(self, node: BaseNode, args: List[TYPE_nvar], kwargs_raw: Dict[str, TYPE_nvar], targetclass) -> Optional[Dict[str, Any]]: def build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs_raw: T.Dict[str, TYPE_nvar], targetclass) -> T.Optional[T.Dict[str, T.Any]]:
args = self.flatten_args(args) args = self.flatten_args(args)
if not args or not isinstance(args[0], str): if not args or not isinstance(args[0], str):
return None return None
@ -186,7 +186,7 @@ class IntrospectionInterpreter(AstInterpreter):
kwargs = self.flatten_kwargs(kwargs_raw, True) kwargs = self.flatten_kwargs(kwargs_raw, True)
source_nodes = [] # type: List[BaseNode] source_nodes = [] # type: T.List[BaseNode]
while srcqueue: while srcqueue:
curr = srcqueue.pop(0) curr = srcqueue.pop(0)
arg_node = None arg_node = None
@ -221,8 +221,8 @@ class IntrospectionInterpreter(AstInterpreter):
kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()} kwargs_reduced = {k: v.value if isinstance(v, ElementaryNode) else v for k, v in kwargs_reduced.items()}
kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)} kwargs_reduced = {k: v for k, v in kwargs_reduced.items() if not isinstance(v, BaseNode)}
for_machine = MachineChoice.HOST for_machine = MachineChoice.HOST
objects = [] # type: List[Any] objects = [] # type: T.List[T.Any]
empty_sources = [] # type: List[Any] empty_sources = [] # type: T.List[T.Any]
# Passing the unresolved sources list causes errors # Passing the unresolved sources list causes errors
target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, objects, self.environment, kwargs_reduced) target = targetclass(name, self.subdir, self.subproject, for_machine, empty_sources, objects, self.environment, kwargs_reduced)
@ -243,7 +243,7 @@ class IntrospectionInterpreter(AstInterpreter):
self.targets += [new_target] self.targets += [new_target]
return new_target return new_target
def build_library(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def build_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
default_library = self.coredata.get_builtin_option('default_library') default_library = self.coredata.get_builtin_option('default_library')
if default_library == 'shared': if default_library == 'shared':
return self.build_target(node, args, kwargs, SharedLibrary) return self.build_target(node, args, kwargs, SharedLibrary)
@ -253,28 +253,28 @@ class IntrospectionInterpreter(AstInterpreter):
return self.build_target(node, args, kwargs, SharedLibrary) return self.build_target(node, args, kwargs, SharedLibrary)
return None return None
def func_executable(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_executable(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_target(node, args, kwargs, Executable) return self.build_target(node, args, kwargs, Executable)
def func_static_lib(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_static_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_target(node, args, kwargs, StaticLibrary) return self.build_target(node, args, kwargs, StaticLibrary)
def func_shared_lib(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_shared_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_target(node, args, kwargs, SharedLibrary) return self.build_target(node, args, kwargs, SharedLibrary)
def func_both_lib(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_both_lib(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_target(node, args, kwargs, SharedLibrary) return self.build_target(node, args, kwargs, SharedLibrary)
def func_shared_module(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_shared_module(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_target(node, args, kwargs, SharedModule) return self.build_target(node, args, kwargs, SharedModule)
def func_library(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_library(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_library(node, args, kwargs) return self.build_library(node, args, kwargs)
def func_jar(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_jar(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
return self.build_target(node, args, kwargs, Jar) return self.build_target(node, args, kwargs, Jar)
def func_build_target(self, node: BaseNode, args: List[TYPE_nvar], kwargs: Dict[str, TYPE_nvar]) -> Optional[Dict[str, Any]]: def func_build_target(self, node: BaseNode, args: T.List[TYPE_nvar], kwargs: T.Dict[str, TYPE_nvar]) -> T.Optional[T.Dict[str, T.Any]]:
if 'target_type' not in kwargs: if 'target_type' not in kwargs:
return None return None
target_type = kwargs.pop('target_type') target_type = kwargs.pop('target_type')

@ -17,7 +17,7 @@
from . import AstVisitor from . import AstVisitor
from .. import mparser from .. import mparser
from typing import Dict import typing as T
class AstIndentationGenerator(AstVisitor): class AstIndentationGenerator(AstVisitor):
def __init__(self) -> None: def __init__(self) -> None:
@ -77,7 +77,7 @@ class AstIndentationGenerator(AstVisitor):
class AstIDGenerator(AstVisitor): class AstIDGenerator(AstVisitor):
def __init__(self) -> None: def __init__(self) -> None:
self.counter = {} # type: Dict[str, int] self.counter = {} # type: T.Dict[str, int]
def visit_default_func(self, node: mparser.BaseNode) -> None: def visit_default_func(self, node: mparser.BaseNode) -> None:
name = type(node).__name__ name = type(node).__name__

@ -21,16 +21,16 @@ from . import environment, dependencies
import os, copy, re import os, copy, re
import collections.abc import collections.abc
from functools import wraps from functools import wraps
from typing import Any, Callable, ClassVar, Dict, Generic, List, Set, Sequence, Tuple, TypeVar, Optional, Union import typing as T
class InterpreterObject: class InterpreterObject:
def __init__(self): def __init__(self):
self.methods = {} # type: Dict[str, Callable] self.methods = {} # type: T.Dict[str, T.Callable]
# Current node set during a method call. This can be used as location # Current node set during a method call. This can be used as location
# when printing a warning message during a method call. # when printing a warning message during a method call.
self.current_node = None # type: mparser.BaseNode self.current_node = None # type: mparser.BaseNode
def method_call(self, method_name: str, args: List[Union[mparser.BaseNode, str, int, float, bool, list, dict, 'InterpreterObject', 'ObjectHolder']], kwargs: Dict[str, Union[mparser.BaseNode, str, int, float, bool, list, dict, 'InterpreterObject', 'ObjectHolder']]): def method_call(self, method_name: str, args: T.List[T.Union[mparser.BaseNode, str, int, float, bool, list, dict, 'InterpreterObject', 'ObjectHolder']], kwargs: T.Dict[str, T.Union[mparser.BaseNode, str, int, float, bool, list, dict, 'InterpreterObject', 'ObjectHolder']]):
if method_name in self.methods: if method_name in self.methods:
method = self.methods[method_name] method = self.methods[method_name]
if not getattr(method, 'no-args-flattening', False): if not getattr(method, 'no-args-flattening', False):
@ -38,24 +38,24 @@ class InterpreterObject:
return method(args, kwargs) return method(args, kwargs)
raise InvalidCode('Unknown method "%s" in object.' % method_name) raise InvalidCode('Unknown method "%s" in object.' % method_name)
TV_InterpreterObject = TypeVar('TV_InterpreterObject') TV_InterpreterObject = T.TypeVar('TV_InterpreterObject')
class ObjectHolder(Generic[TV_InterpreterObject]): class ObjectHolder(T.Generic[TV_InterpreterObject]):
def __init__(self, obj: InterpreterObject, subproject: Optional[str] = None): def __init__(self, obj: InterpreterObject, subproject: T.Optional[str] = None):
self.held_object = obj # type: InterpreterObject self.held_object = obj # type: InterpreterObject
self.subproject = subproject # type: str self.subproject = subproject # type: str
def __repr__(self): def __repr__(self):
return '<Holder: {!r}>'.format(self.held_object) return '<Holder: {!r}>'.format(self.held_object)
TYPE_elementary = Union[str, int, float, bool] TYPE_elementary = T.Union[str, int, float, bool]
TYPE_var = Union[TYPE_elementary, list, dict, InterpreterObject, ObjectHolder] TYPE_var = T.Union[TYPE_elementary, list, dict, InterpreterObject, ObjectHolder]
TYPE_nvar = Union[TYPE_var, mparser.BaseNode] TYPE_nvar = T.Union[TYPE_var, mparser.BaseNode]
TYPE_nkwargs = Dict[Union[mparser.BaseNode, str], TYPE_nvar] TYPE_nkwargs = T.Dict[T.Union[mparser.BaseNode, str], TYPE_nvar]
# Decorators for method calls. # Decorators for method calls.
def check_stringlist(a: Any, msg: str = 'Arguments must be strings.') -> None: def check_stringlist(a: T.Any, msg: str = 'Arguments must be strings.') -> None:
if not isinstance(a, list): if not isinstance(a, list):
mlog.debug('Not a list:', str(a)) mlog.debug('Not a list:', str(a))
raise InvalidArguments('Argument not a list.') raise InvalidArguments('Argument not a list.')
@ -124,13 +124,13 @@ def _get_callee_args(wrapped_args, want_subproject: bool = False):
kwargs = kwargs if kwargs is not None else {} kwargs = kwargs if kwargs is not None else {}
return s, node, args, kwargs, subproject return s, node, args, kwargs, subproject
def flatten(args: Union[TYPE_nvar, List[TYPE_nvar]]) -> List[TYPE_nvar]: def flatten(args: T.Union[TYPE_nvar, T.List[TYPE_nvar]]) -> T.List[TYPE_nvar]:
if isinstance(args, mparser.StringNode): if isinstance(args, mparser.StringNode):
assert isinstance(args.value, str) assert isinstance(args.value, str)
return [args.value] return [args.value]
if not isinstance(args, collections.abc.Sequence): if not isinstance(args, collections.abc.Sequence):
return [args] return [args]
result = [] # type: List[TYPE_nvar] result = [] # type: T.List[TYPE_nvar]
for a in args: for a in args:
if isinstance(a, list): if isinstance(a, list):
rest = flatten(a) rest = flatten(a)
@ -185,8 +185,8 @@ def disablerIfNotFound(f):
class permittedKwargs: class permittedKwargs:
def __init__(self, permitted: Set[str]) -> None: def __init__(self, permitted: T.Set[str]) -> None:
self.permitted = permitted # type: Set[str] self.permitted = permitted # type: T.Set[str]
def __call__(self, f): def __call__(self, f):
@wraps(f) @wraps(f)
@ -206,7 +206,7 @@ class FeatureCheckBase:
# Class variable, shared across all instances # Class variable, shared across all instances
# #
# Format: {subproject: {feature_version: set(feature_names)}} # Format: {subproject: {feature_version: set(feature_names)}}
feature_registry = {} # type: ClassVar[Dict[str, Dict[str, Set[str]]]] feature_registry = {} # type: T.ClassVar[T.Dict[str, T.Dict[str, T.Set[str]]]]
def __init__(self, feature_name: str, version: str) -> None: def __init__(self, feature_name: str, version: str) -> None:
self.feature_name = feature_name # type: str self.feature_name = feature_name # type: str
@ -293,7 +293,7 @@ class FeatureDeprecated(FeatureCheckBase):
class FeatureCheckKwargsBase: class FeatureCheckKwargsBase:
def __init__(self, feature_name: str, feature_version: str, kwargs: List[str]) -> None: def __init__(self, feature_name: str, feature_version: str, kwargs: T.List[str]) -> None:
self.feature_name = feature_name self.feature_name = feature_name
self.feature_version = feature_version self.feature_version = feature_version
self.kwargs = kwargs self.kwargs = kwargs
@ -377,11 +377,11 @@ class InterpreterBase:
def __init__(self, source_root: str, subdir: str, subproject: str) -> None: def __init__(self, source_root: str, subdir: str, subproject: str) -> None:
self.source_root = source_root self.source_root = source_root
self.funcs = {} # type: Dict[str, Callable[[mparser.BaseNode, List[TYPE_nvar], Dict[str, TYPE_nvar]], TYPE_var]] self.funcs = {} # type: T.Dict[str, T.Callable[[mparser.BaseNode, T.List[TYPE_nvar], T.Dict[str, TYPE_nvar]], TYPE_var]]
self.builtin = {} # type: Dict[str, InterpreterObject] self.builtin = {} # type: T.Dict[str, InterpreterObject]
self.subdir = subdir self.subdir = subdir
self.subproject = subproject self.subproject = subproject
self.variables = {} # type: Dict[str, TYPE_var] self.variables = {} # type: T.Dict[str, TYPE_var]
self.argument_depth = 0 self.argument_depth = 0
self.current_lineno = -1 self.current_lineno = -1
# Current node set during a function call. This can be used as location # Current node set during a function call. This can be used as location
@ -403,7 +403,7 @@ class InterpreterBase:
me.file = mesonfile me.file = mesonfile
raise me raise me
def join_path_strings(self, args: Sequence[str]) -> str: def join_path_strings(self, args: T.Sequence[str]) -> str:
return os.path.join(*args).replace('\\', '/') return os.path.join(*args).replace('\\', '/')
def parse_project(self) -> None: def parse_project(self) -> None:
@ -430,7 +430,7 @@ class InterpreterBase:
except SubdirDoneRequest: except SubdirDoneRequest:
pass pass
def evaluate_codeblock(self, node: mparser.CodeBlockNode, start: int = 0, end: Optional[int] = None) -> None: def evaluate_codeblock(self, node: mparser.CodeBlockNode, start: int = 0, end: T.Optional[int] = None) -> None:
if node is None: if node is None:
return return
if not isinstance(node, mparser.CodeBlockNode): if not isinstance(node, mparser.CodeBlockNode):
@ -454,7 +454,7 @@ class InterpreterBase:
raise e raise e
i += 1 # In THE FUTURE jump over blocks and stuff. i += 1 # In THE FUTURE jump over blocks and stuff.
def evaluate_statement(self, cur: mparser.BaseNode) -> Optional[TYPE_var]: def evaluate_statement(self, cur: mparser.BaseNode) -> T.Optional[TYPE_var]:
if isinstance(cur, mparser.FunctionNode): if isinstance(cur, mparser.FunctionNode):
return self.function_call(cur) return self.function_call(cur)
elif isinstance(cur, mparser.AssignmentNode): elif isinstance(cur, mparser.AssignmentNode):
@ -512,10 +512,10 @@ class InterpreterBase:
return arguments return arguments
@FeatureNew('dict', '0.47.0') @FeatureNew('dict', '0.47.0')
def evaluate_dictstatement(self, cur: mparser.DictNode) -> Dict[str, Any]: def evaluate_dictstatement(self, cur: mparser.DictNode) -> T.Dict[str, T.Any]:
(arguments, kwargs) = self.reduce_arguments(cur.args, resolve_key_nodes=False) (arguments, kwargs) = self.reduce_arguments(cur.args, resolve_key_nodes=False)
assert (not arguments) assert (not arguments)
result = {} # type: Dict[str, Any] result = {} # type: T.Dict[str, T.Any]
self.argument_depth += 1 self.argument_depth += 1
for key, value in kwargs.items(): for key, value in kwargs.items():
if not isinstance(key, mparser.StringNode): if not isinstance(key, mparser.StringNode):
@ -530,7 +530,7 @@ class InterpreterBase:
self.argument_depth -= 1 self.argument_depth -= 1
return result return result
def evaluate_notstatement(self, cur: mparser.NotNode) -> Union[bool, Disabler]: def evaluate_notstatement(self, cur: mparser.NotNode) -> T.Union[bool, Disabler]:
v = self.evaluate_statement(cur.value) v = self.evaluate_statement(cur.value)
if isinstance(v, Disabler): if isinstance(v, Disabler):
return v return v
@ -538,7 +538,7 @@ class InterpreterBase:
raise InterpreterException('Argument to "not" is not a boolean.') raise InterpreterException('Argument to "not" is not a boolean.')
return not v return not v
def evaluate_if(self, node: mparser.IfClauseNode) -> Optional[Disabler]: def evaluate_if(self, node: mparser.IfClauseNode) -> T.Optional[Disabler]:
assert(isinstance(node, mparser.IfClauseNode)) assert(isinstance(node, mparser.IfClauseNode))
for i in node.ifs: for i in node.ifs:
result = self.evaluate_statement(i.condition) result = self.evaluate_statement(i.condition)
@ -553,19 +553,19 @@ class InterpreterBase:
self.evaluate_codeblock(node.elseblock) self.evaluate_codeblock(node.elseblock)
return None return None
def validate_comparison_types(self, val1: Any, val2: Any) -> bool: def validate_comparison_types(self, val1: T.Any, val2: T.Any) -> bool:
if type(val1) != type(val2): if type(val1) != type(val2):
return False return False
return True return True
def evaluate_in(self, val1: Any, val2: Any) -> bool: def evaluate_in(self, val1: T.Any, val2: T.Any) -> bool:
if not isinstance(val1, (str, int, float, ObjectHolder)): if not isinstance(val1, (str, int, float, ObjectHolder)):
raise InvalidArguments('lvalue of "in" operator must be a string, integer, float, or object') raise InvalidArguments('lvalue of "in" operator must be a string, integer, float, or object')
if not isinstance(val2, (list, dict)): if not isinstance(val2, (list, dict)):
raise InvalidArguments('rvalue of "in" operator must be an array or a dict') raise InvalidArguments('rvalue of "in" operator must be an array or a dict')
return val1 in val2 return val1 in val2
def evaluate_comparison(self, node: mparser.ComparisonNode) -> Union[bool, Disabler]: def evaluate_comparison(self, node: mparser.ComparisonNode) -> T.Union[bool, Disabler]:
val1 = self.evaluate_statement(node.left) val1 = self.evaluate_statement(node.left)
if isinstance(val1, Disabler): if isinstance(val1, Disabler):
return val1 return val1
@ -610,7 +610,7 @@ The result of this is undefined and will become a hard error in a future Meson r
else: else:
raise InvalidCode('You broke my compare eval.') raise InvalidCode('You broke my compare eval.')
def evaluate_andstatement(self, cur: mparser.AndNode) -> Union[bool, Disabler]: def evaluate_andstatement(self, cur: mparser.AndNode) -> T.Union[bool, Disabler]:
l = self.evaluate_statement(cur.left) l = self.evaluate_statement(cur.left)
if isinstance(l, Disabler): if isinstance(l, Disabler):
return l return l
@ -625,7 +625,7 @@ The result of this is undefined and will become a hard error in a future Meson r
raise InterpreterException('Second argument to "and" is not a boolean.') raise InterpreterException('Second argument to "and" is not a boolean.')
return r return r
def evaluate_orstatement(self, cur: mparser.OrNode) -> Union[bool, Disabler]: def evaluate_orstatement(self, cur: mparser.OrNode) -> T.Union[bool, Disabler]:
l = self.evaluate_statement(cur.left) l = self.evaluate_statement(cur.left)
if isinstance(l, Disabler): if isinstance(l, Disabler):
return l return l
@ -640,7 +640,7 @@ The result of this is undefined and will become a hard error in a future Meson r
raise InterpreterException('Second argument to "or" is not a boolean.') raise InterpreterException('Second argument to "or" is not a boolean.')
return r return r
def evaluate_uminusstatement(self, cur) -> Union[int, Disabler]: def evaluate_uminusstatement(self, cur) -> T.Union[int, Disabler]:
v = self.evaluate_statement(cur.value) v = self.evaluate_statement(cur.value)
if isinstance(v, Disabler): if isinstance(v, Disabler):
return v return v
@ -656,7 +656,7 @@ The result of this is undefined and will become a hard error in a future Meson r
raise InvalidCode('The division operator can only append a string.') raise InvalidCode('The division operator can only append a string.')
return self.join_path_strings((l, r)) return self.join_path_strings((l, r))
def evaluate_division(self, l: Any, r: Any) -> Union[int, str]: def evaluate_division(self, l: T.Any, r: T.Any) -> T.Union[int, str]:
if isinstance(l, str) or isinstance(r, str): if isinstance(l, str) or isinstance(r, str):
return self.evaluate_path_join(l, r) return self.evaluate_path_join(l, r)
if isinstance(l, int) and isinstance(r, int): if isinstance(l, int) and isinstance(r, int):
@ -665,7 +665,7 @@ The result of this is undefined and will become a hard error in a future Meson r
return l // r return l // r
raise InvalidCode('Division works only with strings or integers.') raise InvalidCode('Division works only with strings or integers.')
def evaluate_arithmeticstatement(self, cur: mparser.ArithmeticNode) -> Union[int, str, dict, list, Disabler]: def evaluate_arithmeticstatement(self, cur: mparser.ArithmeticNode) -> T.Union[int, str, dict, list, Disabler]:
l = self.evaluate_statement(cur.left) l = self.evaluate_statement(cur.left)
if isinstance(l, Disabler): if isinstance(l, Disabler):
return l return l
@ -751,7 +751,7 @@ The result of this is undefined and will become a hard error in a future Meson r
# Remember that all variables are immutable. We must always create a # Remember that all variables are immutable. We must always create a
# full new variable and then assign it. # full new variable and then assign it.
old_variable = self.get_variable(varname) old_variable = self.get_variable(varname)
new_value = None # type: Union[str, int, float, bool, dict, list] new_value = None # type: T.Union[str, int, float, bool, dict, list]
if isinstance(old_variable, str): if isinstance(old_variable, str):
if not isinstance(addition, str): if not isinstance(addition, str):
raise InvalidArguments('The += operator requires a string on the right hand side if the variable on the left is a string') raise InvalidArguments('The += operator requires a string on the right hand side if the variable on the left is a string')
@ -803,14 +803,14 @@ The result of this is undefined and will become a hard error in a future Meson r
# We are already checking for the existance of __getitem__, so this should be save # We are already checking for the existance of __getitem__, so this should be save
raise InterpreterException('Index %d out of bounds of array of size %d.' % (index, len(iobject))) # type: ignore raise InterpreterException('Index %d out of bounds of array of size %d.' % (index, len(iobject))) # type: ignore
def function_call(self, node: mparser.FunctionNode) -> Optional[TYPE_var]: def function_call(self, node: mparser.FunctionNode) -> T.Optional[TYPE_var]:
func_name = node.func_name func_name = node.func_name
(posargs, kwargs) = self.reduce_arguments(node.args) (posargs, kwargs) = self.reduce_arguments(node.args)
if is_disabled(posargs, kwargs) and func_name != 'set_variable' and func_name != 'is_disabler': if is_disabled(posargs, kwargs) and func_name != 'set_variable' and func_name != 'is_disabler':
return Disabler() return Disabler()
if func_name in self.funcs: if func_name in self.funcs:
func = self.funcs[func_name] func = self.funcs[func_name]
func_args = posargs # type: Any func_args = posargs # type: T.Any
if not getattr(func, 'no-args-flattening', False): if not getattr(func, 'no-args-flattening', False):
func_args = flatten(posargs) func_args = flatten(posargs)
@ -859,7 +859,7 @@ The result of this is undefined and will become a hard error in a future Meson r
obj.current_node = node obj.current_node = node
return obj.method_call(method_name, args, self.kwargs_string_keys(kwargs)) return obj.method_call(method_name, args, self.kwargs_string_keys(kwargs))
def bool_method_call(self, obj: bool, method_name: str, posargs: List[TYPE_nvar]) -> Union[str, int]: def bool_method_call(self, obj: bool, method_name: str, posargs: T.List[TYPE_nvar]) -> T.Union[str, int]:
if method_name == 'to_string': if method_name == 'to_string':
if not posargs: if not posargs:
if obj: if obj:
@ -881,7 +881,7 @@ The result of this is undefined and will become a hard error in a future Meson r
else: else:
raise InterpreterException('Unknown method "%s" for a boolean.' % method_name) raise InterpreterException('Unknown method "%s" for a boolean.' % method_name)
def int_method_call(self, obj: int, method_name: str, posargs: List[TYPE_nvar]) -> Union[str, bool]: def int_method_call(self, obj: int, method_name: str, posargs: T.List[TYPE_nvar]) -> T.Union[str, bool]:
if method_name == 'is_even': if method_name == 'is_even':
if not posargs: if not posargs:
return obj % 2 == 0 return obj % 2 == 0
@ -901,7 +901,7 @@ The result of this is undefined and will become a hard error in a future Meson r
raise InterpreterException('Unknown method "%s" for an integer.' % method_name) raise InterpreterException('Unknown method "%s" for an integer.' % method_name)
@staticmethod @staticmethod
def _get_one_string_posarg(posargs: List[TYPE_nvar], method_name: str) -> str: def _get_one_string_posarg(posargs: T.List[TYPE_nvar], method_name: str) -> str:
if len(posargs) > 1: if len(posargs) > 1:
m = '{}() must have zero or one arguments' m = '{}() must have zero or one arguments'
raise InterpreterException(m.format(method_name)) raise InterpreterException(m.format(method_name))
@ -913,7 +913,7 @@ The result of this is undefined and will become a hard error in a future Meson r
return s return s
return None return None
def string_method_call(self, obj: str, method_name: str, posargs: List[TYPE_nvar]) -> Union[str, int, bool, List[str]]: def string_method_call(self, obj: str, method_name: str, posargs: T.List[TYPE_nvar]) -> T.Union[str, int, bool, T.List[str]]:
if method_name == 'strip': if method_name == 'strip':
s1 = self._get_one_string_posarg(posargs, 'strip') s1 = self._get_one_string_posarg(posargs, 'strip')
if s1 is not None: if s1 is not None:
@ -962,7 +962,7 @@ The result of this is undefined and will become a hard error in a future Meson r
return mesonlib.version_compare(obj, cmpr) return mesonlib.version_compare(obj, cmpr)
raise InterpreterException('Unknown method "%s" for a string.' % method_name) raise InterpreterException('Unknown method "%s" for a string.' % method_name)
def format_string(self, templ: str, args: List[TYPE_nvar]) -> str: def format_string(self, templ: str, args: T.List[TYPE_nvar]) -> str:
arg_strings = [] arg_strings = []
for arg in args: for arg in args:
if isinstance(arg, mparser.BaseNode): if isinstance(arg, mparser.BaseNode):
@ -982,7 +982,7 @@ The result of this is undefined and will become a hard error in a future Meson r
def unknown_function_called(self, func_name: str) -> None: def unknown_function_called(self, func_name: str) -> None:
raise InvalidCode('Unknown function "%s".' % func_name) raise InvalidCode('Unknown function "%s".' % func_name)
def array_method_call(self, obj: list, method_name: str, posargs: List[TYPE_nvar]) -> TYPE_var: def array_method_call(self, obj: list, method_name: str, posargs: T.List[TYPE_nvar]) -> TYPE_var:
if method_name == 'contains': if method_name == 'contains':
def check_contains(el: list) -> bool: def check_contains(el: list) -> bool:
if len(posargs) != 1: if len(posargs) != 1:
@ -1022,7 +1022,7 @@ The result of this is undefined and will become a hard error in a future Meson r
m = 'Arrays do not have a method called {!r}.' m = 'Arrays do not have a method called {!r}.'
raise InterpreterException(m.format(method_name)) raise InterpreterException(m.format(method_name))
def dict_method_call(self, obj: dict, method_name: str, posargs: List[TYPE_nvar]) -> TYPE_var: def dict_method_call(self, obj: dict, method_name: str, posargs: T.List[TYPE_nvar]) -> TYPE_var:
if method_name in ('has_key', 'get'): if method_name in ('has_key', 'get'):
if method_name == 'has_key': if method_name == 'has_key':
if len(posargs) != 1: if len(posargs) != 1:
@ -1058,15 +1058,15 @@ The result of this is undefined and will become a hard error in a future Meson r
raise InterpreterException('Dictionaries do not have a method called "%s".' % method_name) raise InterpreterException('Dictionaries do not have a method called "%s".' % method_name)
def reduce_arguments(self, args: mparser.ArgumentNode, resolve_key_nodes: bool = True) -> Tuple[List[TYPE_nvar], TYPE_nkwargs]: def reduce_arguments(self, args: mparser.ArgumentNode, resolve_key_nodes: bool = True) -> T.Tuple[T.List[TYPE_nvar], TYPE_nkwargs]:
assert(isinstance(args, mparser.ArgumentNode)) assert(isinstance(args, mparser.ArgumentNode))
if args.incorrect_order(): if args.incorrect_order():
raise InvalidArguments('All keyword arguments must be after positional arguments.') raise InvalidArguments('All keyword arguments must be after positional arguments.')
self.argument_depth += 1 self.argument_depth += 1
reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments] # type: List[TYPE_nvar] reduced_pos = [self.evaluate_statement(arg) for arg in args.arguments] # type: T.List[TYPE_nvar]
reduced_kw = {} # type: TYPE_nkwargs reduced_kw = {} # type: TYPE_nkwargs
for key, val in args.kwargs.items(): for key, val in args.kwargs.items():
reduced_key = key # type: Union[str, mparser.BaseNode] reduced_key = key # type: T.Union[str, mparser.BaseNode]
reduced_val = val # type: TYPE_nvar reduced_val = val # type: TYPE_nvar
if resolve_key_nodes and isinstance(key, mparser.IdNode): if resolve_key_nodes and isinstance(key, mparser.IdNode):
assert isinstance(key.value, str) assert isinstance(key.value, str)
@ -1092,8 +1092,8 @@ The result of this is undefined and will become a hard error in a future Meson r
kwargs[k] = v kwargs[k] = v
return kwargs return kwargs
def kwargs_string_keys(self, kwargs: TYPE_nkwargs) -> Dict[str, TYPE_nvar]: def kwargs_string_keys(self, kwargs: TYPE_nkwargs) -> T.Dict[str, TYPE_nvar]:
kw = {} # type: Dict[str, TYPE_nvar] kw = {} # type: T.Dict[str, TYPE_nvar]
for key, val in kwargs.items(): for key, val in kwargs.items():
if not isinstance(key, str): if not isinstance(key, str):
raise InterpreterException('Key of kwargs is not a string') raise InterpreterException('Key of kwargs is not a string')
@ -1137,7 +1137,7 @@ To specify a keyword argument, use : instead of =.''')
return self.variables[varname] return self.variables[varname]
raise InvalidCode('Unknown variable "%s".' % varname) raise InvalidCode('Unknown variable "%s".' % varname)
def is_assignable(self, value: Any) -> bool: def is_assignable(self, value: T.Any) -> bool:
return isinstance(value, (InterpreterObject, dependencies.Dependency, return isinstance(value, (InterpreterObject, dependencies.Dependency,
str, int, list, dict, mesonlib.File)) str, int, list, dict, mesonlib.File))

@ -17,11 +17,10 @@ import codecs
import textwrap import textwrap
import types import types
import typing as T import typing as T
from typing import Dict, Generic, Generator, List, Tuple, TypeVar, Optional, Union, TYPE_CHECKING
from .mesonlib import MesonException from .mesonlib import MesonException
from . import mlog from . import mlog
if TYPE_CHECKING: if T.TYPE_CHECKING:
from .ast import AstVisitor from .ast import AstVisitor
# This is the regex for the supported escape sequences of a regular string # This is the regex for the supported escape sequences of a regular string
@ -77,16 +76,16 @@ class BlockParseException(MesonException):
self.lineno = lineno self.lineno = lineno
self.colno = colno self.colno = colno
TV_TokenTypes = TypeVar('TV_TokenTypes', int, str, bool) TV_TokenTypes = T.TypeVar('TV_TokenTypes', int, str, bool)
class Token(Generic[TV_TokenTypes]): class Token(T.Generic[TV_TokenTypes]):
def __init__(self, tid: str, filename: str, line_start: int, lineno: int, colno: int, bytespan: Tuple[int, int], value: TV_TokenTypes) -> None: def __init__(self, tid: str, filename: str, line_start: int, lineno: int, colno: int, bytespan: T.Tuple[int, int], value: TV_TokenTypes) -> None:
self.tid = tid # type: str self.tid = tid # type: str
self.filename = filename # type: str self.filename = filename # type: str
self.line_start = line_start # type: int self.line_start = line_start # type: int
self.lineno = lineno # type: int self.lineno = lineno # type: int
self.colno = colno # type: int self.colno = colno # type: int
self.bytespan = bytespan # type: Tuple[int, int] self.bytespan = bytespan # type: T.Tuple[int, int]
self.value = value # type: TV_TokenTypes self.value = value # type: TV_TokenTypes
def __eq__(self, other) -> bool: def __eq__(self, other) -> bool:
@ -150,7 +149,7 @@ class Lexer:
col = 0 col = 0
while loc < len(self.code): while loc < len(self.code):
matched = False matched = False
value = None # type: Union[str, bool, int] value = None # type: T.Union[str, bool, int]
for (tid, reg) in self.token_specification: for (tid, reg) in self.token_specification:
mo = reg.match(self.code, loc) mo = reg.match(self.code, loc)
if mo: if mo:
@ -227,7 +226,7 @@ class Lexer:
raise ParseException('lexer', self.getline(line_start), lineno, col) raise ParseException('lexer', self.getline(line_start), lineno, col)
class BaseNode: class BaseNode:
def __init__(self, lineno: int, colno: int, filename: str, end_lineno: Optional[int] = None, end_colno: Optional[int] = None) -> None: def __init__(self, lineno: int, colno: int, filename: str, end_lineno: T.Optional[int] = None, end_colno: T.Optional[int] = None) -> None:
self.lineno = lineno # type: int self.lineno = lineno # type: int
self.colno = colno # type: int self.colno = colno # type: int
self.filename = filename # type: str self.filename = filename # type: str
@ -246,11 +245,11 @@ class BaseNode:
if callable(func): if callable(func):
func(self) func(self)
class ElementaryNode(Generic[TV_TokenTypes], BaseNode): class ElementaryNode(T.Generic[TV_TokenTypes], BaseNode):
def __init__(self, token: Token[TV_TokenTypes]) -> None: def __init__(self, token: Token[TV_TokenTypes]) -> None:
super().__init__(token.lineno, token.colno, token.filename) super().__init__(token.lineno, token.colno, token.filename)
self.value = token.value # type: TV_TokenTypes self.value = token.value # type: TV_TokenTypes
self.bytespan = token.bytespan # type: Tuple[int, int] self.bytespan = token.bytespan # type: T.Tuple[int, int]
class BooleanNode(ElementaryNode[bool]): class BooleanNode(ElementaryNode[bool]):
def __init__(self, token: Token[bool]) -> None: def __init__(self, token: Token[bool]) -> None:
@ -287,9 +286,9 @@ class BreakNode(ElementaryNode):
class ArgumentNode(BaseNode): class ArgumentNode(BaseNode):
def __init__(self, token: Token[TV_TokenTypes]) -> None: def __init__(self, token: Token[TV_TokenTypes]) -> None:
super().__init__(token.lineno, token.colno, token.filename) super().__init__(token.lineno, token.colno, token.filename)
self.arguments = [] # type: List[BaseNode] self.arguments = [] # type: T.List[BaseNode]
self.commas = [] # type: List[Token[TV_TokenTypes]] self.commas = [] # type: T.List[Token[TV_TokenTypes]]
self.kwargs = {} # type: Dict[BaseNode, BaseNode] self.kwargs = {} # type: T.Dict[BaseNode, BaseNode]
self.order_error = False self.order_error = False
def prepend(self, statement: BaseNode) -> None: def prepend(self, statement: BaseNode) -> None:
@ -374,7 +373,7 @@ class NotNode(BaseNode):
class CodeBlockNode(BaseNode): class CodeBlockNode(BaseNode):
def __init__(self, token: Token[TV_TokenTypes]) -> None: def __init__(self, token: Token[TV_TokenTypes]) -> None:
super().__init__(token.lineno, token.colno, token.filename) super().__init__(token.lineno, token.colno, token.filename)
self.lines = [] # type: List[BaseNode] self.lines = [] # type: T.List[BaseNode]
class IndexNode(BaseNode): class IndexNode(BaseNode):
def __init__(self, iobject: BaseNode, index: BaseNode) -> None: def __init__(self, iobject: BaseNode, index: BaseNode) -> None:
@ -412,9 +411,9 @@ class PlusAssignmentNode(BaseNode):
self.value = value # type: BaseNode self.value = value # type: BaseNode
class ForeachClauseNode(BaseNode): class ForeachClauseNode(BaseNode):
def __init__(self, token: Token, varnames: List[str], items: BaseNode, block: CodeBlockNode) -> None: def __init__(self, token: Token, varnames: T.List[str], items: BaseNode, block: CodeBlockNode) -> None:
super().__init__(token.lineno, token.colno, token.filename) super().__init__(token.lineno, token.colno, token.filename)
self.varnames = varnames # type: List[str] self.varnames = varnames # type: T.List[str]
self.items = items # type: BaseNode self.items = items # type: BaseNode
self.block = block # type: CodeBlockNode self.block = block # type: CodeBlockNode
@ -427,8 +426,8 @@ class IfNode(BaseNode):
class IfClauseNode(BaseNode): class IfClauseNode(BaseNode):
def __init__(self, linenode: BaseNode) -> None: def __init__(self, linenode: BaseNode) -> None:
super().__init__(linenode.lineno, linenode.colno, linenode.filename) super().__init__(linenode.lineno, linenode.colno, linenode.filename)
self.ifs = [] # type: List[IfNode] self.ifs = [] # type: T.List[IfNode]
self.elseblock = EmptyNode(linenode.lineno, linenode.colno, linenode.filename) # type: Union[EmptyNode, CodeBlockNode] self.elseblock = EmptyNode(linenode.lineno, linenode.colno, linenode.filename) # type: T.Union[EmptyNode, CodeBlockNode]
class UMinusNode(BaseNode): class UMinusNode(BaseNode):
def __init__(self, current_location: Token, value: BaseNode): def __init__(self, current_location: Token, value: BaseNode):
@ -722,7 +721,7 @@ class Parser:
self.expect('id') self.expect('id')
assert isinstance(t.value, str) assert isinstance(t.value, str)
varname = t varname = t
varnames = [t.value] # type: List[str] varnames = [t.value] # type: T.List[str]
if self.accept('comma'): if self.accept('comma'):
t = self.current t = self.current
@ -754,7 +753,7 @@ class Parser:
b = self.codeblock() b = self.codeblock()
clause.ifs.append(IfNode(s, s, b)) clause.ifs.append(IfNode(s, s, b))
def elseblock(self) -> Optional[CodeBlockNode]: def elseblock(self) -> T.Optional[CodeBlockNode]:
if self.accept('else'): if self.accept('else'):
self.expect('eol') self.expect('eol')
return self.codeblock() return self.codeblock()

Loading…
Cancel
Save