Skip to content

Return None from next_available_time when key has never been used#359

Merged
kitsuyui merged 4 commits into
mainfrom
fix/audit-datetime-min-as-sentinel-001
Jul 11, 2026
Merged

Return None from next_available_time when key has never been used#359
kitsuyui merged 4 commits into
mainfrom
fix/audit-datetime-min-as-sentinel-001

Conversation

@kitsuyui

@kitsuyui kitsuyui commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

next_available_time returned datetime.datetime.min as an implicit sentinel
for "this key has never been used." The return type was datetime.datetime with
no documentation, so callers could not distinguish a "never used" key from a key
that was genuinely last used near the epoch. Mixing the sentinel with a
timezone-aware datetime also raised TypeError.

Changes

  • throttle_controller/simple.py / throttle_controller/protocol.py:
    Change the return type of next_available_time from datetime.datetime to
    datetime.datetime | None. Return None when the key has never been used.
  • throttle_controller/simple.py: Update wait_time_for to treat None as
    zero wait (i.e. the key is immediately available).
  • tests/test_simple.py: Update test_next_available_time to assert is None
    for an unused key and to check the non-None path with a type-safe assertion.

Validation

  • uv run poe format — reformatted
  • uv run poe check — all checks pass (ruff + mypy)
  • uv run pytest — all tests pass
    (pre-existing test_throttling timing flakiness is unrelated to this change)

Trade-offs

This is a breaking change for callers that compare next_available_time(key)
against datetime.datetime.min or treat the return value as always non-None.
Type checkers will surface these sites as errors. The default wait_if_needed
path is unaffected because it already guards on _has_ever_used.

next_available_time returned datetime.datetime.min as a sentinel for
"never used", but the return type was datetime.datetime with no
documentation. Callers could not distinguish "never used" from a real
past timestamp, and mixing the sentinel with timezone-aware datetimes
raised TypeError.

Change the return type to datetime.datetime | None and return None for
keys with no usage history. Update wait_time_for to treat None as zero
wait. Update the Protocol declaration and the existing test accordingly.
@kitsuyui kitsuyui force-pushed the fix/audit-datetime-min-as-sentinel-001 branch from 22237b6 to c23e1c4 Compare June 5, 2026 01:25
@github-actions

Copy link
Copy Markdown

Code Metrics Report

main (02cd315) #359 (364e152) +/-
Coverage 100.0% 100.0% 0.0%
Code to Test Ratio 1:0.0 1:0.0 +0.0
Test Execution Time 1s 1s 0s
Details
  |                     | main (02cd315) | #359 (364e152) | +/-  |
  |---------------------|----------------|----------------|------|
  | Coverage            |         100.0% |         100.0% | 0.0% |
  |   Files             |              5 |              5 |    0 |
  |   Lines             |            120 |            125 |   +5 |
+ |   Covered           |            120 |            125 |   +5 |
+ | Code to Test Ratio  |          1:0.0 |          1:0.0 | +0.0 |
  |   Code              |         319523 |         319531 |   +8 |
+ |   Test              |            357 |            360 |   +3 |
  | Test Execution Time |             1s |             1s |   0s |

Code coverage of files in pull request scope (100.0% → 100.0%)

Files Coverage +/- Status
throttle_controller/protocol.py 100.0% 0.0% modified
throttle_controller/simple.py 100.0% 0.0% modified

Reported by octocov

@kitsuyui kitsuyui merged commit a171183 into main Jul 11, 2026
10 checks passed
@kitsuyui kitsuyui deleted the fix/audit-datetime-min-as-sentinel-001 branch July 11, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant