From ff7e3fab9429efcb801acf57c6dc326fa309d7e8 Mon Sep 17 00:00:00 2001 From: Mike Helmick Date: Thu, 6 Jun 2013 13:40:39 -0400 Subject: [PATCH] Updating a lot of docstrings, EndpointMixin replaces api_table dict [ci skip] --- twython/api.py | 160 +++--- twython/endpoints.py | 1088 ++++++++++++++++++++++++------------ twython/exceptions.py | 21 +- twython/streaming/api.py | 21 +- twython/streaming/types.py | 18 + 5 files changed, 858 insertions(+), 450 deletions(-) diff --git a/twython/api.py b/twython/api.py index 570b83e..a6cff08 100644 --- a/twython/api.py +++ b/twython/api.py @@ -1,28 +1,38 @@ -import re +# -*- coding: utf-8 -*- + +""" +twython.api +~~~~~~~~~~~ + +This module contains functionality for access to core Twitter API calls, +Twitter Authentication, and miscellaneous methods that are useful when +dealing with the Twitter API +""" import requests from requests_oauthlib import OAuth1 from . import __version__ from .compat import json, urlencode, parse_qsl, quote_plus, str, is_py2 -from .endpoints import api_table +from .endpoints import EndpointsMixin from .exceptions import TwythonError, TwythonAuthError, TwythonRateLimitError from .helpers import _transparent_params -class Twython(object): +class Twython(EndpointsMixin, object): def __init__(self, app_key=None, app_secret=None, oauth_token=None, oauth_token_secret=None, headers=None, proxies=None, api_version='1.1', ssl_verify=True): """Instantiates an instance of Twython. Takes optional parameters for authentication and such (see below). - :param app_key: (optional) Your applications key - :param app_secret: (optional) Your applications secret key - :param oauth_token: (optional) Used with oauth_token_secret to make authenticated calls - :param oauth_token_secret: (optional) Used with oauth_token to make authenticated calls - :param headers: (optional) Custom headers to send along with the request - :param proxies: (optional) A dictionary of proxies, for example {"http":"proxy.example.org:8080", "https":"proxy.example.org:8081"}. - :param ssl_verify: (optional) Turns off ssl verification when False. Useful if you have development server issues. + :param app_key: (optional) Your applications key + :param app_secret: (optional) Your applications secret key + :param oauth_token: (optional) Used with oauth_token_secret to make authenticated calls + :param oauth_token_secret: (optional) Used with oauth_token to make authenticated calls + :param headers: (optional) Custom headers to send along with the request + :param proxies: (optional) A dictionary of proxies, for example {"http":"proxy.example.org:8080", "https":"proxy.example.org:8081"}. + :param ssl_verify: (optional) Turns off ssl verification when False. Useful if you have development server issues. + """ # API urls, OAuth urls and API version; needed for hitting that there API. @@ -62,32 +72,11 @@ class Twython(object): self._last_call = None - def _setFunc(key): - '''Register functions, attaching them to the Twython instance''' - return lambda **kwargs: self._constructFunc(key, **kwargs) - - # Loop through all our Twitter API endpoints made available in endpoints.py - for key in api_table.keys(): - self.__dict__[key] = _setFunc(key) - def __repr__(self): return '' % (self.app_key) - def _constructFunc(self, api_call, **kwargs): - # Go through and replace any {{mustaches}} that are in our API url. - fn = api_table[api_call] - url = re.sub( - '\{\{(?P[a-zA-Z_]+)\}\}', - lambda m: "%s" % kwargs.get(m.group(1)), - self.api_url % self.api_version + fn['url'] - ) - - return self._request(url, method=fn['method'], params=kwargs) - def _request(self, url, method='GET', params=None, api_call=None): - '''Internal response generator, no sense in repeating the same - code twice, right? ;) - ''' + """Internal request method""" method = method.lower() params = params or {} @@ -153,14 +142,21 @@ class Twython(object): return content - ''' - # Dynamic Request Methods - Just in case Twitter releases something in their API - and a developer wants to implement it on their app, but - we haven't gotten around to putting it in Twython yet. :) - ''' - def request(self, endpoint, method='GET', params=None, version='1.1'): + """Return dict of response received from Twitter's API + + :param endpoint: (required) Full url or Twitter API endpoint (e.g. search/tweets) + :type endpoint: string + :param method: (optional) Method of accessing data, either GET or POST. (default GET) + :type method: string + :param params: (optional) Dict of parameters (if any) accepted the by Twitter API endpoint you are trying to access (default None) + :type params: dict or None + :param version: (optional) Twitter API version to access (default 1.1) + :type version: string + + :rtype: dict + """ + # In case they want to pass a full Twitter URL # i.e. https://api.twitter.com/1.1/search/tweets.json if endpoint.startswith('http://') or endpoint.startswith('https://'): @@ -173,25 +169,25 @@ class Twython(object): return content def get(self, endpoint, params=None, version='1.1'): + """Shortcut for GET requests via :class:`request`""" return self.request(endpoint, params=params, version=version) def post(self, endpoint, params=None, version='1.1'): + """Shortcut for POST requests via :class:`request`""" return self.request(endpoint, 'POST', params=params, version=version) - # End Dynamic Request Methods - def get_lastfunction_header(self, header): - """Returns the header in the last function - This must be called after an API call, as it returns header based - information. + """Returns a specific header from the last API call + This will return None if the header is not present - This will return None if the header is not present + :param header: (required) The name of the header you want to get the value of + + Most useful for the following header information: + x-rate-limit-limit, + x-rate-limit-remaining, + x-rate-limit-class, + x-rate-limit-reset - Most useful for the following header information: - x-rate-limit-limit - x-rate-limit-remaining - x-rate-limit-class - x-rate-limit-reset """ if self._last_call is None: raise TwythonError('This function must be called after an API call. It delivers header information.') @@ -202,11 +198,12 @@ class Twython(object): return None def get_authentication_tokens(self, callback_url=None, force_login=False, screen_name=''): - """Returns a dict including an authorization URL (auth_url) to direct a user to + """Returns a dict including an authorization URL, ``auth_url``, to direct a user to - :param callback_url: (optional) Url the user is returned to after they authorize your app (web clients only) - :param force_login: (optional) Forces the user to enter their credentials to ensure the correct users account is authorized. - :param app_secret: (optional) If forced_login is set OR user is not currently logged in, Prefills the username input box of the OAuth login screen with the given value + :param callback_url: (optional) Url the user is returned to after they authorize your app (web clients only) + :param force_login: (optional) Forces the user to enter their credentials to ensure the correct users account is authorized. + :param app_secret: (optional) If forced_login is set OR user is not currently logged in, Prefills the username input box of the OAuth login screen with the given value + :rtype: dict """ callback_url = callback_url or self.callback_url request_args = {} @@ -244,9 +241,11 @@ class Twython(object): return request_tokens def get_authorized_tokens(self, oauth_verifier): - """Returns authorized tokens after they go through the auth_url phase. + """Returns a dict of authorized tokens after they go through the :class:`get_authentication_tokens` phase. + + :param oauth_verifier: (required) The oauth_verifier (or a.k.a PIN for non web apps) retrieved from the callback url querystring + :rtype: dict - :param oauth_verifier: (required) The oauth_verifier (or a.k.a PIN for non web apps) retrieved from the callback url querystring """ response = self.client.get(self.access_token_url, params={'oauth_verifier': oauth_verifier}) authorized_tokens = dict(parse_qsl(response.content.decode('utf-8'))) @@ -262,7 +261,24 @@ class Twython(object): # ------------------------------------------------------------------------------------------------------------------------ @staticmethod - def construct_api_url(base_url, params=None): + def construct_api_url(api_url, **params): + """Construct a Twitter API url, encoded, with parameters + + :param api_url: URL of the Twitter API endpoint you are attempting to construct + :param \*\*params: Parameters that are accepted by Twitter for the endpoint you're requesting + :rtype: string + + Usage:: + + >>> from twython import Twython + >>> twitter = Twython() + + >>> api_url = 'https://api.twitter.com/1.1/search/tweets.json' + >>> constructed_url = twitter.construct_api_url(api_url, q='python', result_type='popular') + >>> print constructed_url + https://api.twitter.com/1.1/search/tweets.json?q=python&result_type=popular + + """ querystring = [] params, _ = _transparent_params(params or {}) params = requests.utils.to_key_val_list(params) @@ -270,18 +286,28 @@ class Twython(object): querystring.append( '%s=%s' % (Twython.encode(k), quote_plus(Twython.encode(v))) ) - return '%s?%s' % (base_url, '&'.join(querystring)) + return '%s?%s' % (api_url, '&'.join(querystring)) - def search_gen(self, search_query, **kwargs): + def search_gen(self, search_query, **params): """Returns a generator of tweets that match a specified query. - Documentation: https://dev.twitter.com/docs/api/1.1/get/search/tweets + Documentation: https://dev.twitter.com/docs/api/1.1/get/search/tweets + + :param search_query: Query you intend to search Twitter for + :param \*\*params: Extra parameters to send with your search request + :rtype: generator + + Usage:: + + >>> from twython import Twython + >>> twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET) + + >>> search = twitter.search_gen('python') + >>> for result in search: + >>> print result - e.g search = x.search_gen('python') - for result in search: - print result """ - content = self.search(q=search_query, **kwargs) + content = self.search(q=search_query, **params) if not content.get('statuses'): raise StopIteration @@ -290,12 +316,12 @@ class Twython(object): yield tweet try: - if not 'since_id' in kwargs: - kwargs['since_id'] = (int(content['statuses'][0]['id_str']) + 1) + if not 'since_id' in params: + params['since_id'] = (int(content['statuses'][0]['id_str']) + 1) except (TypeError, ValueError): raise TwythonError('Unable to generate next page of search results, `page` is not a number.') - for tweet in self.search_gen(search_query, **kwargs): + for tweet in self.search_gen(search_query, **params): yield tweet @staticmethod diff --git a/twython/endpoints.py b/twython/endpoints.py index 1246a3d..41151d4 100644 --- a/twython/endpoints.py +++ b/twython/endpoints.py @@ -1,415 +1,773 @@ +# -*- coding: utf-8 -*- + """ -A huge map of every Twitter API endpoint to a function definition in Twython. +twython.endpoints +~~~~~~~~~~~~~~~~~ -Parameters that need to be embedded in the URL are treated with mustaches, e.g: +This module provides a mixin for a :class:`Twython ` instance. +Parameters that need to be embedded in the API url just need to be passed as a keyword argument. -{{version}}, etc - -When creating new endpoint definitions, keep in mind that the name of the mustache -will be replaced with the keyword that gets passed in to the function at call time. - -i.e, in this case, if I pass version = 47 to any function, {{version}} will be replaced -with 47, instead of defaulting to 1.1 (said defaulting takes place at conversion time). +e.g. Twython.retweet(id=12345) This map is organized the order functions are documented at: https://dev.twitter.com/docs/api/1.1 """ -api_table = { - # Timelines - 'get_mentions_timeline': { - 'url': '/statuses/mentions_timeline.json', - 'method': 'GET', - }, - 'get_user_timeline': { - 'url': '/statuses/user_timeline.json', - 'method': 'GET', - }, - 'get_home_timeline': { - 'url': '/statuses/home_timeline.json', - 'method': 'GET', - }, - 'retweeted_of_me': { - 'url': '/statuses/retweets_of_me.json', - 'method': 'GET', - }, +class EndpointsMixin(object): + # Timelines + def get_mentions_timeline(self, **params): + """Returns the 20 most recent mentions (tweets containing a users's + @screen_name) for the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/mentions_timeline + + """ + return self.get('statuses/mentions_timeline', params=params) + + def get_user_timeline(self, **params): + """Returns a collection of the most recent Tweets posted by the user + indicated by the screen_name or user_id parameters. + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline + + """ + return self.get('statuses/user_timeline', params=params) + + def get_home_timline(self, **params): + """Returns a collection of the most recent Tweets and retweets + posted by the authenticating user and the users they follow. + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline + + """ + return self.get('statuses/home_timline', params=params) + + def retweeted_of_me(self, **params): + """Returns the most recent tweets authored by the authenticating user + that have been retweeted by others. + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/retweets_of_me + + """ + return self.get('statuses/retweets_of_me', params=params) # Tweets - 'get_retweets': { - 'url': '/statuses/retweets/{{id}}.json', - 'method': 'GET', - }, - 'show_status': { - 'url': '/statuses/show/{{id}}.json', - 'method': 'GET', - }, - 'destroy_status': { - 'url': '/statuses/destroy/{{id}}.json', - 'method': 'POST', - }, - 'update_status': { - 'url': '/statuses/update.json', - 'method': 'POST', - }, - 'retweet': { - 'url': '/statuses/retweet/{{id}}.json', - 'method': 'POST', - }, - 'update_status_with_media': { - 'url': '/statuses/update_with_media.json', - 'method': 'POST', - }, - 'get_oembed_tweet': { - 'url': '/statuses/oembed.json', - 'method': 'GET', - }, - 'get_retweeters_ids': { - 'url': '/statuses/retweeters/ids.json', - 'method': 'GET', - }, + def get_retweets(self, **params): + """Returns up to 100 of the first retweets of a given tweet. + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/retweets/%3Aid + + """ + if not 'id' in params: + raise TwythonError('Parameter "id" is required') + return self.get('statuses/retweets/%s' % params['id'], params=params) + + def show_status(self, **params): + """Returns a single Tweet, specified by the id parameter + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/show/%3Aid + + """ + if not 'id' in params: + raise TwythonError('Parameter "id" is required') + return self.get('statuses/show/%s' % params['id'], params=params) + + def destroy_status(self, **params): + """Destroys the status specified by the required ID parameter + + Docs: https://dev.twitter.com/docs/api/1.1/post/statuses/destroy/%3Aid + + """ + if not 'id' in params: + raise TwythonError('Parameter "id" is required') + return self.post('statuses/destroy/%s' % params['id']) + + def update_status(self, **params): + """Updates the authenticating user's current status, also known as tweeting + + Docs: https://dev.twitter.com/docs/api/1.1/post/statuses/update + + """ + return self.post('statuses/update_status', params=params) + + def retweet(self, **params): + """Retweets a tweet specified by the id parameter + + Docs: https://dev.twitter.com/docs/api/1.1/post/statuses/retweet/%3Aid + + """ + if not 'id' in params: + raise TwythonError('Parameter "id" is required') + return self.post('statuses/retweet/%s' % params['id']) + + def update_status_with_media(self, **params): + """Updates the authenticating user's current status and attaches media + for upload. In other words, it creates a Tweet with a picture attached. + + Docs: https://dev.twitter.com/docs/api/1.1/post/statuses/update_with_media + + """ + return self.post('statuses/update_with_media', params=params) + + def get_oembed_tweet(self, **params): + """Returns information allowing the creation of an embedded + representation of a Tweet on third party sites. + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/oembed + + """ + return self.get('statuses/oembed', params=params) + + def get_retweeters_id(self, **params): + """Returns a collection of up to 100 user IDs belonging to users who + have retweeted the tweet specified by the id parameter. + + Docs: https://dev.twitter.com/docs/api/1.1/get/statuses/retweeters/ids + + """ + return self.get('statuses/retweeters/ids', params=params) # Search - 'search': { - 'url': '/search/tweets.json', - 'method': 'GET', - }, + def search(self, **params): + """Returns a collection of relevant Tweets matching a specified query. + Docs: https://dev.twitter.com/docs/api/1.1/get/search/tweets + + """ + return self.get('search/tweets', params=params) # Direct Messages - 'get_direct_messages': { - 'url': '/direct_messages.json', - 'method': 'GET', - }, - 'get_sent_messages': { - 'url': '/direct_messages/sent.json', - 'method': 'GET', - }, - 'get_direct_message': { - 'url': '/direct_messages/show.json', - 'method': 'GET', - }, - 'destroy_direct_message': { - 'url': '/direct_messages/destroy.json', - 'method': 'POST', - }, - 'send_direct_message': { - 'url': '/direct_messages/new.json', - 'method': 'POST', - }, + def get_direct_messages(self, **params): + """Returns the 20 most recent direct messages sent to the authenticating user. + Docs: https://dev.twitter.com/docs/api/1.1/get/direct_messages + + """ + return self.get('direct_messages', params=params) + + def get_sent_messages(self, **params): + """Returns the 20 most recent direct messages sent by the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/direct_messages/sent + + """ + return self.get('direct_messages/sent', params=params) + + def get_direct_message(self, **params): + """Returns a single direct message, specified by an id parameter. + + Docs: https://dev.twitter.com/docs/api/1.1/get/direct_messages/show + + """ + return self.get('direct_messages/show', params=params) + + def destroy_direct_message(self, **params): + """Destroys the direct message specified in the required id parameter + + Docs: https://dev.twitter.com/docs/api/1.1/post/direct_messages/destroy + + """ + return self.post('direct_messages/destroy', params=params) + + def send_direct_message(self, **params): + """Sends a new direct message to the specified user from the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/direct_messages/new + + """ + return self.post('direct_messages/new', params=params) # Friends & Followers - 'get_user_ids_of_blocked_retweets': { - 'url': '/friendships/no_retweets/ids.json', - 'method': 'GET', - }, - 'get_friends_ids': { - 'url': '/friends/ids.json', - 'method': 'GET', - }, - 'get_followers_ids': { - 'url': '/followers/ids.json', - 'method': 'GET', - }, - 'lookup_friendships': { - 'url': '/friendships/lookup.json', - 'method': 'GET', - }, - 'get_incoming_friendship_ids': { - 'url': '/friendships/incoming.json', - 'method': 'GET', - }, - 'get_outgoing_friendship_ids': { - 'url': '/friendships/outgoing.json', - 'method': 'GET', - }, - 'create_friendship': { - 'url': '/friendships/create.json', - 'method': 'POST', - }, - 'destroy_friendship': { - 'url': '/friendships/destroy.json', - 'method': 'POST', - }, - 'update_friendship': { - 'url': '/friendships/update.json', - 'method': 'POST', - }, - 'show_friendship': { - 'url': '/friendships/show.json', - 'method': 'GET', - }, - 'get_friends_list': { - 'url': '/friends/list.json', - 'method': 'GET', - }, - 'get_followers_list': { - 'url': '/followers/list.json', - 'method': 'GET', - }, + def get_user_ids_of_blocked_retweets(self, **params): + """Returns a collection of user_ids that the currently authenticated + user does not want to receive retweets from. + Docs: https://dev.twitter.com/docs/api/1.1/get/friendships/no_retweets/ids + + """ + return self.get('friendships/no_retweets/ids', params=params) + + def get_friends_ids(self, **params): + """Returns a cursored collection of user IDs for every user the + specified user is following (otherwise known as their "friends"). + + Docs: https://dev.twitter.com/docs/api/1.1/get/friends/ids + + """ + return self.get('friends/ids', params=params) + + def get_followers_ids(self, **params): + """Returns a cursored collection of user IDs for every user + following the specified user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/followers/ids + + """ + return self.get('followers/ids', params=params) + + def lookup_friendships(self, **params): + """Returns the relationships of the authenticating user to the + comma-separated list of up to 100 screen_names or user_ids provided. + + Docs: https://dev.twitter.com/docs/api/1.1/get/friendships/lookup + + """ + return self.get('friendships/lookup', params=params) + + def get_incoming_friendship_ids(self, **params): + """Returns a collection of numeric IDs for every user who has a + pending request to follow the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/friendships/incoming + + """ + return self.get('friendships/incoming', params=params) + + def get_outgoing_friendship_ids(self, **params): + """Returns a collection of numeric IDs for every protected user for + whom the authenticating user has a pending follow request. + + Docs: https://dev.twitter.com/docs/api/1.1/get/friendships/outgoing + + """ + return self.get('friendships/outgoing', params=params) + + def create_friendship(self, **params): + """Allows the authenticating users to follow the user specified + in the ID parameter. + + Docs: https://dev.twitter.com/docs/api/1.1/post/friendships/create + + """ + return self.post('friendships/create', params=params) + + def destroy_friendship(self, **params): + """Allows the authenticating user to unfollow the user specified + in the ID parameter. + + Docs: https://dev.twitter.com/docs/api/1.1/post/friendships/destroy + + """ + return self.post('friendships/destroy', params=params) + + def update_friendship(self, **params): + """Allows one to enable or disable retweets and device notifications + from the specified user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/friendships/update + + """ + return self.post('friendships/update', params=params) + + def show_friendship(self, **params): + """Returns detailed information about the relationship between two + arbitrary users. + + Docs: https://dev.twitter.com/docs/api/1.1/get/friendships/show + + """ + return self.get('friendships/show', params=params) + + def get_friends_list(self, **params): + """Returns a cursored collection of user objects for every user the + specified user is following (otherwise known as their "friends"). + + Docs: https://dev.twitter.com/docs/api/1.1/get/friends/list + + """ + return self.get('friends/list', params=params) + + def get_followers_list(self, **params): + """Returns a cursored collection of user objects for users + following the specified user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/followers/list + + """ + return self.get('followers/list', params=params) # Users - 'get_account_settings': { - 'url': '/account/settings.json', - 'method': 'GET', - }, - 'verify_credentials': { - 'url': '/account/verify_credentials.json', - 'method': 'GET', - }, - 'update_account_settings': { - 'url': '/account/settings.json', - 'method': 'POST', - }, - 'update_delivery_service': { - 'url': '/account/update_delivery_device.json', - 'method': 'POST', - }, - 'update_profile': { - 'url': '/account/update_profile.json', - 'method': 'POST', - }, - 'update_profile_background_image': { - 'url': '/account/update_profile_banner.json', - 'method': 'POST', - }, - 'update_profile_colors': { - 'url': '/account/update_profile_colors.json', - 'method': 'POST', - }, - 'update_profile_image': { - 'url': '/account/update_profile_image.json', - 'method': 'POST', - }, - 'list_blocks': { - 'url': '/blocks/list.json', - 'method': 'GET', - }, - 'list_block_ids': { - 'url': '/blocks/ids.json', - 'method': 'GET', - }, - 'create_block': { - 'url': '/blocks/create.json', - 'method': 'POST', - }, - 'destroy_block': { - 'url': '/blocks/destroy.json', - 'method': 'POST', - }, - 'lookup_user': { - 'url': '/users/lookup.json', - 'method': 'GET', - }, - 'show_user': { - 'url': '/users/show.json', - 'method': 'GET', - }, - 'search_users': { - 'url': '/users/search.json', - 'method': 'GET', - }, - 'get_contributees': { - 'url': '/users/contributees.json', - 'method': 'GET', - }, - 'get_contributors': { - 'url': '/users/contributors.json', - 'method': 'GET', - }, - 'remove_profile_banner': { - 'url': '/account/remove_profile_banner.json', - 'method': 'POST', - }, - 'update_profile_background_image': { - 'url': '/account/update_profile_background_image.json', - 'method': 'POST', - }, - 'get_profile_banner_sizes': { - 'url': '/users/profile_banner.json', - 'method': 'GET', - }, + def get_account_settings(self, **params): + """Returns settings (including current trend, geo and sleep time + information) for the authenticating user. + Docs: https://dev.twitter.com/docs/api/1.1/get/account/settings + + """ + return self.get('account/settings', params=params) + + def verify_Credentials(self, **params): + """Returns an HTTP 200 OK response code and a representation of the + requesting user if authentication was successful; returns a 401 status + code and an error message if not. + + Docs: https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials + + """ + return self.get('account/verify_credentials', params=params) + + def update_account_settings(self, **params): + """Updates the authenticating user's settings. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/settings + + """ + return self.post('account/settings', params=params) + + def update_delivery_service(self, **params): + """Sets which device Twitter delivers updates to for the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/update_delivery_device + + """ + return self.post('account/update_delivery_device', params=params) + + def update_profile(self, **params): + """Sets values that users are able to set under the "Account" tab of their settings page. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/update_profile + + """ + return self.post('account/update_profile', params=params) + + def update_profile_background_image(self, **params): + """Updates the authenticating user's profile background image. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/update_profile_background_image + + """ + return self.post('account/update_profile_banner', params=params) + + def update_profile_colors(self, **params): + """Sets one or more hex values that control the color scheme of the + authenticating user's profile page on twitter.com. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/update_profile_colors + + """ + return self.post('account/update_profile_colors', params=params) + + def update_profile_image(self, **params): + """Updates the authenticating user's profile image. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/update_profile_image + + """ + return self.post('account/update_profile_image', params=params) + + def list_blocks(self, **params): + """Returns a collection of user objects that the authenticating user is blocking. + + Docs: https://dev.twitter.com/docs/api/1.1/get/blocks/list + + """ + return self.get('blocks/list', params=params) + + def list_block_ids(self, **params): + """Returns an array of numeric user ids the authenticating user is blocking. + + Docs: https://dev.twitter.com/docs/api/1.1/get/blocks/ids + + """ + return self.get('blocks/ids', params=params) + + def create_block(self, **params): + """Blocks the specified user from following the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/blocks/create + + """ + return self.post('blocks/create', params=params) + + def destroy_block(self, **params): + """Un-blocks the user specified in the ID parameter for the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/blocks/destroy + + """ + return self.post('blocks/destroy', params=params) + + def lookup_user(self, **params): + """Returns fully-hydrated user objects for up to 100 users per request, + as specified by comma-separated values passed to the user_id and/or screen_name parameters. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/lookup + + """ + return self.get('users/lookup', params=params) + + def show_user(self, **params): + """Returns a variety of information about the user specified by the + required user_id or screen_name parameter. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/show + + """ + return self.get('users/show', params=params) + + def search_users(self, **params): + """Provides a simple, relevance-based search interface to public user accounts on Twitter. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/search + + """ + return self.get('users/search', params=params) + + def get_contributees(self, **params): + """Returns a collection of users that the specified user can "contribute" to. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/contributees + + """ + return self.get('users/contributees', params=params) + + def get_contributors(self, **params): + """Returns a collection of users who can contribute to the specified account. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/contributors + + """ + return self.get('users/contributors', params=params) + + def remove_profile_banner(self, **params): + """Removes the uploaded profile banner for the authenticating user. + Returns HTTP 200 upon success. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/remove_profile_banner + + """ + return self.post('account/remove_profile_banner', params=params) + + def update_profile_Background_image(self, **params): + """Uploads a profile banner on behalf of the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/account/update_profile_banner + + """ + return self.post('ccount/update_profile_background_image', params=params) + + def get_profile_banner_sizes(self, **params): + """Returns a map of the available size variations of the specified user's profile banner. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/profile_banner + + """ + return self.get('users/profile_banner', params=params) # Suggested Users - 'get_user_suggestions_by_slug': { - 'url': '/users/suggestions/{{slug}}.json', - 'method': 'GET', - }, - 'get_user_suggestions': { - 'url': '/users/suggestions.json', - 'method': 'GET', - }, - 'get_user_suggestions_statuses_by_slug': { - 'url': '/users/suggestions/{{slug}}/members.json', - 'method': 'GET', - }, + def get_user_suggestions_by_slug(self, **params): + """Access the users in a given category of the Twitter suggested user list. + Docs: https://dev.twitter.com/docs/api/1.1/get/users/suggestions/%3Aslug + + """ + return self.get('users/suggestions/%s' % params['slug'], params=params) + + def get_user_suggestions(self, **params): + """Access to Twitter's suggested user list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/suggestions + + """ + return self.get('users/suggestions', params=params) + + def get_user_suggestions_statuses_by_slug(self, **params): + """Access the users in a given category of the Twitter suggested user + list and return their most recent status if they are not a protected user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/users/suggestions/%3Aslug/members + + """ + return self.get('users/suggestions/%s/members' % param['slug'], params=params) # Favorites - 'get_favorites': { - 'url': '/favorites/list.json', - 'method': 'GET', - }, - 'destroy_favorite': { - 'url': '/favorites/destroy.json', - 'method': 'POST', - }, - 'create_favorite': { - 'url': '/favorites/create.json', - 'method': 'POST', - }, + def get_favorites(self, **params): + """Returns the 20 most recent Tweets favorited by the authenticating or specified user. + Docs: https://dev.twitter.com/docs/api/1.1/get/favorites/list + + """ + return self.get('favorites/list', params=params) + + def destroy_favorite(self, **params): + """Un-favorites the status specified in the ID parameter as the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/favorites/destroy + + """ + return self.post('favorites/destroy', params=params) + + def create_favorite(self, **params): + """Favorites the status specified in the ID parameter as the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/favorites/create + + """ + return self.post('favorites/create', params=params) # Lists - 'show_lists': { - 'url': '/lists/list.json', - 'method': 'GET', - }, - 'get_list_statuses': { - 'url': '/lists/statuses.json', - 'method': 'GET' - }, - 'delete_list_member': { - 'url': '/lists/members/destroy.json', - 'method': 'POST', - }, - 'get_list_memberships': { - 'url': '/lists/memberships.json', - 'method': 'GET', - }, - 'get_list_subscribers': { - 'url': '/lists/subscribers.json', - 'method': 'GET', - }, - 'subscribe_to_list': { - 'url': '/lists/subscribers/create.json', - 'method': 'POST', - }, - 'is_list_subscriber': { - 'url': '/lists/subscribers/show.json', - 'method': 'GET', - }, - 'unsubscribe_from_list': { - 'url': '/lists/subscribers/destroy.json', - 'method': 'POST', - }, - 'create_list_members': { - 'url': '/lists/members/create_all.json', - 'method': 'POST' - }, - 'is_list_member': { - 'url': '/lists/members/show.json', - 'method': 'GET', - }, - 'get_list_members': { - 'url': '/lists/members.json', - 'method': 'GET', - }, - 'add_list_member': { - 'url': '/lists/members/create.json', - 'method': 'POST', - }, - 'delete_list': { - 'url': '/lists/destroy.json', - 'method': 'POST', - }, - 'update_list': { - 'url': '/lists/update.json', - 'method': 'POST', - }, - 'create_list': { - 'url': '/lists/create.json', - 'method': 'POST', - }, - 'get_specific_list': { - 'url': '/lists/show.json', - 'method': 'GET', - }, - 'get_list_subscriptions': { - 'url': '/lists/subscriptions.json', - 'method': 'GET', - }, - 'delete_list_members': { - 'url': '/lists/members/destroy_all.json', - 'method': 'POST' - }, - 'show_owned_lists': { - 'url': '/lists/ownerships.json', - 'method': 'GET' - }, + def show_lists(self, **params): + """Returns all lists the authenticating or specified user subscribes to, including their own. + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/list + + """ + return self.get('lists/list', params=params) + + def get_list_statuses(self, **params): + """Returns a timeline of tweets authored by members of the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/statuses + + """ + return self.get('lists/statuses', params=params) + + def delete_list_member(self, **params): + """Removes the specified member from the list. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/members/destroy + + """ + return self.post('lists/members/destroy', params=params) + + + def get_list_subscribers(self, **params): + """Returns the subscribers of the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/subscribers + + """ + return self.get('lists/subscribers', params=params) + + def subscribe_to_list(self, **params): + """Subscribes the authenticated user to the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/subscribers/create + + """ + return self.post('lists/subscribers/create', params=params) + + def is_list_subscriber(self, **params): + """Check if the specified user is a subscriber of the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/subscribers/show + + """ + return self.get('lists/subscribers/show', params=params) + + def unsubscribe_from_list(self, **params): + """Unsubscribes the authenticated user from the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/subscribers/destroy + + """ + return self.get('lists/subscribers/destroy', params=params) + + def create_list_members(self, **params): + """Adds multiple members to a list, by specifying a comma-separated + list of member ids or screen names. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/members/create_all + + """ + return self.post('lists/members/create_all', params=params) + + def is_list_member(self, **params): + """Check if the specified user is a member of the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/members/show + + """ + return self.get('lists/members/show', params=params) + + def get_list_members(self, **params): + """Returns the members of the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/members + + """ + return self.get('lists/members', params=params) + + def add_list_member(self, **params): + """Add a member to a list. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/members/create + + """ + return self.post('lists/members/create', params=params) + + def delete_list(self, **params): + """Deletes the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/destroy + + """ + return self.post('lists/destroy', params=params) + + def update_list(self, **params): + """Updates the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/update + + """ + return self.post('lists/update', params=params) + + def create_list(self, **params): + """Creates a new list for the authenticated user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/create + + """ + return self.post('lists/create', params=params) + + def get_specific_list(self, **params): + """Returns the specified list. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/show + + """ + return self.get('lists/show', params=params) + + def get_list_subscriptions(self, **params): + """Obtain a collection of the lists the specified user is subscribed to. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/subscriptions + + """ + return self.get('lists/subscriptions', params=params) + + def delete_list_members(self, **params): + """Removes multiple members from a list, by specifying a + comma-separated list of member ids or screen names. + + Docs: https://dev.twitter.com/docs/api/1.1/post/lists/members/destroy_all + + """ + return self.post('lists/members/destroy_all', params=params) + + def show_owned_lists(self, **params): + """Returns the lists owned by the specified Twitter user. + + Docs: https://dev.twitter.com/docs/api/1.1/get/lists/ownerships + + """ + return self.get('lists/ownerships', params=params) # Saved Searches - 'get_saved_searches': { - 'url': '/saved_searches/list.json', - 'method': 'GET', - }, - 'show_saved_search': { - 'url': '/saved_searches/show/{{id}}.json', - 'method': 'GET', - }, - 'create_saved_search': { - 'url': '/saved_searches/create.json', - 'method': 'POST', - }, - 'destroy_saved_search': { - 'url': '/saved_searches/destroy/{{id}}.json', - 'method': 'POST', - }, + def get_saved_searches(self, **params): + """Returns the authenticated user's saved search queries. + Docs: https://dev.twitter.com/docs/api/1.1/get/saved_searches/list + + """ + return self.get('saved_searches/list', params=params) + + def show_saved_search(self, **params): + """Retrieve the information for the saved search represented by the given id. + + Docs: https://dev.twitter.com/docs/api/1.1/get/saved_searches/show/%3Aid + + """ + return self.get('saved_searches/show/%s' % params['id'], params=params) + + def create_saved_search(self, **params): + """Create a new saved search for the authenticated user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/saved_searches/create + + """ + return self.post('saved_searches/create', params=params) + + def destroy_saved_search(self, **params): + """Destroys a saved search for the authenticating user. + + Docs: https://dev.twitter.com/docs/api/1.1/post/saved_searches/destroy/%3Aid + + """ + return self.post('saved_searches/destroy/%s' % params['id'], params=params) # Places & Geo - 'get_geo_info': { - 'url': '/geo/id/{{place_id}}.json', - 'method': 'GET', - }, - 'reverse_geocode': { - 'url': '/geo/reverse_geocode.json', - 'method': 'GET', - }, - 'search_geo': { - 'url': '/geo/search.json', - 'method': 'GET', - }, - 'get_similar_places': { - 'url': '/geo/similar_places.json', - 'method': 'GET', - }, - 'create_place': { - 'url': '/geo/place.json', - 'method': 'POST', - }, + def get_geo_info(self, **params): + """Returns all the information about a known place. + Docs: https://dev.twitter.com/docs/api/1.1/get/geo/id/%3Aplace_id + + """ + return self.get('geo/id/%s' % params['place_id'], params=params) + + def reverse_geocode(self, **params): + """Given a latitude and a longitude, searches for up to 20 places + that can be used as a place_id when updating a status. + + Docs: https://dev.twitter.com/docs/api/1.1/get/geo/reverse_geocode + + """ + return self.get('geo/reverse_geocode', params=params) + + def search_geo(self, **params): + """Search for places that can be attached to a statuses/update. + + Docs: https://dev.twitter.com/docs/api/1.1/get/geo/search + + """ + return self.get('geo/search', params=params) + + def get_similar_places(self, **params): + """Locates places near the given coordinates which are similar in name. + + Docs: https://dev.twitter.com/docs/api/1.1/get/geo/similar_places + + """ + return self.get('geo/similar_places', params=params) + + def create_place(self, **params): + """Creates a new place object at the given latitude and longitude. + + Docs: https://dev.twitter.com/docs/api/1.1/post/geo/place + + """ + return self.post('geo/place', params=params) # Trends - 'get_place_trends': { - 'url': '/trends/place.json', - 'method': 'GET', - }, - 'get_available_trends': { - 'url': '/trends/available.json', - 'method': 'GET', - }, - 'get_closest_trends': { - 'url': '/trends/closest.json', - 'method': 'GET', - }, + def get_place_trends(self, **params): + """Returns the top 10 trending topics for a specific WOEID, if + trending information is available for it. + Docs: https://dev.twitter.com/docs/api/1.1/get/trends/place + + """ + return self.get('trends/place', params=params) + + def get_available_trends(self, **params): + """Returns the locations that Twitter has trending topic information for. + + Docs: https://dev.twitter.com/docs/api/1.1/get/trends/available + + """ + return self.get('trends/available', params=params) + + def get_closest_trends(self, **params): + """Returns the locations that Twitter has trending topic information + for, closest to a specified location. + + Docs: https://dev.twitter.com/docs/api/1.1/get/trends/closest + + """ + return self.get('trends/closest', params=params) # Spam Reporting - 'report_spam': { - 'url': '/users/report_spam.json', - 'method': 'POST', - }, -} + def report_spam(self, **params): + """Report the specified user as a spam account to Twitter. + + Docs: https://dev.twitter.com/docs/api/1.1/post/users/report_spam + + """ + return self.post('users/report_spam', params=params) # from https://dev.twitter.com/docs/error-codes-responses -twitter_http_status_codes = { +TWITTER_HTTP_STATUS_CODE = { 200: ('OK', 'Success!'), 304: ('Not Modified', 'There was no new data to return.'), 400: ('Bad Request', 'The request was invalid. An accompanying error message will explain why. This is the status code will be returned during rate limiting.'), diff --git a/twython/exceptions.py b/twython/exceptions.py index 924a882..be418a2 100644 --- a/twython/exceptions.py +++ b/twython/exceptions.py @@ -1,23 +1,20 @@ -from .endpoints import twitter_http_status_codes +from .endpoints import TWITTER_HTTP_STATUS_CODE class TwythonError(Exception): """Generic error class, catch-all for most Twython issues. Special cases are handled by TwythonAuthError & TwythonRateLimitError. - Note: Syntax has changed as of Twython 1.3. To catch these, - you need to explicitly import them into your code, e.g: + from twython import TwythonError, TwythonRateLimitError, TwythonAuthError - from twython import ( - TwythonError, TwythonRateLimitError, TwythonAuthError - )""" + """ def __init__(self, msg, error_code=None, retry_after=None): self.error_code = error_code - if error_code is not None and error_code in twitter_http_status_codes: + if error_code is not None and error_code in TWITTER_HTTP_STATUS_CODE: msg = 'Twitter API returned a %s (%s), %s' % \ (error_code, - twitter_http_status_codes[error_code][0], + TWITTER_HTTP_STATUS_CODE[error_code][0], msg) super(TwythonError, self).__init__(msg) @@ -29,7 +26,9 @@ class TwythonError(Exception): class TwythonAuthError(TwythonError): """Raised when you try to access a protected resource and it fails due to - some issue with your authentication.""" + some issue with your authentication. + + """ pass @@ -37,7 +36,9 @@ class TwythonRateLimitError(TwythonError): """Raised when you've hit a rate limit. The amount of seconds to retry your request in will be appended - to the message.""" + to the message. + + """ def __init__(self, msg, error_code, retry_after=None): if isinstance(retry_after, int): msg = '%s (Retry after %d seconds)' % (msg, retry_after) diff --git a/twython/streaming/api.py b/twython/streaming/api.py index a246593..05eafdb 100644 --- a/twython/streaming/api.py +++ b/twython/streaming/api.py @@ -1,6 +1,5 @@ from .. import __version__ from ..compat import json, is_py3 -from ..exceptions import TwythonStreamError from .types import TwythonStreamerTypes import requests @@ -112,7 +111,8 @@ class TwythonStreamer(object): See https://dev.twitter.com/docs/streaming-apis/messages for messages sent along in stream responses. - :param data: dict of data recieved from the stream + :param data: data recieved from the stream + :type data: dict """ if 'delete' in data: @@ -129,7 +129,10 @@ class TwythonStreamer(object): want it handled. :param status_code: Non-200 status code sent from stream + :type status_code: int + :param data: Error message sent from stream + :type data: dict """ return @@ -141,8 +144,8 @@ class TwythonStreamer(object): Twitter docs for deletion notices: http://spen.se/8qujd - :param data: dict of data from the 'delete' key recieved from - the stream + :param data: data from the 'delete' key recieved from the stream + :type data: dict """ return @@ -154,8 +157,8 @@ class TwythonStreamer(object): Twitter docs for limit notices: http://spen.se/hzt0b - :param data: dict of data from the 'limit' key recieved from - the stream + :param data: data from the 'limit' key recieved from the stream + :type data: dict """ return @@ -167,13 +170,15 @@ class TwythonStreamer(object): Twitter docs for disconnect notices: http://spen.se/xb6mm - :param data: dict of data from the 'disconnect' key recieved from - the stream + :param data: data from the 'disconnect' key recieved from the stream + :type data: dict """ return def on_timeout(self): + """ Called when the request has timed out """ return def disconnect(self): + """Used to disconnect the streaming client manually""" self.connected = False diff --git a/twython/streaming/types.py b/twython/streaming/types.py index c17cadf..e96adef 100644 --- a/twython/streaming/types.py +++ b/twython/streaming/types.py @@ -1,9 +1,20 @@ +# -*- coding: utf-8 -*- + +""" +twython.streaming.types +~~~~~~~~~~~~~~~~~~~~~~~ + +This module contains classes and methods for :class:`TwythonStreamer` to mak +""" + + class TwythonStreamerTypes(object): """Class for different stream endpoints Not all streaming endpoints have nested endpoints. User Streams and Site Streams are single streams with no nested endpoints Status Streams include filter, sample and firehose endpoints + """ def __init__(self, streamer): self.streamer = streamer @@ -36,6 +47,7 @@ class TwythonStreamerTypesStatuses(object): Available so TwythonStreamer.statuses.filter() is available. Just a bit cleaner than TwythonStreamer.statuses_filter(), statuses_sample(), etc. all being single methods in TwythonStreamer + """ def __init__(self, streamer): self.streamer = streamer @@ -43,6 +55,8 @@ class TwythonStreamerTypesStatuses(object): def filter(self, **params): """Stream statuses/filter + :param \*\*params: Paramters to send with your stream request + Accepted params found at: https://dev.twitter.com/docs/api/1.1/post/statuses/filter """ @@ -53,6 +67,8 @@ class TwythonStreamerTypesStatuses(object): def sample(self, **params): """Stream statuses/sample + :param \*\*params: Paramters to send with your stream request + Accepted params found at: https://dev.twitter.com/docs/api/1.1/get/statuses/sample """ @@ -63,6 +79,8 @@ class TwythonStreamerTypesStatuses(object): def firehose(self, **params): """Stream statuses/firehose + :param \*\*params: Paramters to send with your stream request + Accepted params found at: https://dev.twitter.com/docs/api/1.1/get/statuses/firehose """