Ë
    ‡Î”aZy  ã                   ó<  — d dl mZ 	 eZg d¢Z	 d dlmZ 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	 d dlmZ 	 d dlmZ 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„ Z3d„ Z4 G d„ de&«      Z5 G d„ de$«      Z# G d„ de$«      Z6 G d„ de7«      Z8 G d„ de8«      Z9 G d„ d e8«      Z: G d!„ d"e8«      Z; G d#„ d$e7«      Z< G d%„ d&e<«      Z= G d'„ d(e=«      Z> G d)„ d*e?«      Z@ G d+„ d,e@«      ZA G d-„ d.e@«      ZB G d/„ d0eB«      ZC G d1„ d2eB«      ZD G d3„ d4eD«      ZE G d5„ d6e@«      ZF G d7„ d8e@«      ZG G d9„ d:e@«      ZH G d;„ d<e@«      ZIy# e$ r
 d dlmZ Y �Œaw xY w# e$ r
 d dlmZ Y �ŒLw xY w# e$ r
 d dlmZ Y �ŒWw xY w)=é    )Ú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                  óT   — t        t        j                  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© ó    ú:/usr/lib/python3/dist-packages/launchpadlib/credentials.pyÚ$_ssl_certificate_validation_disabledr!   V   s   € ô ”—
‘
—‘ÐFÈÓNÓOÐOr   c                 ó¾   — t        «       }t        j                  |¬«      j                  | d|t	        |«      ¬«      \  }}|j
                  dk7  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Úcontents         r    Ú
_http_postr2   c   sa   € ô 9Ó:€MÜ Ÿ™Ø+8ôç�gˆc˜&¨'¼	À&Ó8I€gÓJñ €Hˆgð ‡�˜#ÒÜ˜ 'Ó*Ð*Ø�WÐÐr   c                   óz   — e Zd ZdZdZdZdZdZdZd„ Z	e
d„ «       Zdej                  efd	„Zej                  fd
„Zy)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                 óž   — t        «       }| j                  |«       |j                  «       }t        |t        «      r|j                  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Ú
serializeds      r    Ú	serializezCredentials.serialize‚   sA   € ô
 ‹jˆØ�	‰	�#ŒØ—\‘\“^ˆ
Ü�j¤,Ô/Ø#×*Ñ*¨7Ó3ˆJØÐr   c                 óŠ   —  | «       }t        |t        «      s|j                  d«      }|j                  t	        |«      «       |S )z}Create a `Credentials` object from a serialized string.

        This should probably be moved into OAuthAuthorizer.
        r8   )r;   r<   ÚdecodeÚloadr   )ÚclsÚvalueÚcredentialss      r    Úfrom_stringzCredentials.from_stringŽ   s;   € ñ “eˆÜ˜%¤Ô.Ø—L‘L Ó)ˆEØ×Ñœ %›Ô)ØÐr   c                 óž  — | j                   €J d«       ‚| j                  �J d«       ‚t        j                  |«      }t	        | j                   j
                  dd¬«      }|t        z   }d|i}|| j                  k(  rd|d<   t        |||«      \  }}t        |t        «      r|j                  d	«      }|| j                  k(  r8t        j                  |«      }|�||d
<   t        j                  |«      | _        |S t        j#                  |«      | _        |›t$        ›d| j                   j
                  ›�}|�|| j                   _        |d|z  z  }|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.
        zConsumer not specified.zAccess token already obtained.Ú	PLAINTEXTú&)Úoauth_consumer_keyÚoauth_signature_methodÚoauth_signatureÚRefererzapplication/jsonÚAcceptr8   ú
lp.contextú?oauth_token=z&lp.context=%s)ÚconsumerÚaccess_tokenr   Úlookup_web_rootr5   ÚkeyÚrequest_token_pageÚDICT_TOKEN_FORMATr2   r;   ÚbytesrC   ÚjsonÚloadsr   Úfrom_paramsÚ_request_tokenrH   Úauthorize_token_pageÚcontext)	r>   r_   Úweb_rootÚtoken_formatr.   r-   r&   r0   r1   s	            r    Úget_request_tokenzCredentials.get_request_tokenš   sW  € ð8 �}‰}Ð(ÐCÐ*CÓCÐ(Ø× Ñ Ð(ÐJÐ*JÓJÐ(Ü×'Ñ'¨Ó1ˆÜØ#Ÿ}™}×0Ñ0Ø#.Øô
ˆð
 Ô+Ñ+ˆØ˜hÐ'ˆØ˜4×1Ñ1Ò1Ø 2ˆG�HÑÜ& s¨G°VÓ<Ñˆ�'Ü�gœuÔ%Ø—n‘n WÓ-ˆGØ˜4×1Ñ1Ò1Ü—Z‘Z Ó(ˆFØÐ"Ø'.��|Ñ$Ü"-×"9Ñ"9¸&Ó"AˆDÔØˆMä"-×"9Ñ"9¸'Ó"BˆDÔáÞ$Ø×#Ñ#×'Ò'ðˆCð
 Ð"Ø.5�×#Ñ#Ô+ØÐ'¨'Ñ1Ñ1�ØˆJr   c                 ó^  — | j                   €J d«       ‚t        j                  |«      }t        | j                  j
                  d| j                   j
                  d| j                   j                  z  ¬«      }|t        z   }d|i}t        |||«      \  }}t        j                  |«      | _        y)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.rJ   z&%s)rL   rM   Úoauth_tokenrN   rO   )r]   r   rU   r5   rS   rV   ÚsecretÚaccess_token_pager2   r   rH   rT   )r>   r`   r.   r-   r&   r0   r1   s          r    Ú'exchange_request_token_for_access_tokenz3Credentials.exchange_request_token_for_access_token×   s¬   € ð ×ÑÐ+ð	CàBó	CØ+ä×'Ñ'¨Ó1ˆÜØ#Ÿ}™}×0Ñ0Ø#.Ø×+Ñ+×/Ñ/Ø! D×$7Ñ$7×$>Ñ$>Ñ>ô	
ˆð Ô*Ñ*ˆØ˜hÐ'ˆÜ& s¨G°VÓ<Ñˆ�'Ü'×3Ñ3°GÓ<ˆÕr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r]   ÚURI_TOKEN_FORMATrX   ÚITEM_SEPARATORÚNEWLINErA   ÚclassmethodrH   r   ÚSTAGING_WEB_ROOTrb   rg   r   r   r    r
   r
   r   sd   „ ñð €NàÐØÐØ€NØ€Gò
ð ñ	ó ð	ð Ø×&Ñ&Ø%ó	;ð| ×,Ñ,ô=r   r
   c                   ó0   — e Zd ZdZed„ «       Zed„ «       Zy)r   zAn OAuth access token.c                 óL   — |d   }|d   }|j                  d«      } | |||«      S )z:Create and return a new `AccessToken` from the given dict.rd   Úoauth_token_secretrQ   )r   )rE   r.   rV   re   r_   s        r    r\   zAccessToken.from_params÷   s6   € ð �]Ñ#ˆØÐ,Ñ-ˆØ—*‘*˜\Ó*ˆÙ�3˜ Ó(Ð(r   c                 óH  — t        |t        «      s|j                  d«      }t        |d¬«      }|d   }t	        |«      dk(  sJ d«       ‚|d   }|d   }t	        |«      dk(  sJ d	«       ‚|d   }|j                  d
«      }|�t	        |«      dk(  sJ d«       ‚|d   } | |||«      S )z<Create and return a new `AccessToken` from the given string.r8   F)Úkeep_blank_valuesrd   r   z/Query string must have exactly one oauth_token.r   rs   z*Query string must have exactly one secret.rQ   z*Query string must have exactly one context)r;   r<   rC   r   Úlenr   )rE   Úquery_stringr.   rV   re   r_   s         r    rH   zAccessToken.from_stringÿ   sÇ   € ô ˜,¬Ô5Ø'×.Ñ.¨wÓ7ˆLÜ˜,¸%Ô@ˆØ�]Ñ#ˆÜ�3‹x˜1Š}ÐOÐOÓOˆ}Ø�!‰fˆØÐ,Ñ-ˆÜ�6‹{˜aÒÐMÐ!MÓMÐØ˜‘ˆØ—*‘*˜\Ó*ˆØÐä�G“ Ò!ð<à;ó<Ø!à˜a‘jˆGÙ�3˜ Ó(Ð(r   N)rh   ri   rj   rk   ro   r\   rH   r   r   r    r   r   ô   s+   „ Ù àñ)ó ð)ð ñ)ó ñ)r   r   c                   ó"   ‡ — e Zd ZdZˆ fd„Zˆ xZS )r   zoAn OAuth access token that doesn't authenticate anybody.

    This token can be used for anonymous access.
    c                 ó.   •— t         t        | �  dd«       y )NÚ )Úsuperr   Ú__init__)r>   Ú	__class__s    €r    r|   zAnonymousAccessToken.__init__  s   ø€ ÜÔ" DÑ2°2°rÕ:r   )rh   ri   rj   rk   r|   Ú__classcell__©r}   s   @r    r   r     s   ø„ ñ÷
;ð ;r   r   c                   ó0   — e Zd ZdZdd„Zd„ Zd„ Zd„ Zd„ Zy)	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                 ó   — || _         y)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)r>   r‚   s     r    r|   zCredentialStore.__init__&  s   € ð '=ˆÕ#r   c                 ó¨   — 	 | j                  ||«       |S # t        $ r ‚ t        $ r)}| j                  €|‚| j                  «        Y d}~|S d}~ww xY 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Ú	Exceptionr‚   )r>   rG   Úunique_consumer_idÚes       r    r9   zCredentialStore.save0  sa   € ð	*Ø�L‰L˜Ð&8Ô9ð Ðøô  ò 	ØÜò 	*Ø×*Ñ*Ð2Ø�Ø×'Ñ'×)Ð)ØÐûð		*ús   ‚ –A¨AÁA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)r>   rG   r‡   s      r    r„   zCredentialStore.do_save@  s   € ô "Ó#Ð#r   c                 ó$   — | j                  |«      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©r>   Ú
unique_keys     r    rD   zCredentialStore.loadI  s   € ð  �|‰|˜JÓ'Ð'r   c                 ó   — t        «       ‚)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.
        rŠ   rŽ   s     r    r�   zCredentialStore.do_load[  s   € ô "Ó#Ð#r   ©N)	rh   ri   rj   rk   r|   r9   r„   rD   r�   r   r   r    r   r     s    „ ñó=òò $ò(ó$$r   r   c                   óD   ‡ — e Zd ZdZdZdˆ fd„	Zed„ «       Zd„ Zd„ Z	ˆ x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>c                 ó`   •— t         t        | �  |«       d | _        |rt	        |«      | _        y y r‘   )r{   r“   r|   Ú	_fallbackÚMemoryCredentialStore)r>   r‚   Úfallbackr}   s      €r    r|   zKeyringCredentialStore.__init__s  s0   ø€ ÜÔ$ dÑ4Ð5KÔLØˆŒÙÜ2Ð3IÓJˆD�Nð r   c                  óv   — dt        «       vrddladt        «       vr	 ddlma yy# t        $ r	 t
        aY yw xY w)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    Ú_ensure_keyring_importedz/KeyringCredentialStore._ensure_keyring_importedy  s>   € ð œG›IÑ%ãØ¤7£9Ñ,ð.Þ9ð -øô ò .Ü!-’ð.ús   ž& ¦8·8c                 óx  — | j                  «        |j                  «       }| j                  t        |«      z   }	 t        j                  d||j                  d«      «       y# t        $ rO}t        t        k(  rdt        |«      vr‚ | j                  r| j                  j                  ||«       n‚ Y d}~yd}~ww xY w)z2Store newly-authorized credentials in the keyring.Úlaunchpadlibr8   ú$No recommended backend was availableN)rŸ   rA   Ú	B64MARKERr   r™   Úset_passwordrC   rš   rž   Ústrr•   r9   )r>   rG   r�   r@   rˆ   s        r    r„   zKeyringCredentialStore.do_saveŒ  s¤   € à×%Ñ%Ô'Ø ×*Ñ*Ó,ˆ
ð —^‘^¤i°
Ó&;Ñ;ˆ
ð	Ü× Ñ Ø 
¨J×,=Ñ,=¸gÓ,Fõøô ò 	ô ¤,Ò.Ø:Ä#ÀaÃ&ÑHàØ�~Š~Ø—‘×#Ñ# K°Õ<àô =ûð	ús   º&A! Á!	B9Á*AB4Â4B9c                 ó0  — | j                  «        	 t        j                  d|«      }|�vt        |t        «      r|j                  d«      }|j                  | j                  «      r"	 t        |t        | j                  «      d «      }	 t         j#                  |«      }|S y# t        $ rM}t        t        k(  rdt        |«      vr‚ | j                  r | j                  j                  |«      cY d}~S ‚ d}~ww xY w# t        $ r Y yw xY w# t$        $ r Y yw xY w)z&Retrieve credentials from the keyring.r¡   r¢   NÚutf8)rŸ   r™   Úget_passwordrš   rž   r¥   r•   rD   r;   r<   r=   Ú
startswithr£   r   rv   Ú	TypeErrorr
   rH   r†   )r>   r�   Úcredential_stringrˆ   rG   s        r    r�   zKeyringCredentialStore.do_load¥  s  € à×%Ñ%Ô'ð	Ü '× 4Ñ 4Ø 
