Skip to content

Comments

Drop sync API for Activity, Notes, User Status, Weather Status#405

Open
bigcat88 wants to merge 3 commits intomainfrom
refactor/drop-sync-notes-weather-userstatus-activity
Open

Drop sync API for Activity, Notes, User Status, Weather Status#405
bigcat88 wants to merge 3 commits intomainfrom
refactor/drop-sync-notes-weather-userstatus-activity

Conversation

@bigcat88
Copy link
Contributor

@bigcat88 bigcat88 commented Feb 19, 2026

Summary

  • Remove sync wrapper classes (_ActivityAPI, _NotesAPI, _UserStatusAPI, _WeatherStatusAPI) from 4 module files
  • Remove sync registrations and state resets from _NextcloudBasic / NextcloudApp
  • Remove all corresponding sync tests (68 test cases); async tests fully cover the same functionality
  • Fix test_get_conversations_include_status_async in talk_test to use AsyncNextcloud instead of sync Nextcloud for user_status setup
  • Bump version to 0.30.0
  • Add async-first deprecation notice to README

Motivation

Moving nc_py_api toward async-only. This is the first batch of sync removals, targeting modules where async tests already mirror every sync test 1:1.

Test plan

  • Pre-commit passes (isort, black, ruff, pylint)
  • Full test suite: 538 passed, 6 skipped (same skips as before)
  • grep -r '_NotesAPI\|_WeatherStatusAPI\|_UserStatusAPI\|_ActivityAPI' returns zero hits
  • No remaining sync references to removed modules in tests

Summary by CodeRabbit

  • New Features

    • Library is async-first with a full asynchronous API; synchronous wrappers are being phased out.
  • Documentation

    • Deprecation notice for the sync API effective v0.30.0 and migration guidance to async equivalents.
  • Refactor

    • Synchronous implementations for Activity, Notes, User Status and Weather Status removed; async counterparts remain.
  • Tests

    • Many sync tests converted to async variants.
  • Bug Fixes

    • Safer handling for missing talk-bot fields and early-exit for non-message objects.

Remove sync wrapper classes (_ActivityAPI, _NotesAPI, _UserStatusAPI,
_WeatherStatusAPI) and their registrations in _NextcloudBasic. Async
implementations remain unchanged.

- Remove sync classes and NcSessionBasic imports from 4 module files
- Remove sync type annotations, __init__ lines, and state resets from nextcloud.py
- Remove all sync tests; async tests fully cover the same functionality
- Fix talk_test async test to use AsyncNextcloud for user_status setup
- Bump version to 0.30.0
- Add async-first deprecation notice to README
@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Removes synchronous API classes for Activity, Notes, User Status, and Weather Status, making the library async-first; bumps version to 0.30.0 and adds README deprecation/migration notes. Tests were converted to async or removed to reflect async-only usage; some talk-bot helpers were made tolerant to missing fields.

Changes

Cohort / File(s) Summary
Documentation & Version
README.md, nc_py_api/_version.py
Updated README to "async-first", added deprecation/migration notes for the sync API starting v0.30.0, and bumped __version__ to 0.30.0.
Core API removals
nc_py_api/activity.py, nc_py_api/notes.py, nc_py_api/user_status.py, nc_py_api/weather_status.py
Removed synchronous API classes (_ActivityAPI, _NotesAPI, _UserStatusAPI, _WeatherStatusAPI). Retained async counterparts and removed NcSessionBasic imports/usages in favor of AsyncNcSessionBasic.
Client surface
nc_py_api/nextcloud.py
Removed public attributes/initialization for sync Activity/Notes/UserStatus/WeatherStatus from _NextcloudBasic and removed their session-reset side effects in set_user.
Notes tests
tests/actual_tests/notes_test.py
Rewrote multiple Notes tests to async variants using the anc fixture and await (settings, create/delete, get/update, invalid param).
User status tests
tests/actual_tests/user_status_test.py
Converted the user-status test suite from sync to async (many *_async replacements), migrated fixtures to anc, and updated assertions to await async results.
Weather & Activity tests
tests/actual_tests/weather_status_test.py, tests/actual_tests/activity_test.py
Removed synchronous Weather Status and Activity tests; async tests remain as primary coverage.
Misc / App / Talk tests
tests/actual_tests/misc_test.py, tests/actual_tests/nc_app_test.py, tests/actual_tests/talk_test.py
Removed select sync tests (test_ocs_timeout, test_change_user), updated Talk test to use AsyncNextcloud and awaited calls.
Talk bot helpers & tests
nc_py_api/talk_bot.py, tests/_talk_bot.py, tests/_talk_bot_async.py
Made ObjectContent TypedDict optional (total=False); object accessors tolerate missing content/mediaType (return {} or ""); added early-guard in coverage handlers to return when message.object_name != "message".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main change: removing synchronous API implementations for four modules (Activity, Notes, User Status, Weather Status).

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

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/drop-sync-notes-weather-userstatus-activity

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

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.

