Skip to content

Commit

Permalink
Corrected in objects.py: Some methods were returning arguments but wo…
Browse files Browse the repository at this point in the history
…uld not take them as input

git-svn-id: https://python-flickr-api.googlecode.com/svn/trunk@88 c04dc755-9e73-fb1f-9025-638fad5d94ba
  • Loading branch information
alexis.mignon committed Mar 26, 2012
0 parents commit 93c299b
Show file tree
Hide file tree
Showing 15 changed files with 12,136 additions and 0 deletions.
25 changes: 25 additions & 0 deletions INSTALL.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Requires:
- python 2.6+
- python-oauth package (python module from http://code.google.com/p/oauth/)

1) Extract the archive

2) Install
This package uses distutils to install.
After you extracted the archive and moved to the extracted directory:

$ python setup.py install --user # to install in $HOME/.local
$ python setup.py install --prefix=<path> # to install in a custom directory
$ python setup.py install # for system wide installation

3) Configure API keys
Two keys are provided by Flickr and api_key and a secret. To make your
application aware of these keys there are two methods:
i - use the flickr_api.set_keys(api_key,secret_key) function.
ii - create a flickr_keys.py file as follows. Create a file called
$INSTALL_DIR/flickr_api/flickr_keys.py. Edit it so it looks like :

API_KEY = 'xxxxxxxxxxxxxxxxxxx'
API_SECRET = 'yyyyyyyyyyyyyyy'

where x's and y's are replaced by the values provided by flickr.
39 changes: 39 additions & 0 deletions flickr_api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Object Oriented implementation of Flickr API.
Important notes:
- For consistency, the nameing of methods might differ from the name
in the official API. Please check the method "docstring" to know
what is the implemented method.
- For methods which expect an object "id", either the 'id' string
or the object itself can be used as argument. Similar consideration
holds for lists of id's.
For instance if "photo_id" is expected you can give call the function
with named argument "photo = PhotoObject" or with the id string
"photo_id = id_string".
Author : Alexis Mignon (c)
email : alexis.mignon_at_gmail.com
Date : 05/08/2011
"""

from objects import *
import objects
from auth import set_auth_handler

import upload as Upload
from upload import upload,replace
from method_call import set_keys,enable_cache,disable_cache

#~ def set_auth_handler(auth_handler):
#~ if isinstance(auth_handler,str):
#~ ah = AuthHandler.load(auth_handler)
#~ set_auth_handler(ah)
#~ else :
#~ objects.AUTH_HANDLER = auth_handler
#~ Upload.AUTH_HANDLER = auth_handler
#~ api.AUTH_HANDLER = auth_handler
73 changes: 73 additions & 0 deletions flickr_api/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
module: api
This module provide an interface to the REST API through a
syntax mimicking the method names described on Flickr site.
The hierarchy of methods is built once when the module is loaded.
Author : Alexis Mignon (c)
email : alexis.mignon_at_gmail.com
Date : 08/08/2011
"""

from method_call import call_api
import auth
import reflection

__methods__ = reflection.__methods__.keys()
__methods__.sort()

__proxys__ = {}


def _get_proxy(name):
"""
return the FlickrMethodProxy object with called 'name' from
the __proxys__ global dictionnary. Creates the objects if needed.
"""
if name in __proxys__ :
return __proxys__[name]
else :
p = FlickrMethodProxy(name)
__proxys__[name] = p
return p

def _get_children_methods(name):
"""
Get the list of method names having 'name' for prefix
"""
return [ m for m in __methods__ if m.startswith(name+".") ]

class FlickrMethodProxy(object):
"""
Proxy object to perform seamless direct calls to Flickr
API.
"""
def __init__(self,name):
self.name = name
children = _get_children_methods(name)
for child in children :
child_node = child[(len(self.name)+1):].split(".")[0]
child_prefix = "%s.%s"%(self.name,child_node)
self.__dict__[child_node] = _get_proxy(child_prefix)
if self.name in __methods__ :
self.__doc__ = reflection.make_docstring(self.name)

def __call__(self, **kwargs):
return call_api(auth_handler = auth.AUTH_HANDLER,raw = True,method = self.name,**kwargs)

def __repr__(self):
return self.name

def __str__(self):
return repr(self)

@staticmethod
def set_auth_handler(token):
auth.set_auth_handler(token)

if __methods__ :
flickr = _get_proxy("flickr")

162 changes: 162 additions & 0 deletions flickr_api/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
"""
Authentication capabilities for the Flickr API.
It implements the new authentication specifications of Flickr
based on OAuth.
The authentication process is in 3 steps.
- Authorisation request :
>>> a = AuthHandler(call_back_url)
>>> a.get_authorization_url('write')
print 'http://www.flickr.com/services/oauth/authorize?oauth_token=xxxx&perms=write'
- The user gives his authorization at the url given by 'get_authorization_url'
and is redrected to the 'call_back_url' with the oauth_verifier encoded
in the url. This value can then be given to the AuthHandler:
>>> a.set_verifier("66455xxxxx")
- The authorization handler can then be set for the python session
and will be automatically used when needed.
>>> flickr_api.set_authorization_handler(a)
The authorization handler can also be saved and loaded :
>>> a.write(filename)
>>> a = AuthHandler.load(filename)
Author : Alexis Mignon
e-mail : alexis.mignon@gmail.com
Date : 06/08/2011
"""

from oauth import oauth
import time
import urlparse
import urllib2
from method_call import API_KEY, API_SECRET

TOKEN_REQUEST_URL = "http://www.flickr.com/services/oauth/request_token"
AUTHORIZE_URL = "http://www.flickr.com/services/oauth/authorize"
ACCESS_TOKEN_URL = "http://www.flickr.com/services/oauth/access_token"

AUTH_HANDLER = None

class AuthHandlerError(Exception):
pass

class AuthHandler(object):
def __init__(self,key = API_KEY, secret = API_SECRET, callback = None, access_token_key = None, access_token_secret = None):
if callback is None :
callback = "http://api.flickr.com/services/rest/?method=flickr.test.echo&api_key=%s"%key
self.key = key
self.secret = secret
params = {
'oauth_timestamp': str(int(time.time())),
'oauth_signature_method':"HMAC-SHA1",
'oauth_version': "1.0",
'oauth_callback': callback,
'oauth_nonce': oauth.generate_nonce(),
'oauth_consumer_key': self.key
}

self.consumer = oauth.OAuthConsumer(key=self.key, secret=self.secret)
if access_token_key is None :
req = oauth.OAuthRequest(http_method="GET", http_url=TOKEN_REQUEST_URL, parameters=params)
req.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(),self.consumer,None)
resp = urllib2.urlopen(req.to_url())
request_token = dict(urlparse.parse_qsl(resp.read()))
self.request_token = oauth.OAuthToken(request_token['oauth_token'],request_token['oauth_token_secret'])
self.access_token = None
else :
self.request_token = None
self.access_token = oauth.OAuthToken(access_token_key,access_token_secret)


def get_authorization_url(self,perms = 'read'):
if self.request_token is None :
raise AuthHandlerError("Request token is not defined. This ususally means that the access token has been loaded from a file.")
return "%s?oauth_token=%s&perms=%s" % (AUTHORIZE_URL, self.request_token.key, perms)

def set_verifier(self,oauth_verifier):
if self.request_token is None :
raise AuthHandlerError("Request token is not defined. This ususally means that the access token has been loaded from a file.")
self.request_token.set_verifier(oauth_verifier)

access_token_parms = {
'oauth_consumer_key': self.key,
'oauth_nonce': oauth.generate_nonce(),
'oauth_signature_method':"HMAC-SHA1",
'oauth_timestamp': str(int(time.time())),
'oauth_token': self.request_token.key,
'oauth_verifier' : self.request_token.verifier
}

req = oauth.OAuthRequest(http_method="GET", http_url=ACCESS_TOKEN_URL, parameters=access_token_parms)
req.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(),self.consumer,self.request_token)
resp = urllib2.urlopen(req.to_url())
access_token_resp = dict(urlparse.parse_qsl(resp.read()))
self.access_token = oauth.OAuthToken(access_token_resp["oauth_token"],access_token_resp["oauth_token_secret"])

def complete_parameters(self,url,params = {},exclude_signature = []):

defaults = {
'oauth_timestamp': str(int(time.time())),
'oauth_nonce': oauth.generate_nonce(),
'signature_method': "HMAC-SHA1",
'oauth_token':self.access_token.key,
'oauth_consumer_key':self.consumer.key,
}

excluded = {}
for e in exclude_signature :
excluded[e] = params.pop(e)

defaults.update(params)
req = oauth.OAuthRequest(http_method="POST", http_url=url, parameters=defaults)
req.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(),self.consumer,self.access_token)
req.parameters.update(excluded)

return req

def write(self,filename):
if self.access_token is None :
raise AuthHandlerError("Access token not set yet.")
with open(filename,"w") as f :
f.write("\n".join([self.key,self.secret,self.access_token.key,self.access_token.secret]))

def save(self,filename):
self.write(filename)

@staticmethod
def load(filename = None):
with open(filename,"r") as f :
try :
key,secret,access_key,access_secret = f.read().split("\n")
except :
access_key,access_secret = f.read().split("\n")
key = API_KEY
secret = API_SECRET
return AuthHandler(key,secret,access_token_key = access_key,access_token_secret = access_secret)

@staticmethod
def create(token_key,token_secret):
return AuthHandler(access_token_key = access_key,access_token_secret = access_secret)

def token_factory(filename = None, token_key = None, token_secret = None):
if filename is None :
if (token_key is None) or (token_secret is None):
raise ValueError("token_secret and token_key cannot be None")
return AuthHandler.create(token_key,token_secret)
else :
return AuthHandler.load(filename)

def set_auth_handler(auth_handler):
global AUTH_HANDLER
if isinstance(auth_handler,str):
ah = AuthHandler.load(auth_handler)
set_auth_handler(ah)
else :
AUTH_HANDLER = auth_handler
Loading

0 comments on commit 93c299b

Please sign in to comment.