U
    Æ½„b‡  ã                   @   s¾   d dl 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 G d	d
„ d
ƒ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ƒZdS )é    N)Úgettext_lazy)Ú
exceptions)Úunicode_http_header©Ú_reverse)Úapi_settings)Úreplace_query_param)Ú
_MediaTypec                   @   s8   e Zd ZejZejZejZ	dd„ Z
ddd„Zdd„ ZdS )	ÚBaseVersioningc                 O   s   d}t |j| jjd�ƒ‚d S )Nz.{cls}.determine_version() must be implemented.)Úcls)ÚNotImplementedErrorÚformatÚ	__class__Ú__name__)ÚselfÚrequestÚargsÚkwargsÚmsg© r   ú=/tmp/pip-unpacked-wheel-iohwuy7z/rest_framework/versioning.pyÚdetermine_version   s    ÿz BaseVersioning.determine_versionNc                 K   s   t |||||f|ŽS ©Nr   ©r   Úviewnamer   r   r   r   Úextrar   r   r   Úreverse   s    zBaseVersioning.reversec                 C   s&   | j s
dS |d k	r|| jkp$|| j kS )NT)Úallowed_versionsÚdefault_version)r   Úversionr   r   r   Úis_allowed_version   s
    ÿz!BaseVersioning.is_allowed_version)NNNN)r   Ú
__module__Ú__qualname__r   ÚDEFAULT_VERSIONr   ZALLOWED_VERSIONSr   ZVERSION_PARAMÚversion_paramr   r   r    r   r   r   r   r
      s   
r
   c                   @   s    e Zd ZdZedƒZdd„ ZdS )ÚAcceptHeaderVersioningzb
    GET /something/ HTTP/1.1
    Host: example.com
    Accept: application/json; version=1.0
    z#Invalid version in "Accept" header.c                 O   s>   t |jƒ}|j | j| j¡}t|ƒ}|  |¡s:t 	| j
¡‚|S r   )r	   Zaccepted_media_typeÚparamsÚgetr$   r   r   r    r   ZNotAcceptableÚinvalid_version_message)r   r   r   r   Ú
media_typer   r   r   r   r   *   s    

z(AcceptHeaderVersioning.determine_versionN)r   r!   r"   Ú__doc__Ú_r(   r   r   r   r   r   r%   "   s   r%   c                       s2   e Zd ZdZedƒZdd„ Zd‡ fdd„	Z‡  ZS )	ÚURLPathVersioninga8  
    To the client this is the same style as `NamespaceVersioning`.
    The difference is in the backend - this implementation uses
    Django's URL keyword arguments to determine the version.

    An example URL conf for two views that accept two different versions.

    urlpatterns = [
        re_path(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
        re_path(r'^(?P<version>[v1|v2]+)/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')
    ]

    GET /1.0/something/ HTTP/1.1
    Host: example.com
    Accept: application/json
    zInvalid version in URL path.c                 O   s8   |  | j| j¡}|d kr| j}|  |¡s4t | j¡‚|S r   )r'   r$   r   r    r   ÚNotFoundr(   ©r   r   r   r   r   r   r   r   r   I   s    
z#URLPathVersioning.determine_versionNc                    s>   |j d k	r&|d kri n|}|j || j< tƒ j|||||f|ŽS r   )r   r$   Úsuperr   r   ©r   r   r   r   R   s    
    ÿÿzURLPathVersioning.reverse)NNNN©	r   r!   r"   r*   r+   r(   r   r   Ú__classcell__r   r   r0   r   r,   6   s   	r,   c                       s:   e Zd ZdZedƒZdd„ Zd
‡ fdd„	Zdd	„ Z‡  Z	S )ÚNamespaceVersioninga£  
    To the client this is the same style as `URLPathVersioning`.
    The difference is in the backend - this implementation uses
    Django's URL namespaces to determine the version.

    An example URL conf that is namespaced into two separate versions

    # users/urls.py
    urlpatterns = [
        path('/users/', users_list, name='users-list'),
        path('/users/<int:pk>/', users_detail, name='users-detail')
    ]

    # urls.py
    urlpatterns = [
        path('v1/', include('users.urls', namespace='v1')),
        path('v2/', include('users.urls', namespace='v2'))
    ]

    GET /1.0/something/ HTTP/1.1
    Host: example.com
    Accept: application/json
    zBInvalid version in URL path. Does not match any version namespace.c                 O   sX   t |dd ƒ}|d ks|js | jS |j d¡}|D ]}|  |¡r0|  S q0t | j¡‚d S )NÚresolver_matchú:)ÚgetattrÚ	namespacer   Úsplitr    r   r-   r(   )r   r   r   r   r4   Zpossible_versionsr   r   r   r   r   v   s    

z%NamespaceVersioning.determine_versionNc                    s.   |j d k	r|  ||¡}tƒ j|||||f|ŽS r   )r   Úget_versioned_viewnamer/   r   r   r0   r   r   r   ‚   s    
    ÿÿzNamespaceVersioning.reversec                 C   s   |j d | S )Nr5   )r   )r   r   r   r   r   r   r9   ‰   s    z*NamespaceVersioning.get_versioned_viewname)NNNN)
r   r!   r"   r*   r+   r(   r   r   r9   r2   r   r   r0   r   r3   \   s
   r3   c                   @   s*   e Zd ZdZe d¡ZedƒZdd„ Z	dS )ÚHostNameVersioningzX
    GET /something/ HTTP/1.1
    Host: v1.example.com
    Accept: application/json
    z,^([a-zA-Z0-9]+)\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+$zInvalid version in hostname.c           	      O   sN   |  ¡  d¡\}}}| j |¡}|s*| jS | d¡}|  |¡sJt | j	¡‚|S )Nr5   é   )
Úget_hostÚ	partitionÚhostname_regexÚmatchr   Úgroupr    r   r-   r(   )	r   r   r   r   ÚhostnameÚ	separatorÚportr?   r   r   r   r   r   –   s    

z$HostNameVersioning.determine_versionN)
r   r!   r"   r*   ÚreÚcompiler>   r+   r(   r   r   r   r   r   r:   �   s   
r:   c                       s2   e Zd ZdZedƒZdd„ Zd‡ fdd„	Z‡  ZS )	ÚQueryParameterVersioningza
    GET /something/?version=0.1 HTTP/1.1
    Host: example.com
    Accept: application/json
    z#Invalid version in query parameter.c                 O   s,   |j  | j| j¡}|  |¡s(t | j¡‚|S r   )Zquery_paramsr'   r$   r   r    r   r-   r(   r.   r   r   r   r   ¬   s    
z*QueryParameterVersioning.determine_versionNc                    s6   t ƒ j|||||f|Ž}|jd k	r2t|| j|jƒS |S r   )r/   r   r   r   r$   )r   r   r   r   r   r   r   Úurlr0   r   r   r   ²   s        ÿÿ
z QueryParameterVersioning.reverse)NNNNr1   r   r   r0   r   rF   ¤   s   rF   )rD   Zdjango.utils.translationr   r+   Zrest_frameworkr   Zrest_framework.compatr   Zrest_framework.reverser   Zrest_framework.settingsr   Z*rest_framework.templatetags.rest_frameworkr   Zrest_framework.utils.mediatypesr	   r
   r%   r,   r3   r:   rF   r   r   r   r   Ú<module>   s   &1