Caution

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

⚠️ Outside diff range comments (4)
nc_py_api/activity.py (1)

186-188: ⚠️ Potential issue | 🟡 Minor

Typo in docstring: "avalaible" → "available".

📝 Proposed fix
     async def get_filters(self) -> list[ActivityFilter]:
-        """Returns avalaible activity filters."""
+        """Returns available activity filters."""
         return [ActivityFilter(i) for i in await self._session.ocs("GET", self._ep_base + "/api/v2/activity/filters")]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nc_py_api/activity.py` around lines 186 - 188, Fix the typo in the docstring
for get_filters: change "avalaible" to "available" in the triple-quoted string
of the async def get_filters(self) -> list[ActivityFilter] method so the
docstring reads "Returns available activity filters." (locate the get_filters
method and its docstring near ActivityFilter and self._session usage).
nc_py_api/notes.py (1)

77-78: 🧹 Nitpick | 🔵 Trivial

utcfromtimestamp is deprecated since Python 3.12.

Use datetime.datetime.fromtimestamp(modified, tz=datetime.timezone.utc) instead for forwards compatibility.

♻️ Proposed fix
     `@property`
     def last_modified(self) -> datetime.datetime:
         """Last modified date/time of the note.

         If not provided on note creation or content update, the current time is used.
         """
         modified = self._raw_data.get("modified", 0)
-        return datetime.datetime.utcfromtimestamp(modified).replace(tzinfo=datetime.timezone.utc)
+        return datetime.datetime.fromtimestamp(modified, tz=datetime.timezone.utc)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nc_py_api/notes.py` around lines 77 - 78, The code in the method that reads
self._raw_data ("modified = self._raw_data.get(\"modified\", 0)" followed by
"datetime.datetime.utcfromtimestamp...") uses deprecated utcfromtimestamp;
change it to use datetime.datetime.fromtimestamp(modified,
tz=datetime.timezone.utc) so the method (where this appears — the accessor that
returns the modified timestamp) remains forward compatible; ensure you import
datetime.timezone usage if needed and keep the fallback default behavior for
modified unchanged.
tests/actual_tests/user_status_test.py (1)

21-30: ⚠️ Potential issue | 🟡 Minor

Remove assertion status_icon is None—the property returns empty string by default.

