Skip to content

ERA-12660: messages sync/async parity#29

Open
JoshuaVulcan wants to merge 5 commits intomainfrom
ERA-12660/messages-parity
Open

ERA-12660: messages sync/async parity#29
JoshuaVulcan wants to merge 5 commits intomainfrom
ERA-12660/messages-parity

Conversation

@JoshuaVulcan
Copy link
Copy Markdown
Contributor

@JoshuaVulcan JoshuaVulcan commented Feb 10, 2026

Summary

Achieves full sync/async parity for the messages interface in er-client (ERA-12660).

Sync ERClient

  • Add post_message(message) — POST to messages endpoint
  • Add get_message(message_id) — GET single message by ID from messages/{id}
  • Fix get_messages() pagination — the existing method had a bug referencing undefined variable p; now properly carries pagination params forward
  • Accept **kwargs in get_messages() for query param pass-through (e.g. page_size)

Async AsyncERClient

  • Add get_messages(**kwargs) — async generator with automatic pagination via _get_data()
  • Add get_message(message_id) — GET single message by ID
  • Add delete_message(message_id) — DELETE message by ID
  • Add _delete() convenience method — enables DELETE operations in the async client
  • Handle HTTP 204 No Content — async _call() now returns None for 204 responses instead of failing on empty JSON parse

Tests

  • Created new tests/sync_client/ test suite with conftest, fixtures, and tests
  • 18 new tests covering all new methods (sync + async) with success, pagination, empty, not-found, and forbidden scenarios

Merge coordination

This PR adds async _delete() and 204 handling in _call(). PRs #28, #32, and #34 add the same. Whichever merges first, the others should rebase to avoid duplicate/conflicting edits. tests/sync_client/conftest.py may also conflict with other PRs; rebase as needed.

Test plan

  • All 110 tests pass locally (pytest tests/ -v)
  • Verify post_message() against a live ER instance (sync)
  • Verify get_messages() pagination works correctly with real paginated data
  • Verify get_message(id) returns expected detail for a known message
  • Verify delete_message(id) successfully removes a message (async)

Sync ERClient:
- Add post_message() for creating messages
- Add get_message(id) for fetching a single message by ID
- Fix get_messages() pagination bug (undefined variable 'p')
- Accept **kwargs in get_messages() for query param pass-through

Async AsyncERClient:
- Add get_messages() as an async generator with automatic pagination
- Add get_message(id) for fetching a single message by ID
- Add delete_message(id) for deleting messages
- Add _delete() convenience method to async client
- Handle HTTP 204 No Content responses in async _call()

Tests:
- Add sync test suite (tests/sync_client/) with conftest and fixtures
- Add comprehensive tests for all new sync methods (post, get, get_list, delete)
- Add comprehensive tests for all new async methods (get_messages, get_message, delete_message)
- Cover success, pagination, empty results, not-found, and forbidden cases

Co-authored-by: Cursor <cursoragent@cursor.com>
@JoshuaVulcan JoshuaVulcan added autoreviewing PR is currently being auto-reviewed and removed autoreviewing PR is currently being auto-reviewed labels Feb 11, 2026
JoshuaVulcan added a commit that referenced this pull request Feb 11, 2026
…g to _call()

- Async _delete() now delegates to _call(path=path, payload=None, method='DELETE', params=params)
- Add 204 / empty-body handling in async _call() so DELETE responses don't trigger JSON parse
- Aligns with PR review: use _call() delegation pattern like PRs #28, #29, #34; reduces merge conflict

Co-authored-by: Cursor <cursoragent@cursor.com>
JoshuaVulcan and others added 3 commits February 11, 2026 10:56
# Conflicts:
#	erclient/client.py
#	tests/sync_client/conftest.py
…; fix message test URLs and 204 assert

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@JoshuaVulcan JoshuaVulcan requested a review from a team as a code owner February 12, 2026 01:45
Copy link
Copy Markdown
Contributor

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

Adds missing Messages endpoints to both sync and async ER clients and introduces new test coverage to ensure sync/async parity for messages operations.

Changes:

  • Add sync ERClient.post_message() and ERClient.get_message(), and fix ERClient.get_messages() pagination while allowing **kwargs passthrough.
  • Add async AsyncERClient.get_messages() (async generator), plus get_message() and delete_message().
  • Add new sync and async tests for message create/list/get/delete scenarios (including pagination and error cases).

Reviewed changes

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

Show a summary per file
File Description
erclient/client.py Adds messages methods for sync/async clients and updates sync messages pagination behavior.
tests/sync_client/test_post_message.py Sync tests for posting messages (success + error scenarios).
tests/sync_client/test_get_messages.py Sync tests for listing messages (single page, pagination, empty, kwargs passthrough).
tests/sync_client/test_get_message.py Sync tests for getting a single message (success + 404).
tests/sync_client/test_delete_message.py Sync tests for deleting a message (success + error scenarios).
tests/async_client/test_get_messages.py Async tests for listing messages via async generator (single page, pagination, empty).
tests/async_client/test_get_message.py Async tests for getting a single message (success + 404).
tests/async_client/test_delete_message.py Async tests for deleting a message (success + 404).

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

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +73 to +78
call_kwargs = mock_get.call_args
assert call_kwargs is not None
assert "params" in call_kwargs.kwargs or (
len(call_kwargs.args) > 1
or (call_kwargs.kwargs.get("params", {}).get("page_size") == 50)
)
Comment on lines +96 to +99
route = respx_mock.get("messages").return_value = httpx.Response(
httpx.codes.OK,
json={"data": get_messages_single_page_response},
)
"""
Delete a message by ID.
:param message_id: UUID of the message
:return: response data
Comment on lines +653 to +655
url, query_params = split_link(results['next'])
params['page'] = query_params['page']
results = self._get(path='messages', params=params)
@@ -0,0 +1,78 @@
import json
from unittest.mock import patch, MagicMock, call
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