ó!Ðð Ð(ÜÐ+¬\Ô:Ø$5×$<Ñ$<¸VÓ$DÐ!Ø ×+Ñ+¨D¯N©NÔ;ð Ü(1Ø)¬#¨d¯n©nÓ*=Ð*?Ð@ó)Ð%ðÜ)×5Ñ5Ð6GÓH�Ø"Ð"ð øôA ò 	ô ¤,Ò.Ø:Ä#ÀaÃ&ÑHàØ�~Š~Ø—~‘~×*Ñ*¨:Ó6Õ6àûð	ûô( !ò  ñ  ð ûô ò ñ ð	úsH   ’B! Á'!C: Â	D	 Â!	C7Â*AC2Ã+C7Ã1C2Ã2C7Ã:	DÄDÄ		DÄD)NF)rh   ri   rj   rk   r£   r|   ÚstaticmethodrŸ   r„   r�   r~   r   s   @r    r“   r“   i  s3   ø„ ñð €IõKð ñ.ó ð.ò$ö2'r   r“   c                   ó0   ‡ — e Zd ZdZdˆ fd„	Zd„ Zd„ Zˆ x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.
    c                 ó:   •— t         t        | �  |«       || _        y r‘   )r{   r®   r|   Úfilename)r>   r°   r‚   r}   s      €r    r|   z'UnencryptedFileCredentialStore.__init__Ö  s   ø€ ÜÔ,¨dÑ<Ø"ô	
ð !ˆ�r   c                 ó:   — |j                  | j                  «       y)zSave the credentials to disk.N)Úsave_to_pathr°   ©r>   rG   r�   s      r    r„   z&UnencryptedFileCredentialStore.do_saveÜ  s   € à× Ñ  §¡Õ/r   c                 óú   — t         j                  j                  | j                  «      rRt        j                  | j                  «      t        j
                     dk(  st        j                  | j                  «      S y)zLoad the credentials from disk.r   N)r   ÚpathÚexistsr°   ÚstatÚST_SIZEr
   Úload_from_pathrŽ   s     r    r�   z&UnencryptedFileCredentialStore.do_loadà  sN   € ô �G‰G�N‰N˜4Ÿ=™=Ô)Ü—G‘G˜DŸM™MÓ*¬4¯<©<Ñ8¸AÒ=ä×-Ñ-¨d¯m©mÓ<Ð<Ør   r‘   ©rh   ri   rj   rk   r|   r„   r�   r~   r   s   @r    r®   r®   Ï  s   ø„ ñõ!ò0ör   r®   c                   ó0   ‡ — e Zd ZdZdˆ fd„	Zd„ Zd„ Zˆ xZS )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.
    c                 ó:   •— t         t        | �  |«       i | _        y r‘   )r{   r–   r|   Ú_credentials)r>   r‚   r}   s     €r    r|   zMemoryCredentialStore.__init__ñ  s   ø€ ÜÔ# TÑ3Ð4JÔKØˆÕr   c                 ó"   — || j                   |<   y)z!Store the credentials in our dictN)r½   r³   s      r    r„   zMemoryCredentialStore.do_saveõ  s   € à(3ˆ×Ñ˜*Ò%r   c                 ó8   — | j                   j                  |«      S )z&Retrieve the credentials from our dict)r½   r   rŽ   s     r    r�   zMemoryCredentialStore.do_loadù  s   € à× Ñ ×$Ñ$ ZÓ0Ð0r   r‘   rº   r   s   @r    r–   r–   ê  s   ø„ ñõò4ö1r   r–   c                   óJ   — e Zd ZdZdZ	 	 	 d
