[Python-modules-commits] [lazr.restfulclient] 01/03: Import lazr.restfulclient_0.13.5.orig.tar.gz
Colin Watson
cjwatson at moszumanska.debian.org
Mon Sep 4 16:11:44 UTC 2017
This is an automated email from the git hooks/post-receive script.
cjwatson pushed a commit to branch master
in repository lazr.restfulclient.
commit 5d6e593c5785b5f68b18359679a47a0f3e2c42de
Author: Colin Watson <cjwatson at debian.org>
Date: Mon Sep 4 16:41:13 2017 +0100
Import lazr.restfulclient_0.13.5.orig.tar.gz
---
PKG-INFO | 13 +-
setup.py | 1 -
src/lazr.restfulclient.egg-info/PKG-INFO | 13 +-
src/lazr.restfulclient.egg-info/SOURCES.txt | 1 +
src/lazr.restfulclient.egg-info/pbr.json | 1 +
src/lazr/authentication/NEWS.txt | 19 --
src/lazr/authentication/README.txt | 304 ----------------------------
src/lazr/authentication/__init__.py | 22 --
src/lazr/authentication/docs/__init__.py | 16 --
src/lazr/authentication/testing/__init__.py | 0
src/lazr/authentication/testing/oauth.py | 59 ------
src/lazr/authentication/tests/__init__.py | 16 --
src/lazr/authentication/tests/test_docs.py | 52 -----
src/lazr/authentication/version.txt | 1 -
src/lazr/authentication/wsgi.py | 177 ----------------
src/lazr/restfulclient/NEWS.txt | 11 +
src/lazr/restfulclient/_browser.py | 9 +-
src/lazr/restfulclient/resource.py | 47 +++--
src/lazr/restfulclient/tests/test_docs.py | 1 -
src/lazr/restfulclient/tests/test_error.py | 9 +-
src/lazr/restfulclient/version.txt | 2 +-
21 files changed, 78 insertions(+), 696 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index 86007c5..400f633 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: lazr.restfulclient
-Version: 0.13.4
+Version: 0.13.5
Summary: A programmable client library that takes advantage of the commonalities among
Home-page: https://launchpad.net/lazr.restfulclient
Author: LAZR Developers
@@ -56,6 +56,17 @@ Description: ..
NEWS for lazr.restfulclient
===========================
+ 0.13.5 (2017-09-04)
+ ===================
+
+ - Fix bytes vs. unicode in json.loads calls. [bug=1403524]
+ - Decode header before comparison. [bug=1414075]
+ - Fix urllib unquote imports. [bug=1414055]
+ - Fix urllib urlencode imports. [bug=1425609]
+ - Tolerate httplib2 versions earlier than 0.9 again.
+ - Fix handling of 304 responses with an empty body on Python 3.
+ [bug=1714960]
+
0.13.4 (2014-12-05)
===================
diff --git a/setup.py b/setup.py
index 51fcb19..5e83578 100644
--- a/setup.py
+++ b/setup.py
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with lazr.restfulclient. If not, see <http://www.gnu.org/licenses/>.
-import sys
from setuptools import setup, find_packages
# generic helpers primarily for the long_description
diff --git a/src/lazr.restfulclient.egg-info/PKG-INFO b/src/lazr.restfulclient.egg-info/PKG-INFO
index 86007c5..400f633 100644
--- a/src/lazr.restfulclient.egg-info/PKG-INFO
+++ b/src/lazr.restfulclient.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: lazr.restfulclient
-Version: 0.13.4
+Version: 0.13.5
Summary: A programmable client library that takes advantage of the commonalities among
Home-page: https://launchpad.net/lazr.restfulclient
Author: LAZR Developers
@@ -56,6 +56,17 @@ Description: ..
NEWS for lazr.restfulclient
===========================
+ 0.13.5 (2017-09-04)
+ ===================
+
+ - Fix bytes vs. unicode in json.loads calls. [bug=1403524]
+ - Decode header before comparison. [bug=1414075]
+ - Fix urllib unquote imports. [bug=1414055]
+ - Fix urllib urlencode imports. [bug=1425609]
+ - Tolerate httplib2 versions earlier than 0.9 again.
+ - Fix handling of 304 responses with an empty body on Python 3.
+ [bug=1714960]
+
0.13.4 (2014-12-05)
===================
diff --git a/src/lazr.restfulclient.egg-info/SOURCES.txt b/src/lazr.restfulclient.egg-info/SOURCES.txt
index 3be566c..47f9e02 100644
--- a/src/lazr.restfulclient.egg-info/SOURCES.txt
+++ b/src/lazr.restfulclient.egg-info/SOURCES.txt
@@ -8,6 +8,7 @@ src/lazr.restfulclient.egg-info/SOURCES.txt
src/lazr.restfulclient.egg-info/dependency_links.txt
src/lazr.restfulclient.egg-info/namespace_packages.txt
src/lazr.restfulclient.egg-info/not-zip-safe
+src/lazr.restfulclient.egg-info/pbr.json
src/lazr.restfulclient.egg-info/requires.txt
src/lazr.restfulclient.egg-info/top_level.txt
src/lazr/restfulclient/NEWS.txt
diff --git a/src/lazr.restfulclient.egg-info/pbr.json b/src/lazr.restfulclient.egg-info/pbr.json
new file mode 100644
index 0000000..84721e4
--- /dev/null
+++ b/src/lazr.restfulclient.egg-info/pbr.json
@@ -0,0 +1 @@
+{"is_release": false, "git_version": "b278e66"}
\ No newline at end of file
diff --git a/src/lazr/authentication/NEWS.txt b/src/lazr/authentication/NEWS.txt
deleted file mode 100644
index f497c61..0000000
--- a/src/lazr/authentication/NEWS.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-============================
-NEWS for lazr.authentication
-============================
-
-0.1.2 (2010-02-09)
-==================
-
-- Fixed a bug that prevented middleware instances from stacking.
-
-0.1.1 (2009-10-19)
-==================
-
-- Fixed a bug that caused the OAuth middleware to specify the
- authentication realm as Basic.
-
-0.1.0 (2009-10-07)
-==================
-
-- Initial release
diff --git a/src/lazr/authentication/README.txt b/src/lazr/authentication/README.txt
deleted file mode 100644
index 69ea5fa..0000000
--- a/src/lazr/authentication/README.txt
+++ /dev/null
@@ -1,304 +0,0 @@
-..
- This file is part of lazr.authentication.
-
- lazr.authentication is free software: you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, version 3 of the License.
-
- lazr.authentication is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with lazr.authentication. If not, see <http://www.gnu.org/licenses/>.
-
-WSGI Middleware
-===============
-
-lazr.authentication defines some simple WSGI middleware for protecting
-resources with different kinds of HTTP authentication.
-
- >>> import lazr.authentication
- >>> print 'VERSION:', lazr.authentication.__version__
- VERSION: ...
-
-
-BasicAuthMiddleware
--------------------
-
-The BasicAuthMiddleware implements HTTP Basic Auth. Its constructor
-takes a number of arguments, including a callback function that
-performs the actual authentication. This function returns an object
-identifying the user who's trying to authenticate. If the
-authentication credentials are invalid, it's supposed to return None.
-
-First, let's create a really simple WSGI application that responds to
-any request with a 200 response code.
-
- >>> def dummy_application(environ, start_response):
- ... start_response('200', [('Content-type','text/plain')])
- ... return ['Success']
-
-Now let's protect that application. Here's an authentication callback
-function.
-
- >>> def authenticate(username, password):
- ... """Accepts "user/password", rejects everything else.
- ...
- ... :return: The username, if the credentials are valid.
- ... None, otherwise.
- ... """
- ... if username == "user" and password == "password":
- ... return username
- ... return None
-
- >>> print authenticate("user", "password")
- user
-
- >>> print authenticate("notuser", "password")
- None
-
-Here's a WSGI application that protects the application using
-BasicAuthMiddleware.
-
- >>> from lazr.authentication.wsgi import BasicAuthMiddleware
- >>> def protected_application():
- ... return BasicAuthMiddleware(
- ... dummy_application, realm="WSGI middleware test",
- ... protect_path_pattern=".*protected.*",
- ... authenticate_with=authenticate)
-
- >>> import wsgi_intercept
- >>> from wsgi_intercept.httplib2_intercept import install
- >>> install()
- >>> wsgi_intercept.add_wsgi_intercept(
- ... 'basictest', 80, protected_application)
-
-Most of the application's URLs are not protected by the
-middleware. You can access them without providing credentials.
-
- >>> import httplib2
- >>> client = httplib2.Http()
- >>> response, body = client.request('http://basictest/')
- >>> print response['status']
- 200
- >>> print body
- Success
-
-Any URL that includes the string "protected" is protected by the
-middleware, and cannot be accessed without credentials.
-
- >>> response, body = client.request('http://basictest/protected/')
- >>> print response['status']
- 401
- >>> print response['www-authenticate']
- Basic realm="WSGI middleware test"
-
- >>> response, body = client.request(
- ... 'http://basictest/this-is-protected-as-well/')
- >>> print response['status']
- 401
-
-The check_credentials() implementation given at the beginning of the
-test will only accept the user/password combination "user"/"password".
-Provide a bad username or password and you'll get a 401.
-
- >>> client.add_credentials("baduser", "baspassword")
- >>> response, body = client.request('http://basictest/protected/')
- >>> print response['status']
- 401
-
-Provide the correct credentials and you'll get a 200, even for the
-protected URIs.
-
- >>> client.add_credentials("user", "password")
- >>> response, body = client.request('http://basictest/protected/')
- >>> print response['status']
- 200
-
-Teardown.
-
- >>> wsgi_intercept.remove_wsgi_intercept('basictest', 80)
-
-Stacking
-********
-
-BasicAuthMiddleware instances can be stacked, each instance protecting
-a different path pattern. Here, we'll use stacking to protect
-the two regexes ".*protected.*" and ".*different.*", without combining
-them into one complex regex.
-
- >>> def return_user_application(environ, start_response):
- ... start_response('200', [('Content-type','text/plain')])
- ... return [str(environ['authenticated_user'])]
-
- >>> def protected_application():
- ... protected = BasicAuthMiddleware(
- ... return_user_application, realm="WSGI middleware test",
- ... protect_path_pattern=".*protected.*",
- ... authenticate_with=authenticate)
- ... return BasicAuthMiddleware(
- ... protected, realm="Another middleware",
- ... protect_path_pattern=".*different.*",
- ... authenticate_with=authenticate)
-
-Setup.
-
- >>> wsgi_intercept.add_wsgi_intercept(
- ... 'stacked', 80, protected_application)
- >>> client = httplib2.Http()
-
-Both path patterns are protected:
-
- >>> response, body = client.request('http://stacked/protected')
- >>> print response['status']
- 401
- >>> response, body = client.request('http://stacked/different')
- >>> print response['status']
- 401
-
-Both path patterns control respond to the same credentials.
-
- >>> client.add_credentials("user", "password")
-
- >>> response, body = client.request('http://stacked/protected-resource')
- >>> print response['status']
- 200
- >>> print body
- user
-
- >>> response, body = client.request('http://stacked/different-resource')
- >>> print response['status']
- 200
- >>> print body
- user
-
- >>> wsgi_intercept.remove_wsgi_intercept('stacked', 80)
-
-OAuthMiddleware
----------------
-
-The OAuthMiddleware implements section 7 ("Accessing Protected
-Resources") of the OAuth specification. That is, it makes sure that
-incoming consumer keys and access tokens pass some application-defined
-test. It does not help you serve request tokens or exchange a request
-token for an access token.
-
-We'll use OAuthMiddleware to protect the same simple application we
-protected earlier with BasicAuthMiddleware. But since we're using
-OAuth, we'll be checking a consumer key and access token, instead of a
-username and password.
-
- >>> from oauth.oauth import OAuthConsumer, OAuthToken
-
- >>> valid_consumer = OAuthConsumer("consumer", '')
- >>> valid_token = OAuthToken("token", "secret")
-
- >>> def authenticate(consumer, token, parameters):
- ... """Accepts the valid consumer and token, rejects everything else.
- ...
- ... :return: The consumer, if the credentials are valid.
- ... None, otherwise.
- ... """
- ... if consumer == valid_consumer and token == valid_token:
- ... return consumer
- ... return None
-
- >>> print authenticate(valid_consumer, valid_token, None).key
- consumer
-
- >>> invalid_consumer = OAuthConsumer("other consumer", '')
- >>> print authenticate(invalid_consumer, valid_token, None)
- None
-
-To test the OAuthMiddleware's security features, we'll also need to
-create a data store. In a real application the data store would
-probably be a database containing the registered consumer keys and
-tokens. We're using a simple data store designed for testing, and
-telling it about the one valid consumer and token.
-
- >>> from lazr.authentication.testing.oauth import SimpleOAuthDataStore
- >>> data_store = SimpleOAuthDataStore(
- ... {valid_consumer.key : valid_consumer},
- ... {valid_token.key : valid_token})
-
- >>> print data_store.lookup_consumer("consumer").key
- consumer
- >>> print data_store.lookup_consumer("badconsumer")
- None
-
-The data store tracks the use of OAuth nonces. If you call the data
-store's lookup_nonce() twice with the same values, the first call will
-return False and the second call will return True.
-
- >>> print data_store.lookup_nonce("consumer", "token", "nonce")
- False
- >>> print data_store.lookup_nonce("consumer", "token", "nonce")
- True
-
- >>> print data_store.lookup_nonce("newconsumer", "token", "nonce")
- False
-
-Now let's protect an application with lazr.authenticate's
-OAuthMiddleware, using our authentication technique and our simple
-data store.
-
- >>> from lazr.authentication.wsgi import OAuthMiddleware
- >>> def protected_application():
- ... return OAuthMiddleware(
- ... dummy_application, realm="OAuth test",
- ... authenticate_with=authenticate, data_store=data_store)
-
- >>> wsgi_intercept.add_wsgi_intercept(
- ... 'oauthtest', 80, protected_application)
- >>> client = httplib2.Http()
-
-A properly signed request will go through to the underlying WSGI
-application.
-
- >>> from oauth.oauth import (
- ... OAuthRequest, OAuthSignatureMethod_PLAINTEXT)
- >>> def sign_request(url, consumer=valid_consumer, token=valid_token):
- ... request = OAuthRequest().from_consumer_and_token(
- ... consumer, token, http_url=url)
- ... request.sign_request(
- ... OAuthSignatureMethod_PLAINTEXT(), consumer, token)
- ... headers = request.to_header('OAuth test')
- ... return headers
-
- >>> url = 'http://oauthtest/'
- >>> headers = sign_request(url)
- >>> response, body = client.request(url, headers=headers)
- >>> print response['status']
- 200
- >>> print body
- Success
-
-If you replay a signed HTTP request that worked the first time, it
-will fail the second time, because you'll be sending a nonce that was
-already used.
-
- >>> response, body = client.request(url, headers=headers)
- >>> print response['status']
- 401
-
-An unsigned request will fail.
-
- >>> response, body = client.request('http://oauthtest/')
- >>> print response['status']
- 401
- >>> print response['www-authenticate']
- OAuth realm="OAuth test"
-
-A request signed with invalid credentials will fail.
-
- >>> bad_token = OAuthToken("token", "badsecret")
- >>> headers = sign_request(url, token=bad_token)
- >>> response, body = client.request(url, headers=headers)
- >>> print response['status']
- 401
-
-Teardown.
-
- >>> wsgi_intercept.remove_wsgi_intercept('oauthtest', 80)
diff --git a/src/lazr/authentication/__init__.py b/src/lazr/authentication/__init__.py
deleted file mode 100644
index 2ebbfae..0000000
--- a/src/lazr/authentication/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2009 Canonical Ltd. All rights reserved.
-#
-# This file is part of lazr.authentication
-#
-# lazr.authentication is free software: you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation, version 3 of the
-# License.
-#
-# lazr.authentication is distributed in the hope that it will be
-# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.authentication. If not, see <http://www.gnu.org/licenses/>.
-
-"""Code to handle the server side of HTTP authentication."""
-
-import pkg_resources
-__version__ = pkg_resources.resource_string(
- "lazr.authentication", "version.txt").strip()
diff --git a/src/lazr/authentication/docs/__init__.py b/src/lazr/authentication/docs/__init__.py
deleted file mode 100644
index e45cad4..0000000
--- a/src/lazr/authentication/docs/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2009 Canonical Ltd. All rights reserved.
-#
-# This file is part of lazr.authentication
-#
-# lazr.authentication is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# lazr.authentication is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.authentication. If not, see <http://www.gnu.org/licenses/>.
-"""Executable documentation about lazr.authentication."""
diff --git a/src/lazr/authentication/testing/__init__.py b/src/lazr/authentication/testing/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/src/lazr/authentication/testing/oauth.py b/src/lazr/authentication/testing/oauth.py
deleted file mode 100644
index 7ef426c..0000000
--- a/src/lazr/authentication/testing/oauth.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2009 Canonical Ltd. All rights reserved.
-#
-# This file is part of lazr.authentication
-#
-# lazr.authentication is free software: you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation, version 3 of the
-# License.
-#
-# lazr.authentication is distributed in the hope that it will be
-# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with lazr.authentication. If not, see
-# <http://www.gnu.org/licenses/>.
-
-"""Utility classes for testing OAuth authentication."""
-
-__metaclass__ = type
-__all__ = [
- 'SimpleOAuthDataStore',
-]
-
-# Work around relative import behavior. The below is equivalent to
-# from oauth import oauth
-oauth = __import__('oauth.oauth', {}).oauth
-OAuthDataStore = oauth.OAuthDataStore
-
-
-class SimpleOAuthDataStore(OAuthDataStore):
- """A very simple implementation of the oauth library's OAuthDataStore."""
-
- def __init__(self, consumers=None, tokens=None):
- """Initialize with no nonces."""
- self.consumers = consumers or {}
- self.tokens = tokens or {}
- self.nonces = set()
-
- def lookup_token(self, token_type, token_field):
- """Turn a token key into an OAuthToken object."""
- return self.tokens.get(token_field)
-
- def lookup_consumer(self, consumer):
- """Turn a consumer key into an OAuthConsumer object."""
- return self.consumers.get(consumer)
-
- def lookup_nonce(self, consumer, token, nonce):
- """Make sure a nonce has not already been used.
-
- If the nonce has not been used, add it to the set
- so that a future call to this method will return False.
- """
- key = (consumer, token, nonce)
- if key in self.nonces:
- return True
- self.nonces.add(key)
- return False
diff --git a/src/lazr/authentication/tests/__init__.py b/src/lazr/authentication/tests/__init__.py
deleted file mode 100644
index f011bd9..0000000
--- a/src/lazr/authentication/tests/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2009 Canonical Ltd. All rights reserved.
-#
-# This file is part of lazr.authentication
-#
-# lazr.authentication is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# lazr.authentication is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.authentication. If not, see <http://www.gnu.org/licenses/>.
-"The lazr.authentication tests."
diff --git a/src/lazr/authentication/tests/test_docs.py b/src/lazr/authentication/tests/test_docs.py
deleted file mode 100644
index 27a8980..0000000
--- a/src/lazr/authentication/tests/test_docs.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2009 Canonical Ltd. All rights reserved.
-#
-# This file is part of lazr.authentication
-#
-# lazr.authentication is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, version 3 of the License.
-#
-# lazr.authentication is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-# License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.authentication. If not, see <http://www.gnu.org/licenses/>.
-"Test harness for doctests."
-
-# pylint: disable-msg=E0611,W0142
-
-__metaclass__ = type
-__all__ = [
- 'additional_tests',
- ]
-
-import atexit
-import doctest
-import os
-# pylint: disable-msg=F0401
-from pkg_resources import (
- resource_filename, resource_exists, resource_listdir, cleanup_resources)
-import unittest
-
-DOCTEST_FLAGS = (
- doctest.ELLIPSIS |
- doctest.NORMALIZE_WHITESPACE |
- doctest.REPORT_NDIFF)
-
-
-def additional_tests():
- "Run the doc tests (README.txt and docs/*, if any exist)"
- doctest_files = [
- os.path.abspath(resource_filename('lazr.authentication', 'README.txt'))]
- if resource_exists('lazr.authentication', 'docs'):
- for name in resource_listdir('lazr.authentication', 'docs'):
- if name.endswith('.txt'):
- doctest_files.append(
- os.path.abspath(
- resource_filename('lazr.authentication', 'docs/%s' % name)))
- kwargs = dict(module_relative=False, optionflags=DOCTEST_FLAGS)
- atexit.register(cleanup_resources)
- return unittest.TestSuite((
- doctest.DocFileSuite(*doctest_files, **kwargs)))
diff --git a/src/lazr/authentication/version.txt b/src/lazr/authentication/version.txt
deleted file mode 100644
index d917d3e..0000000
--- a/src/lazr/authentication/version.txt
+++ /dev/null
@@ -1 +0,0 @@
-0.1.2
diff --git a/src/lazr/authentication/wsgi.py b/src/lazr/authentication/wsgi.py
deleted file mode 100644
index 1b1a10c..0000000
--- a/src/lazr/authentication/wsgi.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# Copyright 2009 Canonical Ltd. All rights reserved.
-#
-# This file is part of lazr.authenticate
-#
-# lazr.authenticate is free software: you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation, version 3 of the
-# License.
-#
-# lazr.authenticate is distributed in the hope that it will be
-# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with lazr.authenticate. If not, see <http://www.gnu.org/licenses/>.
-
-"""WSGI middleware that handles the server side of HTTP authenticate."""
-
-__metaclass__ = type
-__all__ = [
- 'AuthenticationMiddleware',
- 'BasicAuthMiddleware',
- 'OAuthMiddleware',
-]
-
-import re
-import urlparse
-
-from oauth.oauth import (
- OAuthError, OAuthRequest, OAuthServer, OAuthSignatureMethod_PLAINTEXT)
-
-
-class AuthenticationMiddleware(object):
- """A base class for middleware that authenticates HTTP requests.
-
- This class implements a generic HTTP authenticate workflow:
- check whether the requested resource is protected, get credentials
- from the WSGI environment, validate them (using a callback
- function) and either allow or deny acces.
-
- All subclasses must define the variable AUTH_SCHEME, which is the
- HTTP authentication scheme (eg."Basic", "OAuth"). This string is sent
- along with a HTTP response code of 401 ("Unauthorized").
- """
-
- def __init__(self, application, authenticate_with,
- realm="Restricted area", protect_path_pattern='.*'):
- """Constructor.
-
- :param application: A WSGI application.
-
- :param authenticate_with: A callback function that takes some
- number of credential arguemnts (the number and type
- depends on the implementation of
- getCredentialsFromEnvironment()) and returns an object
- representing the authenticated user. If the credentials
- are invalid or don't identify any existing user, the
- function should return None.
-
- :param realm: The string to give out as the authenticate realm.
- :param protect_path_pattern: A regular expression string. URL
- paths matching this string will be protected with the
- authenticate method. URL paths not matching this string
- can be accessed without authenticating.
- """
- self.application = application
- self.authenticate_with = authenticate_with
- self.realm = realm
- self.protect_path_pattern = re.compile(protect_path_pattern)
-
- def _unauthorized(self, start_response):
- """Short-circuit the request with a 401 error code."""
- start_response("401 Unauthorized",
- [('WWW-Authenticate',
- '%s realm="%s"' % (self.AUTH_SCHEME, self.realm))])
- return ['401 Unauthorized']
-
- def __call__(self, environ, start_response):
- """Protect certain resources by checking auth credentials."""
- path_info = environ.get('PATH_INFO', '/')
- if not self.protect_path_pattern.match(path_info):
- environ.setdefault('authenticated_user')
- return self.application(environ, start_response)
-
- try:
- credentials = self.getCredentialsFromEnvironment(environ)
- except ValueError:
- credentials = None
- if credentials is None:
- return self._unauthorized(start_response)
-
- authenticated_user = self.authenticate_with(*credentials)
- if authenticated_user is None:
- return self._unauthorized(start_response)
-
- environ['authenticated_user'] = authenticated_user
-
- return self.application(environ, start_response)
-
- def getCredentialsFromEnvironment(self, environment):
- """Retrieve a set of credentials from the environment.
-
- This superclass implementation ignores the environment
- entirely, and so never authenticates anybody.
-
- :param environment: The WSGI environment.
- :return: A list of objects to be passed into the authenticate_with
- callback function, or None if the credentials could not
- be determined.
- """
- return None
-
-
-class BasicAuthMiddleware(AuthenticationMiddleware):
- """WSGI middleware that implements HTTP Basic Auth."""
-
- AUTH_SCHEME = "Basic"
-
- def getCredentialsFromEnvironment(self, environ):
- authorization = environ.get('HTTP_AUTHORIZATION')
- if authorization is None:
- return None
-
- method, auth = authorization.split(' ', 1)
- if method.lower() != 'basic':
- return None
-
- auth = auth.strip().decode('base64')
- username, password = auth.split(':', 1)
- return username, password
-
-
-class OAuthMiddleware(AuthenticationMiddleware):
- """WSGI middleware that implements (part of) OAuth.
-
- This middleware only protects resources by making sure requests
- are signed with a valid consumer and access token. It does not
- help clients get request tokens or exchange request tokens for
- access tokens.
- """
-
- AUTH_SCHEME = "OAuth"
-
- def __init__(self, application, authenticate_with, data_store=None,
- realm="Restricted area", protect_path_pattern='.*'):
- """See `AuthenticationMiddleware.`
-
- :param data_store: An OAuthDataStore.
- """
- super(OAuthMiddleware, self).__init__(
- application, authenticate_with, realm, protect_path_pattern)
- self.data_store = data_store
-
- def getCredentialsFromEnvironment(self, environ):
- http_method = environ['REQUEST_METHOD']
-
- # Recreate the URL.
- url_scheme = environ['wsgi.url_scheme']
- hostname = environ['HTTP_HOST']
- path = environ['PATH_INFO']
- query_string = environ.get('QUERY_STRING', '')
- original_url = urlparse.urlunparse(
- (url_scheme, hostname, path, '', query_string, ''))
- headers = {'Authorization' : environ.get('HTTP_AUTHORIZATION', '')}
- request = OAuthRequest().from_request(
- http_method, original_url, headers=headers,
- query_string=query_string)
- if request is None:
- return None
- server = OAuthServer(self.data_store)
- server.add_signature_method(OAuthSignatureMethod_PLAINTEXT())
- try:
- consumer, token, parameters = server.verify_request(request)
- except OAuthError:
- return None
- return consumer, token, parameters
diff --git a/src/lazr/restfulclient/NEWS.txt b/src/lazr/restfulclient/NEWS.txt
index b17713d..ed48928 100644
--- a/src/lazr/restfulclient/NEWS.txt
+++ b/src/lazr/restfulclient/NEWS.txt
@@ -2,6 +2,17 @@
NEWS for lazr.restfulclient
===========================
+0.13.5 (2017-09-04)
+===================
+
+ - Fix bytes vs. unicode in json.loads calls. [bug=1403524]
+ - Decode header before comparison. [bug=1414075]
+ - Fix urllib unquote imports. [bug=1414055]
+ - Fix urllib urlencode imports. [bug=1425609]
+ - Tolerate httplib2 versions earlier than 0.9 again.
+ - Fix handling of 304 responses with an empty body on Python 3.
+ [bug=1714960]
+
0.13.4 (2014-12-05)
===================
diff --git a/src/lazr/restfulclient/_browser.py b/src/lazr/restfulclient/_browser.py
index 8e5cad6..371a72f 100644
--- a/src/lazr/restfulclient/_browser.py
+++ b/src/lazr/restfulclient/_browser.py
@@ -45,6 +45,11 @@ from httplib2 import (
urlnorm,
)
try:
+ from httplib2 import proxy_info_from_environment
+except ImportError:
+ from httplib2 import ProxyInfo
+ proxy_info_from_environment = ProxyInfo.from_environment
+try:
# Python 3 and sufficiently modern Python 2 versions.
from json import dumps
except ImportError:
@@ -318,6 +323,8 @@ class MultipleRepresentationCache(AtomicFileCache):
(scheme, authority, request_uri, cachekey) = urlnorm(uri)
cached_value = self.get(cachekey)
header_start = header + ':'
+ if not isinstance(header_start, bytes):
+ header_start = header_start.encode('utf-8')
if cached_value is not None:
for line in BytesIO(cached_value):
if line.startswith(header_start):
@@ -385,7 +392,7 @@ class Browser:
str(url), method=method, body=data, headers=headers)
if response.status == 304:
# The resource didn't change.
- if content == '':
+ if content == b'':
if ('If-None-Match' in headers
or 'If-Modified-Since' in headers):
# The caller made a conditional request, and the
diff --git a/src/lazr/restfulclient/resource.py b/src/lazr/restfulclient/resource.py
index 3026a07..4b9bc8b 100644
--- a/src/lazr/restfulclient/resource.py
+++ b/src/lazr/restfulclient/resource.py
@@ -48,12 +48,10 @@ except ImportError:
try:
# Python 3.
- from urllib.parse import urljoin, urlparse, parse_qs
+ from urllib.parse import urljoin, urlparse, parse_qs, unquote, urlencode
except ImportError:
from urlparse import urljoin, urlparse, parse_qs
-
-import types
-import urllib
+ from urllib import unquote, urlencode
import sys
if sys.version_info[0] >= 3:
@@ -381,7 +379,7 @@ class Resource(RestfulBase):
representation = self._root._browser.get(self._wadl_resource)
if isinstance(representation, binary_type):
representation = representation.decode('utf-8')
- representation = loads(text_type(representation))
+ representation = loads(representation)
# In rare cases, the resource type served by the
# server conflicts with the type the client thought
@@ -530,8 +528,10 @@ class ServiceRoot(Resource):
url = url[1:]
url = str(self._root_uri.append(url))
document = self._browser.get(url)
+ if isinstance(document, binary_type):
+ document = document.decode('utf-8')
try:
- representation = loads(text_type(document))
+ representation = loads(document)
except ValueError:
raise ValueError("%s doesn't serve a JSON document." % url)
type_link = representation.get("resource_type_link")
@@ -647,13 +647,18 @@ class NamedOperation(RestfulBase):
# The operation returned a document with nothing
# special about it.
if content_type == self.JSON_MEDIA_TYPE:
- return loads(text_type(content))
+ if isinstance(content, binary_type):
+ content = content.decode('utf-8')
+ return loads(content)
# We don't know how to process the content.
return content
# The operation returned a representation of some
# resource. Instantiate a Resource object for it.
- document = loads(text_type(content))
+ if isinstance(content, binary_type):
+ content = content.decode('utf-8')
+
+ document = loads(content)
if document is None:
# The operation returned a null value.
return document
@@ -777,7 +782,9 @@ class Entry(Resource):
if response.status == 209 and content_type == self.JSON_MEDIA_TYPE:
# The server sent back a new representation of the object.
# Use it in preference to the existing representation.
- new_representation = loads(text_type(content))
+ if isinstance(content, binary_type):
+ content = content.decode('utf-8')
+ new_representation = loads(content)
self._wadl_resource.representation = new_representation
self._wadl_resource.media_type = content_type
@@ -822,8 +829,10 @@ class Collection(Resource):
next_link = current_page.get('next_collection_link')
if next_link is None:
break
- current_page = loads(
- text_type(self._root._browser.get(URI(next_link))))
+ next_get = self._root._browser.get(URI(next_link))
+ if isinstance(next_get, binary_type):
+ next_get = next_get.decode('utf-8')
+ current_page = loads(next_get)
def __getitem__(self, key):
"""Look up a slice, or a subordinate resource by index.
@@ -895,8 +904,10 @@ class Collection(Resource):
# Iterate over pages until we have the correct number of entries.
while more_needed > 0 and page_url is not None:
- representation = loads(
- text_type(self._root._browser.get(page_url)))
+ page_get = self._root._browser.get(page_url)
+ if isinstance(page_get, binary_type):
+ page_get = page_get.decode('utf-8')
+ representation = loads(page_get)
current_page_entries = representation['entries']
entry_dicts += current_page_entries[:more_needed]
more_needed = desired_size - len(entry_dicts)
@@ -959,7 +970,7 @@ class Collection(Resource):
else:
... 82 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/lazr.restfulclient.git
More information about the Python-modules-commits
mailing list