o
    ‡Î”aZy  ã                   @   sÂ  d dl mZ 	 eZg d¢Zzd dlmZ W n ey$   d dlmZ Y nw d dl	Z	d dl
Z
d dlZd dlmZ d dlZd dlmZ d dlZzd dlmZ W n ey\   d dlmZ Y nw zd dlmZ W n eyt   d dlmZ Y nw d dlZd d	lmZmZ d d
lmZ eeu rŽeZneZd dl m!Z! d dl"m#Z$m%Z%m&Z&m'Z' d dl(m)Z) dZ*dZ+dZ,dZ-dZ.e/e0e1fZ2dd„ Z3dd„ Z4G dd„ de&ƒZ5G dd„ de$ƒZ#G dd„ de$ƒZ6G dd„ de7ƒZ8G dd „ d e8ƒZ9G d!d"„ d"e8ƒZ:G d#d$„ d$e8ƒZ;G d%d&„ d&e7ƒZ<G d'd(„ d(e<ƒZ=G d)d*„ d*e=ƒZ>G d+d,„ d,e?ƒZ@G d-d.„ d.e@ƒZAG d/d0„ d0e@ƒZBG d1d2„ d2eBƒZCG d3d4„ d4eBƒZDG d5d6„ d6eDƒZEG d7d8„ d8e@ƒZFG d9d:„ d:e@ƒZGG d;d<„ d<e@ƒZHG d=d>„ d>e@ƒZIdS )?é    )Úprint_function)ÚAccessTokenÚAnonymousAccessTokenÚ AuthorizeRequestTokenWithBrowserÚCredentialStoreÚRequestTokenAuthorizationEngineÚConsumerÚCredentials)ÚStringION)Úselect)Ústdin)Ú	urlencode)Úurljoin)Ú	b64decodeÚ	b64encode)Úparse_qs)Ú	HTTPError)r   r   ÚOAuthAuthorizerÚSystemWideConsumer)Úurisz+request-tokenz+access-tokenz+authorize-tokené   i„  c                   C   s   t tj dd¡ƒS )zûWhether the user has disabled SSL certificate connection.

    Some testing servers have broken certificates.  Rather than raising an
    error, we allow an environment variable,
    ``LP_DISABLE_SSL_CERTIFICATE_VALIDATION`` to disable the check.
    Ú%LP_DISABLE_SSL_CERTIFICATE_VALIDATIONF)ÚboolÚosÚenvironÚget© r   r   ú:/usr/lib/python3/dist-packages/launchpadlib/credentials.pyÚ$_ssl_certificate_validation_disabledV   s   
r   c                 C   sD   t ƒ }tj|d�j| d|t|ƒd�\}}|jdkrt||ƒ‚||fS )zàPOST to ``url`` with ``headers`` and a body of urlencoded ``params``.

    Wraps it up to make sure we avoid the SSL certificate validation if our
    environment tells us to.  Also, raises an error on non-200 statuses.
    )Ú"disable_ssl_certificate_validationÚPOST)ÚmethodÚheadersÚbodyéÈ   )r   Úhttplib2ÚHttpÚrequestr   Ústatusr   )Úurlr"   ÚparamsÚcert_disabledÚresponseÚcontentr   r   r   Ú
_http_postc   s   ÿ
þ

r.   c                   @   sX   e Zd ZdZdZdZdZdZdZdd„ Z	e
d	d
„ ƒZdejefdd„Zejfdd„ZdS )r	   zèStandard credentials storage and usage class.

    :ivar consumer: The consumer (application)
    :type consumer: `Consumer`
    :ivar access_token: Access information on behalf of the user
    :type access_token: `AccessToken`
    NÚuriÚdictz<BR>Ú
c                 C   s0   t ƒ }|  |¡ | ¡ }t|tƒr| d¡}|S )zeTurn this object into a string.

        This should probably be moved into OAuthAuthorizer.
        úutf-8)r
   ÚsaveÚgetvalueÚ
isinstanceÚunicode_typeÚencode)ÚselfÚsioÚ
serializedr   r   r   Ú	serialize‚   s   


