diff --git a/README.markdown b/README.markdown index 14b0525..8c46446 100644 --- a/README.markdown +++ b/README.markdown @@ -8,6 +8,20 @@ About Plurk-OAuth is a wrapper for [Plurk API 2.0 beta](http://www.plurk.com/API/2) You will need to [Sign Up](http://www.plurk.com/PlurkApp/register) for your own CUSTOMER TOKENs. +Installation +---- +simply: +``` + $ pip install plurk-oauth +``` + +for development: +``` + $ git clone git@github.com:clsung/plurk-oauth.git + $ cd plurk-oauth + $ pip install -e . +``` + API.keys ---- You will need to save CONSUMER_KEY/CONSUMER_SECRET in API.keys, the @@ -18,31 +32,31 @@ format is JSON. The example is below: Example with API.keys ---- ``` python -from PlurkAPI import PlurkAPI +from plurk_oauth import PlurkAPI plurk = PlurkAPI.fromfile() - print plurk.callAPI('/APP/Profile/getOwnProfile') + print(plurk.callAPI('/APP/Profile/getOwnProfile')) ``` Example with ACCESS_TOKEN ---- ``` python -from PlurkAPI import PlurkAPI +from plurk_oauth import PlurkAPI plurk = PlurkAPI(CONSUMER_KEY, CONSUMER_SECRET) plurk.authorize(ACCESS_TOKEN,ACCESS_TOKEN_SECRET) - print plurk.callAPI('/APP/Profile/getOwnProfile') + print(plurk.callAPI('/APP/Profile/getOwnProfile')) ``` Example without ACCESS_TOKEN ---- ``` python -from PlurkAPI import PlurkAPI +from plurk_oauth import PlurkAPI plurk = PlurkAPI(CONSUMER_KEY, CONSUMER_SECRET) plurk.authorize() - print plurk.callAPI('/APP/Profile/getOwnProfile') + print(plurk.callAPI('/APP/Profile/getOwnProfile')) ``` diff --git a/bin/get_own_profile.py b/bin/get_own_profile.py old mode 100644 new mode 100755 index 427253b..b2dd947 --- a/bin/get_own_profile.py +++ b/bin/get_own_profile.py @@ -1,31 +1,36 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- import sys sys.path.append('plurk_oauth/') -from PlurkAPI import PlurkAPI +from plurk_oauth import PlurkAPI import getopt import json + def usage(): - print '''Help Information: + print('''Help Information: -h: Show help information - ''' + ''') + if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="]) - except getopt.GetoptError, err: - print str(err) # will print something like "option -a not recognized" + except getopt.GetoptError as err: + print(str(err)) # will print something like "option -a not recognized" usage() sys.exit(2) - file = open('API.keys', 'r+') - data = json.load(file) - plurk = PlurkAPI(data["CONSUMER_KEY"], data["CONSUMER_SECRET"]) - if data.get('ACCESS_TOKEN'): - plurk.authorize(data["ACCESS_TOKEN"],data["ACCESS_TOKEN_SECRET"]) - else: - plurk.authorize() - data["ACCESS_TOKEN"] = plurk._oauth.oauth_token['oauth_token'] - data["ACCESS_TOKEN_SECRET"] = plurk._oauth.oauth_token['oauth_token_secret'] - json.dump(data,file) - print plurk.callAPI('/APP/Profile/getOwnProfile') - + with open('API.keys', 'r+') as f: + data = json.load(f) + plurk = PlurkAPI(data["CONSUMER_KEY"], data["CONSUMER_SECRET"]) + if data.get('ACCESS_TOKEN'): + plurk.authorize(data["ACCESS_TOKEN"], data["ACCESS_TOKEN_SECRET"]) + else: + plurk.authorize() + data["ACCESS_TOKEN"] = plurk._oauth.oauth_token['oauth_token'] + data["ACCESS_TOKEN_SECRET"] = plurk._oauth.oauth_token['oauth_token_secret'] + f.seek(0) + json.dump(data, f) + + print(plurk.callAPI('/APP/Profile/getOwnProfile')) diff --git a/bin/post_to_plurk.py b/bin/post_to_plurk.py old mode 100644 new mode 100755 index 1497c8c..2bd7dc1 --- a/bin/post_to_plurk.py +++ b/bin/post_to_plurk.py @@ -1,39 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- import sys sys.path.append('plurk_oauth/') -from PlurkAPI import PlurkAPI +from plurk_oauth import PlurkAPI import getopt import json + def usage(): - print '''Help Information: + print('''Help Information: -h: Show help information - ''' + ''') + if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="]) - except getopt.GetoptError, err: - print str(err) # will print something like "option -a not recognized" + except getopt.GetoptError as err: + print(str(err)) # will print something like "option -a not recognized" usage() sys.exit(2) - file = open('API.keys', 'r+') - data = json.load(file) - plurk = PlurkAPI(data["CONSUMER_KEY"], data["CONSUMER_SECRET"]) - if data.get('ACCESS_TOKEN'): - plurk.authorize(data["ACCESS_TOKEN"],data["ACCESS_TOKEN_SECRET"]) - else: - plurk.authorize() - data["ACCESS_TOKEN"] = plurk._oauth.oauth_token['oauth_token'] - data["ACCESS_TOKEN_SECRET"] = plurk._oauth.oauth_token['oauth_token_secret'] - json.dump(data,file) + with open('API.keys', 'r+') as f: + data = json.load(f) + plurk = PlurkAPI(data["CONSUMER_KEY"], data["CONSUMER_SECRET"]) + if data.get('ACCESS_TOKEN'): + plurk.authorize(data["ACCESS_TOKEN"], data["ACCESS_TOKEN_SECRET"]) + else: + plurk.authorize() + data["ACCESS_TOKEN"] = plurk._oauth.oauth_token['oauth_token'] + data["ACCESS_TOKEN_SECRET"] = plurk._oauth.oauth_token['oauth_token_secret'] + f.seek(0) + json.dump(data, f) content = 'Test from Plurk OAuth API' - if len(sys.argv) > 1: + if len(sys.argv) > 1: content = sys.argv[1] qualifier = 'says' - if len(sys.argv) > 2: + if len(sys.argv) > 2: qualifier = sys.argv[2] - print plurk.callAPI('/APP/Timeline/plurkAdd', { + print(plurk.callAPI('/APP/Timeline/plurkAdd', { 'content': content, - 'qualifier': qualifier } ) - + 'qualifier': qualifier + })) diff --git a/plurk_oauth/PlurkOAuth.py b/plurk_oauth/PlurkOAuth.py deleted file mode 100644 index 070aa49..0000000 --- a/plurk_oauth/PlurkOAuth.py +++ /dev/null @@ -1,135 +0,0 @@ -import oauth2 as oauth -import urlparse -from urllib import urlencode - -class PlurkOAuth: - def __init__(self, customer_key = None, customer_secret = None): - self.baseURL = 'http://www.plurk.com' - self.request_token_url = '/OAuth/request_token' - self.authorization_url = '/OAuth/authorize' - self.access_token_url = '/OAuth/access_token' - self.customer_key = customer_key - self.customer_secret = customer_secret - self.sign_method = oauth.SignatureMethod_HMAC_SHA1() - self.consumer = None - self.token = None - self.oauth_token = {} - if self.customer_key and self.customer_secret: - self.consumer = oauth.Consumer(self.customer_key, self.customer_secret) - - def __unicode__(self): - return self.baseURL - - def _dump(self, data): - #import pprint - #pprint.pprint(data) - pass - - def authorize(self, access_token_key = None, access_token_secret = None): - while not self.consumer: - self.get_consumer_token() - if access_token_key and access_token_secret: - self.oauth_token['oauth_token'] = access_token_key - self.oauth_token['oauth_token_secret'] = access_token_secret - else: - self.get_request_token() - verifier = self.get_verifier() - self.get_access_token(verifier) - - def request(self, url, params = None, data = None): - - # Setup - if self.oauth_token: - self.token = oauth.Token(self.oauth_token['oauth_token'], - self.oauth_token['oauth_token_secret']) - client = oauth.Client(self.consumer, self.token) - req = self._make_request(self.baseURL + url, params) - - # Get Request Token - encodedContent = None - if data: - encodedContent = urlencode(data) - resp, content = client.request(self.baseURL + url, "POST", - headers=req.to_header(), body = encodedContent) - return resp['status'], content, resp.reason - - - def get_consumer_token(self): - - # Setup - print "Prepare the CONSUMER Info" - - verified = 'n' - while verified.lower() != 'y': - key = raw_input('Input the CONSUMER_KEY: ') - secret = raw_input('Input the CONSUMER_SECRET: ') - print 'Consumer Key: %s' % str(key) - print 'Consumer Secret: %s' % str(secret) - verified = raw_input('Are you sure? (y/N) ') - self.customer_key = key - self.customer_secret = secret - self.consumer = oauth.Consumer(self.customer_key, self.customer_secret) - - def _make_request(self, requestURL, param = None): - request = oauth.Request.from_consumer_and_token(consumer=self.consumer, - token=self.token, http_method='POST', - http_url= requestURL, parameters = param, - is_form_encoded=True) - request.sign_request(self.sign_method, self.consumer, self.token) - return request - - def _has_pending_oauth_token(self): - # TODO we dont know this is request or access token, may ambiguous - return self.oauth_token and 'oauth_token' in self.oauth_token and 'oauth_token_secret' in self.oauth_token - - def get_request_token(self): - - if self._has_pending_oauth_token(): - # Already has a request/access token - return - - # Get Token Key/Secret - content = self.request(self.request_token_url) - if str(content[0]) != '200': - # TODO Declare an exception - raise Exception(content[2]) - self.oauth_token = dict(urlparse.parse_qsl(content[1])) - self._dump(self.oauth_token) - #print 'Token Key: %s' % str(token['oauth_token']) - #print 'Token Secret: %s' % str(token['oauth_token_secret']) - - def get_verifier(self): - - # Setup - print "Open the following URL and authorize it" - print "%s?oauth_token=%s" % (self.baseURL + self.authorization_url, - self.oauth_token['oauth_token']) - - verified = 'n' - while verified.lower() == 'n': - verifier = raw_input('Input the verification number: ') - verified = raw_input('Are you sure? (y/n) ') - return verifier - - def get_verifier_url(self): - - if not self.oauth_token or 'oauth_token' not in self.oauth_token: - # TODO Declare an exception - raise Exception('Please request a token first') - return '{0}{1}?oauth_token={2}'.format( self.baseURL, self.authorization_url, self.oauth_token['oauth_token'] ) - - def get_access_token(self, verifier): - - content = self.request(self.access_token_url, { - 'oauth_token_secret': self.oauth_token['oauth_token_secret'], - 'oauth_verifier': verifier, - } ) - if str(content[0]) != '200': - # TODO Declare an exception - raise Exception(content[2]) - # Get Token Key/Secret - self.oauth_token = dict(urlparse.parse_qsl(content[1])) - self._dump(self.oauth_token) - #print 'Access Key: %s' % str(self.oauth_token['oauth_token']) - #print 'Access Secret: %s' % str(self.oauth_token['oauth_token_secret']) - diff --git a/plurk_oauth/__init__.py b/plurk_oauth/__init__.py index e69de29..54bef82 100644 --- a/plurk_oauth/__init__.py +++ b/plurk_oauth/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +from .oauth import PlurkOAuth +from .api import PlurkAPI + +__all__ = (PlurkAPI, PlurkOAuth) diff --git a/plurk_oauth/PlurkAPI.py b/plurk_oauth/api.py similarity index 66% rename from plurk_oauth/PlurkAPI.py rename to plurk_oauth/api.py index 9215f8d..c96915b 100644 --- a/plurk_oauth/PlurkAPI.py +++ b/plurk_oauth/api.py @@ -1,28 +1,30 @@ +# -*- coding: utf-8 -*- import sys -import PlurkOAuth import json +from .oauth import PlurkOAuth + class PlurkAPI: - def __init__(self, key = None, secret = None, - access_token = None, access_secret = None): + def __init__(self, key=None, secret=None, + access_token=None, access_secret=None): if not key or not secret: - raise ValueError, "Both CONSUMER_KEY and CONSUMER_SECRET need to be specified" - self._oauth = PlurkOAuth.PlurkOAuth(key, secret) + raise ValueError("Both CONSUMER_KEY and CONSUMER_SECRET need to be specified") + self._oauth = PlurkOAuth(key, secret) self._authorized = False - self._error = {'code' : 200, 'reason' : '', 'content': ''} + self._error = {'code': 200, 'reason': '', 'content': ''} self._content = '' if access_token and access_secret: self.authorize(access_token, access_secret) @classmethod - def fromfile(cls, filename = "API.keys"): - try: + def fromfile(cls, filename="API.keys"): + try: file = open(filename, 'r+') except IOError: - print "You need to put key/secret in API.keys" + print("You need to put key/secret in API.keys") raise except: - print "Unexpected error:", sys.exc_info()[0] + print("Unexpected error:", sys.exc_info()[0]) else: data = json.load(file) file.close() @@ -30,20 +32,20 @@ def fromfile(cls, filename = "API.keys"): return cls() if data["ACCESS_TOKEN"] and data["ACCESS_TOKEN_SECRET"]: return cls(data["CONSUMER_KEY"], data["CONSUMER_SECRET"], - data["ACCESS_TOKEN"], data["ACCESS_TOKEN_SECRET"]) + data["ACCESS_TOKEN"], data["ACCESS_TOKEN_SECRET"]) else: return cls(data["CONSUMER_KEY"], data["CONSUMER_SECRET"]) def is_authorized(self): return self._authorized - def authorize(self, access_key = None, access_secret = None): + def authorize(self, access_key=None, access_secret=None): self._oauth.authorize(access_key, access_secret) self._authorized = True - def callAPI(self, path, options = None): + def callAPI(self, path, options=None): self._error['code'], self._content, self._error['reason'] = self._oauth.request( - path, None, options) + path, None, options) self._error['content'] = json.loads(self._content) if self._error['code'] != '200': return None @@ -72,10 +74,3 @@ def get_access_token(self, verifier): 'key': self._oauth.oauth_token['oauth_token'], 'secret': self._oauth.oauth_token['oauth_token_secret'], } - - -if __name__ == '__main__': - import os - plurk = PlurkAPI(os.environ["CONSUMERKEY"], os.environ["CONSUMERSECRET"]) -# plurk.authorize('tqRtGMu7Btw9','SCjkkydnkWNA7gwwuZo7y9wshVlzl7Lr') - print plurk.callAPI('/APP/Profile/getOwnProfile') diff --git a/plurk_oauth/oauth.py b/plurk_oauth/oauth.py new file mode 100644 index 0000000..47df323 --- /dev/null +++ b/plurk_oauth/oauth.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +from oauth2 import ( + Client, Consumer, Request, + SignatureMethod_HMAC_SHA1, Token, +) + +# compatible python3 +import sys +if sys.version_info >= (3, 0, 0): + from urllib.parse import parse_qsl + from urllib.parse import urlencode +else: + from urlparse import parse_qsl + from urllib import urlencode + input = raw_input + + +class PlurkOAuth: + def __init__(self, customer_key=None, customer_secret=None): + self.base_url = 'http://www.plurk.com' + self.request_token_url = '/OAuth/request_token' + self.authorization_url = '/OAuth/authorize' + self.access_token_url = '/OAuth/access_token' + self.customer_key = customer_key + self.customer_secret = customer_secret + self.sign_method = SignatureMethod_HMAC_SHA1() + self.consumer = None + self.token = None + self.oauth_token = {} + if self.customer_key and self.customer_secret: + self.consumer = Consumer(self.customer_key, self.customer_secret) + + def __unicode__(self): + return self.base_url + + def _dump(self, data): + # import pprint + # pprint.pprint(data) + pass + + def authorize(self, access_token_key=None, access_token_secret=None): + while not self.consumer: + self.get_consumer_token() + if access_token_key and access_token_secret: + self.oauth_token['oauth_token'] = access_token_key + self.oauth_token['oauth_token_secret'] = access_token_secret + else: + self.get_request_token() + verifier = self.get_verifier() + self.get_access_token(verifier) + + def request(self, url, params=None, data=None): + + # Setup + if self.oauth_token: + self.token = Token(self.oauth_token['oauth_token'], + self.oauth_token['oauth_token_secret']) + client = Client(self.consumer, self.token) + req = self._make_request(self.base_url + url, params) + + # Get Request Token + encoded_content = None + if data: + encoded_content = urlencode(data) + resp, content = client.request(self.base_url + url, "POST", + headers=req.to_header(), body=encoded_content) + # for python3 + if isinstance(content, bytes): + content = content.decode('utf-8') + + return resp['status'], content, resp.reason + + def get_consumer_token(self): + + # Setup + print("Prepare the CONSUMER Info") + + verified = 'n' + while verified.lower() != 'y': + key = input('Input the CONSUMER_KEY: ') + secret = input('Input the CONSUMER_SECRET: ') + print('Consumer Key: %s' % str(key)) + print('Consumer Secret: %s' % str(secret)) + verified = input('Are you sure? (y/N) ') + self.customer_key = key + self.customer_secret = secret + self.consumer = Consumer(self.customer_key, self.customer_secret) + + def _make_request(self, requestURL, param=None): + request = Request.from_consumer_and_token(consumer=self.consumer, + token=self.token, + http_method='POST', + http_url=requestURL, + parameters=param, + is_form_encoded=True) + request.sign_request(self.sign_method, self.consumer, self.token) + return request + + def _has_pending_oauth_token(self): + # TODO we dont know this is request or access token, may ambiguous + return self.oauth_token \ + and 'oauth_token' in self.oauth_token \ + and 'oauth_token_secret' in self.oauth_token + + def get_request_token(self): + + if self._has_pending_oauth_token(): + # Already has a request/access token + return + + # Get Token Key/Secret + status, content, reason = self.request(self.request_token_url) + if str(status) != '200': + # TODO Declare an exception + raise Exception(reason) + self.oauth_token = dict(parse_qsl(content)) + self._dump(self.oauth_token) + # print('Token Key: %s' % str(token['oauth_token'])) + # print('Token Secret: %s' % str(token['oauth_token_secret'])) + + def get_verifier(self): + + # Setup + print("Open the following URL and authorize it") + print("%s?oauth_token=%s" % (self.base_url + self.authorization_url, + self.oauth_token['oauth_token'])) + + verified = 'n' + while verified.lower() == 'n': + verifier = input('Input the verification number: ') + verified = input('Are you sure? (y/n) ') + return verifier + + def get_verifier_url(self): + + if not self.oauth_token or 'oauth_token' not in self.oauth_token: + # TODO Declare an exception + raise Exception('Please request a token first') + return '{0}{1}?oauth_token={2}'.format(self.base_url, + self.authorization_url, + self.oauth_token['oauth_token']) + + def get_access_token(self, verifier): + + status, content, reason = self.request(self.access_token_url, { + 'oauth_token_secret': self.oauth_token['oauth_token_secret'], + 'oauth_verifier': verifier, + }) + if str(status) != '200': + # TODO Declare an exception + raise Exception(reason) + # Get Token Key/Secret + self.oauth_token = dict(parse_qsl(content)) + self._dump(self.oauth_token) + # print('Access Key: %s' % str(self.oauth_token['oauth_token'])) + # print('Access Secret: %s' % str(self.oauth_token['oauth_token_secret'])) diff --git a/tests/api_test.py b/tests/api_test.py index 581a203..1f02f8b 100644 --- a/tests/api_test.py +++ b/tests/api_test.py @@ -1,11 +1,17 @@ -import os -import unittest -from nose.tools import * -from plurk_oauth.PlurkAPI import PlurkAPI -from plurk_oauth.PlurkOAuth import PlurkOAuth -import urlparse +# -*- coding: utf-8 -*- import json -import mox +import unittest +# compatible python3 +import sys +if sys.version_info >= (3, 0, 0): + from mox3 import mox + from urllib.parse import parse_qsl +else: + import mox + from urlparse import parse_qsl + +from plurk_oauth import PlurkAPI, PlurkOAuth + class Test0ConsumerTokenSecret(unittest.TestCase): def setUp(self): @@ -18,28 +24,29 @@ def test_no_consumer_key(self): with self.assertRaises(ValueError): self.plurk = PlurkAPI() self.plurk.callAPI('/APP/Profile/getPublicProfile', - {'user_id': 'clsung'}) + {'user_id': 'clsung'}) def test_invalid_consumer_key(self): self.plurk = PlurkAPI("token", "secret") r = self.plurk.callAPI('/APP/Profile/getPublicProfile', - {'user_id': 'clsung'}) + {'user_id': 'clsung'}) self.assertIsNone(r) err = self.plurk.error() self.assertEqual(err['code'], "400") self.assertEqual(err['reason'], "BAD REQUEST") self.assertEqual(err['content']['error_text'], - "40101:unknown application key") + "40101:unknown application key") + class Test1AccessTokenSecret(unittest.TestCase): def setUp(self): - try: + try: file = open('API.keys', 'r+') except IOError: - print "You need to put key/secret in API.keys" + print("You need to put key/secret in API.keys") raise except: - print "Unexpected error:", sys.exc_info()[0] + print("Unexpected error:", sys.exc_info()[0]) else: data = json.load(file) file.close() @@ -56,7 +63,8 @@ def test_invalid_access_key(self): self.assertEqual(err['code'], "400") self.assertEqual(err['reason'], "BAD REQUEST") self.assertEqual(err['content']['error_text'], - "40106:invalid access token") + "40106:invalid access token") + class TestThreeLeggedAPI(unittest.TestCase): def setUp(self): @@ -72,15 +80,16 @@ def test_get_ownprofile(self): self.assertIsInstance(jdata, dict, "Object should be a dict") self.assertGreater(jdata['user_info']['uid'], 0, "Self Uid > 0") + class TestTwoLeggedAPI(unittest.TestCase): def setUp(self): - try: + try: file = open('API.keys', 'r+') except IOError: - print "You need to put key/secret in API.keys" + print("You need to put key/secret in API.keys") raise except: - print "Unexpected error:", sys.exc_info()[0] + print("Unexpected error:", sys.exc_info()[0]) else: data = json.load(file) file.close() @@ -91,11 +100,12 @@ def teardown(self): def test_get_public_profile(self): jdata = self.plurk.callAPI('/APP/Profile/getPublicProfile', - {'user_id': 'clsung'}) + {'user_id': 'clsung'}) self.assertIsInstance(jdata, dict, "Object is a dict") self.assertGreater(jdata['user_info']['uid'], 0, "Self Uid > 0") self.assertEqual(jdata['user_info']['nick_name'], - "clsung", "Author's Name ;)") + "clsung", "Author's Name ;)") + class TestRequestToken(unittest.TestCase): """ @@ -106,8 +116,8 @@ def setUp(self): self.mox = mox.Mox() self.oauth = PlurkOAuth("CONSUMER_KEY", "CONSUMER_SECRET") self.oauth_response = \ - 'oauth_token_secret=O7WqqqWHA61f4ZE5izQdTQmK&oauth_token=ReqXBFOswcyR&oauth_callback_confirmed=true' - self.golden_token = dict(urlparse.parse_qsl(self.oauth_response)) + 'oauth_token_secret=O7WqqqWHA61f4ZE5izQdTQmK&oauth_token=ReqXBFOswcyR&oauth_callback_confirmed=true' # NOQA + self.golden_token = dict(parse_qsl(self.oauth_response)) self.mox.StubOutWithMock(PlurkOAuth, 'request') def tearDown(self): @@ -123,6 +133,7 @@ def test_get_request_token(self): self.assertEqual(self.golden_token, self.oauth.oauth_token) self.mox.VerifyAll() + class TestAPIAuth(unittest.TestCase): ''' Unit test for PlurkAPI auth part @@ -131,12 +142,12 @@ def setUp(self): self.mox = mox.Mox() self.api = PlurkAPI('CONSUMER_KEY', 'CONSUMER_SECRET') self.oauth_response = \ - 'oauth_token_secret=O7WqqqWHA61f4ZE5izQdTQmK&oauth_token=ReqXBFOswcyR&oauth_callback_confirmed=true' + 'oauth_token_secret=O7WqqqWHA61f4ZE5izQdTQmK&oauth_token=ReqXBFOswcyR&oauth_callback_confirmed=true' # NOQA self.verify_response = \ - 'oauth_token_secret=O7WqqqWHA61f4ZE5izQdTQmK&oauth_token=ReqXBFOswcyR' + 'oauth_token_secret=O7WqqqWHA61f4ZE5izQdTQmK&oauth_token=ReqXBFOswcyR' self.golden_token = { - 'key': 'ReqXBFOswcyR', - 'secret': 'O7WqqqWHA61f4ZE5izQdTQmK', + 'key': 'ReqXBFOswcyR', + 'secret': 'O7WqqqWHA61f4ZE5izQdTQmK', } self.golden_url = 'http://www.plurk.com/OAuth/authorize?oauth_token=ReqXBFOswcyR' self.mox.StubOutWithMock(PlurkOAuth, 'request')