def finish_oauth(self, code):
r = requests.post(self._login_uri("<STR_LIT>"), data={<EOL>"<STR_LIT:code>": code,<EOL>"<STR_LIT>": self.client_id,<EOL>"<STR_LIT>": self.client_secret<EOL>})<EOL>if r.status_code != <NUM_LIT:200>:<EOL><INDENT>raise ApiError("<STR_LIT>", status=r.status_code, json=r.json())<EOL><DEDENT>token = r.json()["<STR_LIT>"]<EOL>scopes = OAuthScopes.parse(r.json()["<STR_LIT>"])<EOL>expiry = datetime.now() + timedelta(seconds=r.json()['<STR_LIT>'])<EOL>refresh_token = r.json()['<STR_LIT>']<EOL>return token, scopes, expiry, refresh_token<EOL>
Given an OAuth Exchange Code, completes the OAuth exchange with the
authentication server.  This should be called once the user has already
been directed to the login_uri, and has been sent back after successfully
authenticating.  For example, in `Flask`_, this might be implemented as
a route like this::

   @app.route("/oauth-redirect")
   def oauth_redirect():
       exchange_code = request.args.get("code")
       login_client = LinodeLoginClient(client_id, client_secret)

       token, scopes = login_client.finish_oauth(exchange_code)

       # store the user's OAuth token in their session for later use
       # and mark that they are logged in.

       return redirect("/")

.. _Flask: http://flask.pocoo.org

:param code: The OAuth Exchange Code returned from the authentication
             server in the query string.
:type code: str

:returns: The new OAuth token, and a list of scopes the token has, when
          the token expires, and a refresh token that can generate a new
          valid token when this one is expired.
:rtype: tuple(str, list)

:raise ApiError: If the OAuth exchange fails.