U
    íˆjc6  ã                   @   s  d Z ddl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 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 eddddddgƒZedddddgƒZdd„ Zdd„ ZG dd„ dƒZG dd„ deƒZG dd„ dejƒZG dd„ deƒZ dS ) aÜ  
Routers provide a convenient and consistent way of automatically
determining the URL conf for your API.

They are used by simply instantiating a Router class, and then registering
all the required ViewSets with that router.

For example, you might have a `urls.py` that looks something like this:

    router = routers.DefaultRouter()
    router.register('users', UserViewSet, 'user')
    router.register('accounts', AccountViewSet, 'account')

    urlpatterns = router.urls
é    N)Ú
namedtuple)ÚImproperlyConfigured)ÚNoReverseMatchÚpathÚre_path)Úviews)ÚResponse)Úreverse)ÚSchemaGenerator)Ú
SchemaView)Úapi_settings)Úformat_suffix_patternsÚRouteÚurlÚmappingÚnameÚdetailÚ
initkwargsÚDynamicRoutec                 C   s   |   dd¡  dd¡S )zK
    Double brackets in regex of url_path for escape string formatting
    Ú{z{{Ú}z}})Úreplace)Úurl_path© r   ú:/tmp/pip-unpacked-wheel-6231m0k6/rest_framework/routers.pyÚescape_curly_brackets"   s    r   c                 C   s
   t j| Ž S )zX
    Takes an iterable of iterables, returns a single iterable containing all items
    )Ú	itertoolsÚchain)Zlist_of_listsr   r   r   Úflatten)   s    r   c                   @   sB   e Zd Zdd„ Zddd„Zdd„ Zdd	„ Zd
d„ Zedd„ ƒZ	dS )Ú
BaseRouterc                 C   s
   g | _ d S ©N)Úregistry©Úselfr   r   r   Ú__init__1   s    zBaseRouter.__init__Nc                 C   sZ   |d kr|   |¡}|  |¡r6d|› d|› d�}t|ƒ‚| j |||f¡ t| dƒrV| `d S )NzRouter with basename "zG" is already registered. Please provide a unique basename for viewset "ú"Ú_urls)Úget_default_basenameÚis_already_registeredr   r!   ÚappendÚhasattrr&   )r#   ÚprefixÚviewsetÚbasenameÚmsgr   r   r   Úregister4   s    


zBaseRouter.registerc                    s   t ‡ fdd„| jD ƒƒS )z;
        Check if `basename` is already registered
        c                 3   s   | ]\}}}|ˆ kV  qd S r    r   )Ú.0Ú_prefixZ_viewsetr-   ©Únew_basenamer   r   Ú	<genexpr>G   s     z3BaseRouter.is_already_registered.<locals>.<genexpr>)Úanyr!   )r#   r3   r   r2   r   r(   C   s    z BaseRouter.is_already_registeredc                 C   s   t dƒ‚dS )úq
        If `basename` is not specified, attempt to automatically determine
        it from the viewset.
        z'get_default_basename must be overriddenN©ÚNotImplementedError)r#   r,   r   r   r   r'   I   s    zBaseRouter.get_default_basenamec                 C   s   t dƒ‚dS )zO
        Return a list of URL patterns, given the registered viewsets.
        zget_urls must be overriddenNr7   r"   r   r   r   Úget_urlsP   s    zBaseRouter.get_urlsc                 C   s   t | dƒs|  ¡ | _| jS )Nr&   )r*   r9   r&   r"   r   r   r   ÚurlsV   s    

zBaseRouter.urls)N)
Ú__name__Ú
__module__Ú__qualname__r$   r/   r(   r'   r9   Úpropertyr:   r   r   r   r   r   0   s   
r   c                	       s¨   e Zd Zeddddœddddid	�ed
ddi d�eddddddœddddid	�edddi d�gZd&‡ fdd„	Zdd„ Zdd„ Zdd„ Z	dd „ Z
d'd"d#„Zd$d%„ Z‡  ZS )(ÚSimpleRouterz^{prefix}{trailing_slash}$ÚlistÚcreate)ÚgetÚpostz{basename}-listFÚsuffixÚList©r   r   r   r   r   z%^{prefix}/{url_path}{trailing_slash}$z{basename}-{url_name})r   r   r   r   z#^{prefix}/{lookup}{trailing_slash}$ÚretrieveÚupdateZpartial_updateÚdestroy)rB   ÚputÚpatchÚdeletez{basename}-detailTZInstancez.^{prefix}/{lookup}/{url_path}{trailing_slash}$c                    sª   |rdnd| _ || _|r,d| _d| _t| _npd| _d| _t| _g }| jD ]L}|j}|d dkrj|d	d … }|d
 dkr‚|d d
… }| 	|j
|d�¡ qH|| _tƒ  ¡  d S )Nú/Ú z5(?P<{lookup_prefix}{lookup_url_kwarg}>{lookup_value})z[^/.]+z2<{lookup_value}:{lookup_prefix}{lookup_url_kwarg}>Ústrr   ú^é   éÿÿÿÿú$)r   )Útrailing_slashÚ
_use_regexÚ_base_patternÚ_default_value_patternr   Ú	_url_confr   Úroutesr   r)   Ú_replaceÚsuperr$   )r#   rT   Zuse_regex_pathZ_routesÚrouteZ	url_param©Ú	__class__r   r   r$   Š   s&    
zSimpleRouter.__init__c                 C   s*   t |ddƒ}|dk	stdƒ‚|jjj ¡ S )r6   ÚquerysetNz�`basename` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.)ÚgetattrÚAssertionErrorÚmodelZ_metaZobject_nameÚlower)r#   r,   r_   r   r   r   r'   £   s    z!SimpleRouter.get_default_basenamec                    sÚ   t tdd„ ˆjD ƒƒƒ‰ | ¡ }‡ fdd„|D ƒ}|rLd}t|d |¡ ƒ‚dd„ |D ƒ}dd„ |D ƒ}g }ˆjD ]b‰tˆtƒr ˆjr |‡‡fdd„|D ƒ7 }qrtˆtƒrÊˆjsÊ|‡‡fd	d„|D ƒ7 }qr| 	ˆ¡ qr|S )
z
        Augment `self.routes` with any dynamically generated routes.

        Returns a list of the Route namedtuple.
        c                 S   s    g | ]}t |tƒr|j ¡ ‘qS r   )Ú
isinstancer   r   Úvalues)r0   r\   r   r   r   Ú
<listcomp>¸   s     
 z+SimpleRouter.get_routes.<locals>.<listcomp>c                    s   g | ]}|j ˆ kr|j ‘qS r   )r;   ©r0   Úaction)Úknown_actionsr   r   rf   ¼   s   
ÿzZCannot use the @action decorator on the following methods, as they are existing routes: %sz, c                 S   s   g | ]}|j r|‘qS r   ©r   rg   r   r   r   rf   Æ   s      c                 S   s   g | ]}|j s|‘qS r   rj   rg   r   r   r   rf   Ç   s      c                    s   g | ]}ˆ  ˆ |¡‘qS r   ©Ú_get_dynamic_routerg   ©r\   r#   r   r   rf   Ì   s     c                    s   g | ]}ˆ  ˆ |¡‘qS r   rk   rg   rm   r   r   rf   Î   s     )
r@   r   rY   Zget_extra_actionsr   Újoinrd   r   r   r)   )r#   r,   Zextra_actionsÚnot_allowedr.   Zdetail_actionsZlist_actionsrY   r   )ri   r\   r#   r   Ú
get_routes°   s$    
ÿ
zSimpleRouter.get_routesc                 C   sL   |j  ¡ }| |j¡ t|jƒ}t|j d|¡|j	|j
 d|j¡|j|d�S )Nz
{url_path}z
{url_name}rF   )r   ÚcopyrH   Úkwargsr   r   r   r   r   r   r   Úurl_namer   )r#   r\   rh   r   r   r   r   r   rl   Ô   s    

ûzSimpleRouter._get_dynamic_routec                 C   s,   i }|  ¡ D ]\}}t||ƒr|||< q|S )zÀ
        Given a viewset, and a mapping of http methods to actions,
        return a new mapping which only includes any mappings that
        are actually implemented by the viewset.
        )Úitemsr*   )r#   r,   Z
method_mapZbound_methodsÚmethodrh   r   r   r   Úget_method_mapâ   s
    

zSimpleRouter.get_method_maprN   c                 C   sZ   t |ddƒ}t |ddƒp|}d}| js2t |ddƒ}|dkrHt |d| jƒ}| jj|||d�S )a�  
        Given a viewset, return the portion of URL regex that is used
        to match against a single instance.

        Note that lookup_prefix is not used directly inside REST rest_framework
        itself, but is required in order to nicely support nested router
        implementations, such as drf-nested-routers.

        https://github.com/alanjds/drf-nested-routers
        Úlookup_fieldÚpkÚlookup_url_kwargNZlookup_value_converterZlookup_value_regex)Úlookup_prefixry   Úlookup_value)r`   rU   rW   rV   Úformat)r#   r,   rz   rw   ry   r{   r   r   r   Úget_lookup_regexî   s    ýzSimpleRouter.get_lookup_regexc              	   C   sö   g }| j D ]æ\}}}|  |¡}|  |¡}|D ]Â}|  ||j¡}|sDq,|jj||| jd�}	|s | jt	kr€|	d dkr |	dd… }	n |	dd… dkr d|	dd…  }	|j
 ¡ }
|
 ||jd	œ¡ |j|f|
Ž}|jj|d
�}| | j|	||d�¡ q,q
|S )zQ
        Use the registered viewsets to generate a list of URL patterns.
        )r+   ÚlookuprT   r   rM   rQ   Né   z^/rP   )r-   r   ©r-   ©r   )r!   r}   rp   rv   r   r   r|   rT   rX   r   r   rq   rH   r   Úas_viewr   r)   )r#   Úretr+   r,   r-   r~   rY   r\   r   Úregexr   Úviewr   r   r   r   r9   
  s8    

ý


þzSimpleRouter.get_urls)TT)rN   )r;   r<   r=   r   r   rY   r$   r'   rp   rl   rv   r}   r9   Ú__classcell__r   r   r]   r   r?   ]   sP   þøüüöüÝ+$
r?   c                   @   s$   e Zd ZdZdZdZdZdd„ ZdS )ÚAPIRootViewz7
    The default basic root view for DefaultRouter
    TNc              	   O   sr   i }|j j}| j ¡ D ]R\}}|r.|d | }z t||||| d¡d�||< W q tk
rf   Y qY qX qt|ƒS )Nú:r|   )Úargsrr   Úrequestr|   )Zresolver_matchÚ	namespaceÚapi_root_dictrt   r	   rB   r   r   )r#   rŠ   r‰   rr   rƒ   r‹   Úkeyrs   r   r   r   rB   B  s     ûzAPIRootView.get)r;   r<   r=   Ú__doc__Z_ignore_model_permissionsZschemarŒ   rB   r   r   r   r   r‡   :  s
   r‡   c                       sR   e Zd ZdZdZdZdZdZeZe	Z
eZ‡ fdd„Zddd„Z‡ fd	d
„Z‡  ZS )ÚDefaultRouterz‘
    The default router extends the SimpleRouter, but also adds in a default
    API root view, and adds format suffix patterns to the URLs.
    Tzapi-rootNc                    s4   d|kr|  d¡| _nttjƒ| _tƒ j||Ž d S )NÚroot_renderers)Úpopr�   r@   r   ZDEFAULT_RENDERER_CLASSESr[   r$   )r#   r‰   rr   r]   r   r   r$   e  s    zDefaultRouter.__init__c                 C   s@   i }| j d j}| jD ]\}}}|j|d�||< q| jj|d�S )z+
        Return a basic root view.
        r   r€   )rŒ   )rY   r   r!   r|   r‡   r‚   )r#   Úapi_urlsrŒ   Z	list_namer+   r,   r-   r   r   r   Úget_api_root_viewl  s
    zDefaultRouter.get_api_root_viewc                    sH   t ƒ  ¡ }| jr6| j|d�}td|| jd�}| |¡ | jrDt|ƒ}|S )z”
        Generate the list of URL patterns, including a default root view
        for the API, and appending `.json` style format suffixes.
        )r’   rN   r�   )	r[   r9   Úinclude_root_viewr“   r   Úroot_view_namer)   Úinclude_format_suffixesr   )r#   r:   r…   Zroot_urlr]   r   r   r9   w  s    

zDefaultRouter.get_urls)N)r;   r<   r=   rŽ   r”   r–   r•   Zdefault_schema_renderersr‡   r   ZAPISchemaViewr
   r$   r“   r9   r†   r   r   r]   r   r�   X  s   
r�   )!rŽ   r   Úcollectionsr   Zdjango.core.exceptionsr   Zdjango.urlsr   r   r   Zrest_frameworkr   Zrest_framework.responser   Zrest_framework.reverser	   Zrest_framework.schemasr
   Zrest_framework.schemas.viewsr   Zrest_framework.settingsr   Zrest_framework.urlpatternsr   r   r   r   r   r   r?   ZAPIViewr‡   r�   r   r   r   r   Ú<module>   s(   - ^