Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

add python 3 support #80

Merged
merged 2 commits into from
Jun 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ constructor:
api = InstagramAPI(client_id='YOUR_CLIENT_ID', client_secret='YOUR_CLIENT_SECRET')
popular_media = api.media_popular(count=20)
for media in popular_media:
print media.images['standard_resolution'].url
print(media.images['standard_resolution'].url)
```

Real-time Subscriptions:
Expand Down
14 changes: 7 additions & 7 deletions get_access_token.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
except Exception:
pass

client_id = raw_input("Client ID: ").strip()
client_secret = raw_input("Client Secret: ").strip()
redirect_uri = raw_input("Redirect URI: ").strip()
raw_scope = raw_input("Requested scope (separated by spaces, blank for just basic read): ").strip()
client_id = input("Client ID: ").strip()
client_secret = input("Client Secret: ").strip()
redirect_uri = input("Redirect URI: ").strip()
raw_scope = input("Requested scope (separated by spaces, blank for just basic read): ").strip()
scope = raw_scope.split(' ')
# For basic, API seems to need to be set explicitly
if not scope or scope == [""]:
Expand All @@ -26,10 +26,10 @@
api = InstagramAPI(client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri)
redirect_uri = api.get_authorize_login_url(scope = scope)

print "Visit this page and authorize access in your browser:\n", redirect_uri
print(("Visit this page and authorize access in your browser:\n", redirect_uri))

code = raw_input("Paste in code in query string after redirect: ").strip()
code = input("Paste in code in query string after redirect: ").strip()

access_token = api.exchange_code_for_access_token(code)
print "access token:\n", access_token
print(("access token:\n", access_token))

4 changes: 2 additions & 2 deletions instagram/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from bind import InstagramAPIError, InstagramClientError
from client import InstagramAPI
from .bind import InstagramAPIError, InstagramClientError
from .client import InstagramAPI
16 changes: 8 additions & 8 deletions instagram/bind.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import urllib
from oauth2 import OAuth2Request
import urllib.request, urllib.parse, urllib.error
from .oauth2 import OAuth2Request
import re
from json_import import simplejson
from .json_import import simplejson
import hmac
from hashlib import sha256

Expand All @@ -10,7 +10,7 @@

def encode_string(value):
return value.encode('utf-8') \
if isinstance(value, unicode) else str(value)
if isinstance(value, str) else str(value)


class InstagramClientError(Exception):
Expand Down Expand Up @@ -76,7 +76,7 @@ def _build_parameters(self, args, kwargs):
except IndexError:
raise InstagramClientError("Too many arguments supplied")

for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this still functions correctly, there isn't a need to try and turn this into a list:

>>> x = {'hello': 'world', 'testing': 'something'}
>>> for k,v in x.items():
...     print(k, v)
...
hello world
testing something
>>> for k,v in list(x.items()):
...     print(k,v)
...
hello world
testing something

if value is None:
continue
if key in self.parameters:
Expand All @@ -91,7 +91,7 @@ def _build_path(self):
name = variable.strip('{}')

try:
value = urllib.quote(self.parameters[name])
value = urllib.parse.quote(self.parameters[name])
except KeyError:
raise Exception('No parameter value found for path variable: %s' % name)
del self.parameters[name]
Expand Down Expand Up @@ -126,11 +126,11 @@ def _do_api_request(self, url, method="GET", body=None, headers=None):
raise InstagramClientError('Unable to parse response, not valid JSON.', status_code=response['status'])

# Handle OAuthRateLimitExceeded from Instagram's Nginx which uses different format to documented api responses
if not content_obj.has_key('meta'):
if 'meta' not in content_obj:
if content_obj.get('code') == 420 or content_obj.get('code') == 429:
error_message = content_obj.get('error_message') or "Your client is making too many request per second"
raise InstagramAPIError(content_obj.get('code'), "Rate limited", error_message)
raise InstagramAPIError(content_obj.has_key('code'), content_obj.has_key('error_type'), content_obj.has_key('error_message'))
raise InstagramAPIError('code' in content_obj, 'error_type' in content_obj, 'error_message' in content_obj)

api_responses = []
status_code = content_obj['meta']['code']
Expand Down
6 changes: 3 additions & 3 deletions instagram/client.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import oauth2
from bind import bind_method
from models import MediaShortcode, Media, User, Location, Tag, Comment, Relationship
from . import oauth2
from .bind import bind_method
from .models import MediaShortcode, Media, User, Location, Tag, Comment, Relationship

MEDIA_ACCEPT_PARAMETERS = ["count", "max_id"]
SEARCH_ACCEPT_PARAMETERS = ["q", "count"]
Expand Down
22 changes: 11 additions & 11 deletions instagram/models.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from helper import timestamp_to_datetime
from .helper import timestamp_to_datetime


class ApiModel(object):
Expand All @@ -8,11 +8,11 @@ def object_from_dictionary(cls, entry):
# make dict keys all strings
if entry is None:
return ""
entry_str_dict = dict([(str(key), value) for key, value in entry.items()])
entry_str_dict = dict([(str(key), value) for key, value in list(entry.items())])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here. No need to turn entry.items to a list.

return cls(**entry_str_dict)

def __repr__(self):
return unicode(self).encode('utf8')
return str(self).encode('utf8')


class Image(ApiModel):
Expand All @@ -36,7 +36,7 @@ class Media(ApiModel):

def __init__(self, id=None, **kwargs):
self.id = id
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment goes for all dict's being converted to lists in this PR.

setattr(self, key, value)

def get_standard_resolution_url(self):
Expand Down Expand Up @@ -67,12 +67,12 @@ def object_from_dictionary(cls, entry):
new_media.user = User.object_from_dictionary(entry['user'])

new_media.images = {}
for version, version_info in entry['images'].iteritems():
for version, version_info in list(entry['images'].items()):
new_media.images[version] = Image.object_from_dictionary(version_info)

if new_media.type == 'video':
new_media.videos = {}
for version, version_info in entry['videos'].iteritems():
for version, version_info in list(entry['videos'].items()):
new_media.videos[version] = Video.object_from_dictionary(version_info)

if 'user_has_liked' in entry:
Expand Down Expand Up @@ -113,14 +113,14 @@ class MediaShortcode(Media):

def __init__(self, shortcode=None, **kwargs):
self.shortcode = shortcode
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):
setattr(self, key, value)


class Tag(ApiModel):
def __init__(self, name, **kwargs):
self.name = name
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):
setattr(self, key, value)

def __unicode__(self):
Expand All @@ -129,7 +129,7 @@ def __unicode__(self):

class Comment(ApiModel):
def __init__(self, *args, **kwargs):
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):
setattr(self, key, value)

@classmethod
Expand All @@ -156,7 +156,7 @@ def __unicode__(self):
class Location(ApiModel):
def __init__(self, id, *args, **kwargs):
self.id = id
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):
setattr(self, key, value)

@classmethod
Expand All @@ -178,7 +178,7 @@ class User(ApiModel):

def __init__(self, id, *args, **kwargs):
self.id = id
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):
setattr(self, key, value)

def __unicode__(self):
Expand Down
12 changes: 6 additions & 6 deletions instagram/oauth2.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from json_import import simplejson
import urllib
from .json_import import simplejson
import urllib.request, urllib.parse, urllib.error
from httplib2 import Http
import mimetypes

Expand Down Expand Up @@ -67,7 +67,7 @@ def _url_for_authorize(self, scope=None):
}
if scope:
client_params.update(scope=' '.join(scope))
url_params = urllib.urlencode(client_params)
url_params = urllib.parse.urlencode(client_params)
return "%s?%s" % (self.api.authorize_url, url_params)

def _data_for_exchange(self, code=None, username=None, password=None, scope=None, user_id=None):
Expand All @@ -87,7 +87,7 @@ def _data_for_exchange(self, code=None, username=None, password=None, scope=None
client_params.update(scope=' '.join(scope))
elif user_id:
client_params.update(user_id=user_id)
return urllib.urlencode(client_params)
return urllib.parse.urlencode(client_params)

def get_authorize_url(self, scope=None):
return self._url_for_authorize(scope=scope)
Expand Down Expand Up @@ -137,7 +137,7 @@ def _full_url_with_params(self, path, params, include_secret=False):
return (self._full_url(path, include_secret) + self._full_query_with_params(params))

def _full_query_with_params(self, params):
params = ("&" + urllib.urlencode(params)) if params else ""
params = ("&" + urllib.parse.urlencode(params)) if params else ""
return params

def _auth_query(self, include_secret=False):
Expand All @@ -150,7 +150,7 @@ def _auth_query(self, include_secret=False):
return base

def _post_body(self, params):
return urllib.urlencode(params)
return urllib.parse.urlencode(params)

def _encode_multipart(params, files):
boundary = "MuL7Ip4rt80uND4rYF0o"
Expand Down
2 changes: 1 addition & 1 deletion instagram/subscriptions.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import hmac
import hashlib
from json_import import simplejson
from .json_import import simplejson

class SubscriptionType:
TAG = 'tag'
Expand Down
48 changes: 24 additions & 24 deletions sample_app.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
unauthenticated_api = client.InstagramAPI(**CONFIG)

def process_tag_update(update):
print update
print(update)

reactor = subscriptions.SubscriptionsReactor()
reactor.register_callback(subscriptions.SubscriptionType.TAG, process_tag_update)
Expand All @@ -28,8 +28,8 @@ def home():
try:
url = unauthenticated_api.get_authorize_url(scope=["likes","comments"])
return '<a href="%s">Connect with Instagram</a>' % url
except Exception, e:
print e
except Exception as e:
print(e)

def get_nav():
nav_menu = ("<h1>Python Instagram</h1>"
Expand All @@ -53,13 +53,13 @@ def on_callback(session):
return 'Missing code'
try:
access_token, user_info = unauthenticated_api.exchange_code_for_access_token(code)
print "access token= " + access_token
print(("access token= " + access_token))
if not access_token:
return 'Could not get access token'
api = client.InstagramAPI(access_token=access_token)
session['access_token']=access_token
except Exception, e:
print e
except Exception as e:
print(e)
return get_nav()

@route('/recent')
Expand All @@ -78,11 +78,11 @@ def on_recent(session):
photos.append('<video controls width height="150"><source type="video/mp4" src="%s"/></video>' % (media.get_standard_resolution_url()))
else:
photos.append('<img src="%s"/>' % (media.get_low_resolution_url()))
print media
print(media)
photos.append("<br/> <a href='/media_like/%s'>Like</a> <a href='/media_unlike/%s'>Un-Like</a> LikesCount=%s</div>" % (media.id,media.id,media.like_count))
content += ''.join(photos)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/media_like/<id>')
Expand Down Expand Up @@ -118,8 +118,8 @@ def on_user_media_feed(session):
photos.append('<img src="%s"/>' % media.get_standard_resolution_url())
counter += 1
content += ''.join(photos)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/location_recent_media')
Expand All @@ -135,8 +135,8 @@ def location_recent_media(session):
for media in recent_media:
photos.append('<img src="%s"/>' % media.get_standard_resolution_url())
content += ''.join(photos)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/media_search')
Expand All @@ -152,8 +152,8 @@ def media_search(session):
for media in media_search:
photos.append('<img src="%s"/>' % media.get_standard_resolution_url())
content += ''.join(photos)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/media_popular')
Expand All @@ -169,8 +169,8 @@ def media_popular(session):
for media in media_search:
photos.append('<img src="%s"/>' % media.get_standard_resolution_url())
content += ''.join(photos)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/user_search')
Expand All @@ -186,8 +186,8 @@ def user_search(session):
for user in user_search:
users.append('<li><img src="%s">%s</li>' % (user.profile_picture,user.username))
content += ''.join(users)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/location_search')
Expand All @@ -203,8 +203,8 @@ def location_search(session):
for location in location_search:
locations.append('<li>%s <a href="https://www.google.com/maps/preview/@%s,%s,19z">Map</a> </li>' % (location.name,location.point.latitude,location.point.longitude))
content += ''.join(locations)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/tag_search')
Expand All @@ -221,8 +221,8 @@ def tag_search(session):
for tag_media in tag_recent_media:
photos.append('<img src="%s"/>' % tag_media.get_standard_resolution_url())
content += ''.join(photos)
except Exception, e:
print e
except Exception as e:
print(e)
return "%s %s <br/>Remaining API Calls = %s/%s" % (get_nav(),content,api.x_ratelimit_remaining,api.x_ratelimit)

@route('/realtime_callback')
Expand All @@ -239,6 +239,6 @@ def on_realtime_callback():
try:
reactor.process(CONFIG['client_secret'], raw_response, x_hub_signature)
except subscriptions.SubscriptionVerifyError:
print "Signature mismatch"
print("Signature mismatch")

run(host='localhost', port=8515, reloader=True)
Loading