From 0b3ece1189b11e36790c99a1a80f75413b826bb4 Mon Sep 17 00:00:00 2001
From: Sergey Vlasov <sigprof@gmail.com>
Date: Fri, 13 Sep 2024 23:52:31 +0300
Subject: `qmk find`: Fix handling of keys with dots in filter functions
 (#24393)

---
 lib/python/qmk/search.py                  | 10 +++--
 lib/python/qmk/tests/test_cli_commands.py | 65 +++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 4 deletions(-)

(limited to 'lib')

diff --git a/lib/python/qmk/search.py b/lib/python/qmk/search.py
index baaf11eb34..25e3d92066 100644
--- a/lib/python/qmk/search.py
+++ b/lib/python/qmk/search.py
@@ -74,28 +74,30 @@ class Exists(FilterFunction):
     func_name = "exists"
 
     def apply(self, target_info: KeyboardKeymapDesc) -> bool:
-        return self.key in target_info.data
+        return self.key in target_info.dotty
 
 
 class Absent(FilterFunction):
     func_name = "absent"
 
     def apply(self, target_info: KeyboardKeymapDesc) -> bool:
-        return self.key not in target_info.data
+        return self.key not in target_info.dotty
 
 
 class Length(FilterFunction):
     func_name = "length"
 
     def apply(self, target_info: KeyboardKeymapDesc) -> bool:
-        return (self.key in target_info.data and len(target_info.data[self.key]) == int(self.value))
+        info_dotty = target_info.dotty
+        return (self.key in info_dotty and len(info_dotty[self.key]) == int(self.value))
 
 
 class Contains(FilterFunction):
     func_name = "contains"
 
     def apply(self, target_info: KeyboardKeymapDesc) -> bool:
-        return (self.key in target_info.data and self.value in target_info.data[self.key])
+        info_dotty = target_info.dotty
+        return (self.key in info_dotty and self.value in info_dotty[self.key])
 
 
 def _get_filter_class(func_name: str, key: str, value: str) -> Optional[FilterFunction]:
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py
index 4c322e0c9d..f18bd12f82 100644
--- a/lib/python/qmk/tests/test_cli_commands.py
+++ b/lib/python/qmk/tests/test_cli_commands.py
@@ -347,3 +347,68 @@ def test_format_json_keymap_auto():
     result = check_subcommand('format-json', '--format', 'auto', 'lib/python/qmk/tests/minimal_keymap.json')
     check_returncode(result)
     assert result.stdout == '{\n    "keyboard": "handwired/pytest/basic",\n    "keymap": "test",\n    "layers": [\n        ["KC_A"]\n    ],\n    "layout": "LAYOUT_ortho_1x1",\n    "version": 1\n}\n'
+
+
+def test_find_exists():
+    result = check_subcommand('find', '-f', 'exists(rgb_matrix.split_count)', '-p', 'rgb_matrix.split_count')
+    check_returncode(result)
+    values = [s for s in result.stdout.splitlines() if 'rgb_matrix.split_count=' in s]
+    assert len(values) > 0
+    for s in values:
+        assert '=None' not in s
+        assert '=[' in s
+
+
+def test_find_absent():
+    result = check_subcommand('find', '-f', 'absent(rgb_matrix.split_count)', '-p', 'rgb_matrix.split_count')
+    check_returncode(result)
+    values = [s for s in result.stdout.splitlines() if 'rgb_matrix.split_count=' in s]
+    assert len(values) > 0
+    for s in values:
+        assert '=None' in s
+        assert '=[' not in s
+
+
+def test_find_length():
+    result = check_subcommand('find', '-f', 'length(matrix_pins.cols, 6)', '-p', 'matrix_pins.cols')
+    check_returncode(result)
+    values = [s for s in result.stdout.splitlines() if 'matrix_pins.cols=' in s]
+    assert len(values) > 0
+    for s in values:
+        assert s.count(',') == 5
+
+
+def test_find_contains():
+    result = check_subcommand('find', '-f', 'contains(matrix_pins.cols, B1)', '-p', 'matrix_pins.cols')
+    check_returncode(result)
+    values = [s for s in result.stdout.splitlines() if 'matrix_pins.cols=' in s]
+    assert len(values) > 0
+    for s in values:
+        assert "'B1'" in s
+
+
+def test_find_multiple_conditions():
+    # this is intended to match at least 'crkbd/rev1'
+    result = check_subcommand(
+        'find', '-f', 'exists(rgb_matrix.split_count)', '-f', 'contains(matrix_pins.cols, B1)', '-f', 'length(matrix_pins.cols, 6)', '-f', 'absent(eeprom.driver)', '-f', 'ws2812.pin=D3', '-p', 'rgb_matrix.split_count', '-p', 'matrix_pins.cols', '-p',
+        'eeprom.driver', '-p', 'ws2812.pin'
+    )
+    check_returncode(result)
+    rgb_matrix_split_count_values = [s for s in result.stdout.splitlines() if 'rgb_matrix.split_count=' in s]
+    assert len(rgb_matrix_split_count_values) > 0
+    for s in rgb_matrix_split_count_values:
+        assert '=None' not in s
+        assert '=[' in s
+    matrix_pins_cols_values = [s for s in result.stdout.splitlines() if 'matrix_pins.cols=' in s]
+    assert len(matrix_pins_cols_values) > 0
+    for s in matrix_pins_cols_values:
+        assert s.count(',') == 5
+        assert "'B1'" in s
+    eeprom_driver_values = [s for s in result.stdout.splitlines() if 'eeprom.driver=' in s]
+    assert len(eeprom_driver_values) > 0
+    for s in eeprom_driver_values:
+        assert '=None' in s
+    ws2812_pin_values = [s for s in result.stdout.splitlines() if 'ws2812.pin=' in s]
+    assert len(ws2812_pin_values) > 0
+    for s in ws2812_pin_values:
+        assert '=D3' in s
-- 
cgit v1.2.3