summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2016-08-13 04:11:43 +0100
committerDimitri John Ledkov <xnox@ubuntu.com>2016-08-13 04:11:43 +0100
commitbc2191500f579eb9f359f0bf1acb2e142ae7d0b7 (patch)
treec3fa7c4ad571ceb0b578b55d04a5f878696866a7 /src
parent8ed2cc710534c26eccf3f1dd2496051a30160960 (diff)
Import python-launchpadlib_1.10.4.orig.tar.gz
Diffstat (limited to 'src')
-rw-r--r--src/launchpadlib.egg-info/PKG-INFO10
-rw-r--r--src/launchpadlib.egg-info/requires.txt2
-rw-r--r--src/launchpadlib/NEWS.txt8
-rw-r--r--src/launchpadlib/__init__.py2
-rw-r--r--src/launchpadlib/apps.py7
-rw-r--r--src/launchpadlib/credentials.py14
-rw-r--r--src/launchpadlib/docs/command-line.txt10
-rw-r--r--src/launchpadlib/docs/introduction.txt14
-rw-r--r--src/launchpadlib/docs/people.txt4
-rw-r--r--src/launchpadlib/launchpad.py23
-rw-r--r--src/launchpadlib/testing/tests/test_launchpad.py2
-rw-r--r--src/launchpadlib/tests/test_http.py43
-rw-r--r--src/launchpadlib/tests/test_launchpad.py2
13 files changed, 90 insertions, 51 deletions
diff --git a/src/launchpadlib.egg-info/PKG-INFO b/src/launchpadlib.egg-info/PKG-INFO
index c8634b2..40f5d79 100644
--- a/src/launchpadlib.egg-info/PKG-INFO
+++ b/src/launchpadlib.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: launchpadlib
-Version: 1.10.3
+Version: 1.10.4
Summary: Script Launchpad through its web services interfaces. Officially supported.
Home-page: https://help.launchpad.net/API/launchpadlib
Author: LAZR Developers
@@ -31,6 +31,14 @@ Description: ..
NEWS for launchpadlib
=====================
+ 1.10.4 (2016-07-12)
+ ===================
+ - Fix _bad_oauth_token crash on Python 3. [bug=1471894]
+ - Time out make_end_user_authorize_token after 15 minutes.
+ - Ignore PendingDeprecationWarning from lazr.restfulclient. [bug=1473577]
+ - Ask forgiveness rather than permission when creating cache directories.
+ - Fix browser token authorization on OS X. [bug=1516080]
+
1.10.3 (2014-12-05)
===================
- Port to Python3.
diff --git a/src/launchpadlib.egg-info/requires.txt b/src/launchpadlib.egg-info/requires.txt
index aeb2b64..dd7b206 100644
--- a/src/launchpadlib.egg-info/requires.txt
+++ b/src/launchpadlib.egg-info/requires.txt
@@ -5,4 +5,4 @@ lazr.uri
oauth
setuptools
testresources
-wadllib
+wadllib \ No newline at end of file
diff --git a/src/launchpadlib/NEWS.txt b/src/launchpadlib/NEWS.txt
index 946d7d0..0122d9b 100644
--- a/src/launchpadlib/NEWS.txt
+++ b/src/launchpadlib/NEWS.txt
@@ -2,6 +2,14 @@
NEWS for launchpadlib
=====================
+1.10.4 (2016-07-12)
+===================
+- Fix _bad_oauth_token crash on Python 3. [bug=1471894]
+- Time out make_end_user_authorize_token after 15 minutes.
+- Ignore PendingDeprecationWarning from lazr.restfulclient. [bug=1473577]
+- Ask forgiveness rather than permission when creating cache directories.
+- Fix browser token authorization on OS X. [bug=1516080]
+
1.10.3 (2014-12-05)
===================
- Port to Python3.
diff --git a/src/launchpadlib/__init__.py b/src/launchpadlib/__init__.py
index b5315ba..0c82b6c 100644
--- a/src/launchpadlib/__init__.py
+++ b/src/launchpadlib/__init__.py
@@ -14,4 +14,4 @@
# You should have received a copy of the GNU Lesser General Public License
# along with launchpadlib. If not, see <http://www.gnu.org/licenses/>.
-__version__ = '1.10.3'
+__version__ = '1.10.4'
diff --git a/src/launchpadlib/apps.py b/src/launchpadlib/apps.py
index ae87139..f58dcb4 100644
--- a/src/launchpadlib/apps.py
+++ b/src/launchpadlib/apps.py
@@ -22,19 +22,14 @@ themselves are kept in bin/.
__all__ = [
'RequestTokenApp',
- 'TrustedTokenAuthorizationConsoleApp',
]
-import getpass
-import sys
-
try:
import json
except ImportError:
import simplejson as json
-from launchpadlib.credentials import (
- Credentials, RequestTokenAuthorizationEngine, TokenAuthorizationException)
+from launchpadlib.credentials import Credentials
from launchpadlib.uris import lookup_web_root
diff --git a/src/launchpadlib/credentials.py b/src/launchpadlib/credentials.py
index aff7569..c0ab813 100644
--- a/src/launchpadlib/credentials.py
+++ b/src/launchpadlib/credentials.py
@@ -82,6 +82,7 @@ request_token_page = '+request-token'
access_token_page = '+access-token'
authorize_token_page = '+authorize-token'
access_token_poll_time = 1
+access_token_poll_timeout = 15 * 60
EXPLOSIVE_ERRORS = (MemoryError, KeyboardInterrupt, SystemExit)
@@ -634,7 +635,8 @@ class AuthorizeRequestTokenWithBrowser(RequestTokenAuthorizationEngine):
self.output(self.WAITING_FOR_USER % authorization_url)
try:
- browser = webbrowser.get().basename
+ browser_obj = webbrowser.get()
+ browser = getattr(browser_obj, "basename", None)
console_browser = browser in self.TERMINAL_BROWSERS
except webbrowser.Error:
browser = None
@@ -649,8 +651,9 @@ class AuthorizeRequestTokenWithBrowser(RequestTokenAuthorizationEngine):
stdin.readline()
self.output(self.WAITING_FOR_LAUNCHPAD)
- if browser is not None:
+ if browser_obj is not None:
webbrowser.open(authorization_url)
+ start_time = time.time()
while credentials.access_token is None:
time.sleep(access_token_poll_time)
try:
@@ -669,6 +672,9 @@ class AuthorizeRequestTokenWithBrowser(RequestTokenAuthorizationEngine):
# There was an error accessing the server.
print("Unexpected response from Launchpad:")
print(e)
+ if time.time() >= start_time + access_token_poll_timeout:
+ raise TokenAuthorizationTimedOut(
+ "Timed out after %d seconds." % access_token_poll_timeout)
class TokenAuthorizationException(Exception):
@@ -683,6 +689,10 @@ class EndUserDeclinedAuthorization(TokenAuthorizationException):
pass
+class TokenAuthorizationTimedOut(TokenAuthorizationException):
+ pass
+
+
class ClientError(TokenAuthorizationException):
pass
diff --git a/src/launchpadlib/docs/command-line.txt b/src/launchpadlib/docs/command-line.txt
index 5027845..b661d0c 100644
--- a/src/launchpadlib/docs/command-line.txt
+++ b/src/launchpadlib/docs/command-line.txt
@@ -28,9 +28,13 @@ token and the available access levels.
>>> token_app = RequestTokenApp(web_root, consumer_name, "context")
>>> token_json = json.loads(token_app.run())
- >>> sorted(token_json.keys())
- ['access_levels', 'lp.context', 'oauth_token',
- 'oauth_token_consumer', 'oauth_token_secret']
+ >>> for param in sorted(token_json.keys()):
+ ... print(param)
+ access_levels
+ lp.context
+ oauth_token
+ oauth_token_consumer
+ oauth_token_secret
>>> print token_json['lp.context']
context
diff --git a/src/launchpadlib/docs/introduction.txt b/src/launchpadlib/docs/introduction.txt
index 0084d3f..72f64b9 100644
--- a/src/launchpadlib/docs/introduction.txt
+++ b/src/launchpadlib/docs/introduction.txt
@@ -215,8 +215,8 @@ get a request token.
>>> authorization_url = credentials.get_request_token(
... context='firefox', web_root='test_dev')
- >>> authorization_url
- 'http://launchpad.dev:8085/+authorize-token?oauth_token=...&lp.context=firefox'
+ >>> print(authorization_url)
+ http://launchpad.dev:8085/+authorize-token?oauth_token=...&lp.context=firefox
We use 'test_dev' as a shorthand for the root URL of the Launchpad
installation. It's defined in the 'uris' module as
@@ -253,9 +253,13 @@ token_format and get a dictionary instead.
The dictionary has useful information about the token and about the
levels of authentication Launchpad offers.
- >>> sorted(dictionary.keys())
- ['access_levels', 'lp.context', 'oauth_token',
- 'oauth_token_consumer', 'oauth_token_secret']
+ >>> for param in sorted(dictionary.keys()):
+ ... print(param)
+ access_levels
+ lp.context
+ oauth_token
+ oauth_token_consumer
+ oauth_token_secret
The _request_token attribute of the Credentials object has the same
fields set as if you had asked for the default URI token format.
diff --git a/src/launchpadlib/docs/people.txt b/src/launchpadlib/docs/people.txt
index 7d92d12..f845d7f 100644
--- a/src/launchpadlib/docs/people.txt
+++ b/src/launchpadlib/docs/people.txt
@@ -85,7 +85,7 @@ can read.
>>> salgado.date_created
datetime.datetime(2005, 6, 6, 8, 59, 51, 596025, ...)
>>> print salgado.time_zone
- None
+ UTC
>>> salgado.is_valid
True
>>> #salgado.wiki_names
@@ -187,7 +187,7 @@ can read.
>>> bassists.date_created
datetime.datetime(...)
>>> print bassists.time_zone
- None
+ UTC
>>> bassists.is_valid
True
>>> #bassists.team_memberships
diff --git a/src/launchpadlib/launchpad.py b/src/launchpadlib/launchpad.py
index 337e015..28dae0f 100644
--- a/src/launchpadlib/launchpad.py
+++ b/src/launchpadlib/launchpad.py
@@ -21,6 +21,7 @@ __all__ = [
'Launchpad',
]
+import errno
import os
try:
from urllib.parse import urlsplit
@@ -28,7 +29,11 @@ except:
from urlparse import urlsplit
import warnings
-from httplib2 import proxy_info_from_environment
+try:
+ from httplib2 import proxy_info_from_environment
+except ImportError:
+ from httplib2 import ProxyInfo
+ proxy_info_from_environment = ProxyInfo.from_environment
from lazr.restfulclient.resource import (
CollectionWithKeyBasedLookup,
@@ -122,9 +127,9 @@ class LaunchpadOAuthAwareHttp(RestfulHttp):
def _bad_oauth_token(self, response, content):
"""Helper method to detect an error caused by a bad OAuth token."""
return (response.status == 401 and
- (content.startswith("Expired token")
- or content.startswith("Invalid token")
- or content.startswith("Unknown access token")))
+ (content.startswith(b"Expired token")
+ or content.startswith(b"Invalid token")
+ or content.startswith(b"Unknown access token")))
def _request(self, *args):
response, content = super(
@@ -600,8 +605,11 @@ class Launchpad(ServiceRoot):
if launchpadlib_dir[:1] == '~':
raise ValueError("Must set $HOME or pass 'launchpadlib_dir' to "
"indicate location to store cached data")
- if not os.path.exists(launchpadlib_dir):
+ try:
os.makedirs(launchpadlib_dir, 0o700)
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
os.chmod(launchpadlib_dir, 0o700)
# Determine the real service root.
service_root = uris.lookup_service_root(service_root)
@@ -609,6 +617,9 @@ class Launchpad(ServiceRoot):
scheme, host_name, path, query, fragment = urlsplit(service_root)
service_root_dir = os.path.join(launchpadlib_dir, host_name)
cache_path = os.path.join(service_root_dir, 'cache')
- if not os.path.exists(cache_path):
+ try:
os.makedirs(cache_path, 0o700)
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
return (service_root, launchpadlib_dir, cache_path, service_root_dir)
diff --git a/src/launchpadlib/testing/tests/test_launchpad.py b/src/launchpadlib/testing/tests/test_launchpad.py
index 387751b..d76b185 100644
--- a/src/launchpadlib/testing/tests/test_launchpad.py
+++ b/src/launchpadlib/testing/tests/test_launchpad.py
@@ -239,7 +239,7 @@ class FakeLaunchpadTest(ResourcedTestCase):
"""
bug = dict(id="1", title="Bug #1")
self.launchpad.bugs = dict(entries=[bug])
- bugs = [bug for bug in self.launchpad.bugs]
+ bugs = list(self.launchpad.bugs)
self.assertEqual(1, len(bugs))
bug = bugs[0]
self.assertEqual("1", bug.id)
diff --git a/src/launchpadlib/tests/test_http.py b/src/launchpadlib/tests/test_http.py
index 0357962..46a4fc9 100644
--- a/src/launchpadlib/tests/test_http.py
+++ b/src/launchpadlib/tests/test_http.py
@@ -32,14 +32,11 @@ from launchpadlib.launchpad import (
Launchpad,
LaunchpadOAuthAwareHttp,
)
-from launchpadlib.testing.helpers import (
- NoNetworkAuthorizationEngine,
- NoNetworkLaunchpad,
- )
+from launchpadlib.testing.helpers import NoNetworkAuthorizationEngine
# The simplest WADL that looks like a representation of the service root.
-SIMPLE_WADL = '''<?xml version="1.0"?>
+SIMPLE_WADL = b'''<?xml version="1.0"?>
<application xmlns="http://research.sun.com/wadl/2006/10">
<resources base="http://www.example.com/">
<resource path="" type="#service-root"/>
@@ -58,7 +55,7 @@ SIMPLE_WADL = '''<?xml version="1.0"?>
'''
# The simplest JSON that looks like a representation of the service root.
-SIMPLE_JSON = dumps({})
+SIMPLE_JSON = dumps({}).encode('utf-8')
class Response:
@@ -140,7 +137,7 @@ class TestAbilityToParseData(SimulatedResponsesTestCase):
def test_minimal_data(self):
"""Make sure that launchpadlib can use the minimal data."""
- launchpad = self.launchpad_with_responses(
+ self.launchpad_with_responses(
Response(200, SIMPLE_WADL),
Response(200, SIMPLE_JSON))
@@ -148,7 +145,7 @@ class TestAbilityToParseData(SimulatedResponsesTestCase):
"""Show that bad WADL causes an exception."""
self.assertRaises(
SyntaxError, self.launchpad_with_responses,
- Response(200, "This is not WADL."),
+ Response(200, b"This is not WADL."),
Response(200, SIMPLE_JSON))
def test_bad_json(self):
@@ -156,7 +153,7 @@ class TestAbilityToParseData(SimulatedResponsesTestCase):
self.assertRaises(
JSONDecodeError, self.launchpad_with_responses,
Response(200, SIMPLE_WADL),
- Response(200, "This is not JSON."))
+ Response(200, b"This is not JSON."))
class TestTokenFailureDuringRequest(SimulatedResponsesTestCase):
@@ -175,19 +172,19 @@ class TestTokenFailureDuringRequest(SimulatedResponsesTestCase):
Response(200, SIMPLE_JSON)]
self.assertEqual(self.engine.access_tokens_obtained, 0)
- launchpad = SimulatedResponsesLaunchpad.login_with(
+ SimulatedResponsesLaunchpad.login_with(
'application name', authorization_engine=self.engine)
self.assertEqual(self.engine.access_tokens_obtained, 1)
def test_bad_token(self):
"""If our token is bad, we get another one."""
SimulatedResponsesLaunchpad.responses = [
- Response(401, "Invalid token."),
+ Response(401, b"Invalid token."),
Response(200, SIMPLE_WADL),
Response(200, SIMPLE_JSON)]
self.assertEqual(self.engine.access_tokens_obtained, 0)
- launchpad = SimulatedResponsesLaunchpad.login_with(
+ SimulatedResponsesLaunchpad.login_with(
'application name', authorization_engine=self.engine)
self.assertEqual(self.engine.access_tokens_obtained, 2)
@@ -195,12 +192,12 @@ class TestTokenFailureDuringRequest(SimulatedResponsesTestCase):
"""If our token is expired, we get another one."""
SimulatedResponsesLaunchpad.responses = [
- Response(401, "Expired token."),
+ Response(401, b"Expired token."),
Response(200, SIMPLE_WADL),
Response(200, SIMPLE_JSON)]
self.assertEqual(self.engine.access_tokens_obtained, 0)
- launchpad = SimulatedResponsesLaunchpad.login_with(
+ SimulatedResponsesLaunchpad.login_with(
'application name', authorization_engine=self.engine)
self.assertEqual(self.engine.access_tokens_obtained, 2)
@@ -208,12 +205,12 @@ class TestTokenFailureDuringRequest(SimulatedResponsesTestCase):
"""If our token is unknown, we get another one."""
SimulatedResponsesLaunchpad.responses = [
- Response(401, "Unknown access token."),
+ Response(401, b"Unknown access token."),
Response(200, SIMPLE_WADL),
Response(200, SIMPLE_JSON)]
self.assertEqual(self.engine.access_tokens_obtained, 0)
- launchpad = SimulatedResponsesLaunchpad.login_with(
+ SimulatedResponsesLaunchpad.login_with(
'application name', authorization_engine=self.engine)
self.assertEqual(self.engine.access_tokens_obtained, 2)
@@ -221,24 +218,24 @@ class TestTokenFailureDuringRequest(SimulatedResponsesTestCase):
"""We get another token no matter when the error happens."""
SimulatedResponsesLaunchpad.responses = [
Response(200, SIMPLE_WADL),
- Response(401, "Expired token."),
+ Response(401, b"Expired token."),
Response(200, SIMPLE_JSON)]
self.assertEqual(self.engine.access_tokens_obtained, 0)
- launchpad = SimulatedResponsesLaunchpad.login_with(
+ SimulatedResponsesLaunchpad.login_with(
'application name', authorization_engine=self.engine)
self.assertEqual(self.engine.access_tokens_obtained, 2)
def test_many_errors(self):
"""We'll keep getting new tokens as long as tokens are the problem."""
SimulatedResponsesLaunchpad.responses = [
- Response(401, "Invalid token."),
+ Response(401, b"Invalid token."),
Response(200, SIMPLE_WADL),
- Response(401, "Expired token."),
- Response(401, "Invalid token."),
+ Response(401, b"Expired token."),
+ Response(401, b"Invalid token."),
Response(200, SIMPLE_JSON)]
self.assertEqual(self.engine.access_tokens_obtained, 0)
- launchpad = SimulatedResponsesLaunchpad.login_with(
+ SimulatedResponsesLaunchpad.login_with(
'application name', authorization_engine=self.engine)
self.assertEqual(self.engine.access_tokens_obtained, 4)
@@ -246,7 +243,7 @@ class TestTokenFailureDuringRequest(SimulatedResponsesTestCase):
"""If the token is not at fault, a 401 error raises an exception."""
SimulatedResponsesLaunchpad.responses = [
- Response(401, "Some other error.")]
+ Response(401, b"Some other error.")]
self.assertRaises(
Unauthorized, SimulatedResponsesLaunchpad.login_with,
diff --git a/src/launchpadlib/tests/test_launchpad.py b/src/launchpadlib/tests/test_launchpad.py
index c9c000b..d4aa4de 100644
--- a/src/launchpadlib/tests/test_launchpad.py
+++ b/src/launchpadlib/tests/test_launchpad.py
@@ -579,6 +579,7 @@ class TestDeprecatedLoginMethods(KeyringTest):
# login() works but triggers a deprecation warning.
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
+ warnings.simplefilter("ignore", PendingDeprecationWarning)
NoNetworkLaunchpad.login('consumer', 'token', 'secret')
self.assertEqual(len(caught), 1)
self.assertEqual(caught[0].category, DeprecationWarning)
@@ -587,6 +588,7 @@ class TestDeprecatedLoginMethods(KeyringTest):
# get_token_and_login() works but triggers a deprecation warning.
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
+ warnings.simplefilter("ignore", PendingDeprecationWarning)
NoNetworkLaunchpad.get_token_and_login('consumer')
self.assertEqual(len(caught), 1)
self.assertEqual(caught[0].category, DeprecationWarning)