summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Vlasov <sigprof@gmail.com>2023-05-30 21:24:19 +0300
committerGitHub <noreply@github.com>2023-05-30 19:24:19 +0100
commit1411c79aefc989f5fae138b795f53f3b10863ec9 (patch)
tree26f6e5ac77c803228dc4dc7fa9e7741b4c0b6d20
parent913691b9f0ae7d99af831704ec3687ee5fd7a689 (diff)
`qmk find`: Fix handling of functions in filters (#21090)
Functions in filters did not work properly except when used in the last (or only) filter. The problem was caused by the peculiarity of the `lambda` behavior in Python — any variables from the outer scope are captured only by reference, therefore any subsequent reassignment of those variables is propagated to all lambdas created earlier in the same scope. Together with the laziness of `filter()` (it returns an iterator which performs filtering on demand) this resulted in all function filters using the values of the `key` and `value` variables which correspond to the last filter in the sequence, therefore the result of filtering was wrong if some filter with a function was not the last one in the sequence. Apparently the shortest way to make a Python lambda capture some variables by value is to add arguments with default values for such variables (default values are evaluated when the lambda is created, and any subsequent reassignments in the outer scope no longer changes them). This makes filters with functions work properly even when such filters are not at the last position in the sequence.
-rw-r--r--lib/python/qmk/search.py8
1 files changed, 4 insertions, 4 deletions
diff --git a/lib/python/qmk/search.py b/lib/python/qmk/search.py
index c8ce85b96e..2bbbc7806f 100644
--- a/lib/python/qmk/search.py
+++ b/lib/python/qmk/search.py
@@ -80,9 +80,9 @@ def search_keymap_targets(keymap='default', filters=[], print_vals=[]):
if value is not None:
if func_name == 'length':
- valid_keymaps = filter(lambda e: key in e[2] and len(e[2].get(key)) == int(value), valid_keymaps)
+ valid_keymaps = filter(lambda e, key=key, value=value: key in e[2] and len(e[2].get(key)) == int(value), valid_keymaps)
elif func_name == 'contains':
- valid_keymaps = filter(lambda e: key in e[2] and value in e[2].get(key), valid_keymaps)
+ valid_keymaps = filter(lambda e, key=key, value=value: key in e[2] and value in e[2].get(key), valid_keymaps)
else:
cli.log.warning(f'Unrecognized filter expression: {function_match.group(0)}')
continue
@@ -90,9 +90,9 @@ def search_keymap_targets(keymap='default', filters=[], print_vals=[]):
cli.log.info(f'Filtering on condition: {{fg_green}}{func_name}{{fg_reset}}({{fg_cyan}}{key}{{fg_reset}}, {{fg_cyan}}{value}{{fg_reset}})...')
else:
if func_name == 'exists':
- valid_keymaps = filter(lambda e: key in e[2], valid_keymaps)
+ valid_keymaps = filter(lambda e, key=key: key in e[2], valid_keymaps)
elif func_name == 'absent':
- valid_keymaps = filter(lambda e: key not in e[2], valid_keymaps)
+ valid_keymaps = filter(lambda e, key=key: key not in e[2], valid_keymaps)
else:
cli.log.warning(f'Unrecognized filter expression: {function_match.group(0)}')
continue