U
    gs&                     @  s  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlmZ ddl	m
Z
mZmZmZmZmZ ddlmZmZmZ ddd	Zed
d edD  eddd e D ZddddddZdddddZdddddZG dd dZG dd  d ZG d!d" d"ee
Z dS )#    )annotationsN)Path   )AsyncByteStreamFileContent	FileTypesRequestDataRequestFilesSyncByteStream)peek_filelike_lengthprimitive_value_to_strto_bytesz%22z\\)"\c                 C  s$   i | ]}|d krt |d|qS )   z%{:02X})chrformat.0c r   4/tmp/pip-unpacked-wheel-ql4n0x43/httpx/_multipart.py
<dictcomp>   s       r       |c                 C  s   g | ]}t |qS r   )reescaper   r   r   r   
<listcomp>   s     r   strbytesnamevaluereturnc                 C  s0   ddddd}t ||}|  d| d S )z;
    Encode a name/value pair within a multipart form.
    ztyping.Match[str]r   )matchr#   c                 S  s   t | d S )Nr   )!_HTML5_FORM_ENCODING_REPLACEMENTSgroup)r$   r   r   r   replacer&   s    z$_format_form_param.<locals>.replacerz="r   )_HTML5_FORM_ENCODING_REsubencode)r!   r"   r'   r   r   r   _format_form_param!   s    r+   z
str | None)filenamer#   c                 C  s   | rt | d pdS dS )z
    Guesses the mimetype based on a filename. Defaults to `application/octet-stream`.

    Returns `None` if `filename` is `None` or empty.
    r   zapplication/octet-streamN)	mimetypes
guess_type)r,   r   r   r   _guess_content_type-   s    r/   bytes | None)content_typer#   c                 C  s^   | r|  dsd S d| krZ| dD ]4}|   dr$| tdd  d  S q$d S )Ns   multipart/form-data   ;s	   boundary=   ")
startswithsplitstriplowerlen)r1   sectionr   r   r   (get_multipart_boundary_from_content_type8   s     r:   c                   @  sZ   e Zd Zd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S )	DataFieldzB
    A single form field item, within a multipart form field.
    r   z str | bytes | int | float | NoneNoner    c                 C  sv   t |ts"tdt| d||d k	rTt |ttttfsTtdt| d||| _t |trh|nt|| _	d S )Nz)Invalid type for name. Expected str, got : z5Invalid type for value. Expected primitive type, got )

isinstancer   	TypeErrortyper   intfloatr!   r   r"   )selfr!   r"   r   r   r   __init__K   s    
zDataField.__init__r   r#   c                 C  s.   t | ds(td| j}dd|dg| _| jS )N_headersr!           Content-Disposition: form-data;    

)hasattrr+   r!   joinrF   )rC   r!   r   r   r   render_headersZ   s    
zDataField.render_headersc                 C  s   t | dst| j| _| jS )N_data)rJ   r   r"   rM   rC   r   r   r   render_datac   s    
zDataField.render_datarA   c                 C  s    |   }|  }t|t| S N)rL   rO   r8   )rC   headersdatar   r   r   
get_lengthi   s    zDataField.get_lengthtyping.Iterator[bytes]c                 c  s   |   V  |  V  d S rP   rL   rO   rN   r   r   r   rendern   s    
zDataField.renderN)	__name__
__module____qualname____doc__rD   rL   rO   rS   rV   r   r   r   r   r;   F   s   	r;   c                   @  s^   e Zd ZdZd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S )	FileFieldzB
    A single file field item, within a multipart form field.
    i   r   r   r<   r    c                 C  s   || _ i }d }t|trTt|dkr.|\}}qnt|dkrF|\}}}qn|\}}}}nttt|ddj }|}|d kr~t|}tdd |D }|d k	r|s||d< t|t	j
rtdt|t	jrtd	|| _|| _|| _d S )
N      r!   uploadc                 s  s   | ]}d |  kV  qdS )zcontent-typeN)r7   )r   keyr   r   r   	<genexpr>   s     z%FileField.__init__.<locals>.<genexpr>Content-Typez?Multipart file uploads require 'io.BytesIO', not 'io.StringIO'.zDMultipart file uploads must be opened in binary mode, not text mode.)r!   r>   tupler8   r   r   getattrr/   anyioStringIOr?   
TextIOBaser,   filerQ   )rC   r!   r"   rQ   r1   r,   fileobjZhas_content_type_headerr   r   r   rD   z   s6    

