******************************* The simulated Launchpad browser ******************************* The SimulatedLaunchpadBrowser class is a scriptable browser-like class that can be trusted with the end-user's username and password. It fulfils the same function as the user's web browser, but because it's scriptable can be used to create non-browser trusted clients. >>> username = 'salgado@ubuntu.com' >>> password = 'zeca' >>> web_root = 'http://launchpad.dev:8085/' Before showing how SimulatedLaunchpadBrowser can authorize a request token, let's create a request token to authorize. >>> from launchpadlib.credentials import Credentials >>> credentials = Credentials("doctest consumer") >>> context="firefox" >>> validate_url = credentials.get_request_token( ... web_root=web_root, context=context) >>> request_token = credentials._request_token.key get_token_info() ================ If you have the end-user's username and password, you can use get_token_info() to get information about one of the user's request tokens. It's useful for confirming that the end-user gave the correct username and password, and for reconciling the list of access levels a client will accept with Launchpad's master list. >>> from launchpadlib.credentials import SimulatedLaunchpadBrowser >>> from launchpadlib.testing.helpers import TestableLaunchpad >>> browser = SimulatedLaunchpadBrowser(web_root) If you make an unauthorized request, you'll get a 401 error. (Launchpad returns 200, but SimulatedLaunchpadBrowser sniffs it and changes it to a 401.) >>> response, content = browser.get_token_info( ... "baduser", "badpasword", request_token) >>> print response.status 401 If you provide the right authorization, you'll get back information about your request token. >>> response, content = browser.get_token_info( ... username, password, request_token) >>> print response['content-type'] application/json # XXX leonardr 2009-10-28 bug=462773 These two URLs should be # exactly the same, but the Content-Location is missing the # lp.context. >>> validate_url.startswith(response['content-location']) True >>> import simplejson >>> json = simplejson.loads(content) >>> json['oauth_token'] == request_token True >>> print json['oauth_token_consumer'] doctest consumer You'll also get information about the available access levels. >>> print sorted([level['value'] for level in json['access_levels']]) ['READ_PRIVATE', ... 'UNAUTHORIZED', ...] If you provide a list of possible access levels, you'll get back a list that reconciles the list you gave with Launchpad's access levels. >>> response, content = browser.get_token_info( ... username, password, request_token, ... ["READ_PUBLIC", "READ_PRIVATE", "NO_SUCH_ACCESS_LEVEL"]) >>> print response['content-type'] application/json >>> json = simplejson.loads(content) >>> print sorted( ... [level['value'] for level in json['access_levels']]) ['READ_PRIVATE', 'READ_PUBLIC', 'UNAUTHORIZED'] Note that the nonexistent access level has been removed from the reconciled list, and the "Unauthorized" access level (which must always be an option) has been added. grant_access() ============== If you have the end-user's username and password, you can use grant_access() to authorize a request token. If you make an unauthorized request, you'll get a 401 error. (As with get_token_info(), Launchpad returns 200, but SimulatedLaunchpadBrowser sniffs it and changes it to a 401.) >>> access_level = "READ_PRIVATE" >>> response, content = browser.grant_access( ... "baduser", "badpasword", request_token, access_level, context) >>> print response.status 401 If you try to grant an invalid level of access, you'll get a 400 error. >>> response, content = browser.grant_access( ... username, password, request_token, ... "NO_SUCH_ACCESS_LEVEL") >>> print response.status 400 If you provide all the necessary information, you'll get a 200 response code and the request token will be authorized. >>> response, content = browser.grant_access( ... username, password, request_token, access_level) >>> print response.status 200 If you try to grant access to a request token that's already been authorized, you'll get a 409 error. >>> response, content = browser.grant_access( ... username, password, request_token, access_level) >>> print response.status 409 Now that the request token is authorized, we can exchange it for an access token. >>> credentials.exchange_request_token_for_access_token( ... web_root=web_root) >>> credentials.access_token.key is None False If you try to grant access to a request token that's already been exchanged for an access token, you'll get a 400 error. >>> response, content = browser.grant_access( ... username, password, request_token, access_level) >>> print response.status 400