zCredentials.serializec                 C   s,   | ƒ }t |tƒs| d¡}| t|ƒ¡ |S )z}Create a `Credentials` object from a serialized string.

        This should probably be moved into OAuthAuthorizer.
        r2   )r5   r6   ÚdecodeÚloadr
   )ÚclsÚvalueÚcredentialsr   r   r   Úfrom_stringŽ   s
   

zCredentials.from_stringc           	      C   sø   | j dus	J dƒ‚| jdu sJ dƒ‚t |¡}t| j jddd�}|t }d|i}|| jkr1d|d	< t|||ƒ\}}t	|t
ƒrC| d
¡}|| jkr]t |¡}|durU||d< t |¡| _|S t |¡| _d|t| jjf }|durz|| j_|d| 7 }|S )aã  Request an OAuth token to Launchpad.

        Also store the token in self._request_token.

        This method must not be called on an object with no consumer
        specified or if an access token has already been obtained.

        :param context: The context of this token, that is, its scope of
            validity within Launchpad.
        :param web_root: The URL of the website on which the token
            should be requested.
        :token_format: How the token should be
            presented. URI_TOKEN_FORMAT means just return the URL to
            the page that authorizes the token.  DICT_TOKEN_FORMAT
            means return a dictionary describing the token
            and the site's authentication policy.

        :return: If token_format is URI_TOKEN_FORMAT, the URL for the
            user to authorize the `AccessToken` provided by
            Launchpad. If token_format is DICT_TOKEN_FORMAT, a dict of
            information about the new access token.
        NzConsumer not specified.zAccess token already obtained.Ú	PLAINTEXTú&)Úoauth_consumer_keyÚoauth_signature_methodÚoauth_signatureÚRefererzapplication/jsonÚAcceptr2   ú
lp.contextz%s%s?oauth_token=%sz&lp.context=%s)ÚconsumerÚaccess_tokenr   Úlookup_web_rootr0   ÚkeyÚrequest_token_pageÚDICT_TOKEN_FORMATr.   r5   Úbytesr<   ÚjsonÚloadsr   Úfrom_paramsÚ_request_tokenrA   Úauthorize_token_pageÚcontext)	r8   rV   Úweb_rootÚtoken_formatr*   r)   r"   r,   r-   r   r   r   Úget_request_tokenš   s>   
ý




ýzCredentials.get_request_tokenc                 C   sl   | j dus	J dƒ‚t |¡}t| jjd| j jd| j j d�}|t }d|i}t|||ƒ\}}t	 
|¡| _dS )ad  Exchange the previously obtained request token for an access token.

        This method must not be called unless get_request_token() has been
        called and completed successfully.

        The access token will be stored as self.access_token.

        :param web_root: The base URL of the website that granted the
            request token.
        Nz5get_request_token() doesn't seem to have been called.rB   z&%s)rD   rE   Úoauth_tokenrF   rG   )rT   r   rL   r0   rJ   rM   ÚsecretÚaccess_token_pager.   r   rA   rK   )r8   rW   r*   r)   r"   r,   r-   r   r   r   Ú'exchange_request_token_for_access_token×   s   ÿ

üz3Credentials.exchange_request_token_for_access_token)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rT   ÚURI_TOKEN_FORMATrO   ÚITEM_SEPARATORÚNEWLINEr;   ÚclassmethodrA   r   ÚSTAGING_WEB_ROOTrY   r]   r   r   r   r   r	   r   s     

