docs: def generate_access_token_from_authorization_code(request, client):
    """ Generates a new AccessToken from a request with an authorization code.
  
    Read the specification: http://tools.ietf.org/html/rfc6749#section-4.1.3
    """
    authorization_code_value = request.POST.get('code')
    if not authorization_code_value:
      raise InvalidRequest('no "code" provided')
  
    try:
      authorization_code = AuthorizationCode.objects.get(
          value=authorization_code_value,
          client=client)
    except AuthorizationCode.DoesNotExist:
      raise InvalidGrant(
          '"{}" is not a valid "code"'.format(authorization_code_value))
  
    if authorization_code.is_expired():
      if authorization_code.invalidated:
        for access_token in authorization_code.access_tokens.all():
          access_token.invalidate()
  
      raise InvalidGrant('provided "code" is expired')
  
    # From http://tools.ietf.org/html/rfc6749#section-4.1.3:
    #
    #     redirect_uri
    #         REQUIRED, if the "redirect_uri" parameter was included in the
    #         authorization request as described in Section 4.1.1, and their
    #         values MUST be identical.
    #
    # and later,
    #
    #     The authorization server MUST:
    #
    #     [ ... snip ... ]
    #
    #     o  ensure that the "redirect_uri" parameter is present if the
    #        "redirect_uri" parameter was included in the initial authorization
    #        request as described in Section 4.1.1, and if included ensure that
    #        their values are identical.
    #
    # The 'redirect_uri' attribute of an AuthorizationCode will only be set if
    # the value was included as a parameter during the related authorization
    # request.
    if (authorization_code.redirect_uri and
        authorization_code.redirect_uri != request.POST.get('redirect_uri')):
      raise InvalidRequest('"redirect_uri" value must match the value from '
                           'the authorization code request')
  
    new_access_token = AccessToken.objects.create(
        user=authorization_code.user,
        client=authorization_code.client)
    new_access_token.scopes = authorization_code.scopes.all()
    new_access_token.authorization_code = authorization_code
    new_access_token.save()
  
    # Mark this token as expired so that any future requests with the same token
    # can be handled with the correct behavior. From
    # http://tools.ietf.org/html/rfc6749#section-4.1.2 :
  
    #     The client MUST NOT use the authorization code more than once.
    authorization_code.invalidate()
  
    return new_access_token