d„Zed„ «       Zd„ Zd„ Z	d„ Z
d	„ Zy)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                 ó$  — t        j                  |«      | _        t        j                  |«      | _        |€|€t        d«      ‚|�|�t        d|›d|›d�«      ‚|€dg}t        |«      }nt        |«      }|}|| _        || _	        |xs g | _
        y)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.zOYou must provide only one of application_name and consumer_name. (You provided z and z.)ÚDESKTOP_INTEGRATION)r   Úlookup_service_rootÚservice_rootÚweb_root_for_service_rootr`   Ú
ValueErrorr   r	   rS   Úapplication_nameÚallow_access_levels)r>   rÅ   rÈ   Úconsumer_namerÉ   rS   s         r    r|   z(RequestTokenAuthorizationEngine.__init__	  s·   € ô@ !×4Ñ4°\ÓBˆÔÜ×6Ñ6°|ÓDˆŒàÐ#¨Ð(=ÜØLóð ð Ð'¨MÐ,EÝò $¢]ð4óð ð Ð ð $9Ð"9ÐÜ)Ð*:Ó;‰Hô   Ó.ˆHØ,Ðà ˆŒØ 0ˆÔà#6Ò#<¸"ˆÕ r   c                 óN   — | j                   j                  dz   | j                  z   S )z7Return a string identifying this consumer on this host.ú@)rS   rV   rÅ   )r>   s    r    r‡   z2RequestTokenAuthorizationEngine.unique_consumer_idI  s$   € ð �}‰}× Ñ  3Ñ&¨×):Ñ):Ñ:Ð:r   c                 óº   — t         ›d|›�}d}t        | j                  «      dkD  r!|||j                  | j                  «      z   z  }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.
        rR   z&allow_permission=r   )r^   rv   rÉ   Újoinr   r`   )r>   Úrequest_tokenÚpageÚallow_permissions       r    Úauthorization_urlz1RequestTokenAuthorizationEngine.authorization_urlN  sc   € ö ';¹MÐJˆØ/ÐÜˆt×'Ñ'Ó(¨1Ò,ØÐ$Ð'7×'<Ñ'<Ø×(Ñ(ó(ñ ñ ˆDô �t—}‘} dÓ+Ð+r   c                 óž   — | j                  |«      }| j                  ||«       |j                  €y|j                  || 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)rb   Úmake_end_user_authorize_tokenrT   r9   r‡   )r>   rG   Úcredential_storeÚrequest_token_strings       r    Ú__call__z(RequestTokenAuthorizationEngine.__call__]  sQ   € ð(  $×5Ñ5°kÓBÐà×*Ñ*¨;Ð8LÔMØ×#Ñ#Ð+àà×Ñ˜k¨4×+BÑ+BÔCØÐr   c                 ób   — |j                  | j                  t        j                  ¬«      }|d   S )z\Get a new request token from the server.

        :param return: The request token.
        )r`   ra   rd   )rb   r`   r
   rX   )r>   rG   Úauthorization_jsons      r    rb   z1RequestTokenAuthorizationEngine.get_request_token{  s6   € ð
 )×:Ñ:Ø—]‘]´×1NÑ1Nð ;ó 
Ðð " -Ñ0Ð0r   c                 ó   — t        «       ‚)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.
        rŠ   )r>   rG   rÏ   s      r    rÔ   z=RequestTokenAuthorizationEngine.make_end_user_authorize_token…  s   € ô "Ó#Ð#r   ©NNN)rh   ri   rj   rk   ÚUNAUTHORIZED_ACCESS_LEVELr|   Úpropertyr‡   rÒ   r×   rb   rÔ   r   r   r    r   r   þ  sH   „ ñð !/Ðð
 ØØ ó>=ð@ ñ;ó ð;ò,òò<1ó$r   r   c                   ó6   — e Zd ZdZdZdZd„ Zd„ Zd„ Zd„ Z	d„ Z
