From 56741d1e24e720124486eaf57c5db371de694a9e Mon Sep 17 00:00:00 2001 From: Nathan Stender Date: Mon, 8 Sep 2025 13:46:42 -0400 Subject: [PATCH 1/3] Fix --- src/allotropy/parsers/utils/json.py | 12 +++++++++--- src/allotropy/parsers/utils/pandas.py | 10 +++++++++- .../parsers/utils/strict_xml_element.py | 18 +++++++++++------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/allotropy/parsers/utils/json.py b/src/allotropy/parsers/utils/json.py index 8f7a654836..264de8c410 100644 --- a/src/allotropy/parsers/utils/json.py +++ b/src/allotropy/parsers/utils/json.py @@ -73,6 +73,14 @@ def _get_custom_key(self, key: str) -> float | str | None: return float_value return self.get(str, key) + def _key_matches(self, match_key: str, key: str) -> bool: + if key == match_key: + return True + # "++" can cause re.compile to fail. Since it is never a valid regex expression + # it is safe to escape it to prevent the error. + match_key = match_key.replace("++", r"\+\+") + return re.fullmatch(match_key, key) + def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: return { matched @@ -80,9 +88,7 @@ def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: key_or_keys if isinstance(key_or_keys, set) else {key_or_keys} ) for matched in [ - k - for k in self.data.keys() - if k == regex_key or re.fullmatch(regex_key, k) + k for k in self.data.keys() if self._key_matches(str(regex_key, str(k))) ] } diff --git a/src/allotropy/parsers/utils/pandas.py b/src/allotropy/parsers/utils/pandas.py index a3dca02250..3b20923bec 100644 --- a/src/allotropy/parsers/utils/pandas.py +++ b/src/allotropy/parsers/utils/pandas.py @@ -273,6 +273,14 @@ def _get_custom_key(self, key: str) -> float | str | None: return float_value return self.get(str, key) + def _key_matches(self, match_key: str, key: str) -> bool: + if key == match_key: + return True + # "++" can cause re.compile to fail. Since it is never a valid regex expression + # it is safe to escape it to prevent the error. + match_key = match_key.replace("++", r"\+\+") + return re.fullmatch(match_key, key) + def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: return { matched @@ -282,7 +290,7 @@ def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: for matched in [ k for k in self.series.index - if k == regex_key or re.fullmatch(str(regex_key), str(k)) + if self._key_matches(str(regex_key), str(k)) ] } diff --git a/src/allotropy/parsers/utils/strict_xml_element.py b/src/allotropy/parsers/utils/strict_xml_element.py index 934c33d40a..929a54080e 100644 --- a/src/allotropy/parsers/utils/strict_xml_element.py +++ b/src/allotropy/parsers/utils/strict_xml_element.py @@ -137,6 +137,14 @@ def _get_all_available_keys(self) -> set[str]: return keys + def _key_matches(self, match_key: str, key: str) -> bool: + if key == match_key: + return True + # "++" can cause re.compile to fail. Since it is never a valid regex expression + # it is safe to escape it to prevent the error. + match_key = match_key.replace("++", r"\+\+") + return re.fullmatch(match_key, key) + def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: """Get keys that match the given pattern(s).""" all_keys = self._get_all_available_keys() @@ -155,9 +163,7 @@ def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: matches_found = False # Check for exact match - if any( - k for k in all_keys if k == attr_key or re.fullmatch(attr_key, k) - ): + if any(k for k in all_keys if self._key_matches(attr_key, k)): normalized_keys.add(attr_key) matches_found = True @@ -184,9 +190,7 @@ def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: return { matched for regex_key in normalized_keys - for matched in [ - k for k in all_keys if k == regex_key or re.fullmatch(regex_key, k) - ] + for matched in [k for k in all_keys if self._key_matches(str(regex_key), k)] } def mark_read(self, key_or_keys: str | set[str]) -> None: @@ -266,7 +270,7 @@ def _apply_regex_filter( ) -> set[str]: """Apply regex filter to attribute keys if provided.""" if regex: - return {k for k in attribute_keys if re.fullmatch(regex, k)} + return {k for k in attribute_keys if self._key_matches(regex, k)} return attribute_keys def _process_attr_key( From 0eb1073471dc98652c89cc4caf49474149ca39ab Mon Sep 17 00:00:00 2001 From: Nathan Stender Date: Mon, 8 Sep 2025 13:47:39 -0400 Subject: [PATCH 2/3] Fix --- src/allotropy/parsers/utils/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/allotropy/parsers/utils/json.py b/src/allotropy/parsers/utils/json.py index 264de8c410..19dcf0a6b6 100644 --- a/src/allotropy/parsers/utils/json.py +++ b/src/allotropy/parsers/utils/json.py @@ -88,7 +88,7 @@ def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: key_or_keys if isinstance(key_or_keys, set) else {key_or_keys} ) for matched in [ - k for k in self.data.keys() if self._key_matches(str(regex_key, str(k))) + k for k in self.data.keys() if self._key_matches(str(regex_key), str(k)) ] } From 9049861a81eff4bcbf307a27d7e6d476f1ea1da3 Mon Sep 17 00:00:00 2001 From: Nathan Stender Date: Mon, 8 Sep 2025 13:52:09 -0400 Subject: [PATCH 3/3] Fix typing --- src/allotropy/parsers/utils/json.py | 2 +- src/allotropy/parsers/utils/pandas.py | 2 +- src/allotropy/parsers/utils/strict_xml_element.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/allotropy/parsers/utils/json.py b/src/allotropy/parsers/utils/json.py index 19dcf0a6b6..b4e87d8807 100644 --- a/src/allotropy/parsers/utils/json.py +++ b/src/allotropy/parsers/utils/json.py @@ -79,7 +79,7 @@ def _key_matches(self, match_key: str, key: str) -> bool: # "++" can cause re.compile to fail. Since it is never a valid regex expression # it is safe to escape it to prevent the error. match_key = match_key.replace("++", r"\+\+") - return re.fullmatch(match_key, key) + return bool(re.fullmatch(match_key, key)) def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: return { diff --git a/src/allotropy/parsers/utils/pandas.py b/src/allotropy/parsers/utils/pandas.py index 3b20923bec..5b1e47f841 100644 --- a/src/allotropy/parsers/utils/pandas.py +++ b/src/allotropy/parsers/utils/pandas.py @@ -279,7 +279,7 @@ def _key_matches(self, match_key: str, key: str) -> bool: # "++" can cause re.compile to fail. Since it is never a valid regex expression # it is safe to escape it to prevent the error. match_key = match_key.replace("++", r"\+\+") - return re.fullmatch(match_key, key) + return bool(re.fullmatch(match_key, key)) def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: return { diff --git a/src/allotropy/parsers/utils/strict_xml_element.py b/src/allotropy/parsers/utils/strict_xml_element.py index 929a54080e..10f73d1a87 100644 --- a/src/allotropy/parsers/utils/strict_xml_element.py +++ b/src/allotropy/parsers/utils/strict_xml_element.py @@ -143,7 +143,7 @@ def _key_matches(self, match_key: str, key: str) -> bool: # "++" can cause re.compile to fail. Since it is never a valid regex expression # it is safe to escape it to prevent the error. match_key = match_key.replace("++", r"\+\+") - return re.fullmatch(match_key, key) + return bool(re.fullmatch(match_key, key)) def _get_matching_keys(self, key_or_keys: str | set[str]) -> set[str]: """Get keys that match the given pattern(s)."""