ü>ÿr	   c                   @   s(   e Zd ZdZedd„ ƒZedd„ ƒZdS )r   zAn OAuth access token.c                 C   s&   |d }|d }|  d¡}| |||ƒS )z:Create and return a new `AccessToken` from the given dict.rZ   Úoauth_token_secretrI   )r   )r>   r*   rM   r[   rV   r   r   r   rS   ÷   s   
zAccessToken.from_paramsc                 C   s¢   t |tƒs
| d¡}t|dd�}|d }t|ƒdksJ dƒ‚|d }|d }t|ƒdks0J d	ƒ‚|d }| d
¡}|durKt|ƒdksGJ dƒ‚|d }| |||ƒS )z<Create and return a new `AccessToken` from the given string.r2   F)Úkeep_blank_valuesrZ   r   z/Query string must have exactly one oauth_token.r   rg   z*Query string must have exactly one secret.rI   Nz*Query string must have exactly one context)r5   r6   r<   r   Úlenr   )r>   Úquery_stringr*   rM   r[   rV   r   r   r   rA   ÿ   s    


ÿzAccessToken.from_stringN)r^   r_   r`   ra   re   rS   rA   r   r   r   r   r   ô   s    
r   c                       s    e Zd ZdZ‡ fdd„Z‡  ZS )r   zoAn OAuth access token that doesn't authenticate anybody.

    This token can be used for anonymous access.
    c                    s   t t| ƒ dd¡ d S )NÚ )Úsuperr   Ú__init__©r8   ©Ú	__class__r   r   rm     s   zAnonymousAccessToken.__init__)r^   r_   r`   ra   rm   Ú__classcell__r   r   ro   r   r     s    r   c                   @   s:   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ ZdS )r   zÖStore OAuth credentials locally.

    This is a generic superclass. To implement a specific way of
    storing credentials locally you'll need to subclass this class,
    and implement `do_save` and `do_load`.
    Nc                 C   s
   || _ dS )a  Constructor.

        :param credential_save_failed: A callback to be invoked if the
            save to local storage fails. You should never invoke this
            callback yourself! Instead, you should raise an exception
            from do_save().
        N)Úcredential_save_failed©r8   rr   r   r   r   rm   &  s   
zCredentialStore.__init__c              
   C   s^   z	|   ||¡ W |S  ty   ‚  ty. } z| jdu r|‚|  ¡  W Y d}~|S d}~ww )zœSave the credentials and invoke the callback on failure.

        Do not override this method when subclassing. Override
        do_save() instead.
        N)Údo_saveÚEXPLOSIVE_ERRORSÚ	Exceptionrr   )r8   r@   Úunique_consumer_idÚer   r   r   r3   0  s   ú
€üzCredentialStore.savec                 C   ó   t ƒ ‚)zõStore newly-authorized credentials locally for later use.

        :param credentials: A Credentials object to save.
        :param unique_consumer_id: A string uniquely identifying an
            OAuth consumer on a Launchpad instance.
        ©ÚNotImplementedError)r8   r@   rw   r   r   r   rt   @  s   zCredentialStore.do_savec                 C   s
   |   |¡S )a0  Retrieve credentials from a local store.

        This method is the inverse of `save`.

        There's no special behavior in this method--it just calls
        `do_load`. There _is_ special behavior in `save`, and this
        way, developers can remember to implement `do_save` and
        `do_load`, not `do_save` and `load`.

        :param unique_key: A string uniquely identifying an OAuth consumer
            on a Launchpad instance.

        :return: A `Credentials` object if one is found in the local
            store, and None otherise.
        )Údo_load©r8   Ú
