├── .gitignore ├── MANIFEST.in ├── README.md ├── README.rst ├── examples ├── box.py ├── douban.py ├── douban_auth_password.py ├── douban_auth_token.py ├── github.py ├── google.py ├── instagram.py ├── qq.py ├── weibo.py └── weibo_token.py ├── pyoauth2 ├── __init__.py ├── client.py └── libs │ ├── __init__.py │ ├── access_token.py │ ├── auth_code.py │ ├── base.py │ ├── connection.py │ ├── password.py │ ├── request.py │ ├── response.py │ └── utils.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | 3 | # Packages 4 | *.egg 5 | *.egg-info 6 | dist 7 | build 8 | eggs 9 | parts 10 | bin 11 | var 12 | sdist 13 | develop-eggs 14 | tests 15 | .installed.cfg 16 | 17 | # Installer logs 18 | pip-log.txt 19 | 20 | # Unit test / coverage reports 21 | .coverage 22 | .tox 23 | 24 | #Translations 25 | *.mo 26 | 27 | #Mr Developer 28 | .mr.developer.cfg 29 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # py-oauth2 2 | 3 | A Python wrapper for the OAuth 2.0 specification 4 | 5 | 6 | ## Installation 7 | 8 | __PIP__ 9 | ``` bash 10 | pip install py-oauth2 11 | ``` 12 | 13 | __Easy Install__ 14 | ``` bash 15 | easy_install py-oauth2 16 | ``` 17 | 18 | ## Usage Examples 19 | 20 | #### Demo for Google 21 | 22 | ``` python 23 | from pyoauth2 import Client 24 | 25 | CLIENT_ID = '' 26 | CLIENT_SECRET = '' 27 | REDIRECT_URL = '' 28 | SCOPE = ['https://www.googleapis.com/auth/userinfo.profile', 29 | 'https://www.googleapis.com/auth/userinfo.email',] 30 | SCOPE = ' '.join(SCOPE) 31 | 32 | client = Client(CLIENT_ID, CLIENT_SECRET, 33 | site='https://www.googleapis.com/oauth2/v1', 34 | authorize_url='https://accounts.google.com/o/oauth2/auth', 35 | token_url='https://accounts.google.com/o/oauth2/token') 36 | 37 | print '-' * 80 38 | authorize_url = client.auth_code.authorize_url(redirect_uri=REDIRECT_URL, 39 | scope=SCOPE) 40 | print 'Go to the following link in your browser:' 41 | print authorize_url 42 | 43 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 44 | code = code.strip() 45 | access_token = client.auth_code.get_token(code, redirect_uri=REDIRECT_URL) 46 | print 'token', access_token.headers 47 | 48 | print '-' * 80 49 | print 'get user info' 50 | ret = access_token.get('/userinfo') 51 | print ret.parsed 52 | 53 | ``` 54 | 55 | ### Demo for Douban 56 | 57 | Get access_token 58 | 59 | ``` python 60 | from pyoauth2 import Client 61 | 62 | KEY = '' 63 | SECRET = '' 64 | CALLBACK = '' 65 | 66 | client = Client(KEY, SECRET, 67 | site='https://api.douban.com', 68 | authorize_url='https://www.douban.com/service/auth2/auth', 69 | token_url='https://www.douban.com/service/auth2/token') 70 | 71 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK, 72 | scope='shuo_basic_w,douban_basic_common') 73 | # got code 74 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK) 75 | ``` 76 | 77 | Get data 78 | 79 | ``` python 80 | ret = access_token.get('/v2/user/~me') 81 | print ret.parsed 82 | ``` 83 | 84 | Upload image 85 | 86 | ``` python 87 | ret = access_token.post('/shuo/v2/statuses/', 88 | text='content from py-oauth2', 89 | files={ 'image': open('/path/pic.jpg')}) 90 | print ret.parsed 91 | ``` 92 | 93 | #### More: 94 | 95 | 96 | 97 | [Demo for Google](https://github.com/liluo/py-oauth2/wiki/Google) 98 | 99 | [Demo for Douban(auth with code)](https://github.com/liluo/py-oauth2/wiki/Douban) 100 | 101 | [Demo for Douban(auth with token)](https://github.com/liluo/py-oauth2/wiki/Douban2) 102 | 103 | [Demo for Douban(auth with password)](https://github.com/liluo/py-oauth2/wiki/Douban3) 104 | 105 | [Demo for GitHub](https://github.com/liluo/py-oauth2/wiki/GitHub) 106 | 107 | [Demo for Weibo](https://github.com/liluo/py-oauth2/wiki/Weibo) 108 | 109 | [Demo for QQ](https://github.com/liluo/py-oauth2/wiki/QQ-OAuth-2.0) 110 | 111 | [Demo for Taobao](https://github.com/liluo/py-oauth2/wiki/Taobao-OAuth-2.0) 112 | 113 | [Demo for Box.com](https://github.com/liluo/py-oauth2/wiki/Box.com) 114 | 115 | [Demo for Instagram](https://github.com/liluo/py-oauth2/wiki/Instagram) 116 | 117 | ## License 118 | 119 | MIT 120 | 121 | ## Authors 122 | 123 | This is the list of authors of py-oauth2, sorted by time: 124 | 125 | 126 | * liluo 127 | * waawal 128 | * qingfeng 129 | * alswl 130 | * Grigi 131 | * skiyo 132 | 133 | ## Submitting a Pull Request 134 | * Fork the repository. 135 | * Create a topic branch. 136 | * Implement your feature or bug fix. 137 | * Add, commit, and push your changes. 138 | * Submit a pull request. 139 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | py-oauth2 3 | ========= 4 | 5 | A Python wrapper for the OAuth 2.0 specification 6 | 7 | Installation 8 | ------------ 9 | 10 | pip:: 11 | 12 | pip install py-oauth2 13 | 14 | 15 | easy_install:: 16 | 17 | easy_install py-oauth2 18 | 19 | 20 | Usage Examples 21 | -------------- 22 | 23 | Demo for Google 24 | --------------- 25 | Get user info:: 26 | 27 | from pyoauth2 import Client 28 | 29 | CLIENT_ID = '' 30 | CLIENT_SECRET = '' 31 | REDIRECT_URL = '' 32 | SCOPE = 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email' 33 | 34 | client = Client(CLIENT_ID, CLIENT_SECRET, 35 | site='https://www.googleapis.com/oauth2/v1', 36 | authorize_url='https://accounts.google.com/o/oauth2/auth', 37 | token_url='https://accounts.google.com/o/oauth2/token') 38 | 39 | print '-' * 80 40 | authorize_url = client.auth_code.authorize_url(redirect_uri=REDIRECT_URL, scope=SCOPE) 41 | print 'Go to the following link in your browser:' 42 | print authorize_url 43 | 44 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 45 | code = code.strip() 46 | access_token = client.auth_code.get_token(code, redirect_uri=REDIRECT_URL) 47 | print 'token', access_token.headers 48 | 49 | print '-' * 80 50 | print 'get user info' 51 | ret = access_token.get('/userinfo') 52 | print ret.parsed 53 | 54 | 55 | Demo for Douban 56 | --------------- 57 | Get access_token:: 58 | 59 | from pyoauth2 import Client 60 | 61 | KEY = '' 62 | SECRET = '' 63 | CALLBACK = '' 64 | 65 | client = Client(KEY, SECRET, 66 | site='https://api.douban.com', 67 | authorize_url='https://www.douban.com/service/auth2/auth', 68 | token_url='https://www.douban.com/service/auth2/token') 69 | 70 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK, scope='shuo_basic_w,douban_basic_common') 71 | 72 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK) 73 | 74 | 75 | Get data:: 76 | 77 | ret = access_token.get('/v2/user/~me') 78 | print ret.parsed 79 | 80 | Upload image:: 81 | 82 | ret = access_token.post('/shuo/v2/statuses/', text='content from py-oauth2', files={ 'image': open('/path/pic.jpg')}) 83 | print ret.parsed 84 | 85 | 86 | More: 87 | 88 | `Examples `_ 89 | 90 | `Demo for Google `_ 91 | 92 | `Demo for Douban(auth with code) `_ 93 | 94 | `Demo for Douban(auth with token) `_ 95 | 96 | `Demo for Douban(auth with password) `_ 97 | 98 | `Demo for GitHub `_ 99 | 100 | `Demo for Weibo `_ 101 | 102 | `Demo for QQ `_ 103 | 104 | `Demo for Taobao `_ 105 | 106 | `Demo for Box.com `_ 107 | 108 | `Demo for Instagram `_ 109 | 110 | Submitting a Pull Request 111 | ------------------------- 112 | * Fork the repository. 113 | * Create a topic branch. 114 | * Implement your feature or bug fix. 115 | * Add, commit, and push your changes. 116 | * Submit a pull request. 117 | -------------------------------------------------------------------------------- /examples/box.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | KEY = '' 4 | SECRET = '' 5 | CALLBACK = '' 6 | 7 | client = Client(KEY, SECRET, 8 | site='https://api.box.com/2.0', 9 | authorize_url='https://api.box.com/oauth2/authorize', 10 | token_url='https://api.box.com/oauth2/token') 11 | 12 | print '-' * 80 13 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK) 14 | print 'Go to the following link in your browser:' 15 | print authorize_url 16 | print '-' * 80 17 | 18 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 19 | code = code.strip() 20 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK) 21 | print 'token', access_token.headers 22 | 23 | print '-' * 80 24 | ret = access_token.get('/folders/0') 25 | print ret.parsed 26 | -------------------------------------------------------------------------------- /examples/douban.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | KEY = '' 4 | SECRET = '' 5 | CALLBACK = '' 6 | 7 | client = Client(KEY, SECRET, 8 | site='https://api.douban.com', 9 | authorize_url='https://www.douban.com/service/auth2/auth', 10 | token_url='https://www.douban.com/service/auth2/token') 11 | 12 | print '-' * 80 13 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK, scope='shuo_basic_w,douban_basic_common') 14 | print 'Go to the following link in your browser:' 15 | print authorize_url 16 | print '-' * 80 17 | 18 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 19 | code = code.strip() 20 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK) 21 | print 'token', access_token.headers 22 | 23 | print '-' * 80 24 | print 'get @me info' 25 | ret = access_token.get('/v2/user/~me') 26 | print ret.parsed 27 | 28 | print '-' * 80 29 | print 'post miniblog...' 30 | ret = access_token.post('/shuo/v2/statuses/', text='hello oauth2, from py-oauth2') 31 | print ret.parsed 32 | -------------------------------------------------------------------------------- /examples/douban_auth_password.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | from pyoauth2 import AccessToken 3 | 4 | KEY = '' 5 | SECRET = '' 6 | CALLBACK = '' 7 | 8 | user_email = '' 9 | user_password = '' 10 | 11 | client = Client(KEY, SECRET, 12 | site='https://api.douban.com', 13 | authorize_url='https://www.douban.com/service/auth2/auth', 14 | token_url='https://www.douban.com/service/auth2/token') 15 | 16 | access_token = client.password.get_token(user_email, user_password) 17 | 18 | print '-' * 80 19 | ret = access_token.get('/v2/user/~me') 20 | print ret.parsed 21 | -------------------------------------------------------------------------------- /examples/douban_auth_token.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | from pyoauth2 import AccessToken 3 | 4 | KEY = '' 5 | SECRET = '' 6 | CALLBACK = '' 7 | 8 | token = '' 9 | 10 | client = Client(KEY, SECRET, 11 | site='https://api.douban.com', 12 | authorize_url='https://www.douban.com/service/auth2/auth', 13 | token_url='https://www.douban.com/service/auth2/token') 14 | 15 | access_token = AccessToken(client, token) 16 | 17 | print '-' * 80 18 | ret = access_token.get('/people/%40me', alt='json') 19 | print ret.parsed 20 | -------------------------------------------------------------------------------- /examples/github.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | KEY = '' 4 | SECRET = '' 5 | CALLBACK = '' 6 | 7 | client = Client(KEY, SECRET, 8 | site='https://api.github.com', 9 | authorize_url='https://github.com/login/oauth/authorize', 10 | token_url='https://github.com/login/oauth/access_token') 11 | 12 | print '-' * 80 13 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK, scope='user,public_repo') 14 | print 'Go to the following link in your browser:' 15 | print authorize_url 16 | print '-' * 80 17 | 18 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 19 | code = code.strip() 20 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK, parse='query') 21 | print 'token', access_token.headers 22 | 23 | print '-' * 80 24 | print 'get user info' 25 | ret = access_token.get('/user') 26 | print ret.parsed 27 | 28 | print '-' * 80 29 | print 'create a repos' 30 | ret = access_token.post('/user/repos', name='test_repo', headers={'content-type': 'application/json'}) 31 | print ret.parsed 32 | -------------------------------------------------------------------------------- /examples/google.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | CLIENT_ID = '' 4 | CLIENT_SECRET = '' 5 | REDIRECT_URL = '' 6 | SCOPE = 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email' 7 | 8 | client = Client(CLIENT_ID, CLIENT_SECRET, 9 | site='https://www.googleapis.com/oauth2/v1', 10 | authorize_url='https://accounts.google.com/o/oauth2/auth', 11 | token_url='https://accounts.google.com/o/oauth2/token') 12 | 13 | print '-' * 80 14 | authorize_url = client.auth_code.authorize_url(redirect_uri=REDIRECT_URL, scope=SCOPE) 15 | print 'Go to the following link in your browser:' 16 | print authorize_url 17 | 18 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 19 | code = code.strip() 20 | access_token = client.auth_code.get_token(code, redirect_uri=REDIRECT_URL) 21 | print 'token', access_token.headers 22 | 23 | print '-' * 80 24 | print 'get user info' 25 | ret = access_token.get('/userinfo') 26 | print ret.parsed 27 | -------------------------------------------------------------------------------- /examples/instagram.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | CLIENT_ID = '' 4 | CLIENT_SECRET = '' 5 | REDIRECT_URL = '' 6 | 7 | client = Client(CLIENT_ID, CLIENT_SECRET, 8 | site='https://api.instagram.com', 9 | authorize_url='/oauth/authorize', 10 | token_url='/oauth/access_token') 11 | 12 | authorize_url = client.auth_code.authorize_url(redirect_uri=REDIRECT_URL) 13 | 14 | print 'Go to the following link in your browser:' 15 | print authorize_url 16 | print '-' * 80 17 | 18 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 19 | code = code.strip() 20 | access_token = client.auth_code.get_token(code, redirect_uri=REDIRECT_URL) 21 | 22 | print 'token', access_token.headers 23 | print 'params', access_token.params 24 | -------------------------------------------------------------------------------- /examples/qq.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | KEY = '' 4 | SECRET = '' 5 | CALLBACK = '' 6 | 7 | client = Client(KEY, SECRET, 8 | site='https://graph.qq.com', 9 | authorize_url='https://graph.qq.com/oauth2.0/authorize', 10 | token_url='https://graph.qq.com/oauth2.0/token') 11 | 12 | print '-' * 80 13 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK, 14 | scope='get_user_info,list_album,upload_pic,do_like') 15 | print 'Go to the following link in your browser:' 16 | print authorize_url 17 | print '-' * 80 18 | 19 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 20 | code = code.strip() 21 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK, parse='query') 22 | 23 | print 'token', access_token.headers 24 | print access_token.expires_at 25 | -------------------------------------------------------------------------------- /examples/weibo.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | 3 | KEY = '' 4 | SECRET = '' 5 | CALLBACK = '' 6 | 7 | client = Client(KEY, SECRET, 8 | site='https://api.weibo.com', 9 | authorize_url='/oauth2/authorize', 10 | token_url='/oauth2/access_token') 11 | 12 | print '-' * 80 13 | authorize_url = client.auth_code.authorize_url(redirect_uri=CALLBACK) 14 | print 'Go to the following link in your browser:' 15 | print authorize_url 16 | 17 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 18 | code = code.strip() 19 | access_token = client.auth_code.get_token(code, redirect_uri=CALLBACK, header_format='OAuth2 %s') 20 | print 'token', access_token.headers 21 | 22 | ret = access_token.get('/2/statuses/public_timeline.json') 23 | print '-' * 80 24 | print 'get public timeline' 25 | print ret.body 26 | 27 | print '-' * 80 28 | print 'post miniblog...' 29 | ret = access_token.post('/2/statuses/update.json', status='now') 30 | print ret.body 31 | -------------------------------------------------------------------------------- /examples/weibo_token.py: -------------------------------------------------------------------------------- 1 | from pyoauth2 import Client 2 | from pyoauth2 import AccessToken 3 | 4 | KEY = '' 5 | SECRET = '' 6 | CALLBACK = '' 7 | 8 | client = Client(KEY, SECRET, site='https://api.weibo.com', 9 | authorize_url='/oauth2/authorize', 10 | token_url='/oauth2/access_token') 11 | 12 | code = raw_input('Enter the verification code and hit ENTER when you\'re done:') 13 | client.auth_code.get_token(code, redirect_uri=CALLBACK) 14 | access_token = AccessToken(client, code) 15 | 16 | print access_token.get('/2/statuses/public_timeline.json', access_token=access_token.token).parsed 17 | -------------------------------------------------------------------------------- /pyoauth2/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .client import Client 4 | from .libs.access_token import AccessToken 5 | 6 | VERSION = __version__ = '0.0.9' 7 | -------------------------------------------------------------------------------- /pyoauth2/client.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .libs.auth_code import AuthCode 4 | from .libs.password import Password 5 | from .libs.access_token import AccessToken 6 | from .libs.request import Request 7 | from .libs.connection import Connection 8 | 9 | 10 | class Client(object): 11 | 12 | def __init__(self, client_id, client_secret, **opts): 13 | self.id = client_id 14 | self.secret = client_secret 15 | self.site = opts.pop('site', '') 16 | self.opts = {'authorize_url': '/oauth/authorize', 17 | 'token_url': '/oauth/token', 18 | 'token_method': 'POST', 19 | 'connection_opts': {}, 20 | 'raise_errors': True, } 21 | self.opts.update(opts) 22 | 23 | def __repr__(self): 24 | return '' 25 | 26 | def authorize_url(self, params={}): 27 | return Connection.build_url(self.site, path=self.opts['authorize_url'], params=params) 28 | 29 | def token_url(self, params={}): 30 | return Connection.build_url(self.site, path=self.opts['token_url'], params=params) 31 | 32 | def request(self, method, uri, **opts): 33 | uri = Connection.build_url(self.site, path=uri) 34 | response = Request(method, uri, **opts).request() 35 | return response 36 | 37 | def get_token(self, **opts): 38 | self.response = self.request(self.opts['token_method'], self.token_url(), **opts) 39 | opts.update(self.response.parsed) 40 | return AccessToken.from_hash(self, **opts) 41 | 42 | @property 43 | def password(self): 44 | return Password(self) 45 | 46 | @property 47 | def auth_code(self): 48 | return AuthCode(self) 49 | -------------------------------------------------------------------------------- /pyoauth2/libs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liluo/py-oauth2/313f195639cd94c7cce47c9a83e71dae487e53e9/pyoauth2/libs/__init__.py -------------------------------------------------------------------------------- /pyoauth2/libs/access_token.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | from .utils import urlparse 4 | 5 | 6 | class AccessTokenException(BaseException): 7 | pass 8 | 9 | 10 | class AccessToken(object): 11 | 12 | def __init__(self, client, token, **opts): 13 | self.client = client 14 | self.token = token 15 | 16 | for attr in ['refresh_token', 'expires_in', 'expires_at']: 17 | if attr in opts.keys(): 18 | setattr(self, attr, opts.pop(attr)) 19 | 20 | if hasattr(self, 'expires_in') and str(self.expires_in).isdigit(): 21 | self.expires_at = int(time.time()) + int(self.expires_in) 22 | 23 | self.opts = {'mode': opts.pop('mode', 'header'), 24 | 'header_format': opts.pop('header_format', 'Bearer %s'), 25 | 'param_name': opts.pop('param_name', 'bearer_token'), 26 | } 27 | self.params = opts 28 | 29 | def __repr__(self): 30 | return '' 31 | 32 | @classmethod 33 | def from_hash(cls, client, **opts): 34 | return cls(client, opts.pop('access_token', ''), **opts) 35 | 36 | @classmethod 37 | def from_kvform(cls, client, kvform): 38 | opts = dict(urlparse.parse_qsl(kvform)) 39 | return cls(client, opts.pop('access_token', ''), **opts) 40 | 41 | def refresh(self, **opts): 42 | if not getattr(self, 'refresh_token', None): 43 | raise AccessTokenException('A refresh_token is not available') 44 | 45 | opts = {'client_id': self.client.id, 46 | 'client_secret': self.client.secret, 47 | 'refresh_token': self.refresh_token, 48 | 'grant_type': 'refresh_token', 49 | } 50 | new_token = self.client.get_token(**opts) 51 | return new_token 52 | 53 | def request(self, method, uri, **opts): 54 | opts = self.__set_token(**opts) 55 | return self.client.request(method, uri, **opts) 56 | 57 | def get(self, uri, **opts): 58 | return self.request('GET', uri, **opts) 59 | 60 | def post(self, uri, **opts): 61 | return self.request('POST', uri, **opts) 62 | 63 | def put(self, uri, **opts): 64 | return self.request('PUT', uri, **opts) 65 | 66 | def patch(self, uri, **opts): 67 | return self.request('PATCH', uri, **opts) 68 | 69 | def delete(self, uri, **opts): 70 | return self.request('DELETE', uri, **opts) 71 | 72 | @property 73 | def headers(self): 74 | return {'Authorization': self.opts['header_format'] % self.token} 75 | 76 | def __set_token(self, **opts): 77 | mode = self.opts['mode'] 78 | if mode == 'header': 79 | headers = opts.get('headers', {}) 80 | headers.update(self.headers) 81 | opts['headers'] = headers 82 | elif mode == 'query': 83 | params = opts.get('params', {}) 84 | params[self.opts['param_name']] = self.token 85 | opts['params'] = params 86 | elif mode == 'body': 87 | body = opts.get('body', {}) 88 | if isinstance(body, dict): 89 | opts['body'][self.opts['param_name']] = self.token 90 | else: 91 | opts['body'] += "&%s=%s" % (self.opts['param_name'], self.token) 92 | else: 93 | raise AccessTokenException("invalid :mode option of %s" % self.opts['param_name']) 94 | 95 | return opts 96 | -------------------------------------------------------------------------------- /pyoauth2/libs/auth_code.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .base import Base 3 | 4 | 5 | class AuthCode(Base): 6 | 7 | def __repr__(self): 8 | return '' % self.client.id 9 | 10 | def authorize_params(self, **params): 11 | params.update({'response_type': 'code', 'client_id': self.client.id}) 12 | return params 13 | 14 | def authorize_url(self, **params): 15 | params = self.authorize_params(**params) 16 | return self.client.authorize_url(params) 17 | 18 | def get_token(self, code, **opts): 19 | params = {'grant_type': 'authorization_code', 'code': code} 20 | params.update(self.client_params) 21 | opts.update(params) 22 | return self.client.get_token(**opts) 23 | -------------------------------------------------------------------------------- /pyoauth2/libs/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | 3 | 4 | class Base(object): 5 | 6 | def __init__(self, client): 7 | self.client = client 8 | 9 | @property 10 | def client_params(self): 11 | return {'client_id': self.client.id, 'client_secret': self.client.secret} 12 | -------------------------------------------------------------------------------- /pyoauth2/libs/connection.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .utils import urlencode 3 | 4 | 5 | class Connection(object): 6 | 7 | def __repr__(self): 8 | return '' 9 | 10 | @classmethod 11 | def build_url(cls, url, path='', params={}): 12 | params = urlencode(params) 13 | params = '?%s' % params if params else '' 14 | url = path if path.startswith(('http://', 'https://')) else '%s%s' % (url, path) 15 | return '%s%s' % (url, params) 16 | -------------------------------------------------------------------------------- /pyoauth2/libs/password.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .base import Base 4 | 5 | 6 | class Password(Base): 7 | 8 | def authorize_url(self): 9 | return NotImplementedError('The authorization endpoint is not used in this strategy') 10 | 11 | def get_token(self, username, password, **opts): 12 | params = {'grant_type': 'password', 13 | 'username': username, 14 | 'password': password, 15 | } 16 | params.update(self.client_params) 17 | opts.update(params) 18 | return self.client.get_token(**opts) 19 | -------------------------------------------------------------------------------- /pyoauth2/libs/request.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import json 3 | import requests 4 | 5 | from .response import Response 6 | 7 | 8 | class Request(object): 9 | 10 | def __init__(self, method, uri, 11 | headers=None, 12 | files=None, 13 | timeout=None, 14 | allow_redirects=True, 15 | proxies=None, 16 | hooks=None, 17 | stream=None, 18 | verify=None, 19 | cert=None, 20 | parse='json', 21 | **opts): 22 | self.method = method 23 | self.uri = uri 24 | self.headers = headers or {} 25 | self.files = files 26 | self.timeout = timeout 27 | self.allow_redirects = allow_redirects 28 | self.proxies = proxies 29 | self.hooks = hooks 30 | self.stream = stream 31 | self.verify = verify 32 | self.cert = cert 33 | self.parse = parse 34 | if self.headers.get('content-type') == 'application/json': 35 | self.opts = json.dumps(opts) 36 | else: 37 | self.opts = opts 38 | 39 | def __repr__(self): 40 | return '' 41 | 42 | def request(self): 43 | data = params = None 44 | if self.method in ('POST', 'PUT'): 45 | data = self.opts 46 | else: 47 | params = self.opts 48 | response = requests.request(self.method, self.uri, 49 | params=params, 50 | data=data, 51 | headers=self.headers, 52 | files=self.files, 53 | timeout=self.timeout, 54 | allow_redirects=self.allow_redirects, 55 | proxies=self.proxies, 56 | hooks=self.hooks, 57 | stream=self.stream, 58 | verify=self.verify, 59 | cert=self.cert) 60 | 61 | response = Response(response, parse=self.parse) 62 | status = response.status_code 63 | #TODO raise error 64 | if status in (301, 302, 303, 307): 65 | return response 66 | elif 200 <= status < 400: 67 | return response 68 | elif 400 <= status < 500: 69 | return response 70 | elif 500 <= status < 600: 71 | return response 72 | return response 73 | -------------------------------------------------------------------------------- /pyoauth2/libs/response.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .utils import urlparse 3 | 4 | 5 | def to_query(txt): 6 | qs = urlparse.parse_qsl(txt) 7 | ret = dict(qs) 8 | return _check_expires_in(ret) 9 | 10 | 11 | def to_text(txt): 12 | return txt 13 | 14 | 15 | def _check_expires_in(ret): 16 | expires_in = ret.get('expires_in') 17 | if expires_in and expires_in.isdigit(): 18 | ret['expires_in'] = int(expires_in) 19 | return ret 20 | 21 | 22 | class Response(object): 23 | 24 | def __init__(self, response, **opts): 25 | self.response = self.resp = response 26 | self.status_code = self.status = response.status_code 27 | self.reason = response.reason 28 | self.content_type = response.headers.get('content-type') 29 | self.body = response.text 30 | 31 | options = {'parse': 'text'} 32 | options.update(opts) 33 | self.options = options 34 | 35 | def __repr__(self): 36 | return '' 37 | 38 | @property 39 | def parsed(self): 40 | fmt = self.options['parse'] 41 | if fmt == 'json': 42 | return self.resp.json() 43 | elif fmt == 'query': 44 | return to_query(self.body) 45 | else: 46 | return self.body 47 | -------------------------------------------------------------------------------- /pyoauth2/libs/utils.py: -------------------------------------------------------------------------------- 1 | try: 2 | from urllib import urlencode 3 | except ImportError: 4 | from urllib.parse import urlencode 5 | 6 | try: 7 | import urlparse 8 | except ImportError: 9 | import urllib.parse as urlparse 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from setuptools import setup, find_packages 5 | 6 | setup( 7 | name='py-oauth2', 8 | version='0.0.9', 9 | keywords=('Python', 'pyoauth2', 'OAuth2', 'Douban', 'GitHub', 'Weibo'), 10 | description='A Python wrapper for the OAuth 2.0 specification.', 11 | long_description=open('README.rst').read(), 12 | license='MIT License', 13 | 14 | url='https://github.com/liluo/py-oauth2', 15 | author='liluo', 16 | author_email='i@liluo.org', 17 | 18 | packages=find_packages(), 19 | include_package_data=True, 20 | platforms='any', 21 | install_requires=['requests'], 22 | classifiers=[ 23 | 'Environment :: Web Environment', 24 | 'Intended Audience :: Developers', 25 | 'License :: OSI Approved :: MIT License', 26 | 'Operating System :: OS Independent', 27 | 'Programming Language :: Python', 28 | 'Programming Language :: Python :: 2.7', 29 | 'Programming Language :: Python :: 3.2', 30 | 'Programming Language :: Python :: 3.3', 31 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 32 | 'Topic :: Software Development :: Libraries :: Python Modules' 33 | ], 34 | ) 35 | --------------------------------------------------------------------------------