typing: more fixes

pull/7657/head
Daniel Mensinger 4 years ago
parent 1b19822a2d
commit 23818fc5a3
No known key found for this signature in database
GPG Key ID: 54DD94C131E277D4
  1. 3
      mesonbuild/ast/introspection.py
  2. 18
      mesonbuild/backend/backends.py
  3. 2
      mesonbuild/backend/ninjabackend.py
  4. 4
      mesonbuild/backend/vs2010backend.py
  5. 51
      mesonbuild/build.py
  6. 81
      mesonbuild/coredata.py
  7. 4
      mesonbuild/dependencies/boost.py
  8. 25
      mesonbuild/environment.py
  9. 42
      mesonbuild/interpreter.py
  10. 6
      mesonbuild/mcompile.py
  11. 8
      mesonbuild/mconf.py
  12. 19
      mesonbuild/mintro.py
  13. 12
      mesonbuild/modules/__init__.py
  14. 18
      mesonbuild/msetup.py
  15. 67
      mesonbuild/mtest.py
  16. 11
      mesonbuild/optinterpreter.py
  17. 2
      mesonbuild/scripts/depfixer.py
  18. 2
      mesonbuild/scripts/meson_exe.py
  19. 1
      run_mypy.py

@ -25,10 +25,11 @@ from ..build import BuildTarget, Executable, Jar, SharedLibrary, SharedModule, S
from ..mparser import BaseNode, ArithmeticNode, ArrayNode, ElementaryNode, IdNode, FunctionNode, StringNode
import typing as T
import os
import argparse
build_target_functions = ['executable', 'jar', 'library', 'shared_library', 'shared_module', 'static_library', 'both_libraries']
class IntrospectionHelper:
class IntrospectionHelper(argparse.Namespace):
# mimic an argparse namespace
def __init__(self, cross_file: str):
self.cross_file = cross_file # type: str

