Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New dict.map() method #13198

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/markdown/snippets/dict_map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## New `map()` method on dict

Dict now have a `map()` method that return a list of values from a given
list of keys.

It allows to keep objects in a dict, and to select needed objects from a list
of keys. For example:

```
dependencies = {
'a': dependency('a'),
'b': dependency('b'),
'c': dependency('c'),
...
}

lib_dependencies = {
'libA': ['a', 'b'],
'libB': ['b', 'c'],
...
}

libA = library('A', dependencies: dependencies.map(lib_dependencies['libA']))
libB = library('B', dependencies: dependencies.map(lib_dependencies['libB']))
...

```
17 changes: 17 additions & 0 deletions docs/yaml/elementary/dict.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,20 @@ methods:
- name: keys
returns: list[str]
description: Returns an array of keys in the dictionary.

- name: map
since: 1.5.0
returns: list
description: Returns a list of dict values for the given list of keys

posargs:
keys:
type: list[str]
description: dict keys to select

kwargs:
ignore_unknown:
type: bool
description: |
If `true`, unknown keys are skipped.
If `false`, an unknown key results in an error.
15 changes: 15 additions & 0 deletions mesonbuild/interpreter/primitives/dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
from ...interpreterbase import (
ObjectHolder,
IterableObject,
KwargInfo,
MesonOperator,
typed_operator,
noKwargs,
noPosargs,
noArgsFlattening,
typed_kwargs,
typed_pos_args,
FeatureNew,

TYPE_var,

Expand All @@ -31,6 +34,7 @@ def __init__(self, obj: T.Dict[str, TYPE_var], interpreter: 'Interpreter') -> No
'has_key': self.has_key_method,
'keys': self.keys_method,
'get': self.get_method,
'map': self.map_method,
})

self.trivial_operators.update({
Expand Down Expand Up @@ -81,6 +85,17 @@ def get_method(self, args: T.Tuple[str, T.Optional[TYPE_var]], kwargs: TYPE_kwar
return args[1]
raise InvalidArguments(f'Key {args[0]!r} is not in the dictionary.')

@FeatureNew('dict.map', '1.5.0')
@noArgsFlattening
@typed_pos_args('dict.map', list)
@typed_kwargs('dict.map', KwargInfo('ignore_unknown', bool, default = False))
def map_method(self, args: T.Tuple[T.List[str]], kwargs: T.Dict[str, bool]) -> list:
keys = [k for k in args[0] if k in self.held_object] if kwargs['ignore_unknown'] else args[0]
try:
return [self.held_object[k] for k in keys]
except KeyError as e:
raise InvalidArguments(f'Key {e} is not in the dictionary.') from e

@typed_operator(MesonOperator.INDEX, str)
def op_index(self, other: str) -> TYPE_var:
if other not in self.held_object:
Expand Down
10 changes: 10 additions & 0 deletions test cases/common/188 dict/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,13 @@ d = {
assert(d['sanity'] == 1)
assert(not is_disabler(d['meson']))
assert(not is_disabler(d['host']))


# Map method
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
assert(d.map(['a', 'c', 'e']) == [1, 3, 5], 'Incorrect result for dictionary map function')
assert(d.map(['a', 'g', 'c', 'e'], ignore_unknown: true) == [1, 3, 5], 'Incorrect result for dictionary map function (ignore unknown keys)')

testcase expect_error('Key \'g\' is not in the dictionary.')
d.map(['a', 'g', 'c'])
endtestcase
Loading