unique_keyr   r   r   r=   I  s   
zCredentialStore.loadc                 C   ry   )a@  Retrieve credentials from a local store.

        This method is the inverse of `do_save`.

        :param unique_key: A string uniquely identifying an OAuth consumer
            on a Launchpad instance.

        :return: A `Credentials` object if one is found in the local
            store, and None otherise.
        rz   r}   r   r   r   r|   [  s   zCredentialStore.do_load©N)	r^   r_   r`   ra   rm   r3   rt   r=   r|   r   r   r   r   r     s    

	r   c                       sB   e Zd ZdZdZd‡ fdd„	Zedd„ ƒZd	d
„ Zdd„ Z	‡  Z
S )ÚKeyringCredentialStorezöStore credentials in the GNOME keyring or KDE wallet.

    This is a good solution for desktop applications and interactive
    scripts. It doesn't work for non-interactive scripts, or for
    integrating third-party websites into Launchpad.
    s   <B64>NFc                    s,   t t| ƒ |¡ d | _|rt|ƒ| _d S d S r   )rl   r€   rm   Ú	_fallbackÚMemoryCredentialStore)r8   rr   Úfallbackro   r   r   rm   s  s
   ÿzKeyringCredentialStore.__init__c                   C   sL   dt ƒ vr	ddladt ƒ vr$z	ddlma W dS  ty#   taY dS w dS )aG  Ensure the keyring module is imported (postponing side effects).

        The keyring module initializes the environment-dependent backend at
        import time (nasty).  We want to avoid that initialization because it
        may do things like prompt the user to unlock their password store
        (e.g., KWallet).
        Úkeyringr   NÚNoKeyringError)r…   )Úglobalsr„   Úkeyring.errorsr…   ÚImportErrorÚRuntimeErrorr   r   r   r   Ú_ensure_keyring_importedy  s   
	

ÿüz/KeyringCredentialStore._ensure_keyring_importedc              
   C   sŽ   |   ¡  | ¡ }| jt|ƒ }zt d|| d¡¡ W dS  tyF } zttkr/dt	|ƒvr/‚ | j
r:| j
 ||¡ n‚ W Y d}~dS d}~ww )z2Store newly-authorized credentials in the keyring.Úlaunchpadlibr2   ú$No recommended backend was availableN)rŠ   r;   Ú	B64MARKERr   r„   Úset_passwordr<   r…   r‰   Ústrr�   r3   )r8   r@   r~   r:   rx   r   r   r   rt   Œ  s"   
ÿþ€÷zKeyringCredentialStore.do_savec              
   C   sê   |   ¡  zt d|¡}W n' ty3 } zttkrdt|ƒvr‚ | jr.| j |¡W  Y d}~S ‚ d}~ww |durst|t	ƒrB| 
d¡}| | j¡r`zt|t| jƒd… ƒ}W n
 ty_   Y dS w zt |¡}|W S  tyr   Y dS w dS )z&Retrieve credentials from the keyring.r‹   rŒ   NÚutf8)rŠ   r„   Úget_passwordr…   r‰   r�   r�   r=   r5   r6   r7   Ú
startswithr�   r   ri   Ú	TypeErrorr	   rA   rv   )r8   r~   Úcredential_stringrx   r@   r   r   r   r|   ¥  s@   ÿ€õ

ÿý
üzKeyringCredentialStore.do_load)NF)r^   r_   r`   ra   r�   rm   ÚstaticmethodrŠ   rt   r|   rq   r   r   ro   r   r€   i  s    
r€   c                       ó2   e Zd ZdZd	‡ fdd„	Zdd„ Zdd„ Z‡  ZS )
ÚUnencryptedFileCredentialStorez‘Store credentials unencrypted in a file on disk.

    This is a good solution for scripts that need to run without any
    user interaction.
    Nc                    s   t t| ƒ |¡ || _d S r   )rl   r—   rm   Úfilename)r8   r˜   rr   ro   r   r   rm   Ö  s   
ÿ
z'UnencryptedFileCredentialStore.__init__c                 C   s   |  | j¡ dS )zSave the credentials to disk.N)Úsave_to_pathr˜   ©r8   r@   r~   r   r   r   rt   Ü  s   z&UnencryptedFileCredentialStore.do_savec                 C   s4   t j | j¡rt  | j¡tj dkst | j¡S dS )zLoad the credentials from disk.r   N)r   ÚpathÚexistsr˜   ÚstatÚST_SIZEr	   Úload_from_pathr}   r   r   r   r|   à  s
   ÿz&UnencryptedFileCredentialStore.do_loadr   ©r^   r_   r`   ra   rm   rt   r|   rq   r   r   ro   r   r—   Ï  s
    r—   c                       r–   )
r‚   z¬CredentialStore that stores keys only in memory.

    This can be used to provide a CredentialStore instance without
    actually saving any key to persistent storage.
    Nc                    s   t t| ƒ |¡ i | _d S r   )rl   r‚   rm   Ú_credentialsrs   ro   r   r   rm   ñ  s   
zMemoryCredentialStore.__init__c                 C   s   || j |< dS )z!Store the credentials in our dictN)r¡   rš   r   r   r   rt   õ  s   zMemoryCredentialStore.do_savec                 C   s   | j  |¡S )z&Retrieve the credentials from our dict)r¡   r   r}   r   r   r   r|   ù  s   zMemoryCredentialStore.do_loadr   r    r   r   ro   r   r‚   ê  s
    r‚   c                   @   sP   e Zd ZdZdZ			ddd„Zedd„ ƒZdd	„ Zd
