From 881eefc6900939fe4fea23f26b0318d7cea39ba4 Mon Sep 17 00:00:00 2001 From: Harmon Date: Mon, 20 Sep 2021 03:04:23 -0500 Subject: [PATCH] Add return_type parameter and attribute for Client Client.hide_reply, Client.unhide_reply, Client.unlike, Client.like, Client.unblock, and Client.block now return the type specified by Client.return_type rather than only Booleans. Other Client methods now return the type specified by Client.return_type rather than only Response. By default, if return_type is not passed when initializing Client, Client.return_type will be Response. Response is now publicly exposed and documented. Resolves #1580 --- docs/client.rst | 11 +++--- tests/test_client.py | 12 +++--- tweepy/__init__.py | 2 +- tweepy/client.py | 89 ++++++++++++++++++++++++-------------------- 4 files changed, 61 insertions(+), 53 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 3857503..00c1b63 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -205,10 +205,11 @@ user data objects. .. _Tweet fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/tweet .. _user fields: https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/user -.. _response_reference: - ``Response`` ============ -The :obj:`Response` returned by :class:`Client` methods is a -:class:`collections.namedtuple`, with ``data``, ``includes``, ``errors``, and -``meta`` fields, corresponding with the fields in responses from Twitter's API. +.. autoclass:: Response + + The :obj:`Response` returned by :class:`Client` methods is a + :class:`collections.namedtuple`, with ``data``, ``includes``, ``errors``, + and ``meta`` fields, corresponding with the fields in responses from + Twitter's API. diff --git a/tests/test_client.py b/tests/test_client.py index fbd9e2e..2b4c26e 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -17,14 +17,14 @@ class TweepyTestCase(unittest.TestCase): @tape.use_cassette("test_hide_and_unhide_reply.yaml", serializer="yaml") def test_hide_and_unhide_reply(self): reply_id = 1344794616005066752 # Test Tweet for reply hide/unhide - self.assertTrue(self.client.hide_reply(reply_id)) - self.assertFalse(self.client.unhide_reply(reply_id)) + self.client.hide_reply(reply_id) + self.client.unhide_reply(reply_id) @tape.use_cassette("test_like_and_unlike.yaml", serializer="yaml") def test_like_and_unlike(self): tweet_id = 1293593516040269825 # @TwitterDev Tweet announcing API v2 - self.assertTrue(self.client.like(tweet_id)) - self.assertFalse(self.client.unlike(tweet_id)) + self.client.like(tweet_id) + self.client.unlike(tweet_id) # TODO: test_search_all_tweets with access to Academic Research product track @@ -56,8 +56,8 @@ class TweepyTestCase(unittest.TestCase): @tape.use_cassette("test_block_and_unblock.yaml", serializer="yaml") def test_block_and_unblock(self): user_id = 17874544 # User ID for @TwitterSupport - self.assertTrue(self.client.block(user_id)) - self.assertFalse(self.client.unblock(user_id)) + self.client.block(user_id) + self.client.unblock(user_id) @tape.use_cassette("test_follow_and_unfollow.yaml", serializer="yaml") def test_follow_and_unfollow(self): diff --git a/tweepy/__init__.py b/tweepy/__init__.py index c071f69..c5e072c 100644 --- a/tweepy/__init__.py +++ b/tweepy/__init__.py @@ -12,7 +12,7 @@ __license__ = 'MIT' from tweepy.api import API from tweepy.auth import AppAuthHandler, OAuthHandler from tweepy.cache import Cache, FileCache, MemoryCache -from tweepy.client import Client +from tweepy.client import Client, Response from tweepy.cursor import Cursor from tweepy.errors import ( BadRequest, Forbidden, HTTPException, NotFound, TooManyRequests, diff --git a/tweepy/client.py b/tweepy/client.py index 1305604..6f36891 100644 --- a/tweepy/client.py +++ b/tweepy/client.py @@ -28,7 +28,13 @@ Response = namedtuple("Response", ("data", "includes", "errors", "meta")) class Client: - """Twitter API v2 Client + """Client( \ + bearer_token=None, consumer_key=None, consumer_secret=None, \ + access_token=None, access_token_secret=None, *, return_type=Response, \ + wait_on_rate_limit=False \ + ) + + Twitter API v2 Client Parameters ---------- @@ -42,6 +48,8 @@ class Client: Twitter API Access Token access_token_secret : Optional[str] Twitter API Access Token Secret + return_type : Type[dict, requests.Response, Response] + Type to return from requests to the API wait_on_rate_limit : bool Whether to wait when rate limit is reached @@ -53,15 +61,18 @@ class Client: User agent used when making requests to the API """ - def __init__(self, bearer_token=None, consumer_key=None, - consumer_secret=None, access_token=None, - access_token_secret=None, *, wait_on_rate_limit=False): + def __init__( + self, bearer_token=None, consumer_key=None, consumer_secret=None, + access_token=None, access_token_secret=None, *, return_type=Response, + wait_on_rate_limit=False + ): self.bearer_token = bearer_token self.consumer_key = consumer_key self.consumer_secret = consumer_secret self.access_token = access_token self.access_token_secret = access_token_secret + self.return_type = return_type self.wait_on_rate_limit = wait_on_rate_limit self.session = requests.Session() @@ -121,7 +132,7 @@ class Client: raise TwitterServerError(response) if not 200 <= response.status_code < 300: raise HTTPException(response) - return response.json() + return response def _make_request(self, method, route, params={}, endpoint_parameters=None, json=None, data_type=None, user_auth=False): @@ -146,6 +157,14 @@ class Client: response = self.request(method, route, params=request_params, json=json, user_auth=user_auth) + if self.return_type is requests.Response: + return response + + response = response.json() + + if self.return_type is dict: + return response + data = response.get("data") if data_type is not None: if isinstance(data, list): @@ -183,8 +202,7 @@ class Client: Returns ------- - bool - Indicates if the Tweet was successfully hidden. + Union[dict, requests.Response, Response] References ---------- @@ -193,7 +211,7 @@ class Client: return self._make_request( "PUT", f"/2/tweets/{id}/hidden", json={"hidden": True}, user_auth=True - )[0]["hidden"] + ) def unhide_reply(self, id): """Unhides a reply to a Tweet. @@ -206,8 +224,7 @@ class Client: Returns ------- - bool - Indicates if the Tweet was successfully unhidden. + Union[dict, requests.Response, Response] References ---------- @@ -216,7 +233,7 @@ class Client: return self._make_request( "PUT", f"/2/tweets/{id}/hidden", json={"hidden": False}, user_auth=True - )[0]["hidden"] + ) # Likes @@ -233,10 +250,7 @@ class Client: Returns ------- - bool - Indicates whether the user is unliking the specified Tweet as a - result of this request. The returned value is ``False`` for a - successful unlike request. + Union[dict, requests.Response, Response] References ---------- @@ -245,7 +259,7 @@ class Client: id = self.access_token.partition('-')[0] route = f"/2/users/{id}/likes/{tweet_id}" - return self._make_request("DELETE", route, user_auth=True)[0]["liked"] + return self._make_request("DELETE", route, user_auth=True) def like(self, tweet_id): """Like a Tweet. @@ -257,9 +271,7 @@ class Client: Returns ------- - bool - Indicates whether the user likes the specified Tweet as a result of - this request. + Union[dict, requests.Response, Response] References ---------- @@ -270,7 +282,7 @@ class Client: return self._make_request( "POST", route, json={"tweet_id": str(tweet_id)}, user_auth=True - )[0]["liked"] + ) # Search Tweets @@ -342,7 +354,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -432,7 +444,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -536,7 +548,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -644,7 +656,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -694,7 +706,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -738,7 +750,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -768,10 +780,7 @@ class Client: Returns ------- - bool - Indicates whether the user is blocking the specified user as a - result of this request. The returned value is ``False`` for a - successful unblock request. + Union[dict, requests.Response, Response] References ---------- @@ -782,7 +791,7 @@ class Client: return self._make_request( "DELETE", route, user_auth=True - )[0]["blocking"] + ) def block(self, target_user_id): """Block another user. @@ -794,9 +803,7 @@ class Client: Returns ------- - bool - Indicates whether the user is blocking the specified user as a - result of this request. + Union[dict, requests.Response, Response] References ---------- @@ -808,7 +815,7 @@ class Client: return self._make_request( "POST", route, json={"target_user_id": str(target_user_id)}, user_auth=True - )[0]["blocking"] + ) # Follows @@ -825,7 +832,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -869,7 +876,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -917,7 +924,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -948,7 +955,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -993,7 +1000,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- @@ -1052,7 +1059,7 @@ class Client: Returns ------- - :ref:`response_reference` + Union[dict, requests.Response, Response] References ---------- -- 2.25.1