diff options
author | Dimitri John Ledkov <xnox@ubuntu.com> | 2016-08-13 04:11:43 +0100 |
---|---|---|
committer | Dimitri John Ledkov <xnox@ubuntu.com> | 2016-08-13 04:11:43 +0100 |
commit | bc2191500f579eb9f359f0bf1acb2e142ae7d0b7 (patch) | |
tree | c3fa7c4ad571ceb0b578b55d04a5f878696866a7 /src | |
parent | 8ed2cc710534c26eccf3f1dd2496051a30160960 (diff) |
Import python-launchpadlib_1.10.4.orig.tar.gz
Diffstat (limited to 'src')
-rw-r--r-- | src/launchpadlib.egg-info/PKG-INFO | 10 | ||||
-rw-r--r-- | src/launchpadlib.egg-info/requires.txt | 2 | ||||
-rw-r--r-- | src/launchpadlib/NEWS.txt | 8 | ||||
-rw-r--r-- | src/launchpadlib/__init__.py | 2 | ||||
-rw-r--r-- | src/launchpadlib/apps.py | 7 | ||||
-rw-r--r-- | src/launchpadlib/credentials.py | 14 | ||||
-rw-r--r-- | src/launchpadlib/docs/command-line.txt | 10 | ||||
-rw-r--r-- | src/launchpadlib/docs/introduction.txt | 14 | ||||
-rw-r--r-- | src/launchpadlib/docs/people.txt | 4 | ||||
-rw-r--r-- | src/launchpadlib/launchpad.py | 23 | ||||
-rw-r--r-- | src/launchpadlib/testing/tests/test_launchpad.py | 2 | ||||
-rw-r--r-- | src/launchpadlib/tests/test_http.py | 43 | ||||
-rw-r--r-- | src/launchpadlib/tests/test_launchpad.py | 2 |
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) |