d„ Z	dd„ Z
dd„ ZdS )r   a/  The superclass of all request token authorizers.

    This base class does not implement request token authorization,
    since that varies depending on how you want the end-user to
    authorize a request token. You'll need to subclass this class and
    implement `make_end_user_authorize_token`.
    ÚUNAUTHORIZEDNc                 C   sŽ   t  |¡| _t  |¡| _|du r|du rtdƒ‚|dur(|dur(td||f ƒ‚|du r4dg}t|ƒ}nt|ƒ}|}|| _|| _	|pCg | _
dS )aD  Base class initialization.

        :param service_root: The root of the Launchpad instance being
            used.

        :param application_name: The name of the application that
            wants to use launchpadlib. This is used in conjunction
            with a desktop-wide integration.

            If you specify this argument, your values for
            consumer_name and allow_access_levels are ignored.

        :param consumer_name: The OAuth consumer name, for an
            application that wants its own point of integration into
            Launchpad. In almost all cases, you want to specify
            application_name instead and do a desktop-wide
            integration. The exception is when you're integrating a
            third-party website into Launchpad.

        :param allow_access_levels: A list of the Launchpad access
            levels to present to the user. ('READ_PUBLIC' and so on.)
            Your value for this argument will be ignored during a
            desktop-wide integration.
        :type allow_access_levels: A list of strings.
        Nz:You must provide either application_name or consumer_name.zZYou must provide only one of application_name and consumer_name. (You provided %r and %r.)ÚDESKTOP_INTEGRATION)r   Úlookup_service_rootÚservice_rootÚweb_root_for_service_rootrW   Ú
ValueErrorr   r   rJ   Úapplication_nameÚallow_access_levels)r8   r¥   r¨   Úconsumer_namer©   rJ   r   r   r   rm   	  s(    ÿþÿ
z(RequestTokenAuthorizationEngine.__init__c                 C   s   | j jd | j S )z7Return a string identifying this consumer on this host.ú@)rJ   rM   r¥   rn   r   r   r   rw   I  s   z2RequestTokenAuthorizationEngine.unique_consumer_idc                 C   s>   dt |f }d}t| jƒdkr||| | j¡ 7 }t| j|ƒS )zÞReturn the authorization URL for a request token.

        This is the URL the end-user must visit to authorize the
        token. How exactly does this happen? That depends on the
        subclass implementation.
        z%s?oauth_token=%sz&allow_permission=r   )rU   ri   r©   Újoinr   rW   )r8   Úrequest_tokenÚpageÚallow_permissionr   r   r   Úauthorization_urlN  s   ÿz1RequestTokenAuthorizationEngine.authorization_urlc                 C   s6   |   |¡}|  ||¡ |jdu rdS | || j¡ |S )ad  Authorize a token and associate it with the given credentials.

        If the credential store runs into a problem storing the
        credential locally, the `credential_save_failed` callback will
        be invoked. The callback will not be invoked if there's a
        problem authorizing the credentials.

        :param credentials: A `Credentials` object. If the end-user
            authorizes these credentials, this object will have its
            .access_token property set.

        :param credential_store: A `CredentialStore` object. If the
            end-user authorizes the credentials, they will be
            persisted locally using this object.

        :return: If the credentials are successfully authorized, the
            return value is the `Credentials` object originally passed
            in. Otherwise the return value is None.
        N)rY   Úmake_end_user_authorize_tokenrK   r3   rw   )r8   r@   Úcredential_storeÚrequest_token_stringr   r   r   Ú__call__]  s   

