Skip to content

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

Merged
oleksandr-nc merged 5 commits intomainfrom
refactor/drop-sync-notes-weather-userstatus-activity
Mar 6, 2026
Merged

Drop sync API for Activity, Notes, User Status, Weather Status#405
oleksandr-nc merged 5 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

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

    • Many sync tests removed or replaced with 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

📝 Walkthrough

Walkthrough

Removes synchronous API classes for Activity, Notes, User Status, and Weather Status (async-first only), bumps package version to 0.30.0.dev0, adds README deprecation/migration notes for the sync API, converts/removes many tests to async, and makes talk-bot accessors tolerant of missing fields.

Changes

Cohort / File(s) Summary
Docs & Version
README.md, nc_py_api/_version.py
README updated to "async-first" with deprecation and migration guidance for sync APIs; package __version__ bumped to 0.30.0.dev0.
Sync 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) and removed NcSessionBasic usage; retained async counterparts and converted availability checks to async where applicable.
Client surface
nc_py_api/nextcloud.py
Removed public attributes/initialization for sync Activity/Notes/UserStatus/WeatherStatus from _NextcloudBasic; removed related set_user side-effects that reset activity/notes state.
Notes & User-status tests
tests/actual_tests/notes_test.py, tests/actual_tests/user_status_test.py
Converted many tests from sync (nc_*) to async (anc_*), renamed functions to *_async, and updated calls/assertions to use await.
Removed sync tests / updated other tests
tests/actual_tests/activity_test.py, tests/actual_tests/weather_status_test.py, tests/actual_tests/misc_test.py, tests/actual_tests/nc_app_test.py, tests/actual_tests/talk_test.py
Removed several synchronous tests (activity, weather, misc timeout, change_user) and updated Talk tests to use AsyncNextcloud with awaited calls.
Talk bot changes
nc_py_api/talk_bot.py, tests/_talk_bot.py, tests/_talk_bot_async.py
ObjectContent TypedDict made total=False (keys optional); object_content/object_media_type now tolerate missing keys (return {}/""); added early guard in coverage handlers to return when message.object_name != "message".

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 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 accurately summarizes the main change: removing synchronous API implementations for Activity, Notes, User Status, and Weather Status modules. It is concise, specific, and reflects the core objective of the PR.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 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

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.

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 94.47%. Comparing base (fb12595) to head (3bc85bc).
⚠️ Report is 1 commits behind head on main.

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   94.87%   94.47%   -0.40%     
==========================================
  Files          46       46              
  Lines        5540     5359     -181     
==========================================
- Hits         5256     5063     -193     
- Misses        284      296      +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.

bigcat88 and others added 2 commits February 19, 2026 17:46
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 (1)
nc_py_api/nextcloud.py (1)

49-80: 🛠️ Refactor suggestion | 🟠 Major

Add explicit migration stubs for removed sync attributes.

Line 49-Line 80 removes activity, notes, user_status, and weather_status from the sync surface entirely. This yields generic AttributeError at runtime for existing consumers. Consider adding deprecated properties on _NextcloudBasic that raise a clear migration error pointing to AsyncNextcloud.

Proposed compatibility shim (actionable failure path)
 class _NextcloudBasic(ABC):  # pylint: disable=too-many-instance-attributes
+    `@property`
+    def activity(self):
+        raise RuntimeError("Sync `activity` API was removed. Use `AsyncNextcloud.activity`.")
+
+    `@property`
+    def notes(self):
+        raise RuntimeError("Sync `notes` API was removed. Use `AsyncNextcloud.notes`.")
+
+    `@property`
+    def user_status(self):
+        raise RuntimeError("Sync `user_status` API was removed. Use `AsyncNextcloud.user_status`.")
+
+    `@property`
+    def weather_status(self):
+        raise RuntimeError("Sync `weather_status` API was removed. Use `AsyncNextcloud.weather_status`.")

As per coding guidelines, "nc_py_api/: This is the main library source code. Pay close attention to: - Public API changes and backwards compatibility"**.

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

In `@nc_py_api/nextcloud.py` around lines 49 - 80, Add explicit deprecated
property stubs on class _NextcloudBasic for the removed attributes activity,
notes, user_status, and weather_status that raise a clear migration error
directing users to AsyncNextcloud; implement them as read-only `@property`
accessors on _NextcloudBasic (matching names activity, notes, user_status,
weather_status) that raise an informative AttributeError (or a custom exception)
explaining the attribute was removed and instructing callers to migrate to
AsyncNextcloud, and include the property names and class _NextcloudBasic in the
error message to aid discovery.
🤖 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/nextcloud.py`:
- Around line 49-80: Add explicit deprecated property stubs on class
_NextcloudBasic for the removed attributes activity, notes, user_status, and
weather_status that raise a clear migration error directing users to
AsyncNextcloud; implement them as read-only `@property` accessors on
_NextcloudBasic (matching names activity, notes, user_status, weather_status)
that raise an informative AttributeError (or a custom exception) explaining the
attribute was removed and instructing callers to migrate to AsyncNextcloud, and
include the property names and class _NextcloudBasic in the error message to aid
discovery.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8144ca72-5b05-475d-b2b9-3497222016f8

📥 Commits

Reviewing files that changed from the base of the PR and between 074771c and 720c96e.

📒 Files selected for processing (2)
  • nc_py_api/_version.py
  • nc_py_api/nextcloud.py

@oleksandr-nc oleksandr-nc merged commit 19ed1e4 into main Mar 6, 2026
13 checks passed
@oleksandr-nc oleksandr-nc deleted the refactor/drop-sync-notes-weather-userstatus-activity branch March 6, 2026 07:52
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.

2 participants