ERA-12662: Subject and source write parity (sync + async)#32
Open
JoshuaVulcan wants to merge 6 commits intomainfrom
Open
ERA-12662: Subject and source write parity (sync + async)#32JoshuaVulcan wants to merge 6 commits intomainfrom
JoshuaVulcan wants to merge 6 commits intomainfrom
Conversation
5 tasks
Fill sync/async gaps for subject and source write operations: Sync ERClient additions: - patch_subject(subject_id, data) for partial subject updates - get_source_assignments(subject_ids, source_ids) with optional filtering Async AsyncERClient additions: - post_subject(subject) to create new subjects - delete_subject(subject_id) to remove subjects - post_source(source) to create new sources - delete_source(source_id) to remove sources - _delete() helper method for DELETE HTTP operations Includes 16 new tests (async + sync) covering success paths, error handling (not found, forbidden, bad request, network errors), and parameter filtering for source assignments. Co-authored-by: Cursor <cursoragent@cursor.com>
Adds TestGetSourceSubjects class to sync_client tests covering: - successful retrieval with URL verification - empty results handling - 404 and 403 error cases Co-authored-by: Cursor <cursoragent@cursor.com>
e9518f1 to
05520c9
Compare
# Conflicts: # tests/sync_client/conftest.py
Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds missing subject/source write (and related read) endpoints to maintain sync/async API parity in ERClient and AsyncERClient, with new targeted test coverage for both clients.
Changes:
- Add sync
ERClientmethods:patch_subject,get_source_subjects,get_source_assignments. - Add async
AsyncERClientmethods:post_subject,delete_subject,post_source,delete_source. - Add new sync + async test suites covering these parity endpoints.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
erclient/client.py |
Introduces new sync and async client methods for subject/source write and related listing operations. |
tests/sync_client/test_subject_source_write.py |
Adds sync tests for new parity methods and verifies existing write methods. |
tests/async_client/test_subject_source_write.py |
Adds async tests for new async subject/source write methods using respx. |
💡 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
+179
to
+231
| # ---- get_source_subjects tests ---- | ||
|
|
||
| class TestGetSourceSubjects: | ||
| def test_get_source_subjects_success(self, er_client): | ||
| source_subjects_response = { | ||
| "data": [ | ||
| { | ||
| "content_type": "observations.subject", | ||
| "id": "d8ad9955-8301-43c4-9000-9a02f1cba675", | ||
| "name": "MMVessel", | ||
| "subject_type": "vehicle", | ||
| "subject_subtype": "vessel", | ||
| "is_active": True, | ||
| } | ||
| ], | ||
| "status": {"code": 200, "message": "OK"}, | ||
| } | ||
| with patch.object(er_client._http_session, 'get') as mock_get: | ||
| mock_get.return_value = _mock_response(200, source_subjects_response) | ||
| source_id = "119feb94-a6cc-4485-8614-06fb0abc2a9c" | ||
| result = er_client.get_source_subjects(source_id) | ||
| assert result == source_subjects_response["data"] | ||
| assert mock_get.called | ||
| url = mock_get.call_args[0][0] | ||
| assert f"source/{source_id}/subjects" in url | ||
|
|
||
| def test_get_source_subjects_empty(self, er_client): | ||
| empty_response = { | ||
| "data": [], | ||
| "status": {"code": 200, "message": "OK"}, | ||
| } | ||
| with patch.object(er_client._http_session, 'get') as mock_get: | ||
| mock_get.return_value = _mock_response(200, empty_response) | ||
| result = er_client.get_source_subjects("119feb94-a6cc-4485-8614-06fb0abc2a9c") | ||
| assert result == [] | ||
|
|
||
| def test_get_source_subjects_not_found(self, er_client): | ||
| with patch.object(er_client._http_session, 'get') as mock_get: | ||
| mock_get.return_value = _mock_response( | ||
| 404, ok=False, text='{"status":{"detail":"not found"}}' | ||
| ) | ||
| with pytest.raises(ERClientNotFound): | ||
| er_client.get_source_subjects("nonexistent-id") | ||
|
|
||
| def test_get_source_subjects_forbidden(self, er_client): | ||
| with patch.object(er_client._http_session, 'get') as mock_get: | ||
| mock_get.return_value = _mock_response( | ||
| 403, ok=False, text='{"status":{"detail":"forbidden"}}' | ||
| ) | ||
| with pytest.raises(ERClientPermissionDenied): | ||
| er_client.get_source_subjects("119feb94-a6cc-4485-8614-06fb0abc2a9c") | ||
|
|
||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
patch_subject(),get_source_subjects(), andget_source_assignments()to syncERClient(previously async-only)post_subject(),delete_subject(),post_source(),delete_source()and_delete()helper toAsyncERClient(previously sync-only)respx+ sync viaunittest.mock) covering success, error handling, and parameter filteringNew Methods
Sync
ERClient(new):patch_subject(subject_id, data)- partial update a subjectget_source_subjects(source_id)- get all subjects linked to a sourceget_source_assignments(subject_ids=None, source_ids=None)- list subject-source links with optional filteringAsync
AsyncERClient(new):post_subject(subject)- create a new subjectdelete_subject(subject_id)- delete a subjectpost_source(source)- create a new sourcedelete_source(source_id)- delete a source_delete(path)- internal async DELETE helperTest Plan
Jira
ERA-12662