From d2ef4e7c4643c5cdfb23f95a804340b7a35e46f8 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Sat, 13 May 2023 10:40:59 -0700 Subject: [PATCH] Fix parsing of nested capability groups --- CHANGELOG.md | 4 ++ monitorcontrol/monitorcontrol.py | 27 ++++---- tests/test_monitorcontrol.py | 109 ++++++++++++++++--------------- 3 files changed, 77 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f55bc75..e3a65bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), as of version 2.1.1. +## [Unreleased] - 2023-05-13 +### Fixed +- Fixed parsing of nested capability groups. + ## [3.0.3] - 2023-04-22 ### Fixed - Fixed dangling file descriptors on linux platforms after calling `get_monitors()`. diff --git a/monitorcontrol/monitorcontrol.py b/monitorcontrol/monitorcontrol.py index ae76baa..314925e 100644 --- a/monitorcontrol/monitorcontrol.py +++ b/monitorcontrol/monitorcontrol.py @@ -524,9 +524,9 @@ def _convert_to_dict(caps_str: str) -> dict: Expected string "04 14(05 06) 16" is converted to:: { - 0x04: [], - 0x14: [0x05, 0x06], - 0x16: [], + 0x04: {}, + 0x14: {0x05: {}, 0x06: {}}, + 0x16: {}, } """ @@ -536,22 +536,25 @@ def _convert_to_dict(caps_str: str) -> dict: return {} result_dict = {} - group = None - prev_digit = None + group = [] + prev_val = None for chunk in caps_str.replace("(", " ( ").replace(")", " ) ").split(" "): if chunk == "": continue elif chunk == "(": - group = prev_digit + group.append(prev_val) elif chunk == ")": - group = None + group.pop(-1) else: val = int(chunk, 16) - if group is None: - result_dict[val] = [] + if len(group) == 0: + result_dict[val] = {} else: - result_dict[group].append(val) - prev_digit = val + d = result_dict + for g in group: + d = d[g] + d[val] = {} + prev_val = val return result_dict @@ -598,7 +601,7 @@ def _parse_capabilities(caps_str: str) -> dict: input_source_cap = vcp.VCPCode("input_select").value if input_source_cap in caps_dict["vcp"]: caps_dict["inputs"] = [] - input_val_list = caps_dict["vcp"][input_source_cap] + input_val_list = list(caps_dict["vcp"][input_source_cap].keys()) input_val_list.sort() for val in input_val_list: diff --git a/tests/test_monitorcontrol.py b/tests/test_monitorcontrol.py index e65438a..8dba0c8 100644 --- a/tests/test_monitorcontrol.py +++ b/tests/test_monitorcontrol.py @@ -261,57 +261,64 @@ def test_convert_to_dict(): "F7(00 01 02 03) F8(00 01) F9 EF FD(00 01) FE(00 01 02) FF" ) expected = { - 0x02: [], - 0x04: [], - 0x05: [], - 0x08: [], - 0x10: [], - 0x12: [], - 0x14: [0x05, 0x08, 0x0B], - 0x16: [], - 0x18: [], - 0x1A: [], - 0x52: [], - 0x60: [0x11, 0x12, 0x0F, 0x10], - 0xAC: [], - 0xAE: [], - 0xB2: [], - 0xB6: [], - 0xC0: [], - 0xC6: [], - 0xC8: [], - 0xC9: [], - 0xD6: [0x01, 0x04], - 0xDF: [], - 0x62: [], - 0x8D: [], - 0xF4: [], - 0xF5: [0x00, 0x01, 0x02], - 0xF6: [0x00, 0x01, 0x02], - 0x4D: [], - 0x4E: [], - 0x4F: [], - 0x15: [ - 0x01, - 0x06, - 0x09, - 0x10, - 0x11, - 0x13, - 0x14, - 0x28, - 0x29, - 0x32, - 0x44, - 0x48, - ], - 0xF7: [0x00, 0x01, 0x02, 0x03], - 0xF8: [0x00, 0x01], - 0xF9: [], - 0xEF: [], - 0xFD: [0x00, 0x01], - 0xFE: [0x00, 0x01, 0x02], - 0xFF: [], + 0x02: {}, + 0x04: {}, + 0x05: {}, + 0x08: {}, + 0x10: {}, + 0x12: {}, + 0x14: {0x05: {}, 0x08: {}, 0x0B: {}}, + 0x16: {}, + 0x18: {}, + 0x1A: {}, + 0x52: {}, + 0x60: {0x11: {}, 0x12: {}, 0x0F: {}, 0x10: {}}, + 0xAC: {}, + 0xAE: {}, + 0xB2: {}, + 0xB6: {}, + 0xC0: {}, + 0xC6: {}, + 0xC8: {}, + 0xC9: {}, + 0xD6: {0x01: {}, 0x04: {}}, + 0xDF: {}, + 0x62: {}, + 0x8D: {}, + 0xF4: {}, + 0xF5: {0x00: {}, 0x01: {}, 0x02: {}}, + 0xF6: {0x00: {}, 0x01: {}, 0x02: {}}, + 0x4D: {}, + 0x4E: {}, + 0x4F: {}, + 0x15: { + 0x01: {}, + 0x06: {}, + 0x09: {}, + 0x10: {}, + 0x11: {}, + 0x13: {}, + 0x14: {}, + 0x28: {}, + 0x29: {}, + 0x32: {}, + 0x44: {}, + 0x48: {}, + }, + 0xF7: {0x00: {}, 0x01: {}, 0x02: {}, 0x03: {}}, + 0xF8: {0x00: {}, 0x01: {}}, + 0xF9: {}, + 0xEF: {}, + 0xFD: {0x00: {}, 0x01: {}}, + 0xFE: {0x00: {}, 0x01: {}, 0x02: {}}, + 0xFF: {}, } assert _convert_to_dict(caps_str) == expected + + +def test_convert_to_dict_nested(): + # https://github.com/newAM/monitorcontrol/issues/249 + caps_str = "DC(00(00 12 13 14))" + expected = {0xDC: {0: {0: {}, 0x12: {}, 0x13: {}, 0x14: {}}}} + assert _convert_to_dict(caps_str) == expected