zFileField.__init__
int | NonerE   c                 C  sP   |   }t| jttfr.t|tt| j S t| j}|d krDd S t|| S rP   )rL   r>   rh   r   r   r8   r   r   )rC   rQ   Zfile_lengthr   r   r   rS      s    
zFileField.get_lengthr   c                 C  s   t | dsdtd| jg}| jr:td| j}|d|g | j D ]0\}}d| d |  }}|||g qD|d d		|| _
| j
S )
NrF   rH   r!   r,   s   ; z
r=   rI   rG   )rJ   r+   r!   r,   extendrQ   itemsr*   appendrK   rF   )rC   partsr,   header_nameheader_valuer_   valr   r   r   rL      s    


zFileField.render_headersrT   c                 c  s   t | jttfr t| jV  d S t| jdrTz| jd W n tjk
rR   Y nX | j	| j
}|rt|V  | j	| j
}qbd S )Nseekr   )r>   rh   r   r   r   rJ   rr   re   UnsupportedOperationread
CHUNK_SIZErC   chunkr   r   r   rO      s    
zFileField.render_datac                 c  s   |   V  |  E d H  d S rP   rU   rN   r   r   r   rV      s    
zFileField.renderN)
rW   rX   rY   rZ   ru   rD   rS   rL   rO   rV   r   r   r   r   r[   s   s   1r[   c                   @  s~   e Zd ZdZdddddddd	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Z
dS )MultipartStreamzC
    Request content as streaming multipart encoded form data.
    Nr   r	   r0   r<   )rR   filesboundaryr#   c                 C  sH   |d krt d d}|| _d|d | _t| ||| _	d S )N   asciiz multipart/form-data; boundary=%s)
osurandomhexr*   rz   decoder1   list_iter_fieldsfields)rC   rR   ry   rz   r   r   r   rD      s    zMultipartStream.__init__z&typing.Iterator[FileField | DataField])rR   ry   r#   c                 c  s   |  D ]>\}}t|ttfr8|D ]}t||dV  q"qt||dV  qt|tjr\|  n|}|D ]\}}t||dV  qdd S )N)r!   r"   )rl   r>   rb   r   r;   typingMappingr[   )rC   rR   ry   r!   r"   itemZ
file_itemsr   r   r   r      s    zMultipartStream._iter_fieldsrT   rE   c                 c  s<   | j D ]$}d| j V  | E d H  dV  qd| j V  d S )Ns   --%s
s   
s   --%s--
)r   rz   rV   )rC   fieldr   r   r   iter_chunks  s
    
zMultipartStream.iter_chunksrj   c                 C  sd   t | j}d}| jD ]:}| }|dkr. dS |d| d 7 }||7 }|d7 }q|d| d 7 }|S )z
        Return the length of the multipart encoded content, or `None` if
        any of the files have a length that cannot be determined upfront.
        r   Nr\      )r8   rz   r   rS   )rC   Zboundary_lengthlengthr   Zfield_lengthr   r   r   get_content_length	  s    


z"MultipartStream.get_content_lengthzdict[str, str]c                 C  s.   |   }| j}|d kr d|dS t||dS )Nchunked)zTransfer-Encodingra   )zContent-Lengthra   )r   r1   r   )rC   content_lengthr1   r   r   r   get_headers  s
    
zMultipartStream.get_headersc                 c  s   |   D ]
}|V  qd S rP   r   rv   r   r   r   __iter__&  s    zMultipartStream.__iter__ztyping.AsyncIterator[bytes]c                 C s   |   D ]
}|V  qd S rP   r   rv   r   r   r   	__aiter__*  s    zMultipartStream.__aiter__)N)rW   rX   rY   rZ   rD   r   r   r   r   r   r   r   r   r   r   rx      s    rx   )!
__future__r   re   r-   r}   r   r   pathlibr   _typesr   r   r   r   r	   r
   _utilsr   r   r   r%   updaterangecompilerK   keysr(   r+   r/   r:   r;   r[   rx   r   r   r   r   <module>   s*    
-m