The status_icon property (nc_py_api/user_status.py:66–68) returns self._raw_data.get("icon", ""), which means it returns an empty string "" when the icon key is absent. The return type is str, never None. The assertion at line 23 of the test should be assert r1.status_icon == "" instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/actual_tests/user_status_test.py` around lines 21 - 30, The test
_test_get_status incorrectly asserts r1.status_icon is None but the
CurrentUserStatus.status_icon property returns an empty string by default;
update the assertion in _test_get_status to assert r1.status_icon == "" so it
matches the implementation of status_icon (which reads
self._raw_data.get("icon", "") in CurrentUserStatus).
nc_py_api/user_status.py (1)

198-203: ⚠️ Potential issue | 🟠 Major

Fix return type mismatch in restore_backup_status.

The method declares return type CurrentUserStatus | None but returns the raw dict from the OCS call. Other methods in this class consistently wrap results—e.g., get_current() and get() both wrap with CurrentUserStatus(...) and UserStatus(...) respectively. Should be return CurrentUserStatus(result) if result else None.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nc_py_api/user_status.py` around lines 198 - 203, The restore_backup_status
method returns the raw OCS dict but is annotated to return CurrentUserStatus |
None; update restore_backup_status to wrap the OCS response in CurrentUserStatus
(i.e., return CurrentUserStatus(result) if result else None) to match the
pattern used by get_current() and get(), keeping the existing capability checks
and the _session.ocs call intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@nc_py_api/activity.py`:
- Around line 186-188: Fix the typo in the docstring for get_filters: change
"avalaible" to "available" in the triple-quoted string of the async def
get_filters(self) -> list[ActivityFilter] method so the docstring reads "Returns
available activity filters." (locate the get_filters method and its docstring
near ActivityFilter and self._session usage).

In `@nc_py_api/notes.py`:
- Around line 77-78: The code in the method that reads self._raw_data ("modified
= self._raw_data.get(\"modified\", 0)" followed by
"datetime.datetime.utcfromtimestamp...") uses deprecated utcfromtimestamp;
change it to use datetime.datetime.fromtimestamp(modified,
tz=datetime.timezone.utc) so the method (where this appears — the accessor that
returns the modified timestamp) remains forward compatible; ensure you import
datetime.timezone usage if needed and keep the fallback default behavior for
modified unchanged.

In `@nc_py_api/user_status.py`:
- Around line 198-203: The restore_backup_status method returns the raw OCS dict
but is annotated to return CurrentUserStatus | None; update
restore_backup_status to wrap the OCS response in CurrentUserStatus (i.e.,
return CurrentUserStatus(result) if result else None) to match the pattern used
by get_current() and get(), keeping the existing capability checks and the
_session.ocs call intact.

In `@tests/actual_tests/user_status_test.py`:
- Around line 21-30: The test _test_get_status incorrectly asserts
r1.status_icon is None but the CurrentUserStatus.status_icon property returns an
empty string by default; update the assertion in _test_get_status to assert
r1.status_icon == "" so it matches the implementation of status_icon (which
reads self._raw_data.get("icon", "") in CurrentUserStatus).

@bigcat88
Copy link
Contributor Author

Pushed fix for flaky test_chat_bot_receive_message_async CI failure — handle missing content/mediaType keys in TalkBotMessage for system messages.

…ssages

The bot callback fires for all message types including system messages
(conversation created, bot joined, etc.) which lack object.content and
object.mediaType keys. This caused intermittent KeyError crashes in CI.

- Make object_content return {} when content key is missing
- Make object_media_type return "" when mediaType key is missing
- Skip bot handler assertions for non-user messages in test helpers
@bigcat88 bigcat88 force-pushed the refactor/drop-sync-notes-weather-userstatus-activity branch from c3bb50b to 19a8e27 Compare February 19, 2026 15:11
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nc_py_api/talk_bot.py`:
- Around line 64-72: The method object_content() can return an empty dict but
ObjectContent currently requires "message" and "parameters"; update the
TypedDict declaration for ObjectContent to make those keys optional (use
total=False or mark keys as Optional) so the type matches possible empty dict
returns, then run the type checker; locate the ObjectContent TypedDict
definition and change it to a non-total TypedDict (or make both keys Optional)
to resolve the contract violation referenced by object_content().

@codecov
Copy link

codecov bot commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 66.66667% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.55%. Comparing base (5b2720e) to head (074771c).

Files with missing lines Patch % Lines
nc_py_api/talk_bot.py 16.66% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #405      +/-   ##
==========================================
- Coverage   93.99%   93.55%   -0.44%     
==========================================
  Files          45       45              
  Lines        5392     5211     -181     
==========================================
- Hits         5068     4875     -193     
- Misses        324      336      +12     
Files with missing lines Coverage Δ
nc_py_api/_version.py 100.00% <100.00%> (ø)
nc_py_api/activity.py 100.00% <100.00%> (ø)
nc_py_api/nextcloud.py 94.78% <100.00%> (-1.48%) ⬇️
nc_py_api/notes.py 100.00% <100.00%> (ø)
nc_py_api/user_status.py 98.43% <100.00%> (+0.54%) ⬆️
nc_py_api/weather_status.py 100.00% <100.00%> (ø)
nc_py_api/talk_bot.py 60.73% <16.66%> (-1.14%) ⬇️

... and 2 files with indirect coverage changes

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

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