Permalink
Browse files

initial commit ๐Ÿฐ

  • Loading branch information...
maxcountryman committed Mar 2, 2012
0 parents commit c4f1995bb5f1ed488a76456eeb7947d37cde947c
Showing with 623 additions and 0 deletions.
  1. +6 โˆ’0 .gitignore
  2. +32 โˆ’0 setup.py
  3. +35 โˆ’0 tests/base.py
  4. +104 โˆ’0 tests/test_hook.py
  5. +111 โˆ’0 tests/test_oauth.py
  6. +41 โˆ’0 webauth/README.markdown
  7. +10 โˆ’0 webauth/__init__.py
  8. +141 โˆ’0 webauth/hook.py
  9. +143 โˆ’0 webauth/oauth.py
@@ -0,0 +1,6 @@
+build/*
+dist/*
+*.egg-info
+*.pyc
+*.un~
+.coverage
@@ -0,0 +1,32 @@
+import os
+import sys
+import webauth
+
+from setuptools import setup, find_packages
+
+if sys.argv[-1] == 'test':
+ os.system('nosetests --with-coverage --cover-package=webauth')
+ sys.exit()
+
+setup(
+ name='webauth',
+ version=webauth.__version__,
+ description='A Python Requests hook providing OAuth 1.0/a support.',
+ long_description=open('README.markdown'),
+ author='Max Countryman', # this is just a stand-in don't know what's preferred
+ author_email='max@litl.com', # ditto
+ url='https://github.com/litl/webauth',
+ packages=find_packages(),
+ install_requires=['requests>=0.10.0'],
+ license='BSD', # i don't know what litl will prefer for this
+ classifiers=(
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'Programming Language :: Python',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ ),
+ zip_safe=False,
+)
@@ -0,0 +1,35 @@
+'''
+ webauth.test_hook
+ -----------------
+
+ Test suite for webauth.hook.
+'''
+
+import unittest
+
+from mock import Mock
+
+
+class WebauthTestCase(unittest.TestCase):
+ def setUp(self):
+ # mock request object
+ request = Mock()
+ request.method = 'GET'
+ request.url = 'http://example.com/'
+ request.headers = {}
+ request.params = {}
+ request.data = {}
+ request.data_and_params = {}
+ self.request = request
+
+ # mock consumer object
+ consumer = Mock()
+ consumer.key = '123'
+ consumer.secret = '456'
+ self.consumer = consumer
+
+ # mock token object
+ token = Mock()
+ token.key = '321'
+ token.secret = '456'
+ self.token = token
@@ -0,0 +1,104 @@
+'''
+ webauth.test_hook
+ -----------------
+
+ Test suite for webauth.hook.
+'''
+
+from base import WebauthTestCase
+from webauth.hook import OAuthHook
+
+
+class OAuthHookTestCase(WebauthTestCase):
+ def test_intialize_oauthhook(self):
+ # without token
+ oauth = OAuthHook('123', '345')
+ self.assertTrue(hasattr(oauth, 'consumer'))
+
+ # with token
+ oauth = OAuthHook('123', '345', '321', '654')
+ self.assertTrue(hasattr(oauth, 'consumer'))
+ self.assertTrue(oauth.token is not None)
+
+ def test_oauth_header_auth(self):
+ oauth = OAuthHook('123', '345', header_auth=True)
+ self.assertTrue(oauth.header_auth)
+ oauth(self.request)
+ auth_header = self.request.headers['Authorization']
+ self.assertTrue(auth_header is not None)
+ self.assertTrue('oauth_timestamp' in auth_header)
+ self.assertTrue('oauth_consumer_key="123"' in auth_header)
+ self.assertTrue('oauth_nonce' in auth_header)
+ self.assertTrue('oauth_version="1.0"' in auth_header)
+ self.assertTrue('oauth_signature_method="HMAC-SHA1"' in auth_header)
+
+ def test_oauth_post(self):
+ oauth = OAuthHook('123', '345')
+
+ # call the instance (this would be a POST)
+ self.request.method = 'POST'
+ oauth(self.request)
+ self.assertTrue('oauth_timestamp' in self.request.data)
+ self.assertEqual('123', self.request.data['oauth_consumer_key'])
+ self.assertTrue('oauth_nonce' in self.request.data)
+ self.assertTrue('oauth_version' in self.request.data)
+ self.assertEqual('1.0', self.request.data['oauth_version'])
+ self.assertTrue('oauth_signature_method' in self.request.data)
+ self.assertEqual('HMAC-SHA1',
+ self.request.data['oauth_signature_method'])
+
+ def test_oauth_get(self):
+ oauth = OAuthHook('123', '345')
+
+ # call the instance (this would be a GET)
+ oauth(self.request)
+ self.assertTrue('oauth_timestamp' in self.request.url)
+ self.assertTrue('oauth_consumer_key' in self.request.url)
+ self.assertTrue('oauth_nonce' in self.request.url)
+ self.assertTrue('oauth_version=1.0' in self.request.url)
+ self.assertTrue('oauth_signature_method=HMAC-SHA1' in self.request.url)
+
+ def test_oauth_callback(self):
+ oauth = OAuthHook('123', '345')
+
+ self.request.params = {'oauth_callback': 'http://example.com/callback'}
+ oauth(self.request)
+ oauth_callback = self.request.oauth_params['oauth_callback']
+ self.assertEqual('http://example.com/callback', oauth_callback)
+
+ self.request.data = {'oauth_callback': 'http://example.com/callback'}
+ oauth(self.request)
+ oauth_callback = self.request.oauth_params['oauth_callback']
+ self.assertEqual('http://example.com/callback', oauth_callback)
+
+ def test_oauth_with_token(self):
+ oauth = OAuthHook('123', '345', '321', '654')
+ oauth(self.request)
+ self.assertTrue(oauth.token.key is not None)
+ self.assertTrue('oauth_token' in self.request.url)
+ self.assertEqual('321', self.request.oauth_params['oauth_token'])
+ self.assertTrue('oauth_verifier' in self.request.url)
+ self.assertEqual('', self.request.oauth_params['oauth_verifier'])
+
+ # test with a verifier
+ oauth.token.verifier = '4242'
+ oauth(self.request)
+ self.assertEqual('4242', self.request.oauth_params['oauth_verifier'])
+
+ def test_unique_nonce(self):
+ oauth = OAuthHook('123', '345')
+ oauth(self.request)
+ first_nonce = self.request.oauth_params['oauth_nonce']
+ oauth(self.request)
+ second_nonce = self.request.oauth_params['oauth_nonce']
+ self.assertTrue(first_nonce != second_nonce)
+
+ def test_params_or_data_as_lists(self):
+ oauth = OAuthHook('123', '345')
+ self.request.params = [('foo', 'bar')]
+ self.request.data = [('foo', 'bar')]
+ self.assertTrue(isinstance(self.request.params, list))
+ self.assertTrue(isinstance(self.request.params, list))
+ oauth(self.request)
+ self.assertTrue(isinstance(self.request.params, dict))
+ self.assertTrue(isinstance(self.request.data, dict))
@@ -0,0 +1,111 @@
+'''
+ webauth.test_oauth
+ ------------------
+
+ Test suite for webauth.oauth.
+'''
+
+from base import WebauthTestCase
+from webauth.oauth import HmacSha1Signature
+
+from urllib import urlencode
+
+
+class OAuthTestCase(WebauthTestCase):
+ def test_hamcsha1_signature(self):
+ self.request.params = {'foo': 'bar'}
+ HmacSha1Signature().sign(self.request, self.consumer, self.token)
+ oauth_signature = self.request.data_and_params['oauth_signature']
+ self.assertTrue(oauth_signature is not None)
+
+ def test_normalize_request_parameters_params(self):
+ # params as a dict
+ self.request.params = {'foo': 'bar'}
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo=bar', normalized)
+
+ # params as a dict with URL encodable chars
+ self.request.data_and_params = {}
+ self.request.params = {'foo+bar': 'baz'}
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo%2Bbar=baz', normalized)
+ self.assertTrue('+' not in normalized)
+
+ # params as a string
+ self.request.data_and_params = {}
+ self.request.params = urlencode({'foo': 'bar'})
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo=bar', normalized)
+
+ # params as a string with URL encodable chars
+ self.request.data_and_params = {}
+ self.request.params = urlencode({'foo+bar': 'baz'})
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo%2Bbar=baz', normalized)
+ self.assertTrue('+' not in normalized)
+
+ # params and dict as dicts
+ self.request.data_and_params = {}
+ self.request.params = {'a': 'b'}
+ self.request.data = {'foo': 'bar'}
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('a=b&foo=bar', normalized)
+
+ def test_normalize_request_parameters_data(self):
+ # data as a dict
+ self.request.data = {'foo': 'bar'}
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo=bar', normalized)
+
+ # data as a dict with URL encodable chars
+ self.request.data_and_params = {}
+ self.request.data = {'foo+bar': 'baz'}
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo%2Bbar=baz', normalized)
+ self.assertTrue('+' not in normalized)
+
+ # data as a string with URL encodable chars
+ self.request.data = urlencode({'foo+bar': 'baz'})
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('foo%2Bbar=baz', normalized)
+ self.assertTrue('+' not in normalized)
+
+ def test_normalize_request_parameters_both_string(self):
+ # params and data both as a string
+ self.request.params = urlencode({'a': 'b'})
+ self.request.data = urlencode({'foo': 'bar'})
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ # this also demonstrates sorting
+ self.assertEqual('a=b&foo=bar', normalized)
+
+ def test_normalize_request_parameters_params_string(self):
+ # params is a string but data is a dict
+ self.request.params = urlencode({'a': 'b'})
+ self.request.data = {'foo': 'bar'}
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('a=b&foo=bar', normalized)
+
+ def test_normalize_request_parameters_data_string(self):
+ # params is a dict but data is a string
+ self.request.params = {'a': 'b'}
+ self.request.data = urlencode({'foo': 'bar'})
+ normalized = \
+ HmacSha1Signature()._normalize_request_parameters(self.request)
+ self.assertEqual('a=b&foo=bar', normalized)
+
+ def test_utf8_encoded_string(self):
+ # in the event a string is already UTF-8
+ self.request.params = {u'foo': u'bar'}
+ self.request.url = u'http://example.com/'
+ HmacSha1Signature().sign(self.request, self.consumer)
+ self.assertEqual({'foo': 'bar'}, self.request.params)
@@ -0,0 +1,41 @@
+# Webauth: OAuth 1.0/a for Python
+
+Webauth is a package providing OAuth 1.0/a consumer support. The package is
+written as a hook over the superb Python Requests package.
+
+
+## Installation
+
+Install the package with one of the following commands:
+
+ $ python setup.py install
+
+or
+
+ $ pip install webauth (not yet!)
+
+
+## Usage
+
+Using the package is quite simple. Ensure that Python Requests is installed.
+Import the relavent module and start utilizing OAuth endpoints!
+
+ from webauth import OAuthHook
+ import requests
+
+ # setup the OAuth Hook
+ oauth = OAuthHook(consumer_key='123', consumer_secret='456')
+ # attach it to a pre-request hook
+ oauth_requests = requests.session(hooks={'prehook': oauth})
+
+ # begin by getting a request token
+ oauth_requests.get('http://example.com/request_token').content
+
+Once the request token is acquired you'll want to update the OAuth Hook and
+request session accordingly, providing the `token` and `token_key` parameters
+to `OAuthHook`.
+
+
+## Documentation
+
+The Sphinx-compiled documentation is available here: (not yet!)
@@ -0,0 +1,10 @@
+''''
+ webauth
+ -------
+
+ OAuth 1.0/a wrapped around Python Requests.
+'''
+
+from webauth.hook import OAuthHook
+
+__version__ = 0.1
Oops, something went wrong.

0 comments on commit c4f1995

Please sign in to comment.