@ -36,7 +36,7 @@ from ..mesonlib import (
)
if T.TYPE_CHECKING:
from ..interpreter import Interpreter
from ..interpreter import Interpreter, Test
class TestProtocol(enum.Enum):
@ -104,7 +104,7 @@ class TargetInstallData:
class ExecutableSerialisation:
def __init__(self, cmd_args, env=None, exe_wrapper=None,
workdir=None, extra_paths=None, capture=None):
workdir=None, extra_paths=None, capture=None) -> None:
self.cmd_args = cmd_args
self.env = env or {}
if exe_wrapper is not None:
@ -182,11 +182,15 @@ class Backend:
self.interpreter = interpreter
self.environment = build.environment
self.processed_targets = {}
self.name = '<UNKNOWN>'
self.build_dir = self.environment.get_build_dir()
self.source_dir = self.environment.get_source_dir()
self.build_to_src = mesonlib.relpath(self.environment.get_source_dir(),
self.environment.get_build_dir())
def generate(self) -> None:
raise RuntimeError('generate is not implemented in {}'.format(type(self).__name__))
def get_target_filename(self, t, *, warn_multi_output: bool = True):
if isinstance(t, build.CustomTarget):
if warn_multi_output and len(t.get_outputs()) != 1:
@ -794,7 +798,7 @@ class Backend:
def write_test_file(self, datafile):
self.write_test_serialisation(self.build.get_tests(), datafile)
def create_test_serialisation(self, tests):
def create_test_serialisation(self, tests: T.List['Test']) -> T.List[TestSerialisation]:
arr = []
for t in sorted(tests, key=lambda tst: -1 * tst.priority):
exe = t.get_exe()
@ -864,7 +868,7 @@ class Backend:
arr.append(ts)
return arr
def write_test_serialisation(self, tests, datafile):
def write_test_serialisation(self, tests: T.List['Test'], datafile: str):
pickle.dump(self.create_test_serialisation(tests), datafile)
def construct_target_rel_path(self, a, workdir):
@ -1128,7 +1132,7 @@ class Backend:
cmd = [i.replace('\\', '/') for i in cmd]
return inputs, outputs, cmd
def run_postconf_scripts(self):
def run_postconf_scripts(self) -> None:
env = {'MESON_SOURCE_ROOT': self.environment.get_source_dir(),
'MESON_BUILD_ROOT': self.environment.get_build_dir(),
'MESONINTROSPECT': ' '.join([shlex.quote(x) for x in self.environment.get_build_command() + ['introspect']]),
@ -1140,7 +1144,7 @@ class Backend:
cmd = s['exe'] + s['args']
subprocess.check_call(cmd, env=child_env)
def create_install_data(self):
def create_install_data(self) -> InstallData:
strip_bin = self.environment.lookup_binary_entry(MachineChoice.HOST, 'strip')
if strip_bin is None:
if self.environment.is_cross_build():
@ -1338,7 +1342,7 @@ class Backend:
d.install_subdirs.append([src_dir, dst_dir, sd.install_mode,
sd.exclude])
def get_introspection_data(self, target_id, target):
def get_introspection_data(self, target_id: str, target: build.Target) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
'''
Returns a list of source dicts with the following format for a given target:
[

@ -2997,7 +2997,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '')
self.add_build(elem)
def get_introspection_data(self, target_id, target):
def get_introspection_data(self, target_id: str, target: build.Target) -> T.List[T.Dict[str, T.Union[bool, str, T.List[T.Union[str, T.Dict[str, T.Union[str, T.List[str], bool]]]]]]]:
if target_id not in self.introspection_data or len(self.introspection_data[target_id]) == 0:
return super().get_introspection_data(target_id, target)

@ -192,11 +192,11 @@ class Vs2010Backend(backends.Backend):
Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir())
@staticmethod
def get_regen_stampfile(build_dir):
def get_regen_stampfile(build_dir: str) -> None:
return os.path.join(os.path.join(build_dir, Environment.private_dir), 'regen.stamp')
@staticmethod
def touch_regen_timestamp(build_dir):
def touch_regen_timestamp(build_dir: str) -> None:
with open(Vs2010Backend.get_regen_stampfile(build_dir), 'w'):
pass

@ -37,6 +37,9 @@ from .compilers import (
from .linkers import StaticLinker
from .interpreterbase import FeatureNew
if T.TYPE_CHECKING:
from .interpreter import Test
pch_kwargs = set(['c_pch', 'cpp_pch'])
lang_arg_kwargs = set([
@ -128,14 +131,14 @@ class Build:
self.project_version = None
self.environment = environment
self.projects = {}
self.targets = OrderedDict()
self.targets = OrderedDict() # type: T.Dict[str, 'Target']
self.run_target_names = set() # type: T.Set[T.Tuple[str, str]]
self.global_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.projects_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.global_link_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.projects_link_args = PerMachine({}, {}) # type: PerMachine[T.Dict[str, T.List[str]]]
self.tests = []
self.benchmarks = []
self.tests = [] # type: T.List['Test']
self.benchmarks = [] # type: T.List['Test']
self.headers = []
self.man = []
self.data = []
@ -178,13 +181,13 @@ class Build:
def get_subproject_dir(self):
return self.subproject_dir
def get_targets(self):
def get_targets(self) -> T.Dict[str, 'Target']:
return self.targets
def get_tests(self):
def get_tests(self) -> T.List['Test']:
return self.tests
def get_benchmarks(self):
def get_benchmarks(self) -> T.List['Test']:
return self.benchmarks
def get_headers(self):
@ -403,13 +406,13 @@ a hard error in the future.'''.format(name))
outdirs[0] = default_install_dir
return outdirs, custom_install_dir
def get_basename(self):
def get_basename(self) -> str:
return self.name
def get_subdir(self):
def get_subdir(self) -> str:
return self.subdir
def get_typename(self):
def get_typename(self) -> str:
return self.typename
@staticmethod
@ -423,7 +426,7 @@ a hard error in the future.'''.format(name))
return h.hexdigest()[:7]
@staticmethod
def construct_id_from_path(subdir, name, type_suffix):
def construct_id_from_path(subdir: str, name: str, type_suffix: str) -> str:
"""Construct target ID from subdir, name and type suffix.
This helper function is made public mostly for tests."""
@ -441,7 +444,7 @@ a hard error in the future.'''.format(name))
return subdir_part + '@@' + my_id
return my_id
def get_id(self):
def get_id(self) -> str:
return self.construct_id_from_path(
self.subdir, self.name, self.type_suffix())
@ -480,6 +483,12 @@ a hard error in the future.'''.format(name))
def is_linkable_target(self) -> bool:
return False
def get_outputs(self) -> T.List[str]:
return []
def should_install(self) -> bool:
return False
class BuildTarget(Target):
known_kwargs = known_build_target_kwargs
@ -1006,7 +1015,7 @@ This will become a hard error in a future Meson release.''')
def get_filename(self):
return self.filename
def get_outputs(self):
def get_outputs(self) -> T.List[str]:
return self.outputs
def get_extra_args(self, language):
@ -1036,7 +1045,7 @@ This will become a hard error in a future Meson release.''')
def get_generated_sources(self):
return self.generated
def should_install(self):
def should_install(self) -> bool:
return self.need_install
def has_pch(self):
@ -1474,7 +1483,7 @@ class GeneratedList:
def get_inputs(self):
return self.infilelist
def get_outputs(self):
def get_outputs(self) -> T.List[str]:
return self.outfilelist
def get_outputs_for(self, filename):
@ -2192,7 +2201,7 @@ class CustomTarget(Target):
def get_dependencies(self):
return self.dependencies
def should_install(self):
def should_install(self) -> bool:
return self.install
def get_custom_install_dir(self):
@ -2201,7 +2210,7 @@ class CustomTarget(Target):
def get_custom_install_mode(self):
return self.install_mode
def get_outputs(self):
def get_outputs(self) -> T.List[str]:
return self.outputs
def get_filename(self):
@ -2289,13 +2298,13 @@ class RunTarget(Target):
def get_sources(self):
return []
def should_install(self):
def should_install(self) -> bool:
return False
def get_filename(self):
def get_filename(self) -> str:
return self.name
def get_outputs(self):
def get_outputs(self) -> T.List[str]:
if isinstance(self.name, str):
return [self.name]
elif isinstance(self.name, list):
@ -2367,7 +2376,7 @@ class CustomTargetIndex:
return '<CustomTargetIndex: {!r}[{}]>'.format(
self.target, self.target.get_outputs().index(self.output))
def get_outputs(self):
def get_outputs(self) -> T.List[str]:
return [self.output]
def get_subdir(self):
@ -2509,6 +2518,6 @@ def load(build_dir: str) -> Build:
raise MesonException(load_fail_msg)
return obj
def save(obj, filename):
def save(obj: Build, filename: str) -> None:
with open(filename, 'wb') as f:
pickle.dump(obj, f)

@ -47,7 +47,7 @@ _T = T.TypeVar('_T')
class MesonVersionMismatchException(MesonException):
'''Build directory generated with Meson version incompatible with current version'''
def __init__(self, old_version, current_version):
def __init__(self, old_version: str, current_version: str) -> None:
super().__init__('Build directory has been generated with Meson version {}, '
'which is incompatible with current version {}.'
.format(old_version, current_version))
@ -56,7 +56,7 @@ class MesonVersionMismatchException(MesonException):
class UserOption(T.Generic[_T]):
def __init__(self, description, choices, yielding):
def __init__(self, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], yielding: T.Optional[bool]):
super().__init__()
self.choices = choices
self.description = description
@ -66,7 +66,8 @@ class UserOption(T.Generic[_T]):
raise MesonException('Value of "yielding" must be a boolean.')
self.yielding = yielding
def printable_value(self):
def printable_value(self) -> T.Union[str, int, bool, T.List[T.Union[str, int, bool]]]:
assert isinstance(self.value, (str, int, bool, list))
return self.value
# Check that the input is a valid value and return the
@ -75,30 +76,32 @@ class UserOption(T.Generic[_T]):
def validate_value(self, value: T.Any) -> _T:
raise RuntimeError('Derived option class did not override validate_value.')
def set_value(self, newvalue):
def set_value(self, newvalue: T.Any) -> None:
self.value = self.validate_value(newvalue)
class UserStringOption(UserOption[str]):
def __init__(self, description, value, choices=None, yielding=None):
super().__init__(description, choices, yielding)
def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
super().__init__(description, None, yielding)
self.set_value(value)
def validate_value(self, value):
def validate_value(self, value: T.Any) -> str:
if not isinstance(value, str):
raise MesonException('Value "%s" for string option is not a string.' % str(value))
return value
class UserBooleanOption(UserOption[bool]):
def __init__(self, description, value, yielding=None):
def __init__(self, description: str, value, yielding: T.Optional[bool] = None) -> None:
super().__init__(description, [True, False], yielding)
self.set_value(value)
def __bool__(self) -> bool:
return self.value
def validate_value(self, value) -> bool:
def validate_value(self, value: T.Any) -> bool:
if isinstance(value, bool):
return value
if not isinstance(value, str):
raise MesonException('Value {} cannot be converted to a boolean'.format(value))
if value.lower() == 'true':
return True
if value.lower() == 'false':
@ -106,7 +109,7 @@ class UserBooleanOption(UserOption[bool]):
raise MesonException('Value %s is not boolean (true or false).' % value)
class UserIntegerOption(UserOption[int]):
def __init__(self, description, value, yielding=None):
def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
min_value, max_value, default_value = value
self.min_value = min_value
self.max_value = max_value
@ -119,7 +122,7 @@ class UserIntegerOption(UserOption[int]):
super().__init__(description, choices, yielding)
self.set_value(default_value)
def validate_value(self, value) -> int:
def validate_value(self, value: T.Any) -> int:
if isinstance(value, str):
value = self.toint(value)
if not isinstance(value, int):
@ -130,35 +133,35 @@ class UserIntegerOption(UserOption[int]):
raise MesonException('New value %d is more than maximum value %d.' % (value, self.max_value))
return value
def toint(self, valuestring) -> int:
def toint(self, valuestring: str) -> int:
try:
return int(valuestring)
except ValueError:
raise MesonException('Value string "%s" is not convertible to an integer.' % valuestring)
class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, int]]):
def __init__(self, description, value, yielding=None):
def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
super().__init__(description, (0, 0o777, value), yielding)
self.choices = ['preserve', '0000-0777']
def printable_value(self):
def printable_value(self) -> str:
if self.value == 'preserve':
return self.value
return format(self.value, '04o')
def validate_value(self, value):
def validate_value(self, value: T.Any) -> T.Union[str, int]:
if value is None or value == 'preserve':
return 'preserve'
return super().validate_value(value)
def toint(self, valuestring):
def toint(self, valuestring: T.Union[str, int]) -> int:
try:
return int(valuestring, 8)
except ValueError as e:
raise MesonException('Invalid mode: {}'.format(e))
class UserComboOption(UserOption[str]):
def __init__(self, description, choices: T.List[str], value, yielding=None):
def __init__(self, description: str, choices: T.List[str], value: T.Any, yielding: T.Optional[bool] = None):
super().__init__(description, choices, yielding)
if not isinstance(self.choices, list):
raise MesonException('Combo choices must be an array.')
@ -167,7 +170,7 @@ class UserComboOption(UserOption[str]):
raise MesonException('Combo choice elements must be strings.')
self.set_value(value)
def validate_value(self, value):
def validate_value(self, value: T.Any) -> str:
if value not in self.choices:
if isinstance(value, bool):
_type = 'boolean'
@ -182,13 +185,13 @@ class UserComboOption(UserOption[str]):
return value
class UserArrayOption(UserOption[T.List[str]]):
def __init__(self, description, value, split_args=False, user_input=False, allow_dups=False, **kwargs):
def __init__(self, description: str, value: T.Union[str, T.List[str]], split_args: bool = False, user_input: bool = False, allow_dups: bool = False, **kwargs: T.Any) -> None:
super().__init__(description, kwargs.get('choices', []), yielding=kwargs.get('yielding', None))
self.split_args = split_args
self.allow_dups = allow_dups
self.value = self.validate_value(value, user_input=user_input)
def validate_value(self, value, user_input: bool = True) -> T.List[str]:
def validate_value(self, value: T.Union[str, T.List[str]], user_input: bool = True) -> T.List[str]:
# User input is for options defined on the command line (via -D
# options). Users can put their input in as a comma separated
# string, but for defining options in meson_options.txt the format
@ -232,16 +235,16 @@ class UserArrayOption(UserOption[T.List[str]]):
class UserFeatureOption(UserComboOption):
static_choices = ['enabled', 'disabled', 'auto']
def __init__(self, description, value, yielding=None):
def __init__(self, description: str, value: T.Any, yielding: T.Optional[bool] = None):
super().__init__(description, self.static_choices, value, yielding)
def is_enabled(self):
def is_enabled(self) -> bool:
return self.value == 'enabled'
def is_disabled(self):
def is_disabled(self) -> bool:
return self.value == 'disabled'
def is_auto(self):
def is_auto(self) -> bool:
return self.value == 'auto'
if T.TYPE_CHECKING:
@ -534,7 +537,7 @@ class CoreData:
value = None
opts_map[optname] = opt.init_option(key, value, default_prefix())
def init_backend_options(self, backend_name):
def init_backend_options(self, backend_name: str) -> None:
if backend_name == 'ninja':
self.backend_options['backend_max_links'] = \
UserIntegerOption(
@ -547,7 +550,7 @@ class CoreData:
'Default project to execute in Visual Studio',
'')
def get_builtin_option(self, optname, subproject=''):
def get_builtin_option(self, optname: str, subproject: str = '') -> T.Union[str, int, bool]:
raw_optname = optname
if subproject:
optname = subproject + ':' + optname
@ -683,7 +686,7 @@ class CoreData:
def get_external_link_args(self, for_machine: MachineChoice, lang):
return self.compiler_options[for_machine][lang]['link_args'].value
def merge_user_options(self, options):
def merge_user_options(self, options: T.Dict[str, T.Union[str, bool, int]]) -> None:
for (name, value) in options.items():
if name not in self.user_options:
self.user_options[name] = value
@ -715,7 +718,7 @@ class CoreData:
if k in build_opts:
build_opts[k].set_value(o.value)
def set_options(self, options, *, subproject='', warn_unknown=True):
def set_options(self, options: T.Dict[str, T.Any], subproject: str = '', warn_unknown: bool = True) -> None:
if not self.is_cross_build():
options = self.strip_build_option_names(options)
# Set prefix first because it's needed to sanitize other options
@ -912,10 +915,10 @@ def parse_machine_files(filenames):
parser = MachineFileParser(filenames)
return parser.sections
def get_cmd_line_file(build_dir):
def get_cmd_line_file(build_dir: str) -> str:
return os.path.join(build_dir, 'meson-private', 'cmd_line.txt')
def read_cmd_line_file(build_dir, options):
def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
filename = get_cmd_line_file(build_dir)
if not os.path.isfile(filename):
return
@ -937,10 +940,10 @@ def read_cmd_line_file(build_dir, options):
# literal_eval to get it into the list of strings.
options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
def cmd_line_options_to_string(options):
def cmd_line_options_to_string(options: argparse.Namespace) -> T.Dict[str, str]:
return {k: str(v) for k, v in options.cmd_line_options.items()}
def write_cmd_line_file(build_dir, options):
def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser()
@ -955,7 +958,7 @@ def write_cmd_line_file(build_dir, options):
with open(filename, 'w') as f:
config.write(f)
def update_cmd_line_file(build_dir, options):
def update_cmd_line_file(build_dir: str, options: argparse.Namespace):
filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser()
config.read(filename)
@ -963,7 +966,7 @@ def update_cmd_line_file(build_dir, options):
with open(filename, 'w') as f:
config.write(f)
def get_cmd_line_options(build_dir, options):
def get_cmd_line_options(build_dir: str, options: argparse.Namespace) -> str:
copy = argparse.Namespace(**vars(options))
read_cmd_line_file(build_dir, copy)
cmdline = ['-D{}={}'.format(k, v) for k, v in copy.cmd_line_options.items()]
@ -976,7 +979,7 @@ def get_cmd_line_options(build_dir, options):
def major_versions_differ(v1, v2):
return v1.split('.')[0:2] != v2.split('.')[0:2]
def load(build_dir):
def load(build_dir: str) -> CoreData:
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
load_fail_msg = 'Coredata file {!r} is corrupted. Try with a fresh build tree.'.format(filename)
try:
@ -995,7 +998,7 @@ def load(build_dir):
raise MesonVersionMismatchException(obj.version, version)
return obj
def save(obj, build_dir):
def save(obj: CoreData, build_dir: str) -> str:
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
prev_filename = filename + '.prev'
tempfilename = filename + '~'
@ -1012,7 +1015,7 @@ def save(obj, build_dir):
return filename
def register_builtin_arguments(parser):
def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
for n, b in BUILTIN_OPTIONS.items():
b.add_to_argparse(n, parser, '', '')
for n, b in BUILTIN_OPTIONS_PER_MACHINE.items():
@ -1021,7 +1024,7 @@ def register_builtin_arguments(parser):
parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
help='Set the value of an option, can be used several times to set multiple options.')
def create_options_dict(options):
def create_options_dict(options: T.List[str]) -> T.Dict[str, str]:
result = OrderedDict()
for o in options:
try:
@ -1031,7 +1034,7 @@ def create_options_dict(options):
result[key] = value
return result
def parse_cmd_line_options(args):
def parse_cmd_line_options(args: argparse.Namespace) -> None:
args.cmd_line_options = create_options_dict(args.projectoptions)
# Merge builtin options set with --option into the dict.

@ -341,7 +341,9 @@ class BoostLibraryFile():
class BoostDependency(ExternalDependency):
def __init__(self, environment: Environment, kwargs: T.Dict[str, T.Any]) -> None:
super().__init__('boost', environment, kwargs, language='cpp')
self.debug = environment.coredata.get_builtin_option('buildtype').startswith('debug')
buildtype = environment.coredata.get_builtin_option('buildtype')
assert isinstance(buildtype, str)
self.debug = buildtype.startswith('debug')
self.multithreading = kwargs.get('threading', 'multi') == 'multi'
self.boost_root = None # type: Path

@ -132,6 +132,9 @@ build_filename = 'meson.build'
CompilersDict = T.Dict[str, Compiler]
if T.TYPE_CHECKING:
import argparse
def detect_gcovr(min_version='3.3', new_rootdir_version='4.2', log=False):
gcovr_exe = 'gcovr'
try:
@ -153,7 +156,7 @@ def detect_llvm_cov():
return tool
return None
def find_coverage_tools():
def find_coverage_tools() -> T.Tuple[T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str], T.Optional[str]]:
gcovr_exe, gcovr_new_rootdir = detect_gcovr()
llvm_cov_exe = detect_llvm_cov()
@ -522,7 +525,7 @@ class Environment:
log_dir = 'meson-logs'
info_dir = 'meson-info'
def __init__(self, source_dir, build_dir, options):
def __init__(self, source_dir: T.Optional[str], build_dir: T.Optional[str], options: 'argparse.Namespace') -> None:
self.source_dir = source_dir
self.build_dir = build_dir
# Do not try to create build directories when build_dir is none.
@ -535,7 +538,7 @@ class Environment:
os.makedirs(self.log_dir, exist_ok=True)
os.makedirs(self.info_dir, exist_ok=True)
try:
self.coredata = coredata.load(self.get_build_dir())
self.coredata = coredata.load(self.get_build_dir()) # type: coredata.CoreData
self.first_invocation = False
except FileNotFoundError:
self.create_new_coredata(options)
@ -807,7 +810,7 @@ class Environment:
self.default_pkgconfig = ['pkg-config']
self.wrap_resolver = None
def create_new_coredata(self, options):
def create_new_coredata(self, options: 'argparse.Namespace') -> None:
# WARNING: Don't use any values from coredata in __init__. It gets
# re-initialized with project options by the interpreter during
# build file parsing.
@ -819,17 +822,17 @@ class Environment:
def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
return self.coredata.is_cross_build(when_building_for)
def dump_coredata(self):
def dump_coredata(self) -> str:
return coredata.save(self.coredata, self.get_build_dir())
def get_script_dir(self):
def get_script_dir(self) -> str:
import mesonbuild.scripts
return os.path.dirname(mesonbuild.scripts.__file__)
def get_log_dir(self):
def get_log_dir(self) -> str:
return self.log_dir
def get_coredata(self):
def get_coredata(self) -> coredata.CoreData:
return self.coredata
def get_build_command(self, unbuffered=False):
@ -1535,7 +1538,7 @@ class Environment:
self._handle_exceptions(popen_exceptions, compilers)
def get_scratch_dir(self):
def get_scratch_dir(self) -> str:
return self.scratch_dir
def detect_objc_compiler(self, for_machine: MachineInfo) -> 'Compiler':
@ -1974,10 +1977,10 @@ class Environment:
self._handle_exceptions(popen_exceptions, linkers, 'linker')
raise EnvironmentException('Unknown static linker "{}"'.format(' '.join(linkers)))
def get_source_dir(self):
def get_source_dir(self) -> str:
return self.source_dir
def get_build_dir(self):
def get_build_dir(self) -> str:
return self.build_dir
def get_import_lib_dir(self) -> str:

@ -31,9 +31,10 @@ from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler, disablerIfNotFound
from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs, FeatureDeprecatedKwargs
from .interpreterbase import ObjectHolder, MesonVersionString
from .modules import ModuleReturnValue
from .interpreterbase import TYPE_var, TYPE_nkwargs
from .modules import ModuleReturnValue, ExtensionModule
from .cmake import CMakeInterpreter
from .backend.backends import TestProtocol
from .backend.backends import TestProtocol, Backend
from pathlib import Path, PurePath
import os
@ -673,22 +674,22 @@ class MachineHolder(InterpreterObject, ObjectHolder):
@noPosargs
@permittedKwargs({})
def cpu_family_method(self, args, kwargs):
def cpu_family_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
return self.held_object.cpu_family
@noPosargs
@permittedKwargs({})
def cpu_method(self, args, kwargs):
def cpu_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
return self.held_object.cpu
@noPosargs
@permittedKwargs({})
def system_method(self, args, kwargs):
def system_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
return self.held_object.system
@noPosargs
@permittedKwargs({})
def endian_method(self, args, kwargs):
def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str:
return self.held_object.endian
class IncludeDirsHolder(InterpreterObject, ObjectHolder):
@ -2333,8 +2334,18 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
class Interpreter(InterpreterBase):
def __init__(self, build, backend=None, subproject='', subdir='', subproject_dir='subprojects',
modules = None, default_project_options=None, mock=False, ast=None):
def __init__(
self,
build: build.Build,
backend: T.Optional[Backend] = None,
subproject: str = '',
subdir: str = '',
subproject_dir: str = 'subprojects',
modules: T.Optional[T.Dict[str, ExtensionModule]] = None,
default_project_options: T.Optional[T.Dict[str, str]] = None,
mock: bool = False,
ast: T.Optional[mparser.CodeBlockNode] = None,
) -> None:
super().__init__(build.environment.get_source_dir(), subdir, subproject)
self.an_unpicklable_object = mesonlib.an_unpicklable_object
self.build = build
@ -2396,7 +2407,8 @@ class Interpreter(InterpreterBase):
self.builtin['target_machine'] = \
MachineHolder(self.build.environment.machines.target)
def get_non_matching_default_options(self):
# TODO: Why is this in interpreter.py and not CoreData or Environment?
def get_non_matching_default_options(self) -> T.Iterator[T.Tuple[str, str, coredata.UserOption]]:
env = self.environment
for def_opt_name, def_opt_value in self.project_default_options.items():
for opts in env.coredata.get_all_options():
@ -2530,7 +2542,7 @@ class Interpreter(InterpreterBase):
self.process_new_values(invalues)
return self.holderify(return_object.return_value)
def get_build_def_files(self):
def get_build_def_files(self) -> T.List[str]:
return self.build_def_files
def add_build_def_file(self, f):
@ -2599,7 +2611,9 @@ class Interpreter(InterpreterBase):
module = importlib.import_module('mesonbuild.modules.' + modname)
except ImportError:
raise InvalidArguments('Module "%s" does not exist' % (modname, ))
self.modules[modname] = module.initialize(self)
ext_module = module.initialize(self)
assert isinstance(ext_module, ExtensionModule)
self.modules[modname] = ext_module
@stringArgs
@noKwargs
@ -4598,7 +4612,7 @@ different subdirectory.
def func_join_paths(self, node, args, kwargs):
return self.join_path_strings(args)
def run(self):
def run(self) -> None:
super().run()
mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets))))
FeatureNew.report(self.subproject)
@ -4608,14 +4622,14 @@ different subdirectory.
if self.subproject == '':
self._print_summary()
def print_extra_warnings(self):
def print_extra_warnings(self) -> None:
# TODO cross compilation
for c in self.coredata.compilers.host.values():
if c.get_id() == 'clang':
self.check_clang_asan_lundef()
break
def check_clang_asan_lundef(self):
def check_clang_asan_lundef(self) -> None:
if 'b_lundef' not in self.coredata.base_options:
return
if 'b_sanitize' not in self.coredata.base_options:

@ -32,7 +32,7 @@ if T.TYPE_CHECKING:
import argparse
def array_arg(value: str) -> T.List[str]:
return T.cast(T.List[str], UserArrayOption(None, value, allow_dups=True, user_input=True).value)
return UserArrayOption(None, value, allow_dups=True, user_input=True).value
def validate_builddir(builddir: Path) -> None:
if not (builddir / 'meson-private' / 'coredata.dat' ).is_file():
@ -45,7 +45,9 @@ def get_backend_from_coredata(builddir: Path) -> str:
"""
Gets `backend` option value from coredata
"""
return T.cast(str, coredata.load(str(builddir)).get_builtin_option('backend'))
backend = coredata.load(str(builddir)).get_builtin_option('backend')
assert isinstance(backend, str)
return backend
def parse_introspect_data(builddir: Path) -> T.Dict[str, T.List[dict]]:
"""

@ -15,15 +15,19 @@
import os
from . import coredata, environment, mesonlib, build, mintro, mlog
from .ast import AstIDGenerator
import typing as T
def add_arguments(parser):
if T.TYPE_CHECKING:
import argparse
def add_arguments(parser: 'argparse.ArgumentParser') -> None:
coredata.register_builtin_arguments(parser)
parser.add_argument('builddir', nargs='?', default='.')
parser.add_argument('--clearcache', action='store_true', default=False,
help='Clear cached state (e.g. found dependencies)')
def make_lower_case(val):
def make_lower_case(val: T.Any) -> T.Union[str, T.List[T.Any]]: # T.Any because of recursion...
if isinstance(val, bool):
return str(val).lower()
elif isinstance(val, list):

@ -254,11 +254,9 @@ def list_buildoptions(coredata: cdata.CoreData, subprojects: T.Optional[T.List[s
'compiler',
machine='host',
)
tmp_dict = dict(coredata.flatten_lang_iterator(coredata.compiler_options.build.items())) # type: T.Dict[str, cdata.UserOption]
add_keys(
{
'build.' + k: o for k, o in
coredata.flatten_lang_iterator(coredata.compiler_options.build.items())
},
{'build.' + k: o for k, o in tmp_dict.items()},
'compiler',
machine='build',
)
@ -305,10 +303,10 @@ def list_deps(coredata: cdata.CoreData) -> T.List[T.Dict[str, T.Union[str, T.Lis
'link_args': d.get_link_args()}]
return result
def get_test_list(testdata: backends.TestSerialisation) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
def get_test_list(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
result = [] # type: T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]
for t in testdata:
to = {}
to = {} # type: T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]
if isinstance(t.fname, str):
fname = [t.fname]
else:
@ -329,21 +327,21 @@ def get_test_list(testdata: backends.TestSerialisation) -> T.List[T.Dict[str, T.
result.append(to)
return result
def list_tests(testdata: backends.TestSerialisation) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
def list_tests(testdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
return get_test_list(testdata)
def list_benchmarks(benchdata: backends.TestSerialisation) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
def list_benchmarks(benchdata: T.List[backends.TestSerialisation]) -> T.List[T.Dict[str, T.Union[str, int, T.List[str], T.Dict[str, str]]]]:
return get_test_list(benchdata)
def list_projinfo(builddata: build.Build) -> T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]:
result = {'version': builddata.project_version,
'descriptive_name': builddata.project_name,
'subproject_dir': builddata.subproject_dir}
'subproject_dir': builddata.subproject_dir} # type: T.Dict[str, T.Union[str, T.List[T.Dict[str, str]]]]
subprojects = []
for k, v in builddata.subprojects.items():
c = {'name': k,
'version': v,
'descriptive_name': builddata.projects.get(k)}
'descriptive_name': builddata.projects.get(k)} # type: T.Dict[str, str]
subprojects.append(c)
result['subprojects'] = subprojects
return result
@ -391,6 +389,7 @@ def run(options: argparse.Namespace) -> int:
# Make sure that log entries in other parts of meson don't interfere with the JSON output
mlog.disable()
backend = backends.get_backend_from_name(options.backend)
assert backend is not None
intr = IntrospectionInterpreter(sourcedir, '', backend.name, visitors = [AstIDGenerator(), AstIndentationGenerator(), AstConditionLevel()])
intr.analyze()
# Re-enable logging just in case

@ -19,14 +19,18 @@ import os
from .. import build
from ..mesonlib import unholder
import typing as T
if T.TYPE_CHECKING:
from ..interpreter import Interpreter
from ..interpreterbase import TYPE_var
class ExtensionModule:
def __init__(self, interpreter):
def __init__(self, interpreter: 'Interpreter') -> None:
self.interpreter = interpreter
self.snippets = set() # List of methods that operate only on the interpreter.
self.snippets = set() # type: T.Set[str] # List of methods that operate only on the interpreter.
def is_snippet(self, funcname):
def is_snippet(self, funcname: str) -> bool:
return funcname in self.snippets
@ -69,7 +73,7 @@ def is_module_library(fname):
class ModuleReturnValue:
def __init__(self, return_value, new_objects):
def __init__(self, return_value: 'TYPE_var', new_objects: T.List['TYPE_var']) -> None:
self.return_value = return_value
assert(isinstance(new_objects, list))
self.new_objects = new_objects

@ -178,12 +178,18 @@ class MesonApp:
logger_fun = mlog.log
else:
logger_fun = mlog.debug
logger_fun('Build machine cpu family:', mlog.bold(intr.builtin['build_machine'].cpu_family_method([], {})))
logger_fun('Build machine cpu:', mlog.bold(intr.builtin['build_machine'].cpu_method([], {})))
mlog.log('Host machine cpu family:', mlog.bold(intr.builtin['host_machine'].cpu_family_method([], {})))
mlog.log('Host machine cpu:', mlog.bold(intr.builtin['host_machine'].cpu_method([], {})))
logger_fun('Target machine cpu family:', mlog.bold(intr.builtin['target_machine'].cpu_family_method([], {})))
logger_fun('Target machine cpu:', mlog.bold(intr.builtin['target_machine'].cpu_method([], {})))
build_machine = intr.builtin['build_machine']
host_machine = intr.builtin['build_machine']
target_machine = intr.builtin['target_machine']
assert isinstance(build_machine, interpreter.MachineHolder)
assert isinstance(host_machine, interpreter.MachineHolder)
assert isinstance(target_machine, interpreter.MachineHolder)
logger_fun('Build machine cpu family:', mlog.bold(build_machine.cpu_family_method([], {})))
logger_fun('Build machine cpu:', mlog.bold(build_machine.cpu_method([], {})))
mlog.log('Host machine cpu family:', mlog.bold(host_machine.cpu_family_method([], {})))
mlog.log('Host machine cpu:', mlog.bold(host_machine.cpu_method([], {})))
logger_fun('Target machine cpu family:', mlog.bold(target_machine.cpu_family_method([], {})))
logger_fun('Target machine cpu:', mlog.bold(target_machine.cpu_method([], {})))
try:
if self.options.profile:
fname = os.path.join(self.build_dir, 'meson-private', 'profile-interpreter.log')

@ -43,10 +43,7 @@ from . import environment
from . import mlog
from .dependencies import ExternalProgram
from .mesonlib import MesonException, get_wine_shortpath, split_args, join_args
from .backend.backends import TestProtocol
if T.TYPE_CHECKING:
from .backend.backends import TestSerialisation
from .backend.backends import TestProtocol, TestSerialisation
# GNU autotools interprets a return code of 77 from tests it executes to
# mean that the test should be skipped.
@ -445,7 +442,7 @@ class JunitBuilder:
class TestRun:
@classmethod
def make_gtest(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
def make_gtest(cls, test: TestSerialisation, test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float,
stdo: T.Optional[str], stde: T.Optional[str],
cmd: T.Optional[T.List[str]]) -> 'TestRun':
@ -459,7 +456,7 @@ class TestRun:
junit=tree)
@classmethod
def make_exitcode(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
def make_exitcode(cls, test: TestSerialisation, test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float,
stdo: T.Optional[str], stde: T.Optional[str],
cmd: T.Optional[T.List[str]], **kwargs: T.Any) -> 'TestRun':
@ -474,7 +471,7 @@ class TestRun:
return cls(test, test_env, res, [], returncode, starttime, duration, stdo, stde, cmd, **kwargs)
@classmethod
def make_tap(cls, test: 'TestSerialisation', test_env: T.Dict[str, str],
def make_tap(cls, test: TestSerialisation, test_env: T.Dict[str, str],
returncode: int, starttime: float, duration: float,
stdo: str, stde: str,
cmd: T.Optional[T.List[str]]) -> 'TestRun':
@ -511,7 +508,7 @@ class TestRun:
return cls(test, test_env, res, results, returncode, starttime, duration, stdo, stde, cmd)
def __init__(self, test: 'TestSerialisation', test_env: T.Dict[str, str],
def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str],
res: TestResult, results: T.List[TestResult], returncode:
int, starttime: float, duration: float,
stdo: T.Optional[str], stde: T.Optional[str],
@ -577,26 +574,32 @@ def write_json_log(jsonlogfile: T.TextIO, test_name: str, result: TestRun) -> No
def run_with_mono(fname: str) -> bool:
return fname.endswith('.exe') and not (is_windows() or is_cygwin())
def load_benchmarks(build_dir: str) -> T.List['TestSerialisation']:
def load_benchmarks(build_dir: str) -> T.List[TestSerialisation]:
datafile = Path(build_dir) / 'meson-private' / 'meson_benchmark_setup.dat'
if not datafile.is_file():
raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
with datafile.open('rb') as f:
obj = T.cast(T.List['TestSerialisation'], pickle.load(f))
obj = pickle.load(f)
assert isinstance(obj, list)
for i in obj:
assert isinstance(i, TestSerialisation)
return obj
def load_tests(build_dir: str) -> T.List['TestSerialisation']:
def load_tests(build_dir: str) -> T.List[TestSerialisation]:
datafile = Path(build_dir) / 'meson-private' / 'meson_test_setup.dat'
if not datafile.is_file():
raise TestException('Directory {!r} does not seem to be a Meson build directory.'.format(build_dir))
with datafile.open('rb') as f:
obj = T.cast(T.List['TestSerialisation'], pickle.load(f))
obj = pickle.load(f)
assert isinstance(obj, list)
for i in obj:
assert isinstance(i, TestSerialisation)
return obj
class SingleTestRunner:
def __init__(self, test: 'TestSerialisation', test_env: T.Dict[str, str],
def __init__(self, test: TestSerialisation, test_env: T.Dict[str, str],
env: T.Dict[str, str], options: argparse.Namespace):
self.test = test
self.test_env = test_env
@ -605,9 +608,9 @@ class SingleTestRunner:
def _get_cmd(self) -> T.Optional[T.List[str]]:
if self.test.fname[0].endswith('.jar'):
return ['java', '-jar'] + T.cast(T.List[str], self.test.fname)
return ['java', '-jar'] + self.test.fname
elif not self.test.is_cross_built and run_with_mono(self.test.fname[0]):
return ['mono'] + T.cast(T.List[str], self.test.fname)
return ['mono'] + self.test.fname
elif self.test.cmd_is_built and self.test.needs_exe_wrapper:
if self.test.exe_runner is None:
# Can not run test on cross compiled executable
@ -620,8 +623,8 @@ class SingleTestRunner:
msg = ('The exe_wrapper defined in the cross file {!r} was not '
'found. Please check the command and/or add it to PATH.')
raise TestException(msg.format(self.test.exe_runner.name))
return T.cast(T.List[str], self.test.exe_runner.get_command()) + T.cast(T.List[str], self.test.fname)
return T.cast(T.List[str], self.test.fname)
return self.test.exe_runner.get_command() + self.test.fname
return self.test.fname
def run(self) -> TestRun:
cmd = self._get_cmd()
@ -833,7 +836,7 @@ class TestHarness:
lfile.close()
setattr(self, f, None)
def merge_suite_options(self, options: argparse.Namespace, test: 'TestSerialisation') -> T.Dict[str, str]:
def merge_suite_options(self, options: argparse.Namespace, test: TestSerialisation) -> T.Dict[str, str]:
if ':' in options.setup:
if options.setup not in self.build_data.test_setups:
sys.exit("Unknown test setup '{}'.".format(options.setup))
@ -855,9 +858,9 @@ class TestHarness:
sys.exit('Conflict: both test setup and command line specify an exe wrapper.')
if options.wrapper is None:
options.wrapper = current.exe_wrapper
return T.cast(T.Dict[str, str], current.env.get_env(os.environ.copy()))
return current.env.get_env(os.environ.copy())
def get_test_runner(self, test: 'TestSerialisation') -> SingleTestRunner:
def get_test_runner(self, test: TestSerialisation) -> SingleTestRunner:
options = deepcopy(self.options)
if not options.setup:
options.setup = self.build_data.test_setup_default_name
@ -889,7 +892,7 @@ class TestHarness:
sys.exit('Unknown test result encountered: {}'.format(result.res))
def print_stats(self, test_count: int, name_max_len: int,
tests: T.List['TestSerialisation'],
tests: T.List[TestSerialisation],
name: str, result: TestRun, i: int) -> None:
ok_statuses = (TestResult.OK, TestResult.EXPECTEDFAIL)
bad_statuses = (TestResult.FAIL, TestResult.TIMEOUT,
@ -983,14 +986,14 @@ class TestHarness:
@staticmethod
def split_suite_string(suite: str) -> T.Tuple[str, str]:
if ':' in suite:
# mypy can't figure out that str.split(n, 1) will return a list of
# length 2, so we have to help it.
return T.cast(T.Tuple[str, str], tuple(suite.split(':', 1)))
split = suite.split(':', 1)
assert len(split) == 2
return split[0], split[1]
else:
return suite, ""
@staticmethod
def test_in_suites(test: 'TestSerialisation', suites: T.List[str]) -> bool:
def test_in_suites(test: TestSerialisation, suites: T.List[str]) -> bool:
for suite in suites:
(prj_match, st_match) = TestHarness.split_suite_string(suite)
for prjst in test.suite:
@ -1021,12 +1024,12 @@ class TestHarness:
return True
return False
def test_suitable(self, test: 'TestSerialisation') -> bool:
def test_suitable(self, test: TestSerialisation) -> bool:
return ((not self.options.include_suites or
TestHarness.test_in_suites(test, self.options.include_suites)) and not
TestHarness.test_in_suites(test, self.options.exclude_suites))
def get_tests(self) -> T.List['TestSerialisation']:
def get_tests(self) -> T.List[TestSerialisation]:
if not self.tests:
print('No tests defined.')
return []
@ -1089,17 +1092,17 @@ class TestHarness:
wrap += options.wrapper
return wrap
def get_pretty_suite(self, test: 'TestSerialisation') -> str:
def get_pretty_suite(self, test: TestSerialisation) -> str:
if len(self.suites) > 1 and test.suite:
rv = TestHarness.split_suite_string(test.suite[0])[0]
s = "+".join(TestHarness.split_suite_string(s)[1] for s in test.suite)
if s:
rv += ":"
return rv + s + " / " + T.cast(str, test.name)
return rv + s + " / " + test.name
else:
return T.cast(str, test.name)
return test.name
def run_tests(self, tests: T.List['TestSerialisation']) -> None:
def run_tests(self, tests: T.List[TestSerialisation]) -> None:
executor = None
futures = [] # type: T.List[T.Tuple[conc.Future[TestRun], int, int, T.List[TestSerialisation], str, int]]
test_count = len(tests)
@ -1141,7 +1144,7 @@ class TestHarness:
finally:
os.chdir(startdir)
def drain_futures(self, futures: T.List[T.Tuple['conc.Future[TestRun]', int, int, T.List['TestSerialisation'], str, int]]) -> None:
def drain_futures(self, futures: T.List[T.Tuple['conc.Future[TestRun]', int, int, T.List[TestSerialisation], str, int]]) -> None:
for x in futures:
(result, test_count, name_max_len, tests, name, i) = x
if self.options.repeat > 1 and self.fail_count:

@ -62,7 +62,6 @@ optname_regex = re.compile('[^a-zA-Z0-9_-]')
def StringParser(description, kwargs):
return coredata.UserStringOption(description,
kwargs.get('value', ''),
kwargs.get('choices', []),
kwargs.get('yield', coredata.default_yielding))
@permitted_kwargs({'value', 'yield'})
@ -134,11 +133,11 @@ option_types = {'string': StringParser,
} # type: T.Dict[str, T.Callable[[str, T.Dict], coredata.UserOption]]
class OptionInterpreter:
def __init__(self, subproject):
def __init__(self, subproject: str) -> None:
self.options = {}
self.subproject = subproject
def process(self, option_file):
def process(self, option_file: str) -> None:
try:
with open(option_file, 'r', encoding='utf8') as f:
ast = mparser.Parser(f.read(), option_file).parse()
@ -159,7 +158,7 @@ class OptionInterpreter:
e.file = option_file
raise e
def reduce_single(self, arg):
def reduce_single(self, arg: T.Union[str, mparser.BaseNode]) -> T.Union[str, int, bool]:
if isinstance(arg, str):
return arg
elif isinstance(arg, (mparser.StringNode, mparser.BooleanNode,
@ -189,7 +188,7 @@ class OptionInterpreter:
else:
raise OptionException('Arguments may only be string, int, bool, or array of those.')
def reduce_arguments(self, args):
def reduce_arguments(self, args: mparser.ArgumentNode) -> T.Tuple[T.List[T.Union[str, int, bool]], T.Dict[str, T.Union[str, int, bool]]]:
assert(isinstance(args, mparser.ArgumentNode))
if args.incorrect_order():
raise OptionException('All keyword arguments must be after positional arguments.')
@ -202,7 +201,7 @@ class OptionInterpreter:
reduced_kw[key.value] = self.reduce_single(a)
return reduced_pos, reduced_kw
def evaluate_statement(self, node):
def evaluate_statement(self, node: mparser.BaseNode) -> None:
if not isinstance(node, mparser.FunctionNode):
raise OptionException('Option file may only contain option definitions')
func_name = node.func_name

@ -311,7 +311,7 @@ class Elf(DataSizes):
old_rpath = self.read_str()
# Some rpath entries may come from multiple sources.
# Only add each one once.
new_rpaths = OrderedSet()
new_rpaths = OrderedSet() # type: OrderedSet[bytes]
if new_rpath:
new_rpaths.add(new_rpath)
if old_rpath:

@ -57,7 +57,7 @@ def run_exe(exe: ExecutableSerialisation) -> int:
if p.returncode == 0xc0000135:
# STATUS_DLL_NOT_FOUND on Windows indicating a common problem that is otherwise hard to diagnose
raise FileNotFoundError('Missing DLLs on calling {!r}'.format(exe.name))
raise FileNotFoundError('Missing DLLs on calling {!r}'.format(cmd_args))
if exe.capture and p.returncode == 0:
skip_write = False

@ -15,6 +15,7 @@ modules = [
# specific files
'mesonbuild/arglist.py',
# 'mesonbuild/compilers/mixins/intel.py',
# 'mesonbuild/coredata.py',
'mesonbuild/dependencies/boost.py',
'mesonbuild/dependencies/hdf5.py',
'mesonbuild/dependencies/mpi.py',

Loading…
Cancel
Save