diff --git a/.gitignore b/.gitignore index 74df2303..4d0ab5f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.py? *.egg-info *.swp +.env diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..8802067f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: python + +python: + - "2.6" + - "2.7" + + +script: + python -m tests.test_oauth + diff --git a/Makefile b/Makefile deleted file mode 100644 index 57472bd1..00000000 --- a/Makefile +++ /dev/null @@ -1,155 +0,0 @@ -PYTHON = $(shell test -x bin/python && echo bin/python || \ - echo `which python`) -PYVERS = $(shell $(PYTHON) -c 'import sys; print "%s.%s" % sys.version_info[0:2]') -VIRTUALENV = $(shell /bin/echo -n `which virtualenv || \ - which virtualenv-$(PYVERS) || \ - which virtualenv$(PYVERS)`) -VIRTUALENV += --no-site-packages -PAGER ?= less -DEPS := $(shell find $(PWD)/deps -type f -printf "file://%p ") -COVERAGE = $(shell test -x bin/coverage && echo bin/coverage || echo true) -SETUP = $(PYTHON) ./setup.py -EZ_INSTALL = $(SETUP) easy_install -f "$(DEPS)" -PYLINT = bin/pylint -PLATFORM = $(shell $(PYTHON) -c "from pkg_resources import get_build_platform; print get_build_platform()") -OS := $(shell uname) -EGG := $(shell $(SETUP) --fullname)-py$(PYVERS).egg -SDIST := $(shell $(SETUP) --fullname).tar.gs -SRCDIR := oauth2 -SOURCES := $(shell find $(SRCDIR) -type f -name \*.py -not -name 'test_*') -TESTS := $(shell find $(SRCDIR) -type f -name test_\*.py) -COVERED := $(SOURCES) -ROOT = $(shell pwd) -ROOTCMD = fakeroot -SIGN_KEY ?= nerds@simplegeo.com -BUILD_NUMBER ?= 1 - - -.PHONY: test dev clean extraclean debian/changelog - -all: egg -egg: dist/$(EGG) - -dist/$(EGG): - $(SETUP) bdist_egg - -sdist: - $(SETUP) sdist - -debian/changelog: - -git branch -D changelog - git checkout -b changelog - git-dch -a -N $(shell $(SETUP) --version) --debian-branch changelog \ - --snapshot --snapshot-number=$(BUILD_NUMBER) - -deb: debian/changelog - test -d dist/deb || mkdir -p dist/deb - dpkg-buildpackage -r$(ROOTCMD) -k$(SIGN_KEY) - mv ../python-oauth2_* dist/deb - -test: - $(SETUP) test --with-coverage --cover-package=oauth2 - -sdist: - python setup.py sdist - -xunit.xml: bin/nosetests $(SOURCES) $(TESTS) - $(SETUP) test --with-xunit --xunit-file=$@ - -bin/nosetests: bin/easy_install - @$(EZ_INSTALL) nose - -coverage: .coverage - @$(COVERAGE) html -d $@ $(COVERED) - -coverage.xml: .coverage - @$(COVERAGE) xml $(COVERED) - -.coverage: $(SOURCES) $(TESTS) bin/coverage bin/nosetests - -@$(COVERAGE) run $(SETUP) test - -bin/coverage: bin/easy_install - @$(EZ_INSTALL) coverage - -profile: .profile bin/pyprof2html - bin/pyprof2html -o $@ $< - -.profile: $(SOURCES) bin/nosetests - -$(SETUP) test -q --with-profile --profile-stats-file=$@ - -bin/pyprof2html: bin/easy_install bin/ - @$(EZ_INSTALL) pyprof2html - -docs: $(SOURCES) bin/epydoc - @echo bin/epydoc -q --html --no-frames -o $@ ... - @bin/epydoc -q --html --no-frames -o $@ $(SOURCES) - -bin/epydoc: bin/easy_install - @$(EZ_INSTALL) epydoc - -bin/pep8: bin/easy_install - @$(EZ_INSTALL) pep8 - -pep8: bin/pep8 - @bin/pep8 --repeat --ignore E225 $(SRCDIR) - -pep8.txt: bin/pep8 - @bin/pep8 --repeat --ignore E225 $(SRCDIR) > $@ - -lint: bin/pylint - -$(PYLINT) -f colorized $(SRCDIR) - -lint.html: bin/pylint - -$(PYLINT) -f html $(SRCDIR) > $@ - -lint.txt: bin/pylint - -$(PYLINT) -f parseable $(SRCDIR) > $@ - -bin/pylint: bin/easy_install - @$(EZ_INSTALL) pylint - -README.html: README.mkd | bin/markdown - bin/markdown -e utf-8 $^ -f $@ - -bin/markdown: bin/easy_install - @$(EZ_INSTALL) Markdown - - -# Development setup -rtfm: - $(PAGER) README.mkd - -tags: TAGS.gz - -TAGS.gz: TAGS - gzip $^ - -TAGS: $(SOURCES) - ctags -eR . - -env: bin/easy_install - -bin/easy_install: - $(VIRTUALENV) . - -test -f deps/setuptools* && $@ -U deps/setuptools* - -dev: develop -develop: env - nice -n 20 $(SETUP) develop - @echo " ---------------------------------------------" - @echo " To activate the development environment, run:" - @echo " . bin/activate" - @echo " ---------------------------------------------" - -clean: -clean: - find . -type f -name \*.pyc -exec rm {} \; - rm -rf build dist TAGS TAGS.gz digg.egg-info tmp .coverage \ - coverage coverage.xml docs lint.html lint.txt profile \ - .profile *.egg xunit.xml - @if test "$(OS)" = "Linux"; then $(ROOTCMD) debian/rules clean; fi - - -xclean: extraclean -extraclean: clean - rm -rf bin lib .Python include diff --git a/README.md b/README.md index 3dca1e34..e8b94114 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,21 @@ +python-oauth2 +============= + +# Forked from simplegeo/python-oauth2 +Seeing as they do not seem to be maintaining the repository anymore + + +Master +[![Build Status](https://secure.travis-ci.org/knowsis/python-oauth2.png?branch=master)](http://travis-ci.org/knowsis/python-oauth2) + +Develop +[![Build Status](https://secure.travis-ci.org/knowsis/python-oauth2.png?branch=develop)](http://travis-ci.org/knowsis/python-oauth2) + + + # Overview -This code was originally forked from [Leah Culver and Andy Smith's oauth.py code](http://github.com/leah/python-oauth/). Some of the tests come from a [fork by Vic Fryzel](http://github.com/shellsage/python-oauth), while a revamped Request class and more tests were merged in from [Mark Paschal's fork](http://github.com/markpasc/python-oauth). A number of notable differences exist between this code and its forefathers: +The original repositories code was originally forked from [Leah Culver and Andy Smith's oauth.py code](http://github.com/leah/python-oauth/). Some of the tests come from a [fork by Vic Fryzel](http://github.com/shellsage/python-oauth), while a revamped Request class and more tests were merged in from [Mark Paschal's fork](http://github.com/markpasc/python-oauth). A number of notable differences exist between this code and its forefathers: * 100% unit test coverage. * The DataStore object has been completely ripped out. While creating unit tests for the library I found several substantial bugs with the implementation and confirmed with Andy Smith that it was never fully baked. diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 7a462a73..00000000 --- a/debian/changelog +++ /dev/null @@ -1,408 +0,0 @@ -python-oauth2 (1.5.211) maverick; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Tue, 13 Dec 2011 17:39:07 +0000 - -python-oauth2 (1.5.210) maverick; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Fri, 09 Dec 2011 01:17:31 +0000 - -python-oauth2 (1.5.170) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Mon, 02 May 2011 23:48:16 +0000 - -python-oauth2 (1.5.169) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Fri, 15 Apr 2011 21:29:41 +0000 - -python-oauth2 (1.5.168) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Tue, 05 Apr 2011 23:13:18 +0000 - -python-oauth2 (1.5.167) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Thu, 17 Feb 2011 21:56:49 +0000 - -python-oauth2 (1.5.166) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * fix encoding of non-ascii data into postdata, really fixes #48 this - time (comes with test) - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Tue, 15 Feb 2011 17:23:00 +0000 - -python-oauth2 (1.5.165) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * get_normalized_parameters() is required to exclude any - oauth_signature that was already there, and it is required to - preserve duplicate keys, even with identical values ref #46, fixes - pull/49, thanks @zyegfryed - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 07 Feb 2011 19:24:56 +0000 - -python-oauth2 (1.5.164) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * make it actually inspect the request, and fix the test to require - the right things of the request ref #46, ref pull/49, thanks - @zyegfryed - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 07 Feb 2011 18:53:56 +0000 - -python-oauth2 (1.5.163) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * add test of #46; fixes #46 - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Fri, 04 Feb 2011 18:14:56 +0000 - -python-oauth2 (1.5.162) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * import parse_qs from cgi if it can't be imported from urlparse, thus - regaining compatibility with Python 2.5 fixes #47 thanks to @vtsao, - @subsume, @worksology - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Fri, 04 Feb 2011 17:50:56 +0000 - -python-oauth2 (1.5.161) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * Include all parameters from URL, even ones that begin with "oauth_", - in signature base. effectively reverts - https://github.com/simplegeo/python- - oauth2/commit/50ca9578f598faff5427e58814e2f45d01d3261c fixes #27 - Thanks to @robhudson for the bug report and help debugging. - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Thu, 03 Feb 2011 18:03:59 +0000 - -python-oauth2 (1.5.160) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * add another unicode test case to the tests just to show to user - saevarom on github - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Thu, 03 Feb 2011 00:01:55 +0000 - -python-oauth2 (1.5.159) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Thu, 03 Feb 2011 00:00:04 +0000 - -python-oauth2 (1.5.158) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * keep empty params parsed from the URL (fixes #22) - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Wed, 02 Feb 2011 19:34:25 +0000 - -python-oauth2 (1.5.155) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * use multiple values under the same key from the body (fixes #23) - Thanks to rogerm, ideasculptor, jiivan, timgraham. - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Tue, 01 Feb 2011 23:43:56 +0000 - -python-oauth2 (1.5.154) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Tue, 01 Feb 2011 18:03:58 +0000 - -python-oauth2 (1.5.153) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * add work-around for bug unicode-handling in urlparse in Python < - 2.7, including tests - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Tue, 01 Feb 2011 16:31:56 +0000 - -python-oauth2 (1.5.152) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * another test for handling of non-ascii, non-utf-8 urls - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Fri, 28 Jan 2011 18:14:34 +0000 - -python-oauth2 (1.5.151) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Thu, 27 Jan 2011 05:31:55 +0000 - -python-oauth2 (1.5.150) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Wed, 26 Jan 2011 17:15:25 +0000 - -python-oauth2 (1.5.149) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * add the body-hash header as specified in - http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth- - bodyhash.html - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Wed, 26 Jan 2011 17:11:34 +0000 - -python-oauth2 (1.5.148) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * default body is the empty string rather than None; add the Realm - header - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Wed, 26 Jan 2011 17:02:34 +0000 - -python-oauth2 (1.5.147) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * pass the body and the is_form_encoding flag in to the Request object - (for future use in implementing the hash-of-body extension) - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Tue, 25 Jan 2011 17:39:34 +0000 - -python-oauth2 (1.5.146) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * refactor internals of the way Client.request() decides whether this - is a x-www-form-urlencoded request or not - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Tue, 25 Jan 2011 17:30:38 +0000 - -python-oauth2 (1.5.145) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * update version number from 1.4 to 1.5 - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 24 Jan 2011 22:08:36 +0000 - -python-oauth2 (1.4.144) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * more thorough unit tests for non-ascii urls, params, and query-args- - in-url - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 24 Jan 2011 22:02:34 +0000 - -python-oauth2 (1.4.143) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * use two-part version number -- version is manually modified, build- - number is automatically modified - - [ Simple Geebus ] - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 24 Jan 2011 20:21:20 +0000 - -python-oauth2 (1.4.134) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Mon, 24 Jan 2011 18:30:58 +0000 - -python-oauth2 (1.4.133) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * handle unicode objects and utf-8 strings in url and params and - encode them to utf-8 when serializing - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 24 Jan 2011 18:25:54 +0000 - -python-oauth2 (1.4.132) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Mon, 24 Jan 2011 17:39:52 +0000 - -python-oauth2 (1.4.131) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Mon, 24 Jan 2011 17:32:18 +0000 - -python-oauth2 (1.4.130) lucid; urgency=low - - * UNRELEASED - - -- SimpleGeo Nerds Mon, 24 Jan 2011 17:22:46 +0000 - -python-oauth2 (1.4.129) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * change manually-managed version number from 1.3 to 1.4 - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Fri, 21 Jan 2011 19:52:32 +0000 - -python-oauth2 (1.3.128) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * raise an exception if the URL passed in is not a unicode object nor - ascii We can't submit a correct URL with arbitrary bytes -- we have - to submit a utf-8 encoded unicode string. (Otherwise we'll cause - either a rejection or a signature mismatch in the server, which is - what has happened at SimpleGeo.) If the caller passes in non-ascii - things in a str then it would be better for them to change their - code to decode it to unicode before passing it in than for us to - decode it, since they have a better chance of knowing what encoding - it is in -- if we did it we would be guessing. - * fix flaws pointed out by ieure, plus test failures I'm not entirely - sure it is appropriate to allow .url and .normalized_url to be non- - existent in addition to allowing them to be None, but I don't really - understand the intent of the url setter. - * Oh, after we've made sure it can be converted to unicode, just leave - it as a unicode object after that. - * raise more specific error message if argument to to_unicode() is - neither unicode nor str - * a couple of cleanups suggested by ieure in code review - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Mon, 10 Jan 2011 22:42:35 +0000 - -python-oauth2 (1.3.127) lucid; urgency=low - - [ Zooko Ofsimplegeo ] - * run tests when building - * raise exception from a test just to see if hudson is *really* - running these tests. I don't see the test results. - * put version number in a file where it can be read and written by - various things (including hudson) - * make oauth2.__version__ exist, rename VERSION to OAUTH_VERSION for - clarity - * debian/control -- build-dep pyflakes - * fix pyflakes - * build-dep requires python-coverage - * switch from nosetests to the builtin test runner Just because it - doesn't seem to currently use any feature of nosetest and this way - we can reduce the dependencies by one. We'll feel free to switch it - back to using nosetests (and add the dep to debian/control this - time) if we want to use some extra feature of nose. - * remove test failure which was inserted just to see if hudson was - running the tests properly - * Fix bug inserted by pyflakes inspired cleanup earlier -- it turns - out that _get_version() wasn't dead code but was having a necessary - side-effect. Add new method named _check_version() to be clearer - about what it does compared to _get_version() - * port tests from mox to mock because they were failing and I don't - understand mox. now they are working. add mock to the python and - debian deps. remove apparently left-over line of code that runs - "sign()" at the end of checking a signature - - [ SimpleGeo Nerds ] - - -- SimpleGeo Nerds Tue, 04 Jan 2011 19:39:34 +0000 - -python-oauth2 (1.2.1) lucid; urgency=low - - [ Joe Stump ] - * Fixed a minor spelling error, added tests for - oauth2.Error.__str__(), and added a test for build_xoauth_string(). - * Added a 'make test' command to the Makefile. - * Added a bunch of new tests. 100% coverage has lapsed a bit. Fixing - now. - - [ Ian Eure ] - * Update deb rule in makefile to sign packages and move them to - dist/deb. - - [ Joe Stump ] - * Implemented a 'fix' for a bug in certain OAuth providers. - http://bit.ly/aUrH43 - - [ Ian Eure ] - * Update packaging. - * Fix version disparity. - - [ coulix ] - * get normalised parameters should not take into account oauth_ params - - [ Mathias Herberts ] - * Modified get_normalized_parameters so it does not encode '~' for - full conformance with RFC 5849 section 3.6 - - [ Peter Bengtsson ] - * made it python 2.4 compatible - - [ Roderic Campbell ] - * tok != token. con != consumer. May be confusing for people not - actually reading the code. - - [ Ian Eure ] - - -- Ian Eure Mon, 28 Jun 2010 12:02:02 -0700 - -python-oauth2 (1.2.1pre2) unstable; urgency=low - - * Fix version disparity between setup.py & debian/changelog. - - -- Ian Eure Fri, 11 Jun 2010 16:11:41 -0700 - -python-oauth2 (1.2.1pre1) unstable; urgency=low - - * Make a native package. - * Increment version. - * Make debian/rules executable. - * Update standards-version, maintainers. - * Remvoe unneeded python-central build dependency. - - -- Ian Eure Fri, 11 Jun 2010 16:09:01 -0700 - -python-oauth2 (1.0.0-1simplegeo01) karmic; urgency=low - - * Initial build for SimpleGeo - - -- SimpleGeo Nerds Wed, 21 Oct 2009 23:24:00 -0700 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7ed6ff82..00000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/debian/control b/debian/control deleted file mode 100644 index de0d42fa..00000000 --- a/debian/control +++ /dev/null @@ -1,24 +0,0 @@ -Source: python-oauth2 -Section: python -Priority: optional -Maintainer: SimpleGeo Nerds -Uploaders: Chris Lea , Ian Eure -Standards-Version: 3.8.4 -XS-Python-Version: all -Build-Depends: debhelper (>= 4.1.13), cdbs (>= 0.4.49), python, python-setuptools, python-support, pyflakes, python-coverage (>= 2.85), python-mock -Homepage: http://github.com/simplegeo/python-oauth2 - -Package: python-oauth2 -Architecture: all -XB-Python-Version: ${python:Versions} -Depends: ${python:Depends}, python-httplib2 -Provides: ${python:Provides} -Suggests: -Description: A Python OAuth class with several useful - features. - . - * 100% unit test coverage. - * The Request class now extends from dict. - * The Client class works and extends from httplib2. - It's a thin wrapper that handles automatically signing - any normal HTTP request you might wish to make. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 8f5e8bda..00000000 --- a/debian/copyright +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2007 Leah Culver - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/debian/pycompat b/debian/pycompat deleted file mode 100644 index 0cfbf088..00000000 --- a/debian/pycompat +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/debian/pyversions b/debian/pyversions deleted file mode 100644 index b3dc41eb..00000000 --- a/debian/pyversions +++ /dev/null @@ -1 +0,0 @@ -2.5- diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 4608bb84..00000000 --- a/debian/rules +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/make -f -# -*- mode: makefile; coding: utf-8 -*- - -DEB_PYTHON_SYSTEM = pysupport - -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/python-distutils.mk - -build/python-oauth2:: - pyflakes oauth2 - python-coverage run --branch --include=oauth2/* setup.py test - python-coverage html -d $(ARTIFACTS)/htmlcov diff --git a/oauth2/__init__.py b/oauth2/__init__.py index 835270e3..f1dd3699 100644 --- a/oauth2/__init__.py +++ b/oauth2/__init__.py @@ -470,11 +470,13 @@ def get_normalized_parameters(self): query = urlparse.urlparse(self.url)[4] url_items = self._split_url_string(query).items() - url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ] + url_items = [(to_utf8(k), to_utf8_optional_iterator(v)) for k, v in url_items if k != 'oauth_signature' ] items.extend(url_items) items.sort() - encoded_str = urllib.urlencode(items) + + encoded_str = urllib.urlencode(items, True) + # Encode signature parameters per Oauth Core 1.0 protocol # spec draft 7, section 3.6 # (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6) @@ -485,11 +487,6 @@ def sign_request(self, signature_method, consumer, token): """Set the signature parameter to the result of sign.""" if not self.is_form_encoded: - # according to - # http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html - # section 4.1.1 "OAuth Consumers MUST NOT include an - # oauth_body_hash parameter on requests with form-encoded - # request bodies." self['oauth_body_hash'] = base64.b64encode(sha(self.body).digest()) if 'oauth_consumer_key' not in self: @@ -500,24 +497,25 @@ def sign_request(self, signature_method, consumer, token): self['oauth_signature_method'] = signature_method.name self['oauth_signature'] = signature_method.sign(self, consumer, token) - + @classmethod def make_timestamp(cls): """Get seconds since epoch (UTC).""" return str(int(time.time())) - + @classmethod def make_nonce(cls): """Generate pseudorandom number.""" return str(random.randint(0, 100000000)) - + @classmethod def from_request(cls, http_method, http_url, headers=None, parameters=None, query_string=None): """Combines multiple parameter sources.""" + if parameters is None: parameters = {} - + # Headers if headers and 'Authorization' in headers: auth_header = headers['Authorization'] @@ -531,22 +529,25 @@ def from_request(cls, http_method, http_url, headers=None, parameters=None, except: raise Error('Unable to parse OAuth parameters from ' 'Authorization header.') - + # GET or POST query string. if query_string: query_params = cls._split_url_string(query_string) parameters.update(query_params) - + # URL parameters. param_str = urlparse.urlparse(http_url)[4] # query url_params = cls._split_url_string(param_str) parameters.update(url_params) - + + res = urlparse.urlparse(http_url) + url = urlparse.urlunparse((res[0],res[1],res[2],'','','')) + if parameters: - return cls(http_method, http_url, parameters) - + return cls(http_method, url, parameters) + return None - + @classmethod def from_consumer_and_token(cls, consumer, token=None, http_method=HTTP_METHOD, http_url=None, parameters=None, @@ -560,7 +561,7 @@ def from_consumer_and_token(cls, consumer, token=None, 'oauth_nonce': cls.make_nonce(), 'oauth_version': cls.version, } - + defaults.update(parameters) parameters = defaults @@ -568,24 +569,24 @@ def from_consumer_and_token(cls, consumer, token=None, parameters['oauth_token'] = token.key if token.verifier: parameters['oauth_verifier'] = token.verifier - + return Request(http_method, http_url, parameters, body=body, is_form_encoded=is_form_encoded) - + @classmethod def from_token_and_callback(cls, token, callback=None, http_method=HTTP_METHOD, http_url=None, parameters=None): if not parameters: parameters = {} - + parameters['oauth_token'] = token.key - + if callback: parameters['oauth_callback'] = callback - + return cls(http_method, http_url, parameters) - + @staticmethod def _split_header(header): """Turn Authorization: header into parameters.""" @@ -602,13 +603,16 @@ def _split_header(header): # Remove quotes and unescape the value. params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\"')) return params - + @staticmethod def _split_url_string(param_str): """Turn URL string into parameters.""" parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True) for k, v in parameters.iteritems(): - parameters[k] = urllib.unquote(v[0]) + if len(v) == 1: + parameters[k] = urllib.unquote(v[0]) + else: + parameters[k] = sorted([urllib.unquote(s) for s in v]) return parameters diff --git a/oauth2/_version.py b/oauth2/_version.py index 9d779eaa..e1ba5cdc 100644 --- a/oauth2/_version.py +++ b/oauth2/_version.py @@ -1,11 +1,9 @@ # This is the version of this source code. -manual_verstr = "1.5" +manual_verstr = "1.7" - -auto_build_num = "211" - +auto_build_num = "212" verstr = manual_verstr + "." + auto_build_num diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..09c3c031 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +httplib2 +coverage +mock diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index acc41e17..f9c61c06 --- a/setup.py +++ b/setup.py @@ -27,11 +27,11 @@ setup(name=PKG, version=verstr, - description="library for OAuth version 1.0", - author="Joe Stump", - author_email="joe@simplegeo.com", - url="http://github.com/simplegeo/python-oauth2", - packages = find_packages(), + description="library for OAuth version 2.0", + author="Joe Stump/Mark Unsworth", + author_email="mark@knows.is", + url="http://github.com/knowsis/python-oauth2", + packages = find_packages(exclude=["tests"]), install_requires = ['httplib2'], license = "MIT License", keywords="oauth", diff --git a/tests/test_oauth.py b/tests/test_oauth.py index 099e5794..7a7e35e7 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# coding=utf-8 """ The MIT License @@ -33,6 +33,7 @@ import urlparse from types import ListType import mock +from mock import patch import httplib2 # Fix for python2.5 compatibility @@ -49,19 +50,19 @@ class TestError(unittest.TestCase): def test_message(self): try: raise oauth.Error - except oauth.Error, e: + except oauth.Error as e: self.assertEqual(e.message, 'OAuth error occurred.') msg = 'OMG THINGS BROKE!!!!' try: raise oauth.Error(msg) - except oauth.Error, e: + except oauth.Error as e: self.assertEqual(e.message, msg) def test_str(self): try: raise oauth.Error - except oauth.Error, e: + except oauth.Error as e: self.assertEquals(str(e), 'OAuth error occurred.') class TestGenerateFunctions(unittest.TestCase): @@ -506,6 +507,7 @@ def test_signature_base_string_nonascii_nonutf8(self): url = u'http://api.simplegeo.com:80/1.0/places/address.json?q=monkeys&category=animal&address=41+Decatur+St,+San+Francisc\u2766,+CA' req = oauth.Request("GET", url) + req.version ="2.0" self.failUnlessReallyEqual(req.normalized_url, u'http://api.simplegeo.com/1.0/places/address.json') req.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None) self.failUnlessReallyEqual(req['oauth_signature'], 'WhufgeZKyYpKsI70GZaiDaYwl6g=') @@ -574,6 +576,19 @@ def test_get_normalized_parameters_duplicate(self): self.assertEquals(expected, res) + def test_get_normalized_parameters_multiple(self): + + url = "http://example.com/v2/search/videos?oauth_nonce=79815175&oauth_timestamp=1295397962&oauth_consumer_key=mykey&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&offset=10&oauth_signature=spWLI%2FGQjid7sQVd5%2FarahRxzJg%3D&tag=one&tag=two" + expected='oauth_consumer_key=mykey&oauth_nonce=79815175&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1295397962&oauth_version=1.0&offset=10&tag=one&tag=two' + + req = oauth.Request("GET", url) + + res = req.get_normalized_parameters() + + self.assertEquals(expected, res) + + + def test_get_normalized_parameters_from_url(self): # example copied from # https://github.com/ciaranj/node-oauth/blob/master/tests/oauth.js @@ -888,6 +903,16 @@ def test_from_request(self): # Test that a boned from_request() call returns None req = oauth.Request.from_request("GET", url) self.assertEquals(None, req) + + + + # Test that a boned from_request() call returns None + url_with_qs = 'http://www.oauth.net?foo=1&bar=2' + + req = oauth.Request.from_request("GET", url_with_qs) + params = req.get_normalized_parameters() + self.assertEquals(params, 'bar=2&foo=1') + def test_from_token_and_callback(self): url = "http://sp.example.com/" @@ -1192,30 +1217,40 @@ class Blah(): self.fail("Client.__init__() accepted invalid Token.") except ValueError: pass - + def test_access_token_get(self): """Test getting an access token via GET.""" - client = oauth.Client(self.consumer, None) - resp, content = client.request(self._uri('request_token'), "GET") - - self.assertEquals(int(resp['status']), 200) + + with patch('httplib2.Http.request') as mockRequest: + + mockRequest.return_value = {'status':200},'' + client = oauth.Client(self.consumer, None) + resp, content = client.request(self._uri('request_token'), "GET") + self.assertEquals(int(resp['status']), 200) def test_access_token_post(self): - """Test getting an access token via POST.""" - client = oauth.Client(self.consumer, None) - resp, content = client.request(self._uri('request_token'), "POST") + """Test getting an access token via POST.""" - self.assertEquals(int(resp['status']), 200) + with patch('httplib2.Http.request') as mockRequest: + + mockRequest.return_value = {'status':200},'oauth_token=123&oauth_token_secret=abcd' + + client = oauth.Client(self.consumer, None) + resp, content = client.request(self._uri('request_token'), "POST") - res = dict(parse_qsl(content)) - self.assertTrue('oauth_token' in res) - self.assertTrue('oauth_token_secret' in res) + self.assertEquals(int(resp['status']), 200) + + res = dict(parse_qsl(content)) + self.assertTrue('oauth_token' in res) + self.assertTrue('oauth_token_secret' in res) def _two_legged(self, method): client = oauth.Client(self.consumer, None) - - return client.request(self._uri('two_legged'), method, - body=urllib.urlencode(self.body)) + with patch('httplib2.Http.request') as mockRequest: + + mockRequest.return_value = {'status':200},'' + return client.request(self._uri('two_legged'), method, + body=urllib.urlencode(self.body)) def test_two_legged_post(self): """A test of a two-legged OAuth POST request."""