From 163c394fbe637cc395c87b98f2c7f05aed46e131 Mon Sep 17 00:00:00 2001 From: Henrik Kjallbring Date: Sun, 1 Feb 2015 21:07:31 -0600 Subject: [PATCH 1/4] converted to py3 --- doc/conf.py | 16 ++--- examples/shorten_url.py | 4 +- examples/tweet.py | 12 ++-- examples/twitter-to-xhtml.py | 18 ++--- examples/view_friends.py | 2 +- get_access_token.py | 44 ++++++------ twitter/__init__.py | 22 +++--- twitter/_file_cache.py | 4 +- twitter/api.py | 130 +++++++++++++++++------------------ twitter/list.py | 2 +- twitter/parse_tweet.py | 2 +- twitter/status.py | 4 +- twitter/user.py | 4 +- twitter_test.py | 86 +++++++++++------------ 14 files changed, 175 insertions(+), 175 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index b162b3b7..921b71fb 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -40,8 +40,8 @@ master_doc = 'index' # General information about the project. -project = u'python-twitter' -copyright = u'2013, python-twitter@googlegroups.com' +project = 'python-twitter' +copyright = '2013, python-twitter@googlegroups.com' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -186,8 +186,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'python-twitter.tex', u'python-twitter Documentation', - u'python-twitter@googlegroups.com', 'manual'), + ('index', 'python-twitter.tex', 'python-twitter Documentation', + 'python-twitter@googlegroups.com', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -216,8 +216,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'python-twitter', u'python-twitter Documentation', - [u'python-twitter@googlegroups.com'], 1) + ('index', 'python-twitter', 'python-twitter Documentation', + ['python-twitter@googlegroups.com'], 1) ] # If true, show URL addresses after external links. @@ -230,8 +230,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'python-twitter', u'python-twitter Documentation', - u'python-twitter@googlegroups.com', 'python-twitter', 'One line description of project.', + ('index', 'python-twitter', 'python-twitter Documentation', + 'python-twitter@googlegroups.com', 'python-twitter', 'One line description of project.', 'Miscellaneous'), ] diff --git a/examples/shorten_url.py b/examples/shorten_url.py index 8c7653de..0ff870a1 100755 --- a/examples/shorten_url.py +++ b/examples/shorten_url.py @@ -19,7 +19,7 @@ TinyURL is provided as the default and as an example. """ -import urllib +import urllib.request, urllib.parse, urllib.error # Change History @@ -63,7 +63,7 @@ def Shorten(self, """ result = None - f = urllib.urlopen("http://tinyurl.com/api-create.php?url=%s" % longURL) + f = urllib.request.urlopen("http://tinyurl.com/api-create.php?url=%s" % longURL) try: result = f.read() finally: diff --git a/examples/tweet.py b/examples/tweet.py index 746d35d0..830b882d 100755 --- a/examples/tweet.py +++ b/examples/tweet.py @@ -4,7 +4,7 @@ __author__ = 'dewitt@google.com' -import ConfigParser +import configparser import getopt import os import sys @@ -48,7 +48,7 @@ def PrintUsageAndExit(): - print USAGE + print(USAGE) sys.exit(2) @@ -92,7 +92,7 @@ def _GetOption(self, option): def _GetConfig(self): if not self._config: - self._config = ConfigParser.ConfigParser() + self._config = configparser.ConfigParser() self._config.read(os.path.expanduser('~/.tweetrc')) return self._config @@ -139,10 +139,10 @@ def main(): try: status = api.PostUpdate(message) except UnicodeDecodeError: - print "Your message could not be encoded. Perhaps it contains non-ASCII characters? " - print "Try explicitly specifying the encoding with the --encoding flag" + print("Your message could not be encoded. Perhaps it contains non-ASCII characters? ") + print("Try explicitly specifying the encoding with the --encoding flag") sys.exit(2) - print "%s just posted: %s" % (status.user.name, status.text) + print("%s just posted: %s" % (status.user.name, status.text)) if __name__ == "__main__": diff --git a/examples/twitter-to-xhtml.py b/examples/twitter-to-xhtml.py index eae1efb6..cd1aabbb 100755 --- a/examples/twitter-to-xhtml.py +++ b/examples/twitter-to-xhtml.py @@ -19,14 +19,14 @@ def Usage(): - print 'Usage: %s [options] twitterid' % __file__ - print - print ' This script fetches a users latest twitter update and stores' - print ' the result in a file as an XHTML fragment' - print - print ' Options:' - print ' --help -h : print this help' - print ' --output : the output file [default: stdout]' + print('Usage: %s [options] twitterid' % __file__) + print() + print(' This script fetches a users latest twitter update and stores') + print(' the result in a file as an XHTML fragment') + print() + print(' Options:') + print(' --help -h : print this help') + print(' --output : the output file [default: stdout]') def FetchTwitter(user, output): @@ -37,7 +37,7 @@ def FetchTwitter(user, output): if output: Save(xhtml, output) else: - print xhtml + print(xhtml) def Save(xhtml, output): diff --git a/examples/view_friends.py b/examples/view_friends.py index 502b2e88..0983eea2 100644 --- a/examples/view_friends.py +++ b/examples/view_friends.py @@ -5,4 +5,4 @@ access_token_key='access_token', access_token_secret='access_token_secret') users = api.GetFriends() -print [u.name for u in users] +print([u.name for u in users]) diff --git a/get_access_token.py b/get_access_token.py index ed0622d0..e8423b2d 100755 --- a/get_access_token.py +++ b/get_access_token.py @@ -26,30 +26,30 @@ def get_access_token(consumer_key, consumer_secret): oauth_client = OAuth1Session(consumer_key, client_secret=consumer_secret) - print 'Requesting temp token from Twitter' + print('Requesting temp token from Twitter') try: resp = oauth_client.fetch_request_token(REQUEST_TOKEN_URL) - except ValueError, e: - print 'Invalid respond from Twitter requesting temp token: %s' % e + except ValueError as e: + print('Invalid respond from Twitter requesting temp token: %s' % e) return url = oauth_client.authorization_url(AUTHORIZATION_URL) - print '' - print 'I will try to start a browser to visit the following Twitter page' - print 'if a browser will not start, copy the URL to your browser' - print 'and retrieve the pincode to be used' - print 'in the next step to obtaining an Authentication Token:' - print '' - print url - print '' + print('') + print('I will try to start a browser to visit the following Twitter page') + print('if a browser will not start, copy the URL to your browser') + print('and retrieve the pincode to be used') + print('in the next step to obtaining an Authentication Token:') + print('') + print(url) + print('') webbrowser.open(url) - pincode = raw_input('Pincode? ') + pincode = input('Pincode? ') - print '' - print 'Generating and signing request for an access token' - print '' + print('') + print('Generating and signing request for an access token') + print('') oauth_client = OAuth1Session(consumer_key, client_secret=consumer_secret, resource_owner_key=resp.get('oauth_token'), @@ -58,18 +58,18 @@ def get_access_token(consumer_key, consumer_secret): ) try: resp = oauth_client.fetch_access_token(ACCESS_TOKEN_URL) - except ValueError, e: - print 'Invalid respond from Twitter requesting access token: %s' % e + except ValueError as e: + print('Invalid respond from Twitter requesting access token: %s' % e) return - print 'Your Twitter Access Token key: %s' % resp.get('oauth_token') - print ' Access Token secret: %s' % resp.get('oauth_token_secret') - print '' + print('Your Twitter Access Token key: %s' % resp.get('oauth_token')) + print(' Access Token secret: %s' % resp.get('oauth_token_secret')) + print('') def main(): - consumer_key = raw_input('Enter your consumer key: ') - consumer_secret = raw_input("Enter your consumer secret: ") + consumer_key = input('Enter your consumer key: ') + consumer_secret = input("Enter your consumer secret: ") get_access_token(consumer_key, consumer_secret) diff --git a/twitter/__init__.py b/twitter/__init__.py index 82a54b12..8bfe48f7 100644 --- a/twitter/__init__.py +++ b/twitter/__init__.py @@ -28,14 +28,14 @@ except ImportError: from md5 import md5 -from _file_cache import _FileCache -from error import TwitterError -from direct_message import DirectMessage -from hashtag import Hashtag -from parse_tweet import ParseTweet -from trend import Trend -from url import Url -from status import Status -from user import User, UserStatus -from list import List -from api import Api +from ._file_cache import _FileCache +from .error import TwitterError +from .direct_message import DirectMessage +from .hashtag import Hashtag +from .parse_tweet import ParseTweet +from .trend import Trend +from .url import Url +from .status import Status +from .user import User, UserStatus +from .list import List +from .api import Api diff --git a/twitter/_file_cache.py b/twitter/_file_cache.py index b0ee787a..4432a2b1 100644 --- a/twitter/_file_cache.py +++ b/twitter/_file_cache.py @@ -63,7 +63,7 @@ def _GetUsername(self): os.getenv('USERNAME') or \ os.getlogin() or \ 'nobody' - except (AttributeError, IOError, OSError), e: + except (AttributeError, IOError, OSError) as e: return 'nobody' def _GetTmpCachePath(self): @@ -100,7 +100,7 @@ class ParseTweet: # compile once on import regexp = {"RT": "^RT", "MT": r"^MT", "ALNUM": r"(@[a-zA-Z0-9_]+)", "HASHTAG": r"(#[\w\d]+)", "URL": r"([http://]?[a-zA-Z\d\/]+[\.]+[a-zA-Z\d\/\.]+)"} - regexp = dict((key, re.compile(value)) for key, value in regexp.items()) + regexp = dict((key, re.compile(value)) for key, value in list(regexp.items())) def __init__(self, timeline_owner, tweet): """ timeline_owner : twitter handle of user account. tweet - 140 chars from feed; object does all computation on construction diff --git a/twitter/api.py b/twitter/api.py index a415eba8..37db3427 100644 --- a/twitter/api.py +++ b/twitter/api.py @@ -27,12 +27,12 @@ import sys import textwrap import types -import urllib -import urllib2 -import urlparse +import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.error, urllib.parse +import urllib.parse import requests from requests_oauthlib import OAuth1 -import StringIO +import io from twitter import (__version__, _FileCache, json, DirectMessage, List, Status, Trend, TwitterError, User, UserStatus) @@ -188,9 +188,9 @@ def __init__(self, if consumer_key is not None and (access_token_key is None or access_token_secret is None): - print >> sys.stderr, 'Twitter now requires an oAuth Access Token for API calls.' - print >> sys.stderr, 'If your using this library from a command line utility, please' - print >> sys.stderr, 'run the included get_access_token.py tool to generate one.' + print('Twitter now requires an oAuth Access Token for API calls.', file=sys.stderr) + print('If your using this library from a command line utility, please', file=sys.stderr) + print('run the included get_access_token.py tool to generate one.', file=sys.stderr) raise TwitterError({'message': "Twitter requires oAuth Access Token for all API access"}) @@ -198,9 +198,9 @@ def __init__(self, if debugHTTP: import logging - import httplib + import http.client - httplib.HTTPConnection.debuglevel = 1 + http.client.HTTPConnection.debuglevel = 1 logging.basicConfig() # you need to initialize logging, otherwise you will not see anything from requests logging.getLogger().setLevel(logging.DEBUG) @@ -322,13 +322,13 @@ def GetSearch(self, if since_id: try: - parameters['since_id'] = long(since_id) + parameters['since_id'] = int(since_id) except ValueError: raise TwitterError({'message': "since_id must be an integer"}) if max_id: try: - parameters['max_id'] = long(max_id) + parameters['max_id'] = int(max_id) except ValueError: raise TwitterError({'message': "max_id must be an integer"}) @@ -526,12 +526,12 @@ def GetHomeTimeline(self, parameters['count'] = count if since_id: try: - parameters['since_id'] = long(since_id) + parameters['since_id'] = int(since_id) except ValueError: raise TwitterError({'message': "'since_id' must be an integer"}) if max_id: try: - parameters['max_id'] = long(max_id) + parameters['max_id'] = int(max_id) except ValueError: raise TwitterError({'message': "'max_id' must be an integer"}) if trim_user: @@ -607,12 +607,12 @@ def GetUserTimeline(self, parameters['screen_name'] = screen_name if since_id: try: - parameters['since_id'] = long(since_id) + parameters['since_id'] = int(since_id) except ValueError: raise TwitterError({'message': "since_id must be an integer"}) if max_id: try: - parameters['max_id'] = long(max_id) + parameters['max_id'] = int(max_id) except ValueError: raise TwitterError({'message': "max_id must be an integer"}) if count: @@ -669,7 +669,7 @@ def GetStatus(self, parameters = {} try: - parameters['id'] = long(id) + parameters['id'] = int(id) except ValueError: raise TwitterError({'message': "'id' must be an integer."}) @@ -738,7 +738,7 @@ def GetStatusOembed(self, if id is not None: try: - parameters['id'] = long(id) + parameters['id'] = int(id) except ValueError: raise TwitterError({'message': "'id' must be an integer."}) elif url is not None: @@ -789,7 +789,7 @@ def DestroyStatus(self, id, trim_user=False): raise TwitterError({'message': "API must be authenticated."}) try: - post_data = {'id': long(id)} + post_data = {'id': int(id)} except ValueError: raise TwitterError({'message': "id must be an integer"}) url = '%s/statuses/destroy/%s.json' % (self.base_url, id) @@ -863,10 +863,10 @@ def PostUpdate(self, url = '%s/statuses/update.json' % self.base_url - if isinstance(status, unicode) or self._input_encoding is None: + if isinstance(status, str) or self._input_encoding is None: u_status = status else: - u_status = unicode(status, self._input_encoding) + u_status = str(status, self._input_encoding) # if self._calculate_status_length(u_status, self._shortlink_size) > CHARACTER_LIMIT: # raise TwitterError("Text must be less than or equal to %d characters. " @@ -928,15 +928,15 @@ def PostMedia(self, url = '%s/statuses/update_with_media.json' % self.base_url - if isinstance(status, unicode) or self._input_encoding is None: + if isinstance(status, str) or self._input_encoding is None: u_status = status else: - u_status = unicode(status, self._input_encoding) + u_status = str(status, self._input_encoding) data = {'status': status} if not hasattr(media, 'read'): if media.startswith('http'): - data['media'] = urllib2.urlopen(media).read() + data['media'] = urllib.request.urlopen(media).read() else: with open(str(media), 'rb') as f: data['media'] = f.read() @@ -995,10 +995,10 @@ def PostMultipleMedia(self, status, media, possibly_sensitive=None, url = '%s/media/upload.json' % self.upload_url - if isinstance(status, unicode) or self._input_encoding is None: + if isinstance(status, str) or self._input_encoding is None: u_status = status else: - u_status = unicode(status, self._input_encoding) + u_status = str(status, self._input_encoding) media_ids = '' for m in range(0, len(media)): @@ -1006,7 +1006,7 @@ def PostMultipleMedia(self, status, media, possibly_sensitive=None, data = {} if not hasattr(media[m], 'read'): if media[m].startswith('http'): - data['media'] = urllib2.urlopen(media[m]).read() + data['media'] = urllib.request.urlopen(media[m]).read() else: data['media'] = open(str(media[m]), 'rb').read() else: @@ -1045,7 +1045,7 @@ def PostUpdates(self, continuation: The character string, if any, to be appended to all but the last message. Note that Twitter strips trailing '...' strings - from messages. Consider using the unicode \u2026 character + from messages. Consider using the unicode \\u2026 character (horizontal ellipsis) instead. [Defaults to None] **kwargs: See api.PostUpdate for a list of accepted parameters. @@ -1385,7 +1385,7 @@ def DestroyBlock(self, id, trim_user=False): raise TwitterError({'message': "API must be authenticated."}) try: - post_data = {'user_id': long(id)} + post_data = {'user_id': int(id)} except ValueError: raise TwitterError({'message': "id must be an integer"}) url = '%s/blocks/destroy.json' % (self.base_url) @@ -1800,7 +1800,7 @@ def UsersLookup(self, json_data = self._RequestUrl(url, 'GET', data=parameters) try: data = self._ParseAndCheckTwitter(json_data.content) - except TwitterError, e: + except TwitterError as e: _, e, _ = sys.exc_info() t = e.args[0] if len(t) == 1 and ('code' in t[0]) and (t[0]['code'] == 34): @@ -2243,12 +2243,12 @@ def GetFavorites(self, parameters['screen_name'] = screen_name if since_id: try: - parameters['since_id'] = long(since_id) + parameters['since_id'] = int(since_id) except ValueError: raise TwitterError({'message': "since_id must be an integer"}) if max_id: try: - parameters['max_id'] = long(max_id) + parameters['max_id'] = int(max_id) except ValueError: raise TwitterError({'message': "max_id must be an integer"}) if count: @@ -2313,12 +2313,12 @@ def GetMentions(self, raise TwitterError({'message': "count must be an integer"}) if since_id: try: - parameters['since_id'] = long(since_id) + parameters['since_id'] = int(since_id) except ValueError: raise TwitterError({'message': "since_id must be an integer"}) if max_id: try: - parameters['max_id'] = long(max_id) + parameters['max_id'] = int(max_id) except ValueError: raise TwitterError({'message': "max_id must be an integer"}) if trim_user: @@ -2415,14 +2415,14 @@ def DestroyList(self, data = {} if list_id: try: - data['list_id'] = long(list_id) + data['list_id'] = int(list_id) except ValueError: raise TwitterError({'message': "list_id must be an integer"}) elif slug: data['slug'] = slug if owner_id: try: - data['owner_id'] = long(owner_id) + data['owner_id'] = int(owner_id) except ValueError: raise TwitterError({'message': "owner_id must be an integer"}) elif owner_screen_name: @@ -2467,14 +2467,14 @@ def CreateSubscription(self, data = {} if list_id: try: - data['list_id'] = long(list_id) + data['list_id'] = int(list_id) except ValueError: raise TwitterError({'message': "list_id must be an integer"}) elif slug: data['slug'] = slug if owner_id: try: - data['owner_id'] = long(owner_id) + data['owner_id'] = int(owner_id) except ValueError: raise TwitterError({'message': "owner_id must be an integer"}) elif owner_screen_name: @@ -2519,14 +2519,14 @@ def DestroySubscription(self, data = {} if list_id: try: - data['list_id'] = long(list_id) + data['list_id'] = int(list_id) except ValueError: raise TwitterError({'message': "list_id must be an integer"}) elif slug: data['slug'] = slug if owner_id: try: - data['owner_id'] = long(owner_id) + data['owner_id'] = int(owner_id) except ValueError: raise TwitterError({'message': "owner_id must be an integer"}) elif owner_screen_name: @@ -2587,14 +2587,14 @@ def ShowSubscription(self, data = {} if list_id: try: - data['list_id'] = long(list_id) + data['list_id'] = int(list_id) except ValueError: raise TwitterError({'message': "list_id must be an integer"}) elif slug: data['slug'] = slug if owner_id: try: - data['owner_id'] = long(owner_id) + data['owner_id'] = int(owner_id) except ValueError: raise TwitterError({'message': "owner_id must be an integer"}) elif owner_screen_name: @@ -2605,7 +2605,7 @@ def ShowSubscription(self, raise TwitterError({'message': "Identify list by list_id or owner_screen_name/owner_id and slug"}) if user_id: try: - data['user_id'] = long(user_id) + data['user_id'] = int(user_id) except ValueError: raise TwitterError({'message': "user_id must be an integer"}) elif screen_name: @@ -2664,7 +2664,7 @@ def GetSubscriptions(self, raise TwitterError({'message': "count must be an integer"}) if user_id is not None: try: - parameters['user_id'] = long(user_id) + parameters['user_id'] = int(user_id) except ValueError: raise TwitterError({'message': "user_id must be an integer"}) elif screen_name is not None: @@ -2788,12 +2788,12 @@ def GetListTimeline(self, parameters['owner_screen_name'] = owner_screen_name if since_id: try: - parameters['since_id'] = long(since_id) + parameters['since_id'] = int(since_id) except ValueError: raise TwitterError({'message': "since_id must be an integer"}) if max_id: try: - parameters['max_id'] = long(max_id) + parameters['max_id'] = int(max_id) except ValueError: raise TwitterError({'message': "max_id must be an integer"}) if count: @@ -2935,14 +2935,14 @@ def CreateListsMember(self, data = {} if list_id: try: - data['list_id'] = long(list_id) + data['list_id'] = int(list_id) except ValueError: raise TwitterError({'message': "list_id must be an integer"}) elif slug: data['slug'] = slug if owner_id: try: - data['owner_id'] = long(owner_id) + data['owner_id'] = int(owner_id) except ValueError: raise TwitterError({'message': "owner_id must be an integer"}) elif owner_screen_name: @@ -2953,15 +2953,15 @@ def CreateListsMember(self, raise TwitterError({'message': "Identify list by list_id or owner_screen_name/owner_id and slug"}) if user_id: try: - if type(user_id) == types.ListType or type(user_id) == types.TupleType: + if type(user_id) == list or type(user_id) == tuple: isList = True data['user_id'] = '%s' % ','.join(user_id) else: - data['user_id'] = long(user_id) + data['user_id'] = int(user_id) except ValueError: raise TwitterError({'message': "user_id must be an integer"}) elif screen_name: - if type(screen_name) == types.ListType or type(screen_name) == types.TupleType: + if type(screen_name) == list or type(screen_name) == tuple: isList = True data['screen_name'] = '%s' % ','.join(screen_name) else: @@ -3014,14 +3014,14 @@ def DestroyListsMember(self, data = {} if list_id: try: - data['list_id'] = long(list_id) + data['list_id'] = int(list_id) except ValueError: raise TwitterError({'message': "list_id must be an integer"}) elif slug: data['slug'] = slug if owner_id: try: - data['owner_id'] = long(owner_id) + data['owner_id'] = int(owner_id) except ValueError: raise TwitterError({'message': "owner_id must be an integer"}) elif owner_screen_name: @@ -3032,15 +3032,15 @@ def DestroyListsMember(self, raise TwitterError({'message': "Identify list by list_id or owner_screen_name/owner_id and slug"}) if user_id: try: - if type(user_id) == types.ListType or type(user_id) == types.TupleType: + if type(user_id) == list or type(user_id) == tuple: isList = True data['user_id'] = '%s' % ','.join(user_id) else: - data['user_id'] = long(user_id) + data['user_id'] = int(user_id) except ValueError: raise TwitterError({'message': "user_id must be an integer"}) elif screen_name: - if type(screen_name) == types.ListType or type(screen_name) == types.TupleType: + if type(screen_name) == list or type(screen_name) == tuple: isList = True data['screen_name'] = '%s' % ','.join(screen_name) else: @@ -3088,7 +3088,7 @@ def GetLists(self, parameters = {} if user_id is not None: try: - parameters['user_id'] = long(user_id) + parameters['user_id'] = int(user_id) except ValueError: raise TwitterError({'message': "user_id must be an integer"}) elif screen_name is not None: @@ -3528,7 +3528,7 @@ def GetSleepTime(self, resources): def _BuildUrl(self, url, path_elements=None, extra_params=None): # Break url into constituent parts - (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url) + (scheme, netloc, path, params, query, fragment) = urllib.parse.urlparse(url) # Add any additional path elements to the path if path_elements: @@ -3548,7 +3548,7 @@ def _BuildUrl(self, url, path_elements=None, extra_params=None): query = extra_query # Return the rebuilt URL - return urlparse.urlunparse((scheme, netloc, path, params, query, fragment)) + return urllib.parse.urlunparse((scheme, netloc, path, params, query, fragment)) def _InitializeRequestHeaders(self, request_headers): if request_headers: @@ -3567,16 +3567,16 @@ def _InitializeDefaultParameters(self): def _DecompressGzippedResponse(self, response): raw_data = response.read() if response.headers.get('content-encoding', None) == 'gzip': - url_data = gzip.GzipFile(fileobj=StringIO.StringIO(raw_data)).read() + url_data = gzip.GzipFile(fileobj=io.StringIO(raw_data)).read() else: url_data = raw_data return url_data def _Encode(self, s): if self._input_encoding: - return unicode(s, self._input_encoding).encode('utf-8') + return str(s, self._input_encoding).encode('utf-8') else: - return unicode(s).encode('utf-8') + return str(s).encode('utf-8') def _EncodeParameters(self, parameters): """Return a string in key=value&key=value form. @@ -3594,7 +3594,7 @@ def _EncodeParameters(self, parameters): if parameters is None: return None else: - return urllib.urlencode(dict([(k, self._Encode(v)) for k, v in parameters.items() if v is not None])) + return urllib.parse.urlencode(dict([(k, self._Encode(v)) for k, v in list(parameters.items()) if v is not None])) def _EncodePostData(self, post_data): """Return a string in key=value&key=value form. @@ -3613,7 +3613,7 @@ def _EncodePostData(self, post_data): if post_data is None: return None else: - return urllib.urlencode(dict([(k, self._Encode(v)) for k, v in post_data.items()])) + return urllib.parse.urlencode(dict([(k, self._Encode(v)) for k, v in list(post_data.items())])) def _ParseAndCheckTwitter(self, json_data): """Try and parse the JSON returned from Twitter and return @@ -3668,9 +3668,9 @@ def _RequestUrl(self, url, verb, data=None): A JSON object. """ if verb == 'POST': - if data.has_key('media_ids'): + if 'media_ids' in data: url = self._BuildUrl(url, extra_params={'media_ids': data['media_ids']}) - if data.has_key('media'): + if 'media' in data: try: return requests.post( url, diff --git a/twitter/list.py b/twitter/list.py index b0a0a832..985a8c7e 100644 --- a/twitter/list.py +++ b/twitter/list.py @@ -34,7 +34,7 @@ def __init__(self, **kwargs): 'following': None, 'user': None} - for (param, default) in param_defaults.iteritems(): + for (param, default) in param_defaults.items(): setattr(self, param, kwargs.get(param, default)) def GetId(self): diff --git a/twitter/parse_tweet.py b/twitter/parse_tweet.py index 119f1f00..ed45ba00 100644 --- a/twitter/parse_tweet.py +++ b/twitter/parse_tweet.py @@ -9,7 +9,7 @@ class ParseTweet: # compile once on import regexp = {"RT": "^RT", "MT": r"^MT", "ALNUM": r"(@[a-zA-Z0-9_]+)", "HASHTAG": r"(#[\w\d]+)", "URL": r"([http://]?[a-zA-Z\d\/]+[\.]+[a-zA-Z\d\/\.]+)"} - regexp = dict((key, re.compile(value)) for key, value in regexp.items()) + regexp = dict((key, re.compile(value)) for key, value in list(regexp.items())) def __init__(self, timeline_owner, tweet): """ timeline_owner : twitter handle of user account. tweet - 140 chars from feed; object does all computation on construction diff --git a/twitter/status.py b/twitter/status.py index 1782f10c..a375af08 100644 --- a/twitter/status.py +++ b/twitter/status.py @@ -120,7 +120,7 @@ def __init__(self, **kwargs): 'withheld_in_countries': None, 'withheld_scope': None} - for (param, default) in param_defaults.iteritems(): + for (param, default) in param_defaults.items(): setattr(self, param, kwargs.get(param, default)) def GetCreatedAt(self): @@ -351,7 +351,7 @@ def GetRelativeCreatedAt(self): A human readable string representing the posting time """ fudge = 1.25 - delta = long(self.now) - long(self.created_at_in_seconds) + delta = int(self.now) - int(self.created_at_in_seconds) if delta < (1 * fudge): return 'about a second ago' diff --git a/twitter/user.py b/twitter/user.py index 09a1e2de..122fdad1 100644 --- a/twitter/user.py +++ b/twitter/user.py @@ -36,7 +36,7 @@ def __init__(self, **kwargs): 'following': None, 'followed_by': None} - for (param, default) in param_defaults.iteritems(): + for (param, default) in param_defaults.items(): setattr(self, param, kwargs.get(param, default)) def GetFollowedBy(self): @@ -201,7 +201,7 @@ def __init__(self, **kwargs): 'created_at': None, 'listed_count': None} - for (param, default) in param_defaults.iteritems(): + for (param, default) in param_defaults.items(): setattr(self, param, kwargs.get(param, default)) diff --git a/twitter_test.py b/twitter_test.py index 19268f37..8c968f2f 100755 --- a/twitter_test.py +++ b/twitter_test.py @@ -25,19 +25,19 @@ import time import calendar import unittest -import urllib +import urllib.request, urllib.parse, urllib.error import twitter class StatusTest(unittest.TestCase): - SAMPLE_JSON = '''{"created_at": "Fri Jan 26 23:17:14 +0000 2007", "id": 4391023, "text": "A l\u00e9gp\u00e1rn\u00e1s haj\u00f3m tele van angoln\u00e1kkal.", "user": {"description": "Canvas. JC Penny. Three ninety-eight.", "id": 718443, "location": "Okinawa, Japan", "name": "Kesuke Miyagi", "profile_image_url": "https://twitter.com/system/user/profile_image/718443/normal/kesuke.png", "screen_name": "kesuke", "url": "https://twitter.com/kesuke"}}''' + SAMPLE_JSON = '''{"created_at": "Fri Jan 26 23:17:14 +0000 2007", "id": 4391023, "text": "A l\\u00e9gp\\u00e1rn\\u00e1s haj\\u00f3m tele van angoln\\u00e1kkal.", "user": {"description": "Canvas. JC Penny. Three ninety-eight.", "id": 718443, "location": "Okinawa, Japan", "name": "Kesuke Miyagi", "profile_image_url": "https://twitter.com/system/user/profile_image/718443/normal/kesuke.png", "screen_name": "kesuke", "url": "https://twitter.com/kesuke"}}''' def _GetSampleUser(self): return twitter.User(id=718443, name='Kesuke Miyagi', screen_name='kesuke', - description=u'Canvas. JC Penny. Three ninety-eight.', + description='Canvas. JC Penny. Three ninety-eight.', location='Okinawa, Japan', url='https://twitter.com/kesuke', profile_image_url='https://twitter.com/system/user/pro' @@ -47,14 +47,14 @@ def _GetSampleUser(self): def _GetSampleStatus(self): return twitter.Status(created_at='Fri Jan 26 23:17:14 +0000 2007', id=4391023, - text=u'A légpárnás hajóm tele van angolnákkal.', + text='A légpárnás hajóm tele van angolnákkal.', user=self._GetSampleUser()) def testInit(self): '''Test the twitter.Status constructor''' status = twitter.Status(created_at='Fri Jan 26 23:17:14 +0000 2007', id=4391023, - text=u'A légpárnás hajóm tele van angolnákkal.', + text='A légpárnás hajóm tele van angolnákkal.', user=self._GetSampleUser()) def testGettersAndSetters(self): @@ -68,8 +68,8 @@ def testGettersAndSetters(self): self.assertEqual(created_at, status.GetCreatedAtInSeconds()) status.SetNow(created_at + 10) self.assertEqual("about 10 seconds ago", status.GetRelativeCreatedAt()) - status.SetText(u'A légpárnás hajóm tele van angolnákkal.') - self.assertEqual(u'A légpárnás hajóm tele van angolnákkal.', + status.SetText('A légpárnás hajóm tele van angolnákkal.') + self.assertEqual('A légpárnás hajóm tele van angolnákkal.', status.GetText()) status.SetUser(self._GetSampleUser()) self.assertEqual(718443, status.GetUser().id) @@ -140,7 +140,7 @@ def testAsDict(self): data = status.AsDict() self.assertEqual(4391023, data['id']) self.assertEqual('Fri Jan 26 23:17:14 +0000 2007', data['created_at']) - self.assertEqual(u'A légpárnás hajóm tele van angolnákkal.', data['text']) + self.assertEqual('A légpárnás hajóm tele van angolnákkal.', data['text']) self.assertEqual(718443, data['user']['id']) def testEq(self): @@ -148,7 +148,7 @@ def testEq(self): status = twitter.Status() status.created_at = 'Fri Jan 26 23:17:14 +0000 2007' status.id = 4391023 - status.text = u'A légpárnás hajóm tele van angolnákkal.' + status.text = 'A légpárnás hajóm tele van angolnákkal.' status.user = self._GetSampleUser() self.assertEqual(status, self._GetSampleStatus()) @@ -172,7 +172,7 @@ def _GetSampleUser(self): return twitter.User(id=673483, name='DeWitt', screen_name='dewitt', - description=u'Indeterminate things', + description='Indeterminate things', location='San Francisco, CA', url='http://unto.net/', profile_image_url='https://twitter.com/system/user/prof' @@ -185,7 +185,7 @@ def testInit(self): user = twitter.User(id=673483, name='DeWitt', screen_name='dewitt', - description=u'Indeterminate things', + description='Indeterminate things', url='https://twitter.com/dewitt', profile_image_url='https://twitter.com/system/user/prof' 'ile_image/673483/normal/me.jpg', @@ -361,7 +361,7 @@ def setUp(self): cache=None) api.SetUrllib(self._urllib) self._api = api - print "Testing the API class. This test is time controlled" + print("Testing the API class. This test is time controlled") def testTwitterError(self): '''Test that twitter responses containing an error message are wrapped.''' @@ -370,7 +370,7 @@ def testTwitterError(self): # Manually try/catch so we can check the exception's value try: statuses = self._api.GetUserTimeline() - except twitter.TwitterError, error: + except twitter.TwitterError as error: # If the error message matches, the test passes self.assertEqual('test error', error.message) else: @@ -379,7 +379,7 @@ def testTwitterError(self): def testGetUserTimeline(self): '''Test the twitter.Api GetUserTimeline method''' time.sleep(8) - print 'Testing GetUserTimeline' + print('Testing GetUserTimeline') self._AddHandler('https://api.twitter.com/1.1/statuses/user_timeline.json?count=1&screen_name=kesuke', curry(self._OpenTestData, 'user_timeline-kesuke.json')) statuses = self._api.GetUserTimeline(screen_name='kesuke', count=1) @@ -399,7 +399,7 @@ def testGetUserTimeline(self): def testGetStatus(self): '''Test the twitter.Api GetStatus method''' time.sleep(8) - print 'Testing GetStatus' + print('Testing GetStatus') self._AddHandler('https://api.twitter.com/1.1/statuses/show.json?include_my_retweet=1&id=89512102', curry(self._OpenTestData, 'show-89512102.json')) status = self._api.GetStatus(89512102) @@ -409,7 +409,7 @@ def testGetStatus(self): def testDestroyStatus(self): '''Test the twitter.Api DestroyStatus method''' time.sleep(8) - print 'Testing DestroyStatus' + print('Testing DestroyStatus') self._AddHandler('https://api.twitter.com/1.1/statuses/destroy/103208352.json', curry(self._OpenTestData, 'status-destroy.json')) status = self._api.DestroyStatus(103208352) @@ -418,17 +418,17 @@ def testDestroyStatus(self): def testPostUpdate(self): '''Test the twitter.Api PostUpdate method''' time.sleep(8) - print 'Testing PostUpdate' + print('Testing PostUpdate') self._AddHandler('https://api.twitter.com/1.1/statuses/update.json', curry(self._OpenTestData, 'update.json')) - status = self._api.PostUpdate(u'Моё судно на воздушной подушке полно угрей'.encode('utf8')) + status = self._api.PostUpdate('Моё судно на воздушной подушке полно угрей'.encode('utf8')) # This is rather arbitrary, but spot checking is better than nothing - self.assertEqual(u'Моё судно на воздушной подушке полно угрей', status.text) + self.assertEqual('Моё судно на воздушной подушке полно угрей', status.text) def testPostRetweet(self): '''Test the twitter.Api PostRetweet method''' time.sleep(8) - print 'Testing PostRetweet' + print('Testing PostRetweet') self._AddHandler('https://api.twitter.com/1.1/statuses/retweet/89512102.json', curry(self._OpenTestData, 'retweet.json')) status = self._api.PostRetweet(89512102) @@ -437,21 +437,21 @@ def testPostRetweet(self): def testPostUpdateLatLon(self): '''Test the twitter.Api PostUpdate method, when used in conjunction with latitude and longitude''' time.sleep(8) - print 'Testing PostUpdateLatLon' + print('Testing PostUpdateLatLon') self._AddHandler('https://api.twitter.com/1.1/statuses/update.json', curry(self._OpenTestData, 'update_latlong.json')) #test another update with geo parameters, again test somewhat arbitrary - status = self._api.PostUpdate(u'Моё судно на воздушной подушке полно угрей'.encode('utf8'), latitude=54.2, + status = self._api.PostUpdate('Моё судно на воздушной подушке полно угрей'.encode('utf8'), latitude=54.2, longitude=-2) - self.assertEqual(u'Моё судно на воздушной подушке полно угрей', status.text) - self.assertEqual(u'Point', status.GetGeo()['type']) + self.assertEqual('Моё судно на воздушной подушке полно угрей', status.text) + self.assertEqual('Point', status.GetGeo()['type']) self.assertEqual(26.2, status.GetGeo()['coordinates'][0]) self.assertEqual(127.5, status.GetGeo()['coordinates'][1]) def testGetReplies(self): '''Test the twitter.Api GetReplies method''' time.sleep(8) - print 'Testing GetReplies' + print('Testing GetReplies') self._AddHandler('https://api.twitter.com/1.1/statuses/user_timeline.json', curry(self._OpenTestData, 'replies.json')) statuses = self._api.GetReplies() @@ -460,7 +460,7 @@ def testGetReplies(self): def testGetRetweetsOfMe(self): '''Test the twitter.API GetRetweetsOfMe method''' time.sleep(8) - print 'Testing GetRetweetsOfMe' + print('Testing GetRetweetsOfMe') self._AddHandler('https://api.twitter.com/1.1/statuses/retweets_of_me.json', curry(self._OpenTestData, 'retweets_of_me.json')) retweets = self._api.GetRetweetsOfMe() @@ -469,7 +469,7 @@ def testGetRetweetsOfMe(self): def testGetFriends(self): '''Test the twitter.Api GetFriends method''' time.sleep(8) - print 'Testing GetFriends' + print('Testing GetFriends') self._AddHandler('https://api.twitter.com/1.1/friends/list.json?cursor=123', curry(self._OpenTestData, 'friends.json')) users = self._api.GetFriends(cursor=123) @@ -479,7 +479,7 @@ def testGetFriends(self): def testGetFollowers(self): '''Test the twitter.Api GetFollowers method''' time.sleep(8) - print 'Testing GetFollowers' + print('Testing GetFollowers') self._AddHandler('https://api.twitter.com/1.1/followers/list.json?cursor=-1', curry(self._OpenTestData, 'followers.json')) users = self._api.GetFollowers() @@ -499,26 +499,26 @@ def testGetFollowers(self): def testGetDirectMessages(self): '''Test the twitter.Api GetDirectMessages method''' time.sleep(8) - print 'Testing GetDirectMessages' + print('Testing GetDirectMessages') self._AddHandler('https://api.twitter.com/1.1/direct_messages.json', curry(self._OpenTestData, 'direct_messages.json')) statuses = self._api.GetDirectMessages() - self.assertEqual(u'A légpárnás hajóm tele van angolnákkal.', statuses[0].text) + self.assertEqual('A légpárnás hajóm tele van angolnákkal.', statuses[0].text) def testPostDirectMessage(self): '''Test the twitter.Api PostDirectMessage method''' time.sleep(8) - print 'Testing PostDirectMessage' + print('Testing PostDirectMessage') self._AddHandler('https://api.twitter.com/1.1/direct_messages/new.json', curry(self._OpenTestData, 'direct_messages-new.json')) - status = self._api.PostDirectMessage('test', u'Моё судно на воздушной подушке полно угрей'.encode('utf8')) + status = self._api.PostDirectMessage('test', 'Моё судно на воздушной подушке полно угрей'.encode('utf8')) # This is rather arbitrary, but spot checking is better than nothing - self.assertEqual(u'Моё судно на воздушной подушке полно угрей', status.text) + self.assertEqual('Моё судно на воздушной подушке полно угрей', status.text) def testDestroyDirectMessage(self): '''Test the twitter.Api DestroyDirectMessage method''' time.sleep(8) - print 'Testing DestroyDirectMessage' + print('Testing DestroyDirectMessage') self._AddHandler('https://api.twitter.com/1.1/direct_messages/destroy.json', curry(self._OpenTestData, 'direct_message-destroy.json')) status = self._api.DestroyDirectMessage(3496342) @@ -528,7 +528,7 @@ def testDestroyDirectMessage(self): def testCreateFriendship(self): '''Test the twitter.Api CreateFriendship method''' time.sleep(8) - print 'Testing CreateFriendship' + print('Testing CreateFriendship') self._AddHandler('https://api.twitter.com/1.1/friendships/create.json', curry(self._OpenTestData, 'friendship-create.json')) user = self._api.CreateFriendship('dewitt') @@ -538,7 +538,7 @@ def testCreateFriendship(self): def testDestroyFriendship(self): '''Test the twitter.Api DestroyFriendship method''' time.sleep(8) - print 'Testing Destroy Friendship' + print('Testing Destroy Friendship') self._AddHandler('https://api.twitter.com/1.1/friendships/destroy.json', curry(self._OpenTestData, 'friendship-destroy.json')) user = self._api.DestroyFriendship('dewitt') @@ -548,7 +548,7 @@ def testDestroyFriendship(self): def testGetUser(self): '''Test the twitter.Api GetUser method''' time.sleep(8) - print 'Testing GetUser' + print('Testing GetUser') self._AddHandler('https://api.twitter.com/1.1/users/show.json?user_id=dewitt', curry(self._OpenTestData, 'show-dewitt.json')) user = self._api.GetUser('dewitt') @@ -624,8 +624,8 @@ def open(self, url, data=None): self._opened = True return self._handlers[url]() else: - print url - print self._handlers + print(url) + print(self._handlers) raise Exception('Unexpected URL %s (Checked: %s)' % (url, self._handlers)) @@ -642,21 +642,21 @@ class ParseTest(unittest.TestCase): """ Test the ParseTweet class """ def testParseTweets(self): - handles4 = u"""Do not use this word! Hurting me! @raja7727: @qadirbasha @manion @Jayks3 உடன்பிறப்பு”"""; + handles4 = """Do not use this word! Hurting me! @raja7727: @qadirbasha @manion @Jayks3 உடன்பிறப்பு”"""; data = twitter.ParseTweet("@twitter", handles4) self.assertEqual([data.RT, data.MT, len(data.UserHandles)], [False, False, 4]) - hashtag_n_URL = u"மனதிற்கு மிகவும் நெருக்கமான பாடல்! உயிரையே கொடுக்கலாம் சார்! #KeladiKanmani https://www.youtube.com/watch?v=FHTiG_g2fM4 … #HBdayRajaSir"; + hashtag_n_URL = "மனதிற்கு மிகவும் நெருக்கமான பாடல்! உயிரையே கொடுக்கலாம் சார்! #KeladiKanmani https://www.youtube.com/watch?v=FHTiG_g2fM4 … #HBdayRajaSir"; data = twitter.ParseTweet("@twitter", hashtag_n_URL) self.assertEqual([len(data.Hashtags), len(data.URLs)], [2, 1]) - url_only = u"""The #Rainbow #Nebula, 544,667 #lightyears away. pic.twitter.com/2A4wSUK25A"""; + url_only = """The #Rainbow #Nebula, 544,667 #lightyears away. pic.twitter.com/2A4wSUK25A"""; data = twitter.ParseTweet("@twitter", url_only) self.assertEqual([data.MT, len(data.Hashtags), len(data.URLs)], [False, 3, 1]) - url_handle = u"""RT ‏@BarackObama POTUS recommends Python-Twitter #unrelated picture pic.twitter.com/w8lFIfuUmI"""; + url_handle = """RT ‏@BarackObama POTUS recommends Python-Twitter #unrelated picture pic.twitter.com/w8lFIfuUmI"""; data = twitter.ParseTweet("@twitter", url_handle) self.assertEqual([data.RT, len(data.Hashtags), len(data.URLs), len(data.UserHandles)], [True, 1, 1, 1]) From 70c20923cf32245df320b6e458e9179a33b21a36 Mon Sep 17 00:00:00 2001 From: hkjallbring Date: Sun, 1 Feb 2015 21:12:05 -0600 Subject: [PATCH 2/4] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3ac1f3fd..0d89e6bb 100755 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ def read(*paths): setup( - name='python-twitter', + name='python-twitter-py3', version='2.3', author='The Python-Twitter Developers', author_email='python-twitter@googlegroups.com', From b729d33879fc53c0a3578a8d60ea28bf1e5c0b3b Mon Sep 17 00:00:00 2001 From: Henrik Kjallbring Date: Sun, 1 Feb 2015 21:40:40 -0600 Subject: [PATCH 3/4] Replaced rfc822 (python <2.3) with email (python3) --- twitter/direct_message.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/twitter/direct_message.py b/twitter/direct_message.py index 129a8218..28d1703a 100644 --- a/twitter/direct_message.py +++ b/twitter/direct_message.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from calendar import timegm -import rfc822 +from email import parser from twitter import json, TwitterError @@ -106,7 +106,7 @@ def GetCreatedAtInSeconds(self): Returns: The time this direct message was posted, in seconds since the epoch. """ - return timegm(rfc822.parsedate(self.created_at)) + return timegm(parser.parsedate(self.created_at)) created_at_in_seconds = property(GetCreatedAtInSeconds, doc="The time this direct message was " From 28caf6fa4eda0e165dd30bbf765762c5380f5dd1 Mon Sep 17 00:00:00 2001 From: Henrik Kjallbring Date: Sun, 1 Feb 2015 21:43:26 -0600 Subject: [PATCH 4/4] the one that got away --- twitter/status.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/twitter/status.py b/twitter/status.py index a375af08..fd341a5d 100644 --- a/twitter/status.py +++ b/twitter/status.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from calendar import timegm -import rfc822 +from email import parser import time from twitter import json, Hashtag, TwitterError, Url @@ -149,7 +149,7 @@ def GetCreatedAtInSeconds(self): Returns: The time this status message was posted, in seconds since the epoch. """ - return timegm(rfc822.parsedate(self.created_at)) + return timegm(parser.parsedate(self.created_at)) created_at_in_seconds = property(GetCreatedAtInSeconds, doc="The time this status message was "