y	)
Ú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                 ó   — t        |«       y)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)r>   Úmessages     r    Úoutputz#AuthorizeRequestTokenWithURL.output¥  s   € ô 	ˆg�r   c                 ó@   — | j                  | j                  |z  «       y)úNotify the end-user of the URL.N)rã   ÚWAITING_FOR_USER)r>   rÒ   s     r    Ú!notify_end_user_authorization_urlz>AuthorizeRequestTokenWithURL.notify_end_user_authorization_url®  s   € à�‰�D×)Ñ)Ð,=Ñ=Õ>r   c                 ó\  — 	 |j                  | j                  «       |j                  duS # t        $ rw}|j                  j                  dk(  rt        |j                  «      ‚|j                  j                  dk7  rt        d«       t        |«       t        |j                  «      ‚d}~ww xY w)z Check if the end-user authorizedi“  i‘  z#Unexpected response from Launchpad:N)
rg   r`   r   r0   r,   ÚEndUserDeclinedAuthorizationr1   rá   ÚEndUserNoAuthorizationrT   )r>   rG   rˆ   s      r    Úcheck_end_user_authorizationz9AuthorizeRequestTokenWithURL.check_end_user_authorization²  s’   € ð	8Ø×?Ñ?ÀÇÁÔNð ×'Ñ'¨tÐ3Ð3øô ò 	8Ø�z‰z× Ñ  CÒ'ô 3°1·9±9Ó=Ð=à—:‘:×$Ñ$¨Ò+äÐ?Ô@Ü˜!”Hä,¨Q¯Y©YÓ7Ð7ûð	8ús   ‚+ «	B+´A2B&Â&B+c                 ó„   — | j                  | j                  «       t        j                  «        | j	                  |«       y)ú"Wait for the end-user to authorizeN)rã   ÚWAITING_FOR_LAUNCHPADr   Úreadlinerë   )r>   rG   s     r    Úwait_for_end_user_authorizationz<AuthorizeRequestTokenWithURL.wait_for_end_user_authorizationÄ  s,   € à�‰�D×.Ñ.Ô/Ü�‰ÔØ×)Ñ)¨+Õ6r   c                 ój   — | j                  |«      }| j                  |«       | j                  |«       y)z2Have the end-user authorize the token using a URL.N)rÒ   rç   rð   )r>   rG   rÏ   rÒ   s       r    rÔ   z:AuthorizeRequestTokenWithURL.make_end_user_authorize_tokenÊ  s0   € à ×2Ñ2°=ÓAÐØ×.Ñ.Ð/@ÔAØ×,Ñ,¨[Õ9r   N)rh   ri   rj   rk   ræ   rî   rã   rç   rë   rð   rÔ   r   r   r    rß   rß   –  s3   „ ñð	;ð ð MÐòò?ò4ò$7ó:r   rß   c                   óN   ‡ — e Zd ZdZdZdZdZdZdZ	 	 	 d
ˆ fd„	Z	ˆ fd„Z
d	„ Zˆ x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...c                 ó2   •— t         t        | �  ||d|«       y)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)r{   r   r|   )r>   rÅ   rÈ   rÊ   r‚   rÉ   r}   s         €r    r|   z)AuthorizeRequestTokenWithBrowser.__init__ò  s    ø€ ô. 	Ô.°Ñ>ØÐ*¨DÐ2Hõ	
r   c                 ó¸  •— t         t        | �  |«       	 t        j                  «       }t        |dd«      }|| j                  v }|r_| j                  | j                  | j                  z  «       t        t        gg g | j                  «      \  }}}|rt        j                  «        |�t        j                  |«       yy# t        j                  $ r d}d}Y Œ“w xY w)rå   ÚbasenameNF)r{   r   rç   Ú
webbrowserr   ÚgetattrÚTERMINAL_BROWSERSÚErrorrã   ÚTIMEOUT_MESSAGEÚTIMEOUTr   r   rï   Úopen)r>   rÒ   Úbrowser_objÚbrowserÚconsole_browserÚrlistÚ_r}   s          €r    rç   zBAuthorizeRequestTokenWithBrowser.notify_end_user_authorization_url  sÉ   ø€ äÜ,¨dñ	,à,=Ô
>ð	$Ü$Ÿ.™.Ó*ˆKÜ˜k¨:°tÓ<ˆGØ%¨×)?Ñ)?Ð?ˆOñ
 Ø�K‰K˜×,Ñ,¨t¯|©|Ñ;Ô<ô !¤% ¨"¨b°$·,±,Ó?‰KˆE�1�aÙÜ—‘Ô àÐ"Ü�O‰OÐ-Õ.ð #øô ×Ñò 	$ØˆKØ#ŠOð	$ús   –/B? Â?CÃCc                 ón  — | j                  | j                  «       t        j                  «       }|j                  €kt        j                  t
        «       	 | j                  |«      ry	 t        j                  «       |t        z   k\  rt        dt        z  «      ‚|j                  €Œjyy# t        $ r Y ŒJw xY w)rí   NzTimed out after %d seconds.)
rã   rî   ÚtimerT   ÚsleepÚaccess_token_poll_timerë   rê   Úaccess_token_poll_timeoutÚTokenAuthorizationTimedOut)r>   rG   Ú
start_times      r    rð   z@AuthorizeRequestTokenWithBrowser.wait_for_end_user_authorization&  s¢   € à�‰�D×.Ñ.Ô/Ü—Y‘Y“[ˆ
Ø×&Ñ&Ð.Ü�J‰JÔ-Ô.ðØ×4Ñ4°[ÔAØð Bô �y‰y‹{˜jÔ+DÑDÒDÜ0Ø1Ô4MÑMóð ð ×&Ñ&Ó.øô
 *ò Ùðús   ÁB( Â(	B4Â3B4rÛ   )rh   ri   rj   rk   ræ   r  r  rÿ   rî   r|   rç   rð   r~   r   s   @r    r   r   Ñ  sL   ø„ ñð	;ð ð H€OØ€Gð	Ðð 	@ð ð Ø#Ø õ
ô6/ö2r   r   c                   ó   — e Zd Zy)ÚTokenAuthorizationExceptionN©rh   ri   rj   r   r   r    r  r  7  ó   „ Ør   r  c                   ó   — e Zd Zy)ÚRequestTokenAlreadyAuthorizedNr  r   r   r    r  r  ;  r  r   r  c                   ó   — e Zd ZdZy)ÚEndUserAuthorizationFailedz?Superclass exception for all failures of end-user authorizationN©rh   ri   rj   rk   r   r   r    r  r  ?  s   „ ÙIàr   r  c                   ó   — e Zd ZdZy)ré   zEnd-user declined authorizationNr  r   r   r    ré   ré   E  s   „ Ù)àr   ré   c                   ó   — e Zd ZdZy)rê   z*End-user did not perform any authorizationNr  r   r   r    rê   rê   K  s   „ Ù4àr   rê   c                   ó   — e Zd ZdZy)r  z<End-user did not perform any authorization in timeout periodNr  r   r   r    r  r  Q  s   „ ÙFàr   r  c                   ó   — e Zd Zy)ÚClientErrorNr  r   r   r    r  r  W  r  r   r  c                   ó   — e Zd Zy)ÚServerErrorNr  r   r   r    r  r  [  r  r   r  c                   ó   — e Zd Zy)ÚNoLaunchpadAccountNr  r   r   r    r!  r!  _  r  r   r!  c                   ó   — e Zd Zy)ÚTooManyAuthenticationFailuresNr  r   r   r    r#  r#  c  r  r   r#  )JÚ
__future__r   ÚtypeÚ__metaclass__Ú__all__Ú	cStringIOr   r�   Úior)   rZ   r   r   r·   Úsysr   r
  Úurllib.parser   Úurllibr   Úurlparserý   Úbase64r   r   Úsix.moves.urllib.parser   rY   r¥   Úunicoder<   Úlazr.restfulclient.errorsr   Ú"lazr.restfulclient.authorize.oauthr   Ú_AccessTokenr	   r   r   r¡   r   rW   rf   r^   r  r  ÚMemoryErrorÚKeyboardInterruptÚ
SystemExitr…   r!   r2   r
   r   Úobjectr   r“   r®   r–   r   rß   r   r†   r  r  r  ré   rê   r  r  r  r!  r#  r   r   r    ú<module>r8     s  ðõ" &à :à€ò€ðÝ"ó Û Û 	Ý Û Ý Û ð!Ý&ð!Ý$ó ÷õ
 ,àˆC�<à�Là€Lå /÷ó õ à%Ð Ø#Ð Ø)Ð ØÐ Ø#Ð àÐ!2°JÐ?Ð ò
Pòô=�/ô =ôD)�,ô )ô@;˜<ô ;ôH$�fô H$ôVc˜_ô côL _ô ô61˜Oô 1ô(U$ fô U$ôp8:Ð#Bô 8:ôvcÐ'Cô côL	 )ô 	ô	Ð$?ô 	ô	Ð!<ô 	ô	Ð#=ô 	ô	Ð7ô 	ô	Ð!7ô 	ô	Ð-ô 	ô	Ð-ô 	ô	Ð4ô 	ô	Ð$?õ 	øðC ò ßÐðûð ò !ß Ð ð!ûð ò !ß Ð ð!ús3   �E( ¶E: ½F Å(E7Å6E7Å:F	ÆF	ÆFÆF