Skip to content

Conversation

@bouwew
Copy link
Contributor

@bouwew bouwew commented Jan 27, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Improved clock synchronization to detect day/month drift and enforce device-side clock updates to prevent incorrect timestamps at month boundaries.
  • Tests

    • Added a month-end clock synchronization test and expanded test data to cover this edge case.
  • Documentation

    • Released v0.47.2 (2026-01-29) changelog entry referencing PR 400 and retaining the Test/validate for Python 3.14 note.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

📝 Walkthrough

Walkthrough

Replaces "Ongoing" with a v0.47.2 changelog entry, refactors Circle.clock_synchronize() to use an extracted _send_clock_set_req() and early weekday drift check, adds a month-end clock-rollover test, extends test response data, and bumps pyproject version to 0.47.2.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Replaced "## Ongoing" with a v0.47.2 entry (2026-01-29) listing PR 400 (Fix for Issue #399) and retaining the Python 3.14 test/validate bullet.
Circle clock sync implementation
plugwise_usb/nodes/circle.py
Refactored clock_synchronize() to perform an early weekday drift check, removed the local days-diff timestamp adjustment, and added async def _send_clock_set_req(self) -> bool to centralize sending CircleClockSetRequest; clock_synchronize() delegates to this helper when drift is detected or exceeded.
Tests — month-end rollover
tests/test_usb.py, tests/stick_test_data.py
Added test_clock_synchronize_month_overflow to tests/test_usb.py and appended a corresponding Circle+ clock-set response entry to RESPONSE_MESSAGES in tests/stick_test_data.py.
Project version
pyproject.toml
Bumped project version from 0.47.1 to 0.47.2.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • dirixmjm
  • ArnoutD
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title "Solve monthly overflow as reported in #399" directly matches the PR's main objective of fixing the monthly overflow issue described in issue #399, as evidenced by version bump, new test case, and code changes to handle clock drift edge cases.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-399

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 27, 2026

Codecov Report

❌ Patch coverage is 92.30769% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.08%. Comparing base (32d8653) to head (574a483).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
tests/test_usb.py 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #400      +/-   ##
==========================================
+ Coverage   82.05%   82.08%   +0.03%     
==========================================
  Files          36       36              
  Lines        8156     8181      +25     
==========================================
+ Hits         6692     6715      +23     
- Misses       1464     1466       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@plugwise_usb/nodes/circle.py`:
- Around line 885-891: The month overflow handling around calculating
circle_timestamp is wrong: when (difference := days_diff - days_to_end_of_month)
> 0 you adjust corrected_day but do not advance the month, producing incorrect
dates; replace the manual day correction logic (the block using
last_day_of_month, days_to_end_of_month, corrected_day and
dt_now.replace(day=...)) by computing circle_timestamp as dt_now +
timedelta(days=days_diff) (using the existing dt_now and days_diff variables) so
month/year boundaries are handled correctly and remove the fragile
corrected_day/replace logic.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes clock synchronization date calculation when the target weekday crosses a month boundary (avoiding invalid datetime.replace(day=...) behavior at month-end).

Changes:

  • Update clock_synchronize() to compute the target date via dt_now + timedelta(days=...) to handle month rollovers safely.
  • Add an “Ongoing” changelog entry referencing the PR/issue.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
plugwise_usb/nodes/circle.py Switches clock-sync date computation to timedelta arithmetic to prevent month-end overflow.
CHANGELOG.md Documents the fix in the ongoing changelog section.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@bouwew bouwew marked this pull request as ready for review January 27, 2026 19:40
@bouwew bouwew requested a review from a team as a code owner January 27, 2026 19:40
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@tests/test_usb.py`:
- Around line 3043-3083: The test_test_clock_synchronize_month_overflow case
doesn't force a month rollover because the frozen date "2026-01-31" is already
Saturday (weekday 5) and mock_clock_get_send sets response.day_of_week.value = 5
so days_diff == 0; update the test so the mocked day_of_week differs by +1 to
force crossing into February (e.g., set response.day_of_week.value = 6) or
change the frozen time in the `@freeze_time` decorator to a Friday date so that
mock_clock_get_send's day_of_week=5 results in a +1 day rollover; modify the
mock_clock_get_send implementation (and/or the freeze_time value) inside
test_clock_synchronize_month_overflow to ensure days_diff != 0 and the code path
that adds timedelta(days=1) is exercised.

Copy link
Contributor

@dirixmjm dirixmjm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
Bedankt voor de actie.

@bouwew
Copy link
Contributor Author

bouwew commented Jan 28, 2026

@dirixmjm Thanks, but I'm not there yet, trying to recreate the ValueError in the original code with the added testcase.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@plugwise_usb/nodes/circle.py`:
- Around line 912-913: The docstring for async def _send_clock_set_req currently
incorrectly references "CirclePlusRealTimeClockSetRequest"; update it to
accurately describe that this method sends a CircleClockSetRequest (e.g., "Send
CircleClockSetRequest.") so the docstring matches the implemented behavior in
_send_clock_set_req and avoids confusion with CirclePlus methods.
- Around line 883-888: The early return calls _send_clock_set_req() when
dt_now.weekday() != response.day_of_week.value but the null-check for
self._node_protocols happens later, which can cause an AttributeError; either
move the existing self._node_protocols is None check so it runs before the early
return or add the same guard at the start of _send_clock_set_req() (and
return/raise gracefully) so _send_clock_set_req() never accesses
self._node_protocols.max when _node_protocols is None; update the call site or
the helper accordingly and ensure logging/behavior remains consistent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugwise_usb/nodes/circle.py (1)

910-923: Helper extraction looks good, but needs the null guard.

The refactoring to extract _send_clock_set_req() follows the pattern established in circle_plus.py and improves code reuse. The implementation is correct, but as noted above, the method should include the _node_protocols null check internally to protect all callers.

Once the null guard is added to the helper, the redundant check at lines 906-909 can be removed since both call sites will be protected by the method itself.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
E Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@bouwew bouwew merged commit cc6dd34 into main Jan 29, 2026
17 of 18 checks passed
@bouwew bouwew deleted the fix-399 branch January 29, 2026 18:24
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.

4 participants