U
    ]                     @   s   d Z zddlmZmZ W n$ ek
r<   ddlmZmZ Y nX ddlZddlZddlm	Z	 G dd de
ZG dd deZG d	d
 d
eZG dd deZG dd deeZG dd deeZdS )zJOSE utilities.    )HashableMappingN)rsac                       s$   e Zd ZdZdZ fddZ  ZS )abstractclassmethoda  Descriptor for an abstract classmethod.

    It augments the :mod:`abc` framework with an abstract
    classmethod. This is implemented as :class:`abc.abstractclassmethod`
    in the standard Python library starting with version 3.2.

    This particular implementation, allegedly based on Python 3.3 source
    code, is stolen from
    http://stackoverflow.com/questions/11217878/python-2-7-combine-abc-abstractmethod-and-classmethod.

    Tc                    s   d|_ tt| | d S )NT)__isabstractmethod__superr   __init__)selftarget	__class__ -/usr/lib/python3/dist-packages/josepy/util.pyr      s    zabstractclassmethod.__init__)__name__
__module____qualname____doc__r   r   __classcell__r   r   r   r   r      s   r   c                   @   sP   e Zd ZdZdd Zdd ZejjfddZ	dd	 Z
d
d Zdd Zdd ZdS )ComparableX509zWrapper for OpenSSL.crypto.X509** objects that supports __eq__.

    :ivar wrapped: Wrapped certificate or certificate request.
    :type wrapped: `OpenSSL.crypto.X509` or `OpenSSL.crypto.X509Req`.

    c                 C   s*   t |tjjs t |tjjs t|| _d S N)
isinstanceOpenSSLcryptoX509ZX509ReqAssertionErrorwrappedr	   r   r   r   r   r   '   s
     zComparableX509.__init__c                 C   s   t | j|S r   )getattrr   r	   namer   r   r   __getattr__,   s    zComparableX509.__getattr__c                 C   s.   t | jtjjrtjj}ntjj}||| jS )aL  Dumps the object into a buffer with the specified encoding.

        :param int filetype: The desired encoding. Should be one of
            `OpenSSL.crypto.FILETYPE_ASN1`,
            `OpenSSL.crypto.FILETYPE_PEM`, or
            `OpenSSL.crypto.FILETYPE_TEXT`.

        :returns: Encoded X509 object.
        :rtype: str

        )r   r   r   r   r   Zdump_certificateZdump_certificate_request)r	   Zfiletypefuncr   r   r   _dump/   s    
zComparableX509._dumpc                 C   s    t || jstS |  | kS r   )r   r   NotImplementedr"   r	   otherr   r   r   __eq__A   s    zComparableX509.__eq__c                 C   s   t | j|  fS r   )hashr   r"   r	   r   r   r   __hash__G   s    zComparableX509.__hash__c                 C   s
   | |k S r   r   r$   r   r   r   __ne__J   s    zComparableX509.__ne__c                 C   s   d | jj| jS Nz<{0}({1!r})>)formatr   r   r   r(   r   r   r   __repr__M   s    zComparableX509.__repr__N)r   r   r   r   r   r    r   r   ZFILETYPE_ASN1r"   r&   r)   r*   r-   r   r   r   r   r       s   r   c                   @   sD   e Zd ZdZeZdd Zdd Zdd Zdd	 Z	d
d Z
dd ZdS )ComparableKeyznComparable wrapper for ``cryptography`` keys.

    See https://github.com/pyca/cryptography/issues/2122.

    c                 C   s
   || _ d S r   )_wrappedr   r   r   r   r   Y   s    zComparableKey.__init__c                 C   s   t | j|S r   )r   r/   r   r   r   r   r    \   s    zComparableKey.__getattr__c                 C   s`   t || jr| jj|jjk	r tS t| jdr<|  | kS t| jdrX|  | kS tS d S )Nprivate_numberspublic_numbers)r   r   r/   r#   hasattrr0   r1   r$   r   r   r   r&   _   s    zComparableKey.__eq__c                 C   s
   | |k S r   r   r$   r   r   r   r*   k   s    zComparableKey.__ne__c                 C   s   d | jj| jS r+   )r,   r   r   r/   r(   r   r   r   r-   n   s    zComparableKey.__repr__c                 C   s   |  | j S )zGet wrapped public key.)r   r/   
public_keyr(   r   r   r   r3   q   s    zComparableKey.public_keyN)r   r   r   r   r#   r)   r   r    r&   r*   r-   r3   r   r   r   r   r.   Q   s   r.   c                   @   s   e Zd ZdZdd ZdS )ComparableRSAKeyzWrapper for ``cryptography`` RSA keys.

    Wraps around:

    - :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`
    - :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`

    c              	   C   sr   t | jtjrD|  }|j}t| j|j|j	|j
|j|j|j|jfS t | jtjrn|  }t| j|j|jfS d S r   )r   r/   r   ZRSAPrivateKeyWithSerializationr0   r1   r'   r   pqZdmp1Zdmq1ZiqmpneZRSAPublicKeyWithSerialization)r	   ZprivZpubr   r   r   r)      s       zComparableRSAKey.__hash__N)r   r   r   r   r)   r   r   r   r   r4   v   s   	r4   c                   @   sT   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd ZdS )ImmutableMapz5Immutable key to value mapping with attribute access.r   c                 K   s\   t |t | jkr8tdd| j|r0d|nd| jD ]}t| ||| q>d S )NzA__init__() takes exactly the following arguments: {0} ({1} given), Znone)set	__slots__	TypeErrorr,   joinobject__setattr__pop)r	   kwargsslotr   r   r   r      s    

zImmutableMap.__init__c                 K   s    t | }|| t| f |S )zReturn updated map.)dictupdatetype)r	   rB   itemsr   r   r   rE      s    
zImmutableMap.updatec                 C   s.   zt | |W S  tk
r(   t|Y nX d S r   )r   AttributeErrorKeyErrorr	   keyr   r   r   __getitem__   s    zImmutableMap.__getitem__c                 C   s
   t | jS r   )iterr<   r(   r   r   r   __iter__   s    zImmutableMap.__iter__c                 C   s
   t | jS r   )lenr<   r(   r   r   r   __len__   s    zImmutableMap.__len__c                    s   t t fdd jD S )Nc                 3   s   | ]}t  |V  qd S r   )r   ).0rC   r(   r   r   	<genexpr>   s     z(ImmutableMap.__hash__.<locals>.<genexpr>)r'   tupler<   r(   r   r(   r   r)      s    zImmutableMap.__hash__c                 C   s   t dd S Nzcan't set attributerH   r	   r   valuer   r   r   r@      s    zImmutableMap.__setattr__c              	   C   s&   d | jjddd t| D S )Nz{0}({1})r:   c                 s   s   | ]\}}d  ||V  qdS z	{0}={1!r}Nr,   rQ   rK   rW   r   r   r   rR      s   z(ImmutableMap.__repr__.<locals>.<genexpr>)r,   r   r   r>   sixZ	iteritemsr(   r   r   r   r-      s    zImmutableMap.__repr__N)r   r   r   r   r<   r   rE   rL   rN   rP   r)   r@   r-   r   r   r   r   r9      s   	r9   c                   @   s\   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd ZdS )
frozendictzFrozen dictionary.)_items_keysc              	   O   sj   |r|st |}n*t|dkr6t|d tr6|d }nt t| d| t| dttt	
| d S )N   r   r]   r^   )rD   rO   r   r   r=   r?   r@   rS   sortedr[   Ziterkeys)r	   argsrB   rG   r   r   r   r      s    

zfrozendict.__init__c                 C   s
   | j | S r   )r]   rJ   r   r   r   rL      s    zfrozendict.__getitem__c                 C   s
   t | jS r   )rM   r^   r(   r   r   r   rN      s    zfrozendict.__iter__c                 C   s
   t | jS r   )rO   r]   r(   r   r   r   rP      s    zfrozendict.__len__c                    s   t  fdd jD S )Nc                 3   s   | ]}| | fV  qd S r   r   )rQ   rK   r(   r   r   rR      s     z+frozendict._sorted_items.<locals>.<genexpr>)rS   r^   r(   r   r(   r   _sorted_items   s    zfrozendict._sorted_itemsc                 C   s   t |  S r   )r'   rb   r(   r   r   r   r)      s    zfrozendict.__hash__c                 C   s.   z| j | W S  tk
r(   t|Y nX d S r   )r]   rI   rH   r   r   r   r   r       s    zfrozendict.__getattr__c                 C   s   t dd S rT   rU   rV   r   r   r   r@      s    zfrozendict.__setattr__c                 C   s   d ddd |  D S )Nzfrozendict({0})r:   c                 s   s   | ]\}}d  ||V  qdS rX   rY   rZ   r   r   r   rR      s
    z&frozendict.__repr__.<locals>.<genexpr>)r,   r>   rb   r(   r   r   r   r-      s    zfrozendict.__repr__N)r   r   r   r   r<   r   rL   rN   rP   rb   r)   r    r@   r-   r   r   r   r   r\      s   r\   )r   Zcollections.abcr   r   ImportErrorcollectionsr   r[   Z)cryptography.hazmat.primitives.asymmetricr   classmethodr   r?   r   r.   r4   r9   r\   r   r   r   r   <module>   s   1%.