fix: anchor string patterns in match() to consume full keypath#579
fix: anchor string patterns in match() to consume full keypath#579gaoflow wants to merge 1 commit into
Conversation
String patterns like '*a' were matched with regex.match() which only checks a prefix, so '(.)*a' matched 'ab' (consuming just 'a', leaving 'b' unconsumed). Fix by appending '$' to string-derived patterns so the entire keypath must be consumed. Raw compiled-regex patterns are unaffected and continue to use match() as before.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #579 +/- ##
=======================================
Coverage 98.32% 98.32%
=======================================
Files 64 64
Lines 2392 2393 +1
=======================================
+ Hits 2352 2353 +1
Misses 40 40
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes incorrect behavior in benedict.match() where string wildcard patterns were converted to regex and evaluated with regex.match(), allowing unintended prefix-only matches (e.g., patterns intended to match suffixes).
Changes:
- Anchor string-derived wildcard patterns so matches must consume the full keypath.
- Add a regression test to ensure suffix wildcard patterns (e.g.,
"*.jpg") don’t match longer strings like"*.jpg.bak".
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
benedict/core/match.py |
Anchors string-derived regex patterns to prevent unintended prefix matches. |
tests/core/test_match.py |
Adds a regression test covering suffix-wildcard matching behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # anchor to end so the full keypath must be consumed | ||
| pattern = pattern + "$" | ||
| regex = re.compile(pattern, flags=re.DOTALL) |
Bug
benedict.match()converts string wildcard patterns to regex and appliesregex.match(), which only verifies a prefix match — the rest of thekeypath is silently ignored.
For a pattern like
"*a"the transformation produces(.)*a. Becauseregex.match("ab")anchors at the start but not the end, it succeeds on"ab"(.consumes"a",amatches the first character,"b"isleft unconsumed). The result: keys that do not end in
"a"areerroneously returned.
Fix
Append
"$"to string-derived patterns before compiling so the fullkeypath must be consumed. Raw compiled-regex patterns (
re.Pattern)are unaffected and continue to use
regex.match()as before.Tests
Added
test_match_with_suffix_wildcardtotests/core/test_match.py;all 261 existing core + keypath tests continue to pass.