Fix uncaught KeyError on date queries containing a stray pipe (#6835)

Date queries detect *relative* dates (`-1w`, `+3m`) with a small regex
whose character classes were written as if `|` meant alternation:

```python
relative_re = "(?P<sign>[+|-]?)(?P<quantity>[0-9]+)(?P<timespan>[y|m|w|d])"
```

Inside `[...]`, `|` is a literal member, so `[y|m|w|d]` also matches
`|`. A date query with a stray pipe — e.g. `beet list added:2000|2001`
(a natural mistake for someone expecting `|` to mean "or") — captures
`|` as the timespan, and `Period.parse` then evaluates
`relative_units["|"]`, raising an uncaught `KeyError` with a traceback.
Malformed date strings are meant to raise
`InvalidQueryArgumentValueError` (see `test_invalid_date_query`), which
upper layers render as a friendly "a valid date/time string" message.

### Fix

Drop the stray `|` from both character classes so the value falls
through to the normal invalid-date path:

```python
relative_re = "(?P<sign>[+-]?)(?P<quantity>[0-9]+)(?P<timespan>[ymwd])"
```

Before: `DateQuery("added", "2000|2001")` → `KeyError: '|'`
After: → `InvalidQueryArgumentValueError: '2000|2001' is not a valid
date/time string`

### Tests / changelog

- Added `test_pipe_in_relative_date_query` (fails before, passes after).
- Added a Bug-fixes changelog entry.

Disclosure: prepared with assistance from Claude (an AI tool); I
reviewed and verified the change locally (fail-before/pass-after).
This commit is contained in:
Šarūnas Nejus
2026-07-15 21:06:28 +01:00
committed by GitHub
3 changed files with 14 additions and 1 deletions

View File

@@ -704,7 +704,7 @@ class Period:
"w": 7,
"d": 1,
}
relative_re = "(?P<sign>[+|-]?)(?P<quantity>[0-9]+)(?P<timespan>[y|m|w|d])"
relative_re = "(?P<sign>[+-]?)(?P<quantity>[0-9]+)(?P<timespan>[ymwd])"
def __init__(self, date: datetime, precision: str) -> None:
"""Create a period with the given date (a `datetime` object) and

View File

@@ -88,6 +88,11 @@ Bug fixes
- :doc:`plugins/smartplaylist`: ``splupdate`` no longer crashes with
``TypeError: unhashable type: 'list'`` when a playlist configuration includes
a ``playlist:`` query. :bug:`5354`
- A date query containing a stray ``|`` (for example ``added:2000|2001``, as
might be typed by a user expecting ``|`` to mean "or") now raises a clean "a
valid date/time string" error instead of crashing with an uncaught
``KeyError``. A ``|`` was being accepted as a relative-date unit due to a
regular expression character-class typo.
..
For plugin developers

View File

@@ -231,6 +231,14 @@ class DateQueryConstructTest(unittest.TestCase):
with pytest.raises(InvalidQueryArgumentValueError):
DateQuery("added", q)
def test_pipe_in_relative_date_query(self):
# A stray "|" (e.g. a user expecting OR syntax like "added:2000|2001")
# must raise a clean InvalidQueryArgumentValueError rather than an
# uncaught KeyError from the relative-date parser.
for q in ["2000|2001", "1|", "5|3d"]:
with pytest.raises(InvalidQueryArgumentValueError):
DateQuery("added", q)
def test_datetime_uppercase_t_separator(self):
date_query = DateQuery("added", "2000-01-01T12")
assert date_query.interval.start == datetime(2000, 1, 1, 12)