From b3309cde86a8f3bbc87336c58f21309115a3aa3f Mon Sep 17 00:00:00 2001 From: Harmon Date: Tue, 2 Feb 2021 10:54:38 -0600 Subject: [PATCH] Replace APIMethod.payload_list and APIMethod.payload_type Replace APIMethod.payload_list and APIMethod.payload_type with payload decorator and APIMethod.execute payload_list and payload_type keyword-only arguments Add payload_list and payload_type keyword-only arguments to ModelParser.parse Allow passing keyword arguments to bind_api and APIMethod through API.send_direct_message, API.lookup_friendships, API.update_profile_image, API.add_list_members, API.remove_list_members --- tweepy/api.py | 191 +++++++++++++++++++++++----------------------- tweepy/binder.py | 27 +++++-- tweepy/cursor.py | 10 ++- tweepy/parsers.py | 13 ++-- 4 files changed, 134 insertions(+), 107 deletions(-) diff --git a/tweepy/api.py b/tweepy/api.py index 1649d41..bf3beab 100644 --- a/tweepy/api.py +++ b/tweepy/api.py @@ -6,7 +6,7 @@ import imghdr import mimetypes import os -from tweepy.binder import bind_api, pagination +from tweepy.binder import bind_api, pagination, payload from tweepy.error import TweepError from tweepy.parsers import ModelParser, Parser from tweepy.utils import list_to_csv @@ -75,6 +75,7 @@ class API: ) @pagination(mode='id') + @payload('status', list=True) def home_timeline(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline :allowed_param: 'count', 'since_id', 'max_id', 'trim_user', @@ -83,12 +84,12 @@ class API: return bind_api( *args, api=self, path='/statuses/home_timeline.json', - payload_type='status', payload_list=True, allowed_param=['count', 'since_id', 'max_id', 'trim_user', 'exclude_replies', 'include_entities'], require_auth=True, **kwargs ) + @payload('status', list=True) def statuses_lookup(self, id_, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-lookup :allowed_param: 'id', 'include_entities', 'trim_user', 'map', @@ -100,13 +101,13 @@ class API: return bind_api( list_to_csv(id_), *args, api=self, path='/statuses/lookup.json', - payload_type='status', payload_list=True, allowed_param=['id', 'include_entities', 'trim_user', 'map', 'include_ext_alt_text', 'include_card_uri'], require_auth=True, **kwargs ) @pagination(mode='id') + @payload('status', list=True) def user_timeline(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline :allowed_param: 'user_id', 'screen_name', 'since_id', 'count', @@ -116,13 +117,13 @@ class API: return bind_api( *args, api=self, path='/statuses/user_timeline.json', - payload_type='status', payload_list=True, allowed_param=['user_id', 'screen_name', 'since_id', 'count', 'max_id', 'trim_user', 'exclude_replies', 'include_rts'], **kwargs ) @pagination(mode='id') + @payload('status', list=True) def mentions_timeline(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-mentions_timeline :allowed_param: 'since_id', 'max_id', 'count' @@ -130,12 +131,12 @@ class API: return bind_api( *args, api=self, path='/statuses/mentions_timeline.json', - payload_type='status', payload_list=True, allowed_param=['since_id', 'max_id', 'count'], require_auth=True, **kwargs ) @pagination(mode='id') + @payload('status', list=True) def retweets_of_me(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweets_of_me :allowed_param: 'since_id', 'max_id', 'count' @@ -143,11 +144,11 @@ class API: return bind_api( *args, api=self, path='/statuses/retweets_of_me.json', - payload_type='status', payload_list=True, allowed_param=['since_id', 'max_id', 'count'], require_auth=True, **kwargs ) + @payload('status') def get_status(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-show-id :allowed_param: 'id', 'trim_user', 'include_my_retweet', @@ -157,12 +158,12 @@ class API: return bind_api( *args, api=self, path='/statuses/show.json', - payload_type='status', allowed_param=['id', 'trim_user', 'include_my_retweet', 'include_entities', 'include_ext_alt_text', 'include_card_uri'], **kwargs ) + @payload('status') def update_status(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update :allowed_param: 'status', 'in_reply_to_status_id', @@ -179,7 +180,6 @@ class API: *args, api=self, path='/statuses/update.json', method='POST', - payload_type='status', allowed_param=['status', 'in_reply_to_status_id', 'auto_populate_reply_metadata', 'exclude_reply_user_ids', 'attachment_url', @@ -190,6 +190,7 @@ class API: require_auth=True, **kwargs ) + @payload('media') def media_upload(self, filename, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload :allowed_param: @@ -216,7 +217,6 @@ class API: *args, api=self, path='/media/upload.json', method='POST', - payload_type='media', allowed_param=[], require_auth=True, upload_api=True, **kwargs @@ -240,6 +240,7 @@ class API: upload_api=True, **kwargs ) + @payload('status') def update_with_media(self, filename, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update_with_media :allowed_param: 'status', 'possibly_sensitive', @@ -257,7 +258,6 @@ class API: *args, api=self, path='/statuses/update_with_media.json', method='POST', - payload_type='status', allowed_param=['status', 'possibly_sensitive', 'in_reply_to_status_id', 'in_reply_to_status_id_str', @@ -266,6 +266,7 @@ class API: require_auth=True, **kwargs ) + @payload('status') def destroy_status(self, status_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-destroy-id :allowed_param: @@ -274,10 +275,10 @@ class API: *args, api=self, path=f'/statuses/destroy/{status_id}.json', method='POST', - payload_type='status', require_auth=True, **kwargs ) + @payload('status') def retweet(self, status_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id :allowed_param: @@ -286,10 +287,10 @@ class API: *args, api=self, path=f'/statuses/retweet/{status_id}.json', method='POST', - payload_type='status', require_auth=True, **kwargs ) + @payload('status') def unretweet(self, status_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-unretweet-id :allowed_param: @@ -298,10 +299,10 @@ class API: *args, api=self, path=f'/statuses/unretweet/{status_id}.json', method='POST', - payload_type='status', require_auth=True, **kwargs ) + @payload('status', list=True) def retweets(self, status_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweets-id :allowed_param: 'count' @@ -309,12 +310,12 @@ class API: return bind_api( *args, api=self, path=f'/statuses/retweets/{status_id}.json', - payload_type='status', payload_list=True, allowed_param=['count'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('ids') def retweeters(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweeters-ids :allowed_param: 'id', 'cursor', 'stringify_ids @@ -322,10 +323,10 @@ class API: return bind_api( *args, api=self, path='/statuses/retweeters/ids.json', - payload_type='ids', allowed_param=['id', 'cursor', 'stringify_ids'], **kwargs ) + @payload('user') def get_user(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-show :allowed_param: 'id', 'user_id', 'screen_name' @@ -333,10 +334,10 @@ class API: return bind_api( *args, api=self, path='/users/show.json', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name'], **kwargs ) + @payload('json') def get_oembed(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-oembed :allowed_param: 'url', 'maxwidth', 'hide_media', 'hide_thread', @@ -346,12 +347,12 @@ class API: return bind_api( *args, api=self, path='/statuses/oembed.json', - payload_type='json', allowed_param=['url', 'maxwidth', 'hide_media', 'hide_thread', 'omit_script', 'align', 'related', 'lang', 'theme', 'link_color', 'widget_type', 'dnt'], **kwargs ) + @payload('user', list=True) def lookup_users(self, user_ids=None, screen_names=None, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup :allowed_param: 'user_id', 'screen_name', 'include_entities', @@ -360,7 +361,6 @@ class API: return bind_api( list_to_csv(user_ids), list_to_csv(screen_names), *args, api=self, path='/users/lookup.json', - payload_type='user', payload_list=True, method='POST', allowed_param=['user_id', 'screen_name', 'include_entities', 'tweet_mode'], **kwargs @@ -371,6 +371,7 @@ class API: return self.get_user(screen_name=self.auth.get_username()) @pagination(mode='page') + @payload('user', list=True) def search_users(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search :allowed_param: 'q', 'count', 'page' @@ -378,11 +379,11 @@ class API: return bind_api( *args, api=self, path='/users/search.json', - payload_type='user', payload_list=True, require_auth=True, allowed_param=['q', 'count', 'page'], **kwargs ) + @payload('direct_message') def get_direct_message(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/get-event :allowed_param: 'id' @@ -390,12 +391,12 @@ class API: return bind_api( *args, api=self, path='/direct_messages/events/show.json', - payload_type='direct_message', allowed_param=['id'], require_auth=True, **kwargs ) @pagination(mode='dm_cursor') + @payload('direct_message', list=True) def list_direct_messages(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/list-events :allowed_param: 'count', 'cursor' @@ -403,14 +404,14 @@ class API: return bind_api( *args, api=self, path='/direct_messages/events/list.json', - payload_type='direct_message', payload_list=True, allowed_param=['count', 'cursor'], require_auth=True, **kwargs ) + @payload('direct_message') def send_direct_message(self, recipient_id, text, quick_reply_options=None, attachment_type=None, attachment_media_id=None, - ctas=None): + ctas=None, **kwargs): """ :reference: https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/new-event :allowed_param: 'recipient_id', 'text', 'quick_reply_type', 'attachment_type', attachment_media_id' @@ -440,9 +441,8 @@ class API: api=self, path='/direct_messages/events/new.json', method='POST', - payload_type='direct_message', require_auth=True, - json_payload=json_payload + json_payload=json_payload, **kwargs ) def destroy_direct_message(self, *args, **kwargs): @@ -457,6 +457,7 @@ class API: require_auth=True, **kwargs ) + @payload('user') def create_friendship(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create :allowed_param: 'id', 'user_id', 'screen_name', 'follow' @@ -465,11 +466,11 @@ class API: *args, api=self, path='/friendships/create.json', method='POST', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name', 'follow'], require_auth=True, **kwargs ) + @payload('user') def destroy_friendship(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy :allowed_param: 'id', 'user_id', 'screen_name' @@ -478,11 +479,11 @@ class API: *args, api=self, path='/friendships/destroy.json', method='POST', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name'], require_auth=True, **kwargs ) + @payload('friendship') def show_friendship(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-show :allowed_param: 'source_id', 'source_screen_name', 'target_id', @@ -491,24 +492,24 @@ class API: return bind_api( *args, api=self, path='/friendships/show.json', - payload_type='friendship', allowed_param=['source_id', 'source_screen_name', 'target_id', 'target_screen_name'], **kwargs ) - def lookup_friendships(self, user_ids=None, screen_names=None): + @payload('relationship', list=True) + def lookup_friendships(self, user_ids=None, screen_names=None, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-lookup :allowed_param: 'user_id', 'screen_name' """ return bind_api( list_to_csv(user_ids), list_to_csv(screen_names), api=self, path='/friendships/lookup.json', - payload_type='relationship', payload_list=True, allowed_param=['user_id', 'screen_name'], - require_auth=True + require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('ids') def friends_ids(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-ids :allowed_param: 'id', 'user_id', 'screen_name', 'cursor' @@ -516,11 +517,11 @@ class API: return bind_api( *args, api=self, path='/friends/ids.json', - payload_type='ids', allowed_param=['id', 'user_id', 'screen_name', 'cursor'], **kwargs ) @pagination(mode='cursor') + @payload('user', list=True) def friends(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-list :allowed_param: 'id', 'user_id', 'screen_name', 'cursor', 'count', @@ -529,12 +530,12 @@ class API: return bind_api( *args, api=self, path='/friends/list.json', - payload_type='user', payload_list=True, allowed_param=['id', 'user_id', 'screen_name', 'cursor', 'count', 'skip_status', 'include_user_entities'], **kwargs ) @pagination(mode='cursor') + @payload('ids') def friendships_incoming(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-incoming :allowed_param: 'cursor' @@ -542,11 +543,11 @@ class API: return bind_api( *args, api=self, path='/friendships/incoming.json', - payload_type='ids', allowed_param=['cursor'], **kwargs ) @pagination(mode='cursor') + @payload('ids') def friendships_outgoing(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-outgoing :allowed_param: 'cursor' @@ -554,11 +555,11 @@ class API: return bind_api( *args, api=self, path='/friendships/outgoing.json', - payload_type='ids', allowed_param=['cursor'], **kwargs ) @pagination(mode='cursor') + @payload('ids') def followers_ids(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids :allowed_param: 'id', 'user_id', 'screen_name', 'cursor', 'count' @@ -566,12 +567,12 @@ class API: return bind_api( *args, api=self, path='/followers/ids.json', - payload_type='ids', allowed_param=['id', 'user_id', 'screen_name', 'cursor', 'count'], **kwargs ) @pagination(mode='cursor') + @payload('user', list=True) def followers(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-list :allowed_param: 'id', 'user_id', 'screen_name', 'cursor', 'count', @@ -580,20 +581,20 @@ class API: return bind_api( *args, api=self, path='/followers/list.json', - payload_type='user', payload_list=True, allowed_param=['id', 'user_id', 'screen_name', 'cursor', 'count', 'skip_status', 'include_user_entities'], **kwargs ) + @payload('json') def get_settings(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-settings """ return bind_api( *args, api=self, path='/account/settings.json', - payload_type='json', use_cache=False, **kwargs ) + @payload('json') def set_settings(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-settings :allowed_param: 'sleep_time_enabled', 'start_sleep_time', @@ -605,7 +606,6 @@ class API: *args, api=self, path='/account/settings.json', method='POST', - payload_type='json', allowed_param=['sleep_time_enabled', 'start_sleep_time', 'end_sleep_time', 'time_zone', 'trend_location_woeid', @@ -613,6 +613,7 @@ class API: use_cache=False, **kwargs ) + @payload('user') def verify_credentials(self, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials :allowed_param: 'include_entities', 'skip_status', 'include_email' @@ -623,7 +624,6 @@ class API: return bind_api( api=self, path='/account/verify_credentials.json', - payload_type='user', require_auth=True, allowed_param=['include_entities', 'skip_status', 'include_email'], **kwargs @@ -633,6 +633,7 @@ class API: return False raise + @payload('json') def rate_limit_status(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/developer-utilities/rate-limit-status/api-reference/get-application-rate_limit_status :allowed_param: 'resources' @@ -640,12 +641,12 @@ class API: return bind_api( *args, api=self, path='/application/rate_limit_status.json', - payload_type='json', allowed_param=['resources'], use_cache=False, **kwargs ) - def update_profile_image(self, filename, file_=None): + @payload('user') + def update_profile_image(self, filename, file_=None, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image :allowed_param: 'include_entities', 'skip_status' """ @@ -654,10 +655,9 @@ class API: self, api=self, path='/account/update_profile_image.json', method='POST', - payload_type='user', allowed_param=['include_entities', 'skip_status'], require_auth=True, - post_data=post_data, headers=headers + post_data=post_data, headers=headers, **kwargs ) def update_profile_banner(self, filename, **kwargs): @@ -676,6 +676,7 @@ class API: post_data=post_data, headers=headers ) + @payload('user') def update_profile(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile :allowed_param: 'name', 'url', 'location', 'description', @@ -685,13 +686,13 @@ class API: *args, api=self, path='/account/update_profile.json', method='POST', - payload_type='user', allowed_param=['name', 'url', 'location', 'description', 'profile_link_color'], require_auth=True, **kwargs ) @pagination(mode='id') + @payload('status', list=True) def favorites(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-favorites-list :allowed_param: 'screen_name', 'user_id', 'max_id', 'count', @@ -700,11 +701,11 @@ class API: return bind_api( *args, api=self, path='/favorites/list.json', - payload_type='status', payload_list=True, allowed_param=['screen_name', 'user_id', 'max_id', 'count', 'since_id'], **kwargs ) + @payload('status') def create_favorite(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-create :allowed_param: 'id' @@ -713,11 +714,11 @@ class API: *args, api=self, path='/favorites/create.json', method='POST', - payload_type='status', allowed_param=['id'], require_auth=True, **kwargs ) + @payload('status') def destroy_favorite(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-destroy :allowed_param: 'id' @@ -726,11 +727,11 @@ class API: *args, api=self, path='/favorites/destroy.json', method='POST', - payload_type='status', allowed_param=['id'], require_auth=True, **kwargs ) + @payload('user') def create_block(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-create :allowed_param: 'id', 'user_id', 'screen_name' @@ -739,11 +740,11 @@ class API: *args, api=self, path='/blocks/create.json', method='POST', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name'], require_auth=True, **kwargs ) + @payload('user') def destroy_block(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-destroy :allowed_param: 'id', 'user_id', 'screen_name' @@ -752,12 +753,12 @@ class API: *args, api=self, path='/blocks/destroy.json', method='POST', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('ids') def mutes_ids(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-ids :allowed_param: 'cursor' @@ -765,12 +766,12 @@ class API: return bind_api( *args, api=self, path='/mutes/users/ids.json', - payload_type='ids', allowed_param=['cursor'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('user', list=True) def mutes(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-list :allowed_param: 'cursor', 'include_entities', 'skip_status' @@ -778,11 +779,11 @@ class API: return bind_api( *args, api=self, path='/mutes/users/list.json', - payload_type='user', payload_list=True, allowed_param=['cursor', 'include_entities', 'skip_status'], required_auth=True, **kwargs ) + @payload('user') def create_mute(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-create :allowed_param: 'id', 'user_id', 'screen_name' @@ -791,11 +792,11 @@ class API: *args, api=self, path='/mutes/users/create.json', method='POST', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name'], require_auth=True, **kwargs ) + @payload('user') def destroy_mute(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-destroy :allowed_param: 'id', 'user_id', 'screen_name' @@ -804,12 +805,12 @@ class API: *args, api=self, path='/mutes/users/destroy.json', method='POST', - payload_type='user', allowed_param=['id', 'user_id', 'screen_name'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('user', list=True) def blocks(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-list :allowed_param: 'cursor' @@ -817,12 +818,12 @@ class API: return bind_api( *args, api=self, path='/blocks/list.json', - payload_type='user', payload_list=True, allowed_param=['cursor'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('ids') def blocks_ids(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-ids :allowed_param: 'cursor' @@ -830,11 +831,11 @@ class API: return bind_api( *args, api=self, path='/blocks/ids.json', - payload_type='ids', allowed_param=['cursor'], require_auth=True, **kwargs ) + @payload('user') def report_spam(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-users-report_spam :allowed_param: 'user_id', 'screen_name', 'perform_block' @@ -843,20 +844,20 @@ class API: *args, api=self, path='/users/report_spam.json', method='POST', - payload_type='user', allowed_param=['user_id', 'screen_name', 'perform_block'], require_auth=True, **kwargs ) + @payload('saved_search', list=True) def saved_searches(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-saved_searches-list """ return bind_api( *args, api=self, path='/saved_searches/list.json', - payload_type='saved_search', payload_list=True, require_auth=True, **kwargs ) + @payload('saved_search') def get_saved_search(self, saved_search_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-saved_searches-show-id :allowed_param: @@ -864,10 +865,10 @@ class API: return bind_api( *args, api=self, path=f'/saved_searches/show/{saved_search_id}.json', - payload_type='saved_search', require_auth=True, **kwargs ) + @payload('saved_search') def create_saved_search(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-saved_searches-create :allowed_param: 'query' @@ -876,11 +877,11 @@ class API: *args, api=self, path='/saved_searches/create.json', method='POST', - payload_type='saved_search', allowed_param=['query'], require_auth=True, **kwargs ) + @payload('saved_search') def destroy_saved_search(self, saved_search_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-saved_searches-destroy-id :allowed_param: @@ -889,10 +890,10 @@ class API: *args, api=self, path=f'/saved_searches/destroy/{saved_search_id}.json', method='POST', - payload_type='saved_search', require_auth=True, **kwargs ) + @payload('list') def create_list(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-create :allowed_param: 'name', 'mode', 'description' @@ -901,11 +902,11 @@ class API: *args, api=self, path='/lists/create.json', method='POST', - payload_type='list', allowed_param=['name', 'mode', 'description'], require_auth=True, **kwargs ) + @payload('list') def destroy_list(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-destroy :allowed_param: 'owner_screen_name', 'owner_id', 'list_id', 'slug' @@ -914,11 +915,11 @@ class API: *args, api=self, path='/lists/destroy.json', method='POST', - payload_type='list', allowed_param=['owner_screen_name', 'owner_id', 'list_id', 'slug'], require_auth=True, **kwargs ) + @payload('list') def update_list(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-update :allowed_param: 'list_id', 'slug', 'name', 'mode', 'description', @@ -928,12 +929,12 @@ class API: *args, api=self, path='/lists/update.json', method='POST', - payload_type='list', allowed_param=['list_id', 'slug', 'name', 'mode', 'description', 'owner_screen_name', 'owner_id'], require_auth=True, **kwargs ) + @payload('list', list=True) def lists_all(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-list :allowed_param: 'screen_name', 'user_id', 'reverse' @@ -941,12 +942,12 @@ class API: return bind_api( *args, api=self, path='/lists/list.json', - payload_type='list', payload_list=True, allowed_param=['screen_name', 'user_id', 'reverse'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('list', list=True) def lists_memberships(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-memberships :allowed_param: 'screen_name', 'user_id', 'filter_to_owned_lists', @@ -955,13 +956,13 @@ class API: return bind_api( *args, api=self, path='/lists/memberships.json', - payload_type='list', payload_list=True, allowed_param=['screen_name', 'user_id', 'filter_to_owned_lists', 'cursor', 'count'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('list', list=True) def lists_ownerships(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships :allowed_param: 'user_id', 'screen_name', 'count', 'cursor' @@ -969,12 +970,12 @@ class API: return bind_api( *args, api=self, path='/lists/ownerships.json', - payload_type='list', payload_list=True, allowed_param=['user_id', 'screen_name', 'count', 'cursor'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('list', list=True) def lists_subscriptions(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-subscriptions :allowed_param: 'screen_name', 'user_id', 'cursor', 'count' @@ -982,12 +983,12 @@ class API: return bind_api( *args, api=self, path='/lists/subscriptions.json', - payload_type='list', payload_list=True, allowed_param=['screen_name', 'user_id', 'cursor', 'count'], require_auth=True, **kwargs ) @pagination(mode='id') + @payload('status', list=True) def list_timeline(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-statuses :allowed_param: 'owner_screen_name', 'slug', 'owner_id', 'list_id', @@ -997,12 +998,12 @@ class API: return bind_api( *args, api=self, path='/lists/statuses.json', - payload_type='status', payload_list=True, allowed_param=['owner_screen_name', 'slug', 'owner_id', 'list_id', 'since_id', 'max_id', 'count', 'include_entities', 'include_rts'], **kwargs ) + @payload('list') def get_list(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-show :allowed_param: 'owner_screen_name', 'owner_id', 'slug', 'list_id' @@ -1010,11 +1011,11 @@ class API: return bind_api( *args, api=self, path='/lists/show.json', - payload_type='list', allowed_param=['owner_screen_name', 'owner_id', 'slug', 'list_id'], **kwargs ) + @payload('list') def add_list_member(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-create :allowed_param: 'screen_name', 'user_id', 'owner_screen_name', @@ -1024,12 +1025,12 @@ class API: *args, api=self, path='/lists/members/create.json', method='POST', - payload_type='list', allowed_param=['screen_name', 'user_id', 'owner_screen_name', 'owner_id', 'slug', 'list_id'], require_auth=True, **kwargs ) + @payload('list') def remove_list_member(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-destroy :allowed_param: 'screen_name', 'user_id', 'owner_screen_name', @@ -1039,14 +1040,15 @@ class API: *args, api=self, path='/lists/members/destroy.json', method='POST', - payload_type='list', allowed_param=['screen_name', 'user_id', 'owner_screen_name', 'owner_id', 'slug', 'list_id'], require_auth=True, **kwargs ) + @payload('list') def add_list_members(self, screen_name=None, user_id=None, slug=None, - list_id=None, owner_id=None, owner_screen_name=None): + list_id=None, owner_id=None, owner_screen_name=None, + **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-create_all :allowed_param: 'screen_name', 'user_id', 'slug', 'list_id', 'owner_id', 'owner_screen_name' @@ -1057,15 +1059,15 @@ class API: api=self, path='/lists/members/create_all.json', method='POST', - payload_type='list', allowed_param=['screen_name', 'user_id', 'slug', 'list_id', 'owner_id', 'owner_screen_name'], - require_auth=True + require_auth=True, **kwargs ) + @payload('list') def remove_list_members(self, screen_name=None, user_id=None, slug=None, list_id=None, owner_id=None, - owner_screen_name=None): + owner_screen_name=None, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-destroy_all :allowed_param: 'screen_name', 'user_id', 'slug', 'list_id', 'owner_id', 'owner_screen_name' @@ -1076,13 +1078,13 @@ class API: api=self, path='/lists/members/destroy_all.json', method='POST', - payload_type='list', allowed_param=['screen_name', 'user_id', 'slug', 'list_id', 'owner_id', 'owner_screen_name'], - require_auth=True + require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('user', list=True) def list_members(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-members :allowed_param: 'owner_screen_name', 'slug', 'list_id', 'owner_id', @@ -1091,11 +1093,11 @@ class API: return bind_api( *args, api=self, path='/lists/members.json', - payload_type='user', payload_list=True, allowed_param=['owner_screen_name', 'slug', 'list_id', 'owner_id', 'cursor'], **kwargs ) + @payload('user') def show_list_member(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-members-show :allowed_param: 'list_id', 'slug', 'user_id', 'screen_name', @@ -1104,11 +1106,11 @@ class API: return bind_api( *args, api=self, path='/lists/members/show.json', - payload_type='user', allowed_param=['list_id', 'slug', 'user_id', 'screen_name', 'owner_screen_name', 'owner_id'], **kwargs ) + @payload('list') def subscribe_list(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-subscribers-create :allowed_param: 'owner_screen_name', 'slug', 'owner_id', 'list_id' @@ -1117,11 +1119,11 @@ class API: *args, api=self, path='/lists/subscribers/create.json', method='POST', - payload_type='list', allowed_param=['owner_screen_name', 'slug', 'owner_id', 'list_id'], require_auth=True, **kwargs ) + @payload('list') def unsubscribe_list(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-subscribers-destroy :allowed_param: 'owner_screen_name', 'slug', 'owner_id', 'list_id' @@ -1130,12 +1132,12 @@ class API: *args, api=self, path='/lists/subscribers/destroy.json', method='POST', - payload_type='list', allowed_param=['owner_screen_name', 'slug', 'owner_id', 'list_id'], require_auth=True, **kwargs ) @pagination(mode='cursor') + @payload('user', list=True) def list_subscribers(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-subscribers :allowed_param: 'owner_screen_name', 'slug', 'owner_id', 'list_id', @@ -1145,12 +1147,12 @@ class API: return bind_api( *args, api=self, path='/lists/subscribers.json', - payload_type='user', payload_list=True, allowed_param=['owner_screen_name', 'slug', 'owner_id', 'list_id', 'cursor', 'count', 'include_entities', 'skip_status'], **kwargs ) + @payload('user') def show_list_subscriber(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-subscribers-show :allowed_param: 'owner_screen_name', 'slug', 'screen_name', @@ -1159,19 +1161,20 @@ class API: return bind_api( *args, api=self, path='/lists/subscribers/show.json', - payload_type='user', allowed_param=['owner_screen_name', 'slug', 'screen_name', 'owner_id', 'list_id', 'user_id'], **kwargs ) + @payload('json') def trends_available(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-available """ return bind_api( *args, api=self, path='/trends/available.json', - payload_type='json', **kwargs + **kwargs ) + @payload('json') def trends_place(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/trends/trends-for-location/api-reference/get-trends-place :allowed_param: 'id', 'exclude' @@ -1179,10 +1182,10 @@ class API: return bind_api( *args, api=self, path='/trends/place.json', - payload_type='json', allowed_param=['id', 'exclude'], **kwargs ) + @payload('json') def trends_closest(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-closest :allowed_param: 'lat', 'long' @@ -1190,11 +1193,11 @@ class API: return bind_api( *args, api=self, path='/trends/closest.json', - payload_type='json', allowed_param=['lat', 'long'], **kwargs ) @pagination(mode='id') + @payload('search_results') def search(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets :allowed_param: 'q', 'lang', 'locale', 'since_id', 'geocode', @@ -1204,13 +1207,13 @@ class API: return bind_api( *args, api=self, path='/search/tweets.json', - payload_type='search_results', allowed_param=['q', 'lang', 'locale', 'since_id', 'geocode', 'max_id', 'until', 'result_type', 'count', 'include_entities'], **kwargs ) @pagination(mode='next') + @payload('status', list=True) def search_30_day(self, environment_name, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/search/api-reference/premium-search :allowed_param: 'query', 'tag', 'fromDate', 'toDate', 'maxResults', @@ -1219,13 +1222,13 @@ class API: return bind_api( *args, api=self, path=f'/tweets/search/30day/{environment_name}.json', - payload_type='status', payload_list=True, allowed_param=['query', 'tag', 'fromDate', 'toDate', 'maxResults', 'next'], require_auth=True, **kwargs ) @pagination(mode='next') + @payload('status', list=True) def search_full_archive(self, environment_name, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/tweets/search/api-reference/premium-search :allowed_param: 'query', 'tag', 'fromDate', 'toDate', 'maxResults', @@ -1234,12 +1237,12 @@ class API: return bind_api( *args, api=self, path=f'/tweets/search/fullarchive/{environment_name}.json', - payload_type='status', payload_list=True, allowed_param=['query', 'tag', 'fromDate', 'toDate', 'maxResults', 'next'], require_auth=True, **kwargs ) + @payload('place', list=True) def reverse_geocode(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-reverse_geocode :allowed_param: 'lat', 'long', 'accuracy', 'granularity', @@ -1248,11 +1251,11 @@ class API: return bind_api( *args, api=self, path='/geo/reverse_geocode.json', - payload_type='place', payload_list=True, allowed_param=['lat', 'long', 'accuracy', 'granularity', 'max_results'], **kwargs ) + @payload('place') def geo_id(self, place_id, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/geo/place-information/api-reference/get-geo-id-place_id :allowed_param: @@ -1260,9 +1263,10 @@ class API: return bind_api( *args, api=self, path=f'/geo/id/{place_id}.json', - payload_type='place', **kwargs + **kwargs ) + @payload('place', list=True) def geo_search(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-search :allowed_param: 'lat', 'long', 'query', 'ip', 'granularity', @@ -1272,27 +1276,26 @@ class API: return bind_api( *args, api=self, path='/geo/search.json', - payload_type='place', payload_list=True, allowed_param=['lat', 'long', 'query', 'ip', 'granularity', 'accuracy', 'max_results', 'contained_within'], **kwargs ) + @payload('json') def supported_languages(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/developer-utilities/supported-languages/api-reference/get-help-languages """ return bind_api( *args, api=self, path='/help/languages.json', - payload_type='json', require_auth=True, **kwargs ) + @payload('json') def configuration(self, *args, **kwargs): """ :reference: https://developer.twitter.com/en/docs/developer-utilities/configuration/api-reference/get-help-configuration """ return bind_api( *args, api=self, path='/help/configuration.json', - payload_type='json', require_auth=True, **kwargs ) diff --git a/tweepy/binder.py b/tweepy/binder.py index 2f64c68..7e2a8a7 100644 --- a/tweepy/binder.py +++ b/tweepy/binder.py @@ -19,8 +19,6 @@ class APIMethod: def __init__(self, *args, **kwargs): self.api = api = kwargs.pop('api') - self.payload_type = kwargs.pop('payload_type', None) - self.payload_list = kwargs.pop('payload_list', False) self.allowed_param = kwargs.pop('allowed_param', []) self.session = requests.Session() @@ -52,8 +50,9 @@ class APIMethod: log.debug("PARAMS: %r", self.session.params) def execute(self, method, path, *, headers=None, json_payload=None, - post_data=None, require_auth=False, return_cursors=False, - upload_api=False, use_cache=True): + payload_list=False, payload_type=None, post_data=None, + require_auth=False, return_cursors=False, upload_api=False, + use_cache=True): # If authentication is required and no credentials # are provided, throw an error. if require_auth and not self.api.auth: @@ -170,7 +169,9 @@ class APIMethod: # Parse the response payload return_cursors = (return_cursors or 'cursor' in self.session.params or 'next' in self.session.params) - result = self.parser.parse(self, resp.text, return_cursors=return_cursors) + result = self.parser.parse(self, resp.text, payload_list=payload_list, + payload_type=payload_type, + return_cursors=return_cursors) # Store result into cache if one is available. if use_cache and self.api.cache and method == 'GET' and result: @@ -184,6 +185,8 @@ def bind_api(*args, **kwargs): path = kwargs.pop('path') headers = kwargs.pop('headers', {}) json_payload = kwargs.pop('json_payload', None) + payload_list = kwargs.pop('payload_list', False) + payload_type = kwargs.pop('payload_type', None) post_data = kwargs.pop('post_data', None) require_auth = kwargs.pop('require_auth', False) return_cursors = kwargs.pop('return_cursors', False) @@ -197,6 +200,7 @@ def bind_api(*args, **kwargs): else: return method.execute( http_method, path, headers=headers, json_payload=json_payload, + payload_list=payload_list, payload_type=payload_type, post_data=post_data, require_auth=require_auth, return_cursors=return_cursors, upload_api=upload_api, use_cache=use_cache @@ -210,3 +214,16 @@ def pagination(mode): method.pagination_mode = mode return method return decorator + + +def payload(payload_type, **payload_kwargs): + payload_list = payload_kwargs.get('list', False) + def decorator(method): + def wrapper(*args, **kwargs): + kwargs['payload_list'] = payload_list + kwargs['payload_type'] = payload_type + return method(*args, **kwargs) + wrapper.payload_list = payload_list + wrapper.payload_type = payload_type + return wrapper + return decorator diff --git a/tweepy/cursor.py b/tweepy/cursor.py index 2031812..fbc8ae8 100644 --- a/tweepy/cursor.py +++ b/tweepy/cursor.py @@ -133,8 +133,14 @@ class IdIterator(BaseIterator): # This is a special invocation that returns the underlying # APIMethod class - model = ModelParser().parse(self.method(create=True), data) - result = self.method.__self__.parser.parse(self.method(create=True), data) + model = ModelParser().parse(self.method(create=True), data, + payload_list=self.method.payload_list, + payload_type=self.method.payload_type) + result = self.method.__self__.parser.parse( + self.method(create=True), data, + payload_list=self.method.payload_list, + payload_type=self.method.payload_type + ) if len(self.results) != 0: self.index += 1 diff --git a/tweepy/parsers.py b/tweepy/parsers.py index fb5efde..2eea766 100644 --- a/tweepy/parsers.py +++ b/tweepy/parsers.py @@ -43,7 +43,7 @@ class JSONParser(Parser): payload_format = 'json' - def parse(self, method, payload, *, return_cursors=False): + def parse(self, method, payload, *, return_cursors=False, **kwargs): try: json = json_lib.loads(payload) except Exception as e: @@ -81,13 +81,14 @@ class ModelParser(JSONParser): JSONParser.__init__(self) self.model_factory = model_factory or ModelFactory - def parse(self, method, payload, *, return_cursors=False): + def parse(self, method, payload, *, payload_list=False, payload_type=None, + return_cursors=False): try: - if method.payload_type is None: + if payload_type is None: return - model = getattr(self.model_factory, method.payload_type) + model = getattr(self.model_factory, payload_type) except AttributeError: - raise TweepError(f'No model for this payload type: {method.payload_type}') + raise TweepError(f'No model for this payload type: {payload_type}') json = JSONParser.parse(self, method, payload, return_cursors=return_cursors) if isinstance(json, tuple): @@ -95,7 +96,7 @@ class ModelParser(JSONParser): else: cursors = None - if method.payload_list: + if payload_list: result = model.parse_list(method.api, json) else: result = model.parse(method.api, json) -- 2.25.1