z(RequestTokenAuthorizationEngine.__call__c                 C   s   |j | jtjd�}|d S )z\Get a new request token from the server.

        :param return: The request token.
        )rW   rX   rZ   )rY   rW   r	   rO   )r8   r@   Úauthorization_jsonr   r   r   rY   {  s   ÿz1RequestTokenAuthorizationEngine.get_request_tokenc                 C   ry   )a5  Authorize the given request token using the given credentials.

        Your subclass must implement this method: it has no default
        implementation.

        Because an access token may expire or be revoked in the middle
        of a session, this method may be called at arbitrary points in
        a launchpadlib session, or even multiple times during a single
        session (with a different request token each time).

        In most cases, however, this method will be called at the
        beginning of a launchpadlib session, or not at all.
        rz   )r8   r@   r­   r   r   r   r±   …  s   z=RequestTokenAuthorizationEngine.make_end_user_authorize_token©NNN)r^   r_   r`   ra   ÚUNAUTHORIZED_ACCESS_LEVELrm   Úpropertyrw   r°   r´   rY   r±   r   r   r   r   r   þ  s    
û@

r   c                   @   s@   e Zd ZdZdZdZdd„ Zdd„ Zdd	„ Zd
d„ Z	dd„ Z
dS )ÚAuthorizeRequestTokenWithURLz–Authorize using a URL.

    This authorizer simply shows the URL for the user to open for
    authorization, and waits until the server responds.
    zŠPlease open this authorization page:
 (%s)
in your browser. Use your browser to authorize
this program to access Launchpad on your behalf.z.Press Enter after authorizing in your browser.c                 C   s   t |ƒ dS )z³Display a message.

        By default, prints the message to standard output. The message
        does not require any user interaction--it's solely
        informative.
        N)Úprint)r8   Úmessager   r   r   Úoutput¥  s   z#AuthorizeRequestTokenWithURL.outputc                 C   s   |   | j| ¡ dS )úNotify the end-user of the URL.N)r¼   ÚWAITING_FOR_USER)r8   r°   r   r   r   Ú!notify_end_user_authorization_url®  s   z>AuthorizeRequestTokenWithURL.notify_end_user_authorization_urlc              
   C   sp   z|  | j¡ W n* ty2 } z|jjdkrt|jƒ‚|jjdkr)tdƒ t|ƒ t|jƒ‚d}~ww |j	duS )z Check if the end-user authorizedi“  i‘  z#Unexpected response from Launchpad:N)
r]   rW   r   r,   r(   ÚEndUserDeclinedAuthorizationr-   rº   ÚEndUserNoAuthorizationrK   )r8   r@   rx   r   r   r   Úcheck_end_user_authorization²  s   

€õ
z9AuthorizeRequestTokenWithURL.check_end_user_authorizationc                 C   s"   |   | j¡ t ¡  |  |¡ dS )ú"Wait for the end-user to authorizeN)r¼   ÚWAITING_FOR_LAUNCHPADr   ÚreadlinerÂ   )r8   r@   r   r   r   Úwait_for_end_user_authorizationÄ  s   z<AuthorizeRequestTokenWithURL.wait_for_end_user_authorizationc                 C   s"   |   |¡}|  |¡ |  |¡ dS )z2Have the end-user authorize the token using a URL.N)r°   r¿   rÆ   )r8   r@   r­   r°   r   r   r   r±   Ê  s   

z:AuthorizeRequestTokenWithURL.make_end_user_authorize_tokenN)r^   r_   r`   ra   r¾   rÄ   r¼   r¿   rÂ   rÆ   r±   r   r   r   r   r¹   –  s    ÿ	r¹   c                       sP   e Zd ZdZdZdZdZdZdZ			d‡ fdd	„	Z	‡ fd
d„Z
dd„ Z‡  ZS )r   aS  Authorize using a URL that pops-up automatically in a browser.

    This authorizer simply opens up the end-user's web browser to a
    Launchpad URL and lets the end-user authorize the request token
    themselves.

    This is the same as its superclass, except this class also
    performs the browser automatic opening of the URL.
    z�The authorization page:
 (%s)
should be opening in your browser. Use your browser to authorize
this program to access Launchpad on your behalf.z/Press Enter to continue or wait (%d) seconds...é   )zwww-browserÚlinksÚlinks2ÚlynxÚelinkszelinks-liteÚnetrikÚw3mz5Waiting to hear from Launchpad about your decision...Nc                    s   t t| ƒ ||d|¡ dS )ao  Constructor.

        :param service_root: See `RequestTokenAuthorizationEngine`.
        :param application_name: See `RequestTokenAuthorizationEngine`.
        :param consumer_name: The value of this argument is
            ignored. If we have the capability to open the end-user's
            web browser, we must be running on the end-user's computer,
            so we should do a full desktop integration.
        :param credential_save_failed: See `RequestTokenAuthorizationEngine`.
        :param allow_access_levels: The value of this argument is
            ignored, for the same reason as consumer_name.
        N)rl   r   rm   )r8   r¥   r¨   rª   rr   r©   ro   r   r   rm   ò  s   
