aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2020-03-02 11:11:17 -0800
committerDylan Baker <dylan@pnwbakers.com>2020-03-05 09:31:29 -0800
commita8293dd59c0a22817f2336df8ae97dce1232f72a (patch)
tree123b316ad1bf34c52f75c29d05e8b94ab05d52be
parent1a82880730e2d9f58eaa67179aa40c6976835278 (diff)
downloadmeson-a8293dd59c0a22817f2336df8ae97dce1232f72a.zip
meson-a8293dd59c0a22817f2336df8ae97dce1232f72a.tar.gz
meson-a8293dd59c0a22817f2336df8ae97dce1232f72a.tar.bz2
mesonlib: Replace unholder argument to listify
listify shouldn't be unholdering, it's a function to turn scalar values into lists, or flatten lists. Having a separate function is clearer, easier to understand, and can be run recursively if necessary.
-rw-r--r--mesonbuild/build.py24
-rw-r--r--mesonbuild/compilers/compilers.py2
-rw-r--r--mesonbuild/interpreter.py24
-rw-r--r--mesonbuild/mesonlib.py19
-rw-r--r--mesonbuild/modules/gnome.py6
-rw-r--r--mesonbuild/modules/pkgconfig.py4
-rwxr-xr-xrun_unittests.py24
7 files changed, 51 insertions, 52 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 17b5f11..770e851 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -26,7 +26,7 @@ from . import mlog
from .mesonlib import (
File, MesonException, MachineChoice, PerMachine, OrderedSet, listify,
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
- get_filenames_templates_dict, substitute_values, has_path_sep,
+ get_filenames_templates_dict, substitute_values, has_path_sep, unholder
)
from .compilers import Compiler, is_object, clink_langs, sort_clink, lang_suffixes
from .linkers import StaticLinker
@@ -856,7 +856,7 @@ just like those detected with the dependency() function.''')
if dfeature_debug:
dfeatures['debug'] = dfeature_debug
if 'd_import_dirs' in kwargs:
- dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs', unholder=True)
+ dfeature_import_dirs = unholder(extract_as_list(kwargs, 'd_import_dirs'))
for d in dfeature_import_dirs:
if not isinstance(d, IncludeDirs):
raise InvalidArguments('Arguments to d_import_dirs must be include_directories.')
@@ -1083,7 +1083,7 @@ You probably should put it in link_with instead.''')
return isinstance(self, StaticLibrary) and not self.need_install
def link(self, target):
- for t in listify(target, unholder=True):
+ for t in unholder(listify(target)):
if isinstance(self, StaticLibrary) and self.need_install and t.is_internal():
# When we're a static library and we link_with to an
# internal/convenience library, promote to link_whole.
@@ -1105,7 +1105,7 @@ You probably should put it in link_with instead.''')
self.link_targets.append(t)
def link_whole(self, target):
- for t in listify(target, unholder=True):
+ for t in unholder(listify(target)):
if isinstance(t, (CustomTarget, CustomTargetIndex)):
if not t.is_linkable_target():
raise InvalidArguments('Custom target {!r} is not linkable.'.format(t))
@@ -1261,7 +1261,7 @@ You probably should put it in link_with instead.''')
if dl != linker.language:
stdlib_args += all_compilers[dl].language_stdlib_only_link_flags()
added_languages.add(dl)
- # Type of var 'linker' is Compiler.
+ # Type of var 'linker' is Compiler.
# Pretty hard to fix because the return value is passed everywhere
return linker, stdlib_args
@@ -1372,7 +1372,7 @@ class Generator:
raise InvalidArguments('Capture must be boolean.')
self.capture = capture
if 'depends' in kwargs:
- depends = listify(kwargs['depends'], unholder=True)
+ depends = unholder(listify(kwargs['depends']))
for d in depends:
if not isinstance(d, BuildTarget):
raise InvalidArguments('Depends entries must be build targets.')
@@ -2054,7 +2054,7 @@ class CustomTarget(Target):
return bdeps
def flatten_command(self, cmd):
- cmd = listify(cmd, unholder=True)
+ cmd = unholder(listify(cmd))
final_cmd = []
for c in cmd:
if isinstance(c, str):
@@ -2082,7 +2082,7 @@ class CustomTarget(Target):
def process_kwargs(self, kwargs, backend):
self.process_kwargs_base(kwargs)
- self.sources = extract_as_list(kwargs, 'input', unholder=True)
+ self.sources = unholder(extract_as_list(kwargs, 'input'))
if 'output' not in kwargs:
raise InvalidArguments('Missing keyword argument "output".')
self.outputs = listify(kwargs['output'])
@@ -2411,18 +2411,18 @@ class ConfigureFile:
class ConfigurationData:
def __init__(self) -> None:
super().__init__()
- self.values = {}
+ self.values = {} # T.Dict[str, T.Union[str, int, bool]]
def __repr__(self):
return repr(self.values)
- def __contains__(self, value):
+ def __contains__(self, value: str) -> bool:
return value in self.values
- def get(self, name):
+ def get(self, name: str) -> T.Tuple[T.Union[str, int, bool], T.Optional[str]]:
return self.values[name] # (val, desc)
- def keys(self):
+ def keys(self) -> T.Iterator[str]:
return self.values.keys()
# A bit poorly named, but this represents plain data files to copy
diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py
index 1c0adff..caa8600 100644
--- a/mesonbuild/compilers/compilers.py
+++ b/mesonbuild/compilers/compilers.py
@@ -35,6 +35,8 @@ if T.TYPE_CHECKING:
from ..environment import Environment
from ..linkers import DynamicLinker # noqa: F401
+ CompilerType = T.TypeVar('CompilerType', bound=Compiler)
+
"""This file contains the data files of all compilers Meson knows
about. To support a new compiler, add its information below.
Also add corresponding autodetection code in environment.py."""
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 9e88975..4c0807c 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -21,7 +21,7 @@ from . import optinterpreter
from . import compilers
from .wrap import wrap, WrapMode
from . import mesonlib
-from .mesonlib import FileMode, MachineChoice, Popen_safe, listify, extract_as_list, has_path_sep
+from .mesonlib import FileMode, MachineChoice, Popen_safe, listify, extract_as_list, has_path_sep, unholder
from .dependencies import ExternalProgram
from .dependencies import InternalDependency, Dependency, NotFoundDependency, DependencyException
from .depfile import DepFile
@@ -2460,11 +2460,11 @@ class Interpreter(InterpreterBase):
if not isinstance(version, str):
raise InterpreterException('Version must be a string.')
incs = self.extract_incdirs(kwargs)
- libs = extract_as_list(kwargs, 'link_with', unholder=True)
- libs_whole = extract_as_list(kwargs, 'link_whole', unholder=True)
+ libs = unholder(extract_as_list(kwargs, 'link_with'))
+ libs_whole = unholder(extract_as_list(kwargs, 'link_whole'))
sources = extract_as_list(kwargs, 'sources')
- sources = listify(self.source_strings_to_files(sources), unholder=True)
- deps = extract_as_list(kwargs, 'dependencies', unholder=True)
+ sources = unholder(listify(self.source_strings_to_files(sources)))
+ deps = unholder(extract_as_list(kwargs, 'dependencies'))
compile_args = mesonlib.stringlistify(kwargs.get('compile_args', []))
link_args = mesonlib.stringlistify(kwargs.get('link_args', []))
variables = kwargs.get('variables', {})
@@ -3581,12 +3581,12 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
if 'command' not in kwargs:
raise InterpreterException('Missing "command" keyword argument')
all_args = extract_as_list(kwargs, 'command')
- deps = extract_as_list(kwargs, 'depends', unholder=True)
+ deps = unholder(extract_as_list(kwargs, 'depends'))
else:
raise InterpreterException('Run_target needs at least one positional argument.')
cleaned_args = []
- for i in listify(all_args, unholder=True):
+ for i in unholder(listify(all_args)):
if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, dependencies.ExternalProgram, mesonlib.File)):
mlog.debug('Wrong type:', str(i))
raise InterpreterException('Invalid argument to run_target.')
@@ -3617,7 +3617,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
name = args[0]
if not isinstance(name, str):
raise InterpreterException('First argument must be a string.')
- deps = listify(args[1:], unholder=True)
+ deps = unholder(listify(args[1:]))
for d in deps:
if not isinstance(d, (build.BuildTarget, build.CustomTarget)):
raise InterpreterException('Depends items must be build targets.')
@@ -3675,7 +3675,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
par = kwargs.get('is_parallel', True)
if not isinstance(par, bool):
raise InterpreterException('Keyword argument is_parallel must be a boolean.')
- cmd_args = extract_as_list(kwargs, 'args', unholder=True)
+ cmd_args = unholder(extract_as_list(kwargs, 'args'))
for i in cmd_args:
if not isinstance(i, (str, mesonlib.File, build.Target)):
raise InterpreterException('Command line arguments must be strings, files or targets.')
@@ -3703,7 +3703,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
if len(s) > 0:
s = ':' + s
suite.append(prj.replace(' ', '_').replace(':', '_') + s)
- depends = extract_as_list(kwargs, 'depends', unholder=True)
+ depends = unholder(extract_as_list(kwargs, 'depends'))
for dep in depends:
if not isinstance(dep, (build.CustomTarget, build.BuildTarget)):
raise InterpreterException('Depends items must be build targets.')
@@ -4066,7 +4066,7 @@ This will become a hard error in the future.''' % kwargs['input'], location=self
return mesonlib.File.from_built_file(self.subdir, output)
def extract_incdirs(self, kwargs):
- prospectives = listify(kwargs.get('include_directories', []), unholder=True)
+ prospectives = unholder(extract_as_list(kwargs, 'include_directories'))
result = []
for p in prospectives:
if isinstance(p, build.IncludeDirs):
@@ -4127,7 +4127,7 @@ different subdirectory.
if ":" not in setup_name:
setup_name = (self.subproject if self.subproject else self.build.project_name) + ":" + setup_name
try:
- inp = extract_as_list(kwargs, 'exe_wrapper', unholder=True)
+ inp = unholder(extract_as_list(kwargs, 'exe_wrapper'))
exe_wrapper = []
for i in inp:
if isinstance(i, str):
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 49ddc94..07e30e2 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -1058,34 +1058,25 @@ def unholder(item):
return item
-def listify(item: T.Any,
- flatten: bool = True,
- unholder: bool = False) -> T.List[T.Any]:
+def listify(item: T.Any, flatten: bool = True) -> T.List[T.Any]:
'''
Returns a list with all args embedded in a list if they are not a list.
This function preserves order.
@flatten: Convert lists of lists to a flat list
- @unholder: Replace each item with the object it holds, if required
-
- Note: unholding only works recursively when flattening
'''
if not isinstance(item, list):
- if unholder and hasattr(item, 'held_object'):
- item = item.held_object
return [item]
result = [] # type: T.List[T.Any]
for i in item:
- if unholder and hasattr(i, 'held_object'):
- i = i.held_object
if flatten and isinstance(i, list):
- result += listify(i, flatten=True, unholder=unholder)
+ result += listify(i, flatten=True)
else:
result.append(i)
return result
def extract_as_list(dict_object: T.Dict[_T, _U], *keys: _T, pop: bool = False,
- **kwargs: T.Any) -> T.List[T.Union[_U, T.List[_U]]]:
+ flatten: bool = True) -> T.List[T.Union[_U, T.List[_U]]]:
'''
Extracts all values from given dict_object and listifies them.
'''
@@ -1095,10 +1086,10 @@ def extract_as_list(dict_object: T.Dict[_T, _U], *keys: _T, pop: bool = False,
fetch = dict_object.pop
# If there's only one key, we don't return a list with one element
if len(keys) == 1:
- return listify(fetch(keys[0], []), **kwargs)
+ return listify(fetch(keys[0], []), flatten=True)
# Return a list of values corresponding to *keys
for key in keys:
- result.append(listify(fetch(key, []), **kwargs))
+ result.append(listify(fetch(key, []), flatten=True))
return result
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index 1743b59..4ff40ad 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -316,7 +316,7 @@ class GnomeModule(ExtensionModule):
# require two args in order, such as -framework AVFoundation
external_ldflags_nodedup = []
gi_includes = OrderedSet()
- deps = mesonlib.listify(deps, unholder=True)
+ deps = mesonlib.unholder(mesonlib.listify(deps))
for dep in deps:
if isinstance(dep, InternalDependency):
@@ -776,7 +776,7 @@ class GnomeModule(ExtensionModule):
langs_compilers = self._get_girtargets_langs_compilers(girtargets)
cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers)
deps = self._get_gir_targets_deps(girtargets)
- deps += extract_as_list(kwargs, 'dependencies', pop=True, unholder=True)
+ deps += mesonlib.unholder(extract_as_list(kwargs, 'dependencies', pop=True))
typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends)
# ldflags will be misinterpreted by gir scanner (showing
# spurious dependencies) but building GStreamer fails if they
@@ -1057,7 +1057,7 @@ This will become a hard error in the future.''')
def _get_build_args(self, kwargs, state, depends):
args = []
- deps = extract_as_list(kwargs, 'dependencies', unholder=True)
+ deps = mesonlib.unholder(extract_as_list(kwargs, 'dependencies'))
cflags = []
cflags.extend(mesonlib.stringlistify(kwargs.pop('c_args', [])))
deps_cflags, internal_ldflags, external_ldflags, gi_includes = \
diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py
index 8de88c9..1d8e8a9 100644
--- a/mesonbuild/modules/pkgconfig.py
+++ b/mesonbuild/modules/pkgconfig.py
@@ -74,7 +74,7 @@ class DependenciesHelper:
def _process_reqs(self, reqs):
'''Returns string names of requirements'''
processed_reqs = []
- for obj in mesonlib.listify(reqs, unholder=True):
+ for obj in mesonlib.unholder(mesonlib.listify(reqs)):
if not isinstance(obj, str):
FeatureNew('pkgconfig.generate requirement from non-string object', '0.46.0').use(self.state.subproject)
if hasattr(obj, 'generated_pc'):
@@ -108,7 +108,7 @@ class DependenciesHelper:
self.cflags += mesonlib.stringlistify(cflags)
def _process_libs(self, libs, public):
- libs = mesonlib.listify(libs, unholder=True)
+ libs = mesonlib.unholder(mesonlib.listify(libs))
processed_libs = []
processed_reqs = []
processed_cflags = []
diff --git a/run_unittests.py b/run_unittests.py
index 658da37..b39ba28 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -686,12 +686,17 @@ class InternalTests(unittest.TestCase):
self.assertEqual([holder1], listify([holder1]))
self.assertEqual([holder1, 2], listify([holder1, 2]))
self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]]))
- self.assertEqual([1], listify(holder1, unholder=True))
- self.assertEqual([1], listify([holder1], unholder=True))
- self.assertEqual([1, 2], listify([holder1, 2], unholder=True))
- self.assertEqual([1, 2, 3], listify([holder1, 2, [holder3]], unholder=True))
- # Unholding doesn't work recursively when not flattening
- self.assertEqual([1, [2], [holder3]], listify([holder1, [2], [holder3]], unholder=True, flatten=False))
+
+ def test_unholder(self):
+ unholder = mesonbuild.mesonlib.unholder
+
+ holder1 = ObjectHolder(1)
+ holder3 = ObjectHolder(3)
+ holders = [holder1, holder3]
+
+ self.assertEqual(1, unholder(holder1))
+ self.assertEqual([1], unholder([holder1]))
+ self.assertEqual([1, 3], unholder(holders))
def test_extract_as_list(self):
extract = mesonbuild.mesonlib.extract_as_list
@@ -704,14 +709,15 @@ class InternalTests(unittest.TestCase):
# Test unholding
holder3 = ObjectHolder(3)
kwargs = {'sources': [1, 2, holder3]}
- self.assertEqual([1, 2, 3], extract(kwargs, 'sources', unholder=True))
self.assertEqual(kwargs, {'sources': [1, 2, holder3]})
- self.assertEqual([1, 2, 3], extract(kwargs, 'sources', unholder=True, pop=True))
- self.assertEqual(kwargs, {})
# Test listification
kwargs = {'sources': [1, 2, 3], 'pch_sources': [4, 5, 6]}
self.assertEqual([[1, 2, 3], [4, 5, 6]], extract(kwargs, 'sources', 'pch_sources'))
+ # flatten nested lists
+ kwargs = {'sources': [1, [2, [3]]]}
+ self.assertEqual([1, 2, 3], extract(kwargs, 'sources', flatten=True))
+
def test_pkgconfig_module(self):
class Mock: