U
    dj                  
   @   sZ  d dl Z d dlZd dlmZmZ d dlmZ d dlmZ d dl	m
Z
 ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZmZ ddlmZ d dlmZ dddddZededededddiZ e!dZ"dZ#de#iZ$e!dej%Z&e!dej'Z(dd Z)dd Z*dd Z+dd Z,d d! Z-d"d# Z.d$d% Z/d&d' Z0d.d(d)Z1d*d+ Z2G d,d- d-e3Z4dS )/    N)isclassgetdoc)OrderedDict)Hashable)current_app   )fields)Model	ModelBaseOrderedModel)RequestParser)mergenot_nonenot_none_sorted)
HTTPStatus)quoteintegernumberstring)intfloatr   defaultbooleanvoidz<(?:[^:<>]+:)?([^<>]+)>ZSuccessdescriptionz8^:raises\s+(?P<name>[\w\d_]+)\s*:\s*(?P<description>.*)$ao  
    (?P<static>[^<]*)                           # static rule data
    <
    (?:
        (?P<converter>[a-zA-Z_][a-zA-Z0-9_]*)   # converter name
        (?:\((?P<args>.*?)\))?                  # converter arguments
        \:                                      # variable delimiter
    )?
    (?P<variable>[a-zA-Z_][a-zA-Z0-9_]*)        # variable name
    >
    c                 C   s*   t | tr| jn| }ddt|ddiS )z*Return a reference to model in definitions$refz#/definitions/{0} )safe)
isinstancer
   nameformatr   )modelr    r"   7/tmp/pip-unpacked-wheel-dt_sn2ih/flask_restx/swagger.pyref>   s    r$   c                 C   s   t | r|  S | S )zDereference values (callable))callable)valuer"   r"   r#   _vD   s    r'   c                 C   s   t d| S )zB
    Transform a Flask/Werkzeug URL pattern in a Swagger one.
    z{\1})RE_URLsub)pathr"   r"   r#   extract_pathI   s    r+   c           
      c   s   d}t | }tj}t }||k r|| |}|dkr4q| }|d rTdd|d fV  |d }|d pfd}||krtd|d|| ||d	 pd|fV  | }q||k r| |d }	d
|	ksd|	krtd| dd|	fV  dS )aB  
    Parse a rule and return it as generator. Each iteration yields tuples in the form
    ``(converter, arguments, variable)``. If the converter is `None` it's a static url part, otherwise it's a dynamic
    one.

    Note: This originally lived in werkzeug.routing.parse_rule until it was removed in werkzeug 2.2.0.
    r   NZstaticvariable	converterr   zvariable name z used twice.args><zmalformed url rule: )lenRE_PARSE_RULEmatchset	groupdict
ValueErroraddend)
Zruleposr8   Zdo_matchZ
used_namesmdatar,   r-   	remainingr"   r"   r#   
parse_ruleP   s.    


r=   c                 C   sp   t  }t| D ]\\}}}|sq|ddd}|tkr@t| |d< n"|tjjkrVd|d< ntd| |||< q|S )zM
    Extract Flask-style parameters from an URL pattern as Swagger ones.
    r*   T)r   inrequiredtyper   zUnsupported type converter: %s)r   r=   
PATH_TYPESr   Zurl_map
convertersr6   )r*   paramsr-   	argumentsr,   paramr"   r"   r#   extract_path_paramsq   s    

rF   c                 C   s    |  dd  |  dd  t| S )Nr>   r   )pop_clean_header)rE   r"   r"   r#   _param_to_header   s    rI   c                 C   s   t | trd| i} | dd}t |tr>|tkr>t| | d< ndt |ttfrt|dkr|d tkrd| d< dt|d  i| d< n t|dr| 	|j
 n|| d< t| S )	Nr   r@   r   r   r   arrayitems
__schema__)r   strgetr   PY_TYPESlisttupler1   hasattrupdaterL   r   )headerZtypedefr"   r"   r#   rH      s"    



rH   c                 C   s   t | }|r*|ddd dd nd }i }|rN||dddnd }t|p\dD ].}|d||d< |r`||dd}q`||pd |pd d g |d	}|S )
Nz 

r   .r   z. 
r   r   )rawsummarydetailsZreturnsrC   raises)r   stripsplitreplacelstrip	RE_RAISESfinditergroup)objrW   rX   rZ   rY   r3   parsedr"   r"   r#   parse_docstring   s     & rd   c                 C   s$   |dkrdS t | do| jdkS dS )z|
    Determine whether a Resource has been hidden from Swagger documentation
    i.e. by using Api.doc(False) decorator
    FT
__apidoc__N)rR   re   )resource	route_docr"   r"   r#   	is_hidden   s    rh   c                 C   s:   i }| D ]}d| ddi||d < qdddd|dd	S )
a  
    :param body_params: List of JSON schema of body parameters.
    :type body_params: list of dict, generated from the json body parameters of a request parser
    :return dict: The Swagger schema representation of the request body

    :Example:
        {
            'name': 'payload',
            'required': True,
            'in': 'body',
            'schema': {
                'type': 'object',
                'properties': [
                    'parameter1': {
                        'type': 'integer'
                    },
                    'parameter2': {
                        'type': 'string'
                    }
                ]
            }
        }
    r@   r   r   payloadTbodyobject)r@   
propertiesr   r?   r>   schemarN   )body_paramsrl   rE   r"   r"   r#   $build_request_body_parameters_schema   s    rq   c                   @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd/ddZdd Z	dd Z
d0ddZdd Zdd Zdd Zdd Zdd Zdd Zd1d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 )2Swaggerz>
    A Swagger documentation wrapper for an API instance.
    c                 C   s   || _ i | _d S N)api_registered_models)selfrt   r"   r"   r#   __init__   s    zSwagger.__init__c                 C   s8  | j j}t|dkr*|dr*|dd }t| j jt| j jd}| j jr\t| j j|d< | j jrtt| j j|d< | j j	r| j j
s| j jrt| j j	t| j j
t| j jd|d	< | j jrd
t| j ji|d< | j jrt| j j|d d< i }| | j }|  }| j jD ]\}|jD ]N\}}}	}
| j ||D ]0}t|}| j|||fd|	i|
}|||< q0qqtjd r| j jD ]}| | q~| j jD ]8}|jr| j jdkri | j _t| j j|j| j _qd|t||t| j j dg| j jpd| | j j pd|| ! pd|p$d| " d}t#|S )z
        Output the specification as a serializable ``dict``.

        :returns: the full Swagger specification in a serializable format
        :rtype: dict
        r   /N)titleversionr   ZtermsOfService)r   emailurlcontactr   licenser}   rg   ZRESTX_INCLUDE_ALL_MODELSz2.0zapplication/json)ZswaggerZbasePathpathsinfoproducesconsumesZsecurityDefinitionssecuritytagsZdefinitions	responseshost)$rt   	base_pathr1   endswithr'   rz   r{   r   Z	terms_urlr~   contact_emailZcontact_urlr   Zlicense_urlextract_tagsregister_errors
namespaces	resourcesZns_urlsr+   serialize_resourcer   configmodelsregister_modelZauthorizationsr   r   rP   Zrepresentationskeyssecurity_requirementsr   serialize_definitionsget_hostr   )rv   ZbasepathZinfosr   r   r   nsrf   urlsrg   kwargsr}   r*   Z
serializedr:   specsr"   r"   r#   as_dict   sz    





   zSwagger.as_dictc                 C   s@   t jdd pd }|r<| jjr<| jjjr<d| jjj|f}|S )NZSERVER_NAMErV   )r   r   rN   rt   Z	blueprintZ	subdomainjoin)rv   hostnamer"   r"   r#   r   6  s    zSwagger.get_hostc                 C   s   g }i }|j D ]r}t|tr&d|i}nDt|ttfrH|d |d d}n"t|tr\d|kr\ntd||| |||d < q|j	D ]h}|j
sqtdd |j
D rq|j|kr||jr|j|jdnd|ji q|jr|j||j d< q|S )	Nr   r   r   )r   r   zUnsupported tag format for {0}c                 s   s   | ]}t |j|jd V  qdS )rg   N)rh   rf   rg   ).0rr"   r"   r#   	<genexpr>O  s     z'Swagger.extract_tags.<locals>.<genexpr>r   )r   r   rM   rP   rQ   dictr6   r    appendr   r   allr   r   )rv   rt   r   Zby_nametagr   r"   r"   r#   r   <  s4    





zSwagger.extract_tagsNc                    s.  |d kri n|}|dkrdS t t|di |}|dkr:dS |rLd|j|n|j|d< t | ||dt }t |t|}dd | D }t	 dd	 |j
pg D }|D ]}||t }	t||}
t|
d
r|
j}
nt|
dr|
j}
t |	t|
dt }	|	dk	rt|
|	d< | |	 t  |	di  t fdd| D }t | |	d< |	d  D ].\}}||ddf}||krf| qf|	||< qr|D ]`}||}	|	sqdd |	d pi  D }D ]$}||kr|| |	d |d < qqtfdd| D |d< |S )NFre   z{}_{}r   rC   c                 S   s"   i | ]\}}|| d df|qS r>   queryro   r   npr"   r"   r#   
<dictcomp>l  s      z0Swagger.extract_resource_doc.<locals>.<dictcomp>c                 S   s   g | ]}|  qS r"   lowerr   r:   r"   r"   r#   
<listcomp>n  s     z0Swagger.extract_resource_doc.<locals>.<listcomp>im_func__func__	docstringc                 3   s"   | ]\}}| kr||fV  qd S rs   r"   r   kv)method_paramsr"   r#   r   }  s     z/Swagger.extract_resource_doc.<locals>.<genexpr>r>   r   c                 S   s"   i | ]\}}|| d df|qS r   ro   r   r"   r"   r#   r     s    r   c                 3   s&   | ]\}}| kr|d  |fV  qdS )r   Nr"   )r   r   r   )need_to_go_downr"   r#   r     s     )r   getattrr    __name__expected_paramsrN   r   rF   rK   r4   methodsrR   r   r   rd   r7   )rv   rf   r}   rg   docrC   Z	up_paramsr   method
method_docZmethod_implZinherited_paramsr   rE   keyr"   )r   r   r#   extract_resource_doc[  sh    


 





zSwagger.extract_resource_docc                 C   s   t  }d|kr|S |dg D ]}t|trlt dd |jD }|| dd |jD }|rt||d< qt|trtddd| 	|d	|d< qt|t
tfrt|d
kr|\}}tddd| 	||d|d< qtddd| 	|d	|d< q|S )Nexpectc                 s   s&   | ]}|d  dkr|d |fV  qdS )r>   rj   r   Nr"   r   r   r"   r"   r#   r     s     z*Swagger.expected_params.<locals>.<genexpr>c                 S   s   g | ]}|d  dkr|qS )r>   rj   r"   r   r"   r"   r#   r     s      z+Swagger.expected_params.<locals>.<listcomp>ri   Trj   rm      )r   r?   r>   rn   r   )r   rN   r   r   rL   rS   rq   r
   r   serialize_schemarP   rQ   r1   )rv   r   rC   r   Zparser_paramsrp   r!   r   r"   r"   r#   r     sR    







zSwagger.expected_paramsc           	      C   s   i }| j j D ]r\}}t|}d|d i}t|di }| || d|krtt|d  d \}}}| ||d< t	|||j
< q|S )Nr   rX   re   r   r   rn   )rt   error_handlersrK   rd   r   process_headersrP   valuesr   r   r   )	rv   r   	exceptionhandlerr   responseZapidoc_r!   r"   r"   r#   r     s    zSwagger.register_errorsc           
      K   s   | j |||d}|dkrd S d| |p*d i}dd |jp<g D D ]T}dd |dg D }	|| dksB|	rv||	krvqB| ||||< |jg|| d< qBt|S )	Nr   F
parametersc                 S   s   g | ]}|  qS r"   r   r   r"   r"   r#   r     s     z.Swagger.serialize_resource.<locals>.<listcomp>c                 S   s   g | ]}|  qS r"   r   r   r"   r"   r#   r     s     r   r   )r   parameters_forr   rN   serialize_operationr   r   )
rv   r   rf   r}   rg   r   r   r*   r   r   r"   r"   r#   r     s    zSwagger.serialize_resourcec              	   C   s  |  ||pd || d d | ||p*d | ||| || pDd | ||d}d|| krp|| d |d< |ds|| drd|d< t|di  }||d pg  }|rtd	d
 |D rtdd
 |D rdg|d< nddg|d< |	| 
|| t|S )Nr   rX   )r   rX   r   ZoperationIdr   r   r   
deprecatedTrC   r   c                 s   s   | ]}|d  dkV  qdS )r>   ZformDataNr"   r   r"   r"   r#   r     s     z.Swagger.serialize_operation.<locals>.<genexpr>c                 s   s   | ]}|d  dkV  qdS )r@   fileNr"   r   r"   r"   r#   r     s     zmultipart/form-datar   z!application/x-www-form-urlencoded)responses_fordescription_foroperation_id_forr   security_forrN   rP   r   anyrS   vendor_fieldsr   )rv   r   r   Z	operationZ
doc_params
all_paramsr"   r"   r#   r     s*    

	zSwagger.serialize_operationc                 C   s"   t dd || di  D S )z
        Extract custom 3rd party Vendor fields prefixed with ``x-``

        See: https://swagger.io/specification/#specification-extensions
        c                 s   s.   | ]&\}}| d r|nd||fV  qdS )zx-zx-{0}N)
startswithr    r   r"   r"   r#   r   	  s   z(Swagger.vendor_fields.<locals>.<genexpr>vendor)r   rN   rK   rv   r   r   r"   r"   r#   r     s    zSwagger.vendor_fieldsc                 C   sx   g }d|kr| |d pd ||krDd|| krD| || d  || d d rj| || d d  d| S )zDExtract the description metadata and fallback on the whole docstringr   r   r   rY   rU   )r   r   r[   )rv   r   r   partsr"   r"   r#   r     s    zSwagger.description_forc                 C   s*   d|| kr|| d S | j |d |S )zExtract the operation ididr   )rt   Z
default_idr   r"   r"   r#   r     s    
zSwagger.operation_id_forc                 C   s  g }|d   D ]\}}||d< d|kr8d|kr8d|d< d|krHd|d< d|krd|kr|dd }t|ttfr|d }d	|d< dt||i|d
< n&t|ttd fr|tkrt| |d< || q|d}|rtj	d rtj	d ddddd}t|t
r||d< || |S )NrC   r   r@   rn   r   r>   r   r   rJ   rK   Z__mask__ZRESTX_MASK_SWAGGERZRESTX_MASK_HEADERrT   maskzAn optional fields mask)r   r>   r@   r    r   r   )rK   rN   r   rP   rQ   rO   r@   r   r   r   rM   )rv   r   rC   r   rE   ptypetypr   r"   r"   r#   r   "  s8    

zSwagger.parameters_forc              
   C   s   i }||| fD ]}d|kr|d   D ]\}}t|}t|trT|}d }i }	n:t|dkrl|\}}}	n"t|dkr|\}}i }	ntd|pt}||kr|| j|d nd|i||< |r| |}
|	d}|rd||
ii}
|
|| d	< | 	|| |||	d
 q,d|kr^t|dt
j}||krH| 	t ||||< | |d || d	< d|kr|d d   D ]~\}}| jj  D ]f\}}t|di di }|rtt| d nd }|r|j|krdd|i||<  qvqqvq|s| 	t |||tt
jj< |S )Nr      r   z"Unsupported response specification)r   r   enveloperl   rn   headersr!   Zdefault_coder   rZ   re   r   r   z#/responses/{0})rK   rM   r   r1   r6   DEFAULT_RESPONSE_DESCRIPTIONrS   r   rN   r   r   OKDEFAULT_RESPONSEcopyrt   r   r   rP   r   r   r    r&   )rv   r   r   r   dcoder   r   r!   r   rn   r   r   r   r   Zerror_responsesr"   r"   r#   r   G  sz    



   

     zSwagger.responses_forc              	   C   sd   | |i }d|ks d|ks |r`tdd t| di  | di  |pNi  D |d< |S )Nr   c                 s   s   | ]\}}|t |fV  qd S rs   )rH   r   r"   r"   r#   r     s   z*Swagger.process_headers.<locals>.<genexpr>)rN   r   	itertoolschainrK   )rv   r   r   r   r   r   r"   r"   r#   r     s    
zSwagger.process_headersc                 C   s   t dd | j D S )Nc                 s   s   | ]\}}||j fV  qd S rs   )rL   )r   r   r!   r"   r"   r#   r     s    z0Swagger.serialize_definitions.<locals>.<genexpr>)r   ru   rK   rv   r"   r"   r#   r     s    zSwagger.serialize_definitionsc                 C   s   t |ttfr&|d }d| |dS t |trB| | t|S t |tr^| | t|S t|r~t	|t
jr~| | S t |t
jr|jS t |ttd fr|tkrdt| iS td|d S )Nr   rJ   )r@   rK   r@   Model {0} not registered)r   rP   rQ   r   r
   r   r$   rM   r   
issubclassr   ZRawrL   r@   rO   r6   r    )rv   r!   r"   r"   r#   r     s$    



zSwagger.serialize_schemac                 C   s   t |tr|jn|}|| jjkr.td|| jj| }|| jkrLt|S || j|< t |trv|j	D ]}| 
| qft |ttfr| D ]}| | qt|S )Nr   )r   r
   r   rt   r   r6   r    ru   r$   Z__parents__r   r	   r   r   register_field)rv   r!   r   r   parentfieldr"   r"   r#   r     s    



zSwagger.register_modelc                 C   sd   t |tjr(|j D ]}| | qn8t |tjrB| |j nt |tjtj	fr`| 
|j d S rs   )r   r   Z	Polymorphmappingr   r   ZNestednestedListZWildcardr   	container)rv   r   r!   r"   r"   r#   r     s    zSwagger.register_fieldc                 C   sD   d }d|kr|d }|  |}d|| kr@|| d }|  |}|S )Nr   )r   )rv   r   r   r   authr"   r"   r#   r     s    

zSwagger.security_forc                    sD   t |ttfr  fdd|D S |r< |}|r8|gS d S g S d S )Nc                    s   g | ]}  |qS r"   )security_requirement)r   r   r   r"   r#   r     s     z1Swagger.security_requirements.<locals>.<listcomp>)r   rP   rQ   r   )rv   r&   requirementr"   r   r#   r     s    
zSwagger.security_requirementsc                 C   s:   t |tr|g iS t |tr2tdd | D S d S d S )Nc                 s   s.   | ]&\}}|t |ttfr|n|gfV  qd S rs   )r   rP   rQ   r   r"   r"   r#   r     s   z/Swagger.security_requirement.<locals>.<genexpr>)r   rM   r   rK   )rv   r&   r"   r"   r#   r     s    

zSwagger.security_requirement)N)N)NN)r   
__module____qualname____doc__rw   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r"   r"   r"   r#   rr      s.   J
?2
%>
		rr   )N)5r   reinspectr   r   collectionsr   collections.abcr   Zflaskr   r   r   r!   r	   r
   r   Zreqparser   utilsr   r   r   Z_httpr   urllib.parser   rA   r   r   rM   boolrO   compiler(   r   r   	MULTILINEr_   VERBOSEr2   r$   r'   r+   r=   rF   rI   rH   rd   rh   rq   rk   rr   r"   r"   r"   r#   <module>   sb   	     
 !
%