ÿz)AuthorizeRequestTokenWithBrowser.__init__c                    s¤   t t| ƒ |¡ zt ¡ }t|ddƒ}|| jv }W n tjy'   d}d}Y nw |rE|  | j	| j
 ¡ ttgg g | j
ƒ\}}}|rEt ¡  |durPt |¡ dS dS )r½   ÚbasenameNF)rl   r   r¿   Ú
webbrowserr   ÚgetattrÚTERMINAL_BROWSERSÚErrorr¼   ÚTIMEOUT_MESSAGEÚTIMEOUTr   r   rÅ   Úopen)r8   r°   Úbrowser_objÚbrowserÚconsole_browserÚrlistÚ_ro   r   r   r¿     s(   ÿþÿzBAuthorizeRequestTokenWithBrowser.notify_end_user_authorization_urlc                 C   s~   |   | j¡ t ¡ }|jdu r=t t¡ z
|  |¡rW dS W n	 ty'   Y nw t ¡ |t kr6t	dt ƒ‚|jdu sdS dS )rÃ   NzTimed out after %d seconds.)
r¼   rÄ   ÚtimerK   ÚsleepÚaccess_token_poll_timerÂ   rÁ   Úaccess_token_poll_timeoutÚTokenAuthorizationTimedOut)r8   r@   Ú
start_timer   r   r   rÆ   &  s    


ÿÿÿøz@AuthorizeRequestTokenWithBrowser.wait_for_end_user_authorizationr¶   )r^   r_   r`   ra   r¾   rÓ   rÔ   rÑ   rÄ   rm   r¿   rÆ   rq   r   r   ro   r   r   Ñ  s    ÿÿúr   c                   @   ó   e Zd ZdS )ÚTokenAuthorizationExceptionN©r^   r_   r`   r   r   r   r   râ   7  ó    râ   c                   @   rá   )ÚRequestTokenAlreadyAuthorizedNrã   r   r   r   r   rå   ;  rä   rå   c                   @   ó   e Zd ZdZdS )ÚEndUserAuthorizationFailedz?Superclass exception for all failures of end-user authorizationN©r^   r_   r`   ra   r   r   r   r   rç   ?  ó    rç   c                   @   ræ   )rÀ   zEnd-user declined authorizationNrè   r   r   r   r   rÀ   E  ré   rÀ   c                   @   ræ   )rÁ   z*End-user did not perform any authorizationNrè   r   r   r   r   rÁ   K  ré   rÁ   c                   @   ræ   )rß   z<End-user did not perform any authorization in timeout periodNrè   r   r   r   r   rß   Q  ré   rß   c                   @   rá   )ÚClientErrorNrã   r   r   r   r   rê   W  rä   rê   c                   @   rá   )ÚServerErrorNrã   r   r   r   r   rë   [  rä   rë   c                   @   rá   )ÚNoLaunchpadAccountNrã   r   r   r   r   rì   _  rä   rì   c                   @   rá   )ÚTooManyAuthenticationFailuresNrã   r   r   r   r   rí   c  rä   rí   )JÚ
__future__r   ÚtypeÚ__metaclass__Ú__all__Ú	cStringIOr
   rˆ   Úior%   rQ   r   r   r�   Úsysr   rÛ   Úurllib.parser   Úurllibr   ÚurlparserÏ   Úbase64r   r   Úsix.moves.urllib.parser   rP   r�   Úunicoder6   Úlazr.restfulclient.errorsr   Ú"lazr.restfulclient.authorize.oauthr   Ú_AccessTokenr   r   r   r‹   r   rN   r\   rU   rÝ   rÞ   ÚMemoryErrorÚKeyboardInterruptÚ
SystemExitru   r   r.   r	   r   Úobjectr   r€   r—   r‚   r   r¹   r   rv   râ   rå   rç   rÀ   rÁ   rß   rê   rë   rì   rí   r   r   r   r   Ú<module>   s‚   
ÿÿÿ
  
Kf ;f