From 0bcec8163c198be7e88b11351fbaeff08c7bc51c Mon Sep 17 00:00:00 2001 From: simonwt Date: Thu, 16 Apr 2026 21:31:32 +0100 Subject: [PATCH] Wrappers accept item_key where possible More tests --- development.md | 18 -------- .../wrappers/comment/create_comment.py | 9 +++- .../wrappers/post/create_post.py | 8 +++- .../wrappers/post/update_post.py | 10 +++- .../wrappers/reaction/react.py | 15 +++++- .../wrappers/trust/trust.py | 5 +- .../wrappers/vote/votecast.py | 17 ++++++- tests/apiclient.py | 2 +- tests/wrappers/react.py | 18 +++++++- tests/wrappers/trust.py | 2 +- tests/wrappers/update_post.py | 46 ++++++++++++++++++- tests/wrappers/vote.py | 21 ++++++++- 12 files changed, 140 insertions(+), 31 deletions(-) diff --git a/development.md b/development.md index 17ec664..6485a6d 100644 --- a/development.md +++ b/development.md @@ -26,24 +26,6 @@ potentially misleading. 2. Make more wrappers 3. Write more documentation 4. Wrappers should also accept actual keys for when you know them -5. Use this: - -```python -try: - # NOTE: Maybe define self.session = requests.Session() in an __init__ or similar and use it here instead of the 'with' block for better performance. - # Session for connection pooling and performance improvement - with requests.Session() as session: - # Update session headers once instead of every request - session.headers.update(headers) - - # GET requests to fetch normal and removed posts - res_n = session.get(url_normal, timeout=60) - # res_r = session.get(url_removed, timeout=60) - - # Checking if both requests are good before proceeding - res_n.raise_for_status() - # res_r.raise_for_status() -``` Trust diff --git a/src/trustcafeapiwrapper/wrappers/comment/create_comment.py b/src/trustcafeapiwrapper/wrappers/comment/create_comment.py index 32f4f1d..a01d0b3 100644 --- a/src/trustcafeapiwrapper/wrappers/comment/create_comment.py +++ b/src/trustcafeapiwrapper/wrappers/comment/create_comment.py @@ -1,7 +1,14 @@ from trustcafeapiwrapper.utils.get_parent_pksk_from_path import get_parent_pksk_from_path from trustcafeapiwrapper.utils.get_post_pksk import get_post_pksk -def create_comment(comment_text, post_slug=None, parent_path=None, post_key=None, blur_label=None, version=3): +def create_comment( + comment_text:str, + post_slug:str|None=None, + parent_path:str|None=None, + post_key:dict|None=None, + blur_label:str|None=None, + version:int=3 + ): """ Creates a new comment. diff --git a/src/trustcafeapiwrapper/wrappers/post/create_post.py b/src/trustcafeapiwrapper/wrappers/post/create_post.py index af25048..4c52e0a 100644 --- a/src/trustcafeapiwrapper/wrappers/post/create_post.py +++ b/src/trustcafeapiwrapper/wrappers/post/create_post.py @@ -1,6 +1,12 @@ from trustcafeapiwrapper.utils.get_parent_pksk_from_path import get_parent_pksk_from_path -def create_post(post_text, parent_path='/', blur_label=None, card_url=None, collaborative=False): +def create_post( + post_text:str, + parent_path:str|None='/', + blur_label:str|None=None, + card_url:str|None=None, + collaborative:bool=False + ): """ Creates a new post. diff --git a/src/trustcafeapiwrapper/wrappers/post/update_post.py b/src/trustcafeapiwrapper/wrappers/post/update_post.py index c4b3cfe..7fc64b2 100644 --- a/src/trustcafeapiwrapper/wrappers/post/update_post.py +++ b/src/trustcafeapiwrapper/wrappers/post/update_post.py @@ -1,6 +1,14 @@ from trustcafeapiwrapper.utils import get_post_pksk, get_parent_pksk_from_path -def update_post( post_text, post_path=None, parent_path='/', post_key=None, blur_label=None, card_url=None, collaborative=False): +def update_post( + post_text:str, + post_path:str|None=None, + parent_path:str|None='/', + post_key:dict|None=None, + blur_label:str|None=None, + card_url:str|None=None, + collaborative:bool=False + ): """ Updates an existing post. diff --git a/src/trustcafeapiwrapper/wrappers/reaction/react.py b/src/trustcafeapiwrapper/wrappers/reaction/react.py index 26bc2e0..b46ae3f 100644 --- a/src/trustcafeapiwrapper/wrappers/reaction/react.py +++ b/src/trustcafeapiwrapper/wrappers/reaction/react.py @@ -1,6 +1,11 @@ from trustcafeapiwrapper.utils import get_child_spksk_from_paths -def react(reaction_type: str, parent_path: str, item_path: str): +def react( + reaction_type: str, + parent_path: str|None=None, + item_path: str|None=None, + item_key: dict|None=None + ): """ React to something. ie a post or a comment. This is one endpoint for creating, updating and deleting reactions. @@ -12,7 +17,13 @@ def react(reaction_type: str, parent_path: str, item_path: str): dict: A dictionary containing the job name and payload for creating the post that will be processed by the API client wrapper function. """ - parent = get_child_spksk_from_paths(parent_path, item_path) + if item_key is not None: + parent = { + 'pk': item_key.get('pk', None), + 'sk': item_key.get('sk', None) + } + else: + parent = get_child_spksk_from_paths(parent_path, item_path) return { "job_function": "reaction.reacttosomething", "payload": { diff --git a/src/trustcafeapiwrapper/wrappers/trust/trust.py b/src/trustcafeapiwrapper/wrappers/trust/trust.py index 3bb5c56..ef3f98f 100644 --- a/src/trustcafeapiwrapper/wrappers/trust/trust.py +++ b/src/trustcafeapiwrapper/wrappers/trust/trust.py @@ -1,6 +1,9 @@ from trustcafeapiwrapper.utils import get_user_slug_from_path, get_userprofile_pksk_from_slug -def trust(trustLevel: str, userprofile_path: str): +def trust( + trustLevel: str, + userprofile_path: str + ): """ Creates new or update existing trust entry in the API. diff --git a/src/trustcafeapiwrapper/wrappers/vote/votecast.py b/src/trustcafeapiwrapper/wrappers/vote/votecast.py index 742d24b..efb03b6 100644 --- a/src/trustcafeapiwrapper/wrappers/vote/votecast.py +++ b/src/trustcafeapiwrapper/wrappers/vote/votecast.py @@ -1,6 +1,11 @@ from trustcafeapiwrapper.utils import get_child_spksk_from_paths -def votecast(vote: str, parent_path: str, item_path: str): +def votecast( + vote: str, + parent_path: str|None=None, + item_path: str|None=None, + item_key: dict|None=None + ): """ Creates a new vote in the API. @@ -10,7 +15,15 @@ def votecast(vote: str, parent_path: str, item_path: str): dict: A dictionary containing the job name and payload for creating the post that will be processed by the API client wrapper function. """ - parent = get_child_spksk_from_paths(parent_path, item_path) + if item_key is not None: + parent = { + 'pk': item_key.get('pk', None), + 'sk': item_key.get('sk', None), + 'slug': item_key.get('sk', '').split('#')[-1], + 'entity': item_key.get('sk', '').split('#')[0] + } + else: + parent = get_child_spksk_from_paths(parent_path, item_path) return { "job_function": "vote.votecast", diff --git a/tests/apiclient.py b/tests/apiclient.py index fa7ec3a..a7e0b0e 100644 --- a/tests/apiclient.py +++ b/tests/apiclient.py @@ -79,7 +79,7 @@ class TestAPIClient(unittest.TestCase): self.api_client.make_request("GET", "invalid_endpoint", "test") - @patch('trustcafeapiwrapper.apiclient.requests.request') + @patch('trustcafeapiwrapper.apiclient.requests.Session.request') def test_make_request(self, mock_request): # This test should be expanded # Or the the functions should be broken up more to be more easily testable diff --git a/tests/wrappers/react.py b/tests/wrappers/react.py index 641a535..529f3cc 100644 --- a/tests/wrappers/react.py +++ b/tests/wrappers/react.py @@ -32,4 +32,20 @@ class TestReact(unittest.TestCase): self.assertEqual(result["payload"]["parent"]["pk"], "post#12345-abcv") self.assertEqual(result["payload"]["parent"]["sk"], "comment#67890") self.assertEqual(result["payload"]["parent"]["entity"], "comment") - self.assertEqual(result["payload"]["parent"]["slug"], "67890") \ No newline at end of file + self.assertEqual(result["payload"]["parent"]["slug"], "67890") + + def react_with_parent_key(self): + reaction_type = 'like' + parent_key = { + 'pk': 'post#12345-abcv', + 'sk': 'comment#67890' + } + result = react(reaction_type, parent_key=parent_key) + + self.assertIsInstance(result, dict) + self.assertIn("job_function", result) + self.assertIn("payload", result) + self.assertEqual(result["job_function"], "reaction.reacttosomething") + self.assertEqual(result["payload"]["reaction"], reaction_type) + self.assertEqual(result["payload"]["parent"]["pk"], "post#12345-abcv") + self.assertEqual(result["payload"]["parent"]["sk"], "comment#67890") \ No newline at end of file diff --git a/tests/wrappers/trust.py b/tests/wrappers/trust.py index fe723f8..84a8cf9 100644 --- a/tests/wrappers/trust.py +++ b/tests/wrappers/trust.py @@ -12,4 +12,4 @@ class TestTrustCreateOrUpdate(unittest.TestCase): self.assertIn("payload", result) self.assertEqual(result["job_function"], "trust.createorupdate") self.assertEqual(result["payload"]["trustLevel"], trustLevel) - self.assertEqual(result["payload"]["parentSlug"], "johndoe") \ No newline at end of file + self.assertEqual(result["payload"]["parentSlug"], "johndoe") diff --git a/tests/wrappers/update_post.py b/tests/wrappers/update_post.py index f8cd43d..b9ccafe 100644 --- a/tests/wrappers/update_post.py +++ b/tests/wrappers/update_post.py @@ -90,4 +90,48 @@ class TestUpdatePost(unittest.TestCase): self.assertEqual(result["payload"]["key"]["sk"], "post#1235-abcv") self.assertNotIn("slug", result["payload"]["key"]) self.assertEqual(result["payload"]["blurLabel"], blur_label) - self.assertEqual(result["payload"]["cardUrl"], card_url) \ No newline at end of file + self.assertEqual(result["payload"]["cardUrl"], card_url) + + def test_update_post_with_post_key(self): + post_key = { + "pk": "maintrunk#maintrunk", + "sk": "post#1235-abcv" + } + result = update_post( + post_key=post_key, + post_text=self.post_text, + blur_label=self.blur_label, + card_url=self.card_url, + collaborative=self.collaborative, + ) + self.assertIsInstance(result, dict) + self.assertIn("job_function", result) + self.assertIn("payload", result) + self.assertEqual(result["job_function"], "post.update") + self.assertEqual(result["payload"]["postText"], self.post_text) + self.assertEqual(result["payload"]["postSlug"], "1235-abcv") + self.assertEqual(result["payload"]["key"]["pk"], post_key["pk"]) + self.assertEqual(result["payload"]["key"]["sk"], post_key["sk"]) + self.assertNotIn("slug", result["payload"]["key"]) + + def test_update_post_missing_post_text(self): + with self.assertRaises(ValueError) as context: + update_post( + parent_path='/', + post_path='/post/1235-abcv', + post_text=None, + blur_label=self.blur_label, + card_url=self.card_url, + collaborative=self.collaborative + ) + self.assertEqual(str(context.exception), "post_text is required.") + + def test_update_post_missing_identification(self): + with self.assertRaises(ValueError) as context: + update_post( + post_text=self.post_text, + blur_label=self.blur_label, + card_url=self.card_url, + collaborative=self.collaborative + ) + self.assertEqual(str(context.exception), "Either post_path and parent_path or post_key must be provided.") \ No newline at end of file diff --git a/tests/wrappers/vote.py b/tests/wrappers/vote.py index 5f672f5..7906380 100644 --- a/tests/wrappers/vote.py +++ b/tests/wrappers/vote.py @@ -31,4 +31,23 @@ class TestVoteCast(unittest.TestCase): self.assertEqual(result["payload"]["parent"]["pk"], "post#12345") self.assertEqual(result["payload"]["parent"]["sk"], "comment#67890") self.assertEqual(result["payload"]["parent"]["entity"], "comment") - self.assertEqual(result["payload"]["parent"]["slug"], "67890") \ No newline at end of file + self.assertEqual(result["payload"]["parent"]["slug"], "67890") + + def test_vote_cast_with_parent_key(self): + vote = 'up' + parent_key = { + 'pk': 'post#12345', + 'sk': 'comment#67890' + } + + result = votecast(vote, item_key=parent_key) + + self.assertIsInstance(result, dict) + self.assertIn("job_function", result) + self.assertIn("payload", result) + self.assertEqual(result["job_function"], "vote.votecast") + self.assertEqual(result["payload"]["vote"], vote) + self.assertEqual(result["payload"]["parent"]["pk"], "post#12345") + self.assertEqual(result["payload"]["parent"]["sk"], "comment#67890") + self.assertEqual(result["payload"]["parent"]["entity"], "comment") + self.assertEqual(result["payload"]["parent"]["slug"], "67890")