Skip to content

todo_complete crashes on recurring VTODO with COUNT (re.replace + precedence bug) #120

Description

@tobixen

⚠️ This issue is AI-generated (Claude Opus 4.8 via Claude Code) on behalf of tobixen

Completing a recurring VTODO whose RRULE contains a COUNT= crashes in todo_complete().

In calendar_cli/legacy.py (around line 684):

count_search = re.search(r'COUNT=(\d+)', completed_task.instance.vtodo.rrule.value)
if count_search:
    remaining_task.instance.vtodo.rrule.value = re.replace(r'COUNT=(\d+)', 'COUNT=%d' % int(count_search.group(1))-1)

That single line has three independent bugs:

  1. re.replace does not exist. The re module has no replace function — the intended call is re.sub. This alone raises AttributeError.
  2. The subject string is missing. re.sub takes (pattern, repl, string), but the rrule value to operate on is never passed.
  3. Operator-precedence bug. 'COUNT=%d' % int(...) - 1 parses as ('COUNT=%d' % int(...)) - 1, i.e. str - int, which raises TypeError. The intent was to decrement inside the parentheses: int(...) - 1.

The net effect: any code path that reaches this branch — completing a recurring task whose RRULE carries a COUNT, in order to decrement the remaining occurrences — raises an exception.

Likely intended implementation:

if count_search:
    new_count = int(count_search.group(1)) - 1
    remaining_task.instance.vtodo.rrule.value = re.sub(
        r'COUNT=(\d+)',
        'COUNT=%d' % new_count,
        remaining_task.instance.vtodo.rrule.value,
    )

There is currently no test covering completion of recurring todos with a COUNT; a regression test should accompany the fix.

Context: surfaced by ruff during project modernization. The W605 invalid-escape warnings on these regex literals were already fixed (raw strings); the logic bugs above were intentionally left out of scope for that change.

⚠️ This issue is AI-generated (Claude Opus 4.8 via Claude Code) on behalf of tobixen

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions