-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Corrected in objects.py: Some methods were returning arguments but wo…
…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
Showing
15 changed files
with
12,136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.