o
    SDi                     @   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
mZ d dlmZ d dlmZ d d	lmZ d d
lmZ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  ee!Z"G dd deZ#dS )    N)Sequence)
ContextVar)cached_property)	getLogger)AnyUnion)	APIRouter)URL)RedirectResponse)	BaseRouteMatch)ReceiveScopeSend)DEFAULT_API_VERSION_VAR)same_definition_as_in)APIVersionFormat)VersionTypec                
       s  e Zd Zdededeeedf  dedef
 fddZd	e	d
e
e fddZdededed
dfddZedd Zeejdedef fddZeejdedef fddZeejdedef fddZeejdedef fddZdedededee d
df
ddZ  ZS )_RootCadwynAPIRouterargsapi_version_parameter_nameapi_version_varNapi_version_formatkwargsc                   s8   t  j|i | i | _| | _|| _g | _|| _d S N)super__init__versioned_routerslowerr   r   unversioned_routesr   )selfr   r   r   r   r   	__class__ G/var/www/Datamplify/venv/lib/python3.10/site-packages/cadwyn/routing.pyr      s   

z_RootCadwynAPIRouter.__init__versionreturnc                    sP   | j dkr&t| j|}|dkrg S | j|d  }| j| | j| jS g S )a8  Pick the versioned routes for the given version in case we failed to pick a concrete version

        If the app has two versions: 2022-01-02 and 2022-01-05, and the request header
        is 2022-01-03, then the request will be routed to 2022-01-02 version as it the closest
        version, but lower than the request header.

        Exact match is always preferred over partial match and a request will never be
        matched to the higher versioned route.

        We implement routing like this because it is extremely convenient with microservice
        architecture. For example, imagine that you have two Cadwyn services: Payables and Receivables,
        each defining its own API versions. Payables service might contain 10 versions while receivables
        service might contain only 2 versions because it didn't need as many breaking changes.
        If a client requests a version that does not exist in receivables -- we will just waterfall
        to some earlier version, making receivables behavior consistent even if API keeps getting new versions.
        dater      )r   bisectbisect_leftversionsr   setr   routes)r    r%   indexpicked_versionr#   r#   r$   )_get_routes_from_closest_suitable_version&   s   
z>_RootCadwynAPIRouter._get_routes_from_closest_suitable_versionscopereceivesendc                    s   d|vr	| |d< |d dkr|  |||I d H  d S | jd }td }|s,| j}n|| jv r8| j| j}n| |I d H }|rG| j| }| j||||dI d H  d S )Nroutertypelifespan)r1   r2   r3   r-   )	r6   r   getr   r   r   r-   r0   process_request)r    r1   r2   r3   r%   default_version_that_was_pickedr-   r#   r#   r$   __call__C   s    


z_RootCadwynAPIRouter.__call__c                 C   s   t | j S r   )sortedr   keys)r    r#   r#   r$   r+   _   s   z_RootCadwynAPIRouter.versionsc                    (   t  j|i | | j| jd  d S N)r   add_api_router   appendr-   r    r   r   r!   r#   r$   r@   c      z"_RootCadwynAPIRouter.add_api_routec                    r=   r>   )r   	add_router   rA   r-   rB   r!   r#   r$   rD   h   rC   z_RootCadwynAPIRouter.add_routec                    r=   r>   )r   add_api_websocket_router   rA   r-   rB   r!   r#   r$   rE   m   rC   z,_RootCadwynAPIRouter.add_api_websocket_routec                    r=   r>   )r   add_websocket_router   rA   r-   rB   r!   r#   r$   rF   r   rC   z(_RootCadwynAPIRouter.add_websocket_router-   c                    sN  d }i }|D ]-}| |\}}	|tjkr'||	 ||||I d H   d S |tjkr4|d u r4|}|	}q|d urH|| ||||I d H S |d dkr| jr|d dkrt|}
|d drl|
d 	d|
d< n|
d d |
d< |D ]&}| |
\}}	|tj
krt|
d}tt|d}||||I d H   d S qv| |||I d H S )Nr5   httppath/)r1   )url)matchesr   FULLupdatehandlePARTIALredirect_slashesdictendswithrstripNONEr	   r
   strdefault)r    r1   r2   r3   r-   partialpartial_scoperoutematchchild_scoperedirect_scoperedirect_urlresponser#   r#   r$   r8   w   s<   




z$_RootCadwynAPIRouter.process_request)__name__
__module____qualname__r   rU   r   r   r   r   r   listr   r0   r   r   r   r:   r   r+   r   r   r@   rD   rE   rF   r   r8   __classcell__r#   r#   r!   r$   r      s2    
*r   )$r)   collections.abcr   contextvarsr   	functoolsr   loggingr   typingr   r   fastapi.routingr   starlette.datastructuresr	   starlette.responsesr
   starlette.routingr   r   starlette.typesr   r   r   cadwyn._internal.context_varsr   cadwyn._utilsr   cadwyn.middlewarer   cadwyn.structure.commonr   r_   _loggerr   r#   r#   r#   r$   <module>   s"    