B
    ]bj                 @  s   d dl mZ d dlZd dlmZmZmZmZmZm	Z	m
Z
mZmZ ejdd dkr`d dlmZ neZddd	gZG d
d	 d	eZG dd de
eef ZG dd deZeee	eef eeeef  ef ZdS )    )annotationsN)	AnyDictIterableIteratorListMappingMutableMappingTupleUnion   )      )ProtocolHeadersHeadersLikeMultipleValuesErrorc                  s&   e Zd ZdZdd fddZ  ZS )r   zT
    Exception raised when :class:`Headers` has more than one value for a key.

    str)returnc               s&   t | jdkrt| jd S t  S )N   r   )lenargsreprsuper__str__)self)	__class__ 8lib/python3.7/site-packages/websockets/datastructures.pyr       s    zMultipleValuesError.__str__)__name__
__module____qualname____doc__r   __classcell__r   r   )r   r   r      s   c                  s  e Zd ZdZddgZdddddd	Zdd
ddZdd
ddZd d
ddZdd
ddZ	dddddZ
dd
ddZdd
ddZddddd Zdddd!d"d#Zdddd$d%Zd&dd'd(d)Zdd
d*d+Zdddd fd,d-Zdd.dd/d0Zd1d
d2d3Z  ZS )4r   a  
    Efficient data structure for manipulating HTTP headers.

    A :class:`list` of ``(name, values)`` is inefficient for lookups.

    A :class:`dict` doesn't suffice because header names are case-insensitive
    and multiple occurrences of headers with the same name are possible.

    :class:`Headers` stores HTTP headers in a hybrid data structure to provide
    efficient insertions and lookups while preserving the original data.

    In order to account for multiple values with minimal hassle,
    :class:`Headers` follows this logic:

    - When getting a header with ``headers[name]``:
        - if there's no value, :exc:`KeyError` is raised;
        - if there's exactly one value, it's returned;
        - if there's more than one value, :exc:`MultipleValuesError` is raised.

    - When setting a header with ``headers[name] = value``, the value is
      appended to the list of values for that header.

    - When deleting a header with ``del headers[name]``, all values for that
      header are removed (this is slow).

    Other methods for manipulating headers are consistent with this logic.

    As long as no header occurs multiple times, :class:`Headers` behaves like
    :class:`dict`, except keys are lower-cased to provide case-insensitivity.

    Two methods support manipulating multiple values explicitly:

    - :meth:`get_all` returns a list of all values for a header;
    - :meth:`raw_items` returns an iterator of ``(name, values)`` pairs.

    _dict_listr   r   None)r   kwargsr   c             O  s   i | _ g | _| j|| d S )N)r$   r%   update)r   r   r'   r   r   r   __init__P   s    zHeaders.__init__)r   c             C  s   d dd | jD d S )N c             s  s"   | ]\}}| d | dV  qdS )z: z
Nr   ).0keyvaluer   r   r   	<genexpr>V   s    z"Headers.__str__.<locals>.<genexpr>z
)joinr%   )r   r   r   r   r   U   s    zHeaders.__str__c             C  s   | j j d| jdS )N())r   r   r%   )r   r   r   r   __repr__X   s    zHeaders.__repr__c             C  s$   |   }| j |_| j |_|S )N)r   r$   copyr%   )r   r3   r   r   r   r3   [   s    zHeaders.copybytesc             C  s   t |  S )N)r   encode)r   r   r   r   	serializea   s    zHeaders.serializeobjectbool)r,   r   c             C  s   t |to| | jkS )N)
isinstancer   lowerr$   )r   r,   r   r   r   __contains__g   s    zHeaders.__contains__zIterator[str]c             C  s
   t | jS )N)iterr$   )r   r   r   r   __iter__j   s    zHeaders.__iter__intc             C  s
   t | jS )N)r   r$   )r   r   r   r   __len__m   s    zHeaders.__len__c             C  s.   | j |  }t|dkr"|d S t|d S )Nr   r   )r$   r:   r   r   )r   r,   r-   r   r   r   __getitem__r   s    zHeaders.__getitem__)r,   r-   r   c             C  s,   | j | g | | j||f d S )N)r$   
setdefaultr:   appendr%   )r   r,   r-   r   r   r   __setitem__y   s    zHeaders.__setitem__c               s.   |   | j   fdd| jD | _d S )Nc               s$   g | ]\}}|   kr||fqS r   )r:   )r+   kv)	key_lowerr   r   
<listcomp>   s    z'Headers.__delitem__.<locals>.<listcomp>)r:   r$   __delitem__r%   )r   r,   r   )rF   r   rH   }   s    zHeaders.__delitem__r   )otherr   c             C  s   t |tstS | j|jkS )N)r9   r   NotImplementedr$   )r   rI   r   r   r   __eq__   s    
zHeaders.__eq__c             C  s   i | _ g | _dS )z&
        Remove all headers.

        N)r$   r%   )r   r   r   r   clear   s    zHeaders.clearc               s$   t dd |D }t j|| dS )zT
        Update from a :class:`Headers` instance and/or keyword arguments.

        c             s  s$   | ]}t |tr| n|V  qd S )N)r9   r   	raw_items)r+   argr   r   r   r.      s    z!Headers.update.<locals>.<genexpr>N)tupler   r(   )r   r   r'   )r   r   r   r(      s    zHeaders.updatez	List[str]c             C  s   | j | g S )z|
        Return the (possibly empty) list of all values for a header.

        Args:
            key: header name.

        )r$   getr:   )r   r,   r   r   r   get_all   s    zHeaders.get_allzIterator[Tuple[str, str]]c             C  s
   t | jS )zO
        Return an iterator of all values as ``(name, value)`` pairs.

        )r<   r%   )r   r   r   r   rM      s    zHeaders.raw_items)r   r    r!   r"   	__slots__r)   r   r2   r3   r6   r;   r=   r?   r@   rC   rH   rK   rL   r(   rQ   rM   r#   r   r   )r   r   r   '   s$   $
c               @  s.   e Zd ZdZddddZddddd	Zd
S )SupportsKeysAndGetItemz_
    Dict-like types with ``keys() -> str`` and ``__getitem__(key: str) -> str`` methods.

    zIterable[str])r   c             C  s   d S )Nr   )r   r   r   r   keys   s    zSupportsKeysAndGetItem.keysr   )r,   r   c             C  s   d S )Nr   )r   r,   r   r   r   r@      s    z"SupportsKeysAndGetItem.__getitem__N)r   r    r!   r"   rT   r@   r   r   r   r   rS      s   rS   )Z
__future__r   systypingr   r   r   r   r   r   r	   r
   r   version_infor   r7   __all__LookupErrorr   r   r   rS   r   r   r   r   r   <module>   s    ,
 	
