From: Josh Roesslein Date: Thu, 30 Jul 2009 20:55:20 +0000 (-0500) Subject: Implemented new pluggable auth system into binder. Implemented basic auth handler... X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=a304de7e91b29e3a96d63dec30ff6b8334ed1cd3;p=tweepy.git Implemented new pluggable auth system into binder. Implemented basic auth handler. Started work on oauth handler. --- diff --git a/oauth/__init__.py b/oauth/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tweepy/__init__.py b/tweepy/__init__.py index ab4d5eb..e3543c7 100644 --- a/tweepy/__init__.py +++ b/tweepy/__init__.py @@ -11,6 +11,7 @@ from models import * from error import TweepError from api import API from cache import * +from auth import BasicAuthHandler, OAuthHandler # Global, unauthenticated instance of API api = API() diff --git a/tweepy/api.py b/tweepy/api.py index 8880c65..5b48053 100644 --- a/tweepy/api.py +++ b/tweepy/api.py @@ -2,8 +2,6 @@ # Copyright 2009 Joshua Roesslein # See LICENSE -import base64 - from binder import bind_api from parsers import * from models import User, Status, DirectMessage, Friendship, SavedSearch, SearchResult @@ -12,24 +10,15 @@ from error import TweepError """Twitter API""" class API(object): - def __init__(self, username=None, password=None, host='twitter.com', - cache=None, secure=False, - classes={'user': User, 'status': Status, + def __init__(self, auth_handler=None, host='twitter.com', cache=None, + secure=False, classes={'user': User, 'status': Status, 'direct_message': DirectMessage, 'friendship': Friendship, 'saved_search': SavedSearch, 'search_result': SearchResult}): - if username and password: - self.set_credentials(username, password) - else: - self._b64up = None + self.auth_handler = auth_handler self.host = host self.cache = cache self.secure = secure self.classes = classes - self.username = username - - def set_credentials(self, username, password): - self._b64up = base64.b64encode('%s:%s' % (username, password)) - self.username = username """Get public timeline""" public_timeline = bind_api( diff --git a/tweepy/auth.py b/tweepy/auth.py new file mode 100644 index 0000000..db7db97 --- /dev/null +++ b/tweepy/auth.py @@ -0,0 +1,75 @@ +# Tweepy +# Copyright 2009 Joshua Roesslein +# See LICENSE + +from urllib2 import Request, urlopen +import base64 + +import oauth +from error import TweepError + +class AuthHandler(object): + + def apply_auth(self, headers): + """Apply authentication headers to request""" + raise NotImplemented + +class BasicAuthHandler(AuthHandler): + + def __init__(self, username, password): + self._b64up = base64.b64encode('%s:%s' % (username, password)) + + def apply_auth(self, headers): + headers['Authorization'] = 'Basic %s' % self._b64up + +"""OAuth authentication handler""" +class OAuthHandler(AuthHandler): + + REQUEST_TOKEN_URL = 'http://twitter.com/oauth/request_token' + AUTHORIZATION_URL = 'http://twitter.com/oauth/authorize' + ACCESS_TOKEN_URL = 'http://twitter.com/oauth/access_token' + + def __init__(self, consumer_key, consumer_secrete): + self._consumer = oauth.OAuthConsumer(consumer_key, consumer_secrete) + self._sigmethod = oauth.OAuthSignatureMethod_HMAC_SHA1() + self.request_token = None + self.access_token = None + + def _get_request_token(self): + try: + request = oauth.OAuthRequest.from_consumer_and_token(self._consumer, http_url = self.REQUEST_TOKEN_URL) + request.sign_request(self._sigmethod, self._consumer, None) + resp = urlopen(Request(self.REQUEST_TOKEN_URL, headers=request.to_header())) + return oauth.OAuthToken.from_string(resp.read()) + + except Exception, e: + raise TweepError(e) + + def get_authorization_url(self, callback=None): + try: + # get the request token + self.request_token = self._get_request_token() + + # build auth request and return as url + request = oauth.OAuthRequest.from_token_and_callback( + token=token, callback=callback, http_url=self.AUTHORIZATION_URL) + return request.to_url() + + except Exception, e: + raise TweepError(e) + + def get_access_token(self): + try: + # build request + request = oauth.OAuthRequest.from_consumer_and_token(self._consumer, + token=self.request_token, http_url=self.ACCESS_TOKEN_URL) + request.sign_request(self._sigmethod, self._consumer, self.request_token) + + # send request + resp = urlopen(Request(self.ACCESS_TOKEN_URL, headers=request.to_header())) + self.access_token = oauth.OAuthToken.from_string(resp.read()) + except Exception, e: + raise TweepError(e) + + + diff --git a/tweepy/binder.py b/tweepy/binder.py index 43a43b9..57f11ab 100644 --- a/tweepy/binder.py +++ b/tweepy/binder.py @@ -13,7 +13,7 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False, def _call(api, *args, **kargs): # If require auth, throw exception if credentials not provided - if require_auth and not api._b64up: + if not api.auth_handler: raise TweepError('Authentication required!') # Filter out unallowed parameters @@ -50,8 +50,10 @@ def bind_api(path, parser, allowed_param=None, method='GET', require_auth=False, headers = { 'User-Agent': 'tweepy' } - if api._b64up: - headers['Authorization'] = 'Basic %s' % api._b64up + + # Apply authentication + if api.auth_handler: + api.auth_handler.apply_auth(headers) # Build request conn.request(method, url, headers=headers) diff --git a/tweepy/error.py b/tweepy/error.py index 04924fe..2905bee 100644 --- a/tweepy/error.py +++ b/tweepy/error.py @@ -8,7 +8,7 @@ Tweepy exception class TweepError(Exception): def __init__(self, reason): - self.reason = reason + self.reason = str(reason) def __str__(self): return self.reason diff --git a/oauth/oauth.py b/tweepy/oauth.py similarity index 100% rename from oauth/oauth.py rename to tweepy/oauth.py