o
    ADiv                     @  sn  d dl mZ d dlZd dlZd dlZd dlmZmZmZ d dl	m
Z
mZmZmZmZ d dlmZmZmZmZmZ d dlmZ d dlmZmZmZ d dlZdd	lmZ ed
Zd*ddZdZ dZ!ej"G dd dZ#ej"G dd dZ$ej%G dd dZ&d+ddZ'edZ(edZ)ed Z*ed!Z+ed"Z,ed#Z-ed$Z.ed%Z/ed&Z0ed'Z1ej%G d(d) d)Z2dS ),    )annotationsN)	AwaitableCallableIterator)AbstractAsyncContextManagerAbstractContextManagerasynccontextmanagercontextmanagersuppress)isasyncgenfunctionisawaitableiscoroutineiscoroutinefunctionisgeneratorfunction)TracebackType)AnyTypeVaroverload   )ServiceNotFoundErrorsvcsobjobjectreturnstrc                 C  s0   z
| j  d| j W S  ty   t|  Y S w )N.)
__module____qualname__AttributeErrorrepr)r    r    C/var/www/Datamplify/venv/lib/python3.10/site-packages/svcs/_core.py
_full_name%   s
   r"   svcs_registrysvcs_containerc                   @  sj   e Zd ZU dZded< ejddZded< ded	< ded
< ejddZded< e	dddZ
dddZdS )RegisteredServicea  
    A recipe for creating a service.

    .. warning::

        Strictly read-only.

    Attributes:
        svc_type: The type under which the type has been registered.

        factory: Callable that creates the service.

        takes_container:
            Whether the factory takes a container as its first argument.

        enter: Whether context managers returned by the factory are entered.

        ping: See :ref:`health`.
    typesvc_typeF)hashr   factorybooltakes_containerenterCallable | Nonepingr   r   c                 C  s
   t | jS N)r"   r'   selfr    r    r!   nameM   s   
zRegisteredService.namec                 C  s2   d| j  d| j d| j d| j d| jd u dS )Nz<RegisteredService(svc_type=z
, factory=z, takes_container=z, enter=z, has_ping=)>)r2   r)   r+   r,   r.   r0   r    r    r!   __repr__Q   s   zRegisteredService.__repr__Nr   r   )__name__r   r   __doc____annotations__attrsfieldr)   r.   propertyr2   r4   r    r    r    r!   r%   1   s   
 r%   c                   @  sN   e Zd ZU dZded< ded< ded< ded	< d
ed< dddZdddZdS )ServicePinga  
    A service health check as returned by :meth:`svcs.Container.get_pings`.

    Attributes:
        name: A fully-qualified name of the service type.

        is_async: Whether the service needs to be pinged using :meth:`aping`.

    See Also:
        :ref:`health`
    r   r2   r*   is_asyncr&   	_svc_typer   _ping	Container
_containerr   Nonec                 C  s   | j | j}| | dS )z
        Acquire the service, schedule its cleanup, and call its ping callable
        with the acquired service as its only argument.
        N)rA   getr>   r?   r1   svcr    r    r!   r.   q   s   zServicePing.pingc                   s>   | j | jI dH }| jr| |I dH  dS | | dS )z
        Same as :meth:`ping` but acquire and/or ping asynchronously, if
        necessary.

        Also works with synchronous services, so in an async application, just
        use this.
        N)rA   agetr>   r=   r?   rD   r    r    r!   apingy   s
   zServicePing.apingNr   rB   )r6   r   r   r7   r8   r.   rG   r    r    r    r!   r<   ]   s   
 
r<   c                   @  s   e Zd ZU dZeeZded< ee	Z
ded< d=dd	Zd>ddZd?ddZd@ddZdAddZd@ddZdAdd ZdBd!d"Zd#d$d$d%dCd-d.Zd/d$d$d%dDd2d3Z	$dEdFd5d6ZdGd7d8ZdBd9d:ZdBd;d<Zd$S )HRegistryai  
    A central registry of recipes for creating services.

    An instance of this should live as long as your application does.

    Also works as a context manager that runs ``on_registry_close`` callbacks
    on exit:

    .. doctest::

        >>> import svcs
        >>> with svcs.Registry() as reg:
        ...     reg.register_value(
        ...         int, 42,
        ...         on_registry_close=lambda: print("closed!")
        ...     )
        closed!

    ``async with`` is also supported.

    Warns:
        ResourceWarning:
            If a registry with pending cleanups is garbage-collected.
    zdict[type, RegisteredService]	_servicesz&list[tuple[str, Callable | Awaitable]]	_on_closer   r   c                 C  s   dt | j dS )Nz<svcs.Registry(num_services=r3   )lenrJ   r0   r    r    r!   r4      s   zRegistry.__repr__r'   r&   r*   c                 C  
   || j v S )a  
        Check whether this registry knows how to create *svc_type*:

        .. doctest::

            >>> reg = svcs.Registry()
            >>> reg.register_value(int, 42)
            >>> int in reg
            True
            >>> str in reg
            False
        )rJ   r1   r'   r    r    r!   __contains__   s   
zRegistry.__contains__Iterator[RegisteredService]c                 C  s   t | j S )zn
        Returns:
            An iterator over registered services.

        .. versionadded:: 25.1.0
        )iterrJ   valuesr0   r    r    r!   __iter__   s   zRegistry.__iter__c                 C     | S r/   r    r0   r    r    r!   	__enter__      zRegistry.__enter__exc_typetype[BaseException] | Noneexc_valBaseException | Noneexc_tbTracebackType | NonerB   c                 C     |    d S r/   closer1   rW   rY   r[   r    r    r!   __exit__      zRegistry.__exit__c                      | S r/   r    r0   r    r    r!   
__aenter__      zRegistry.__aenter__c                      |   I d H  d S r/   acloser`   r    r    r!   	__aexit__      zRegistry.__aexit__c                 C  $   t | ddrtjdtdd dS dS )zD
        Warn if the registry is gc'ed before being closed.
        rK   Nz5Registry was garbage-collected with pending cleanups.r   
stacklevelgetattrwarningswarnResourceWarningr0   r    r    r!   __del__      
zRegistry.__del__TNr,   r.   on_registry_closer)   r   r,   r.   r-   rv   Callable | Awaitable | Nonec                C  s:   | j |||||d}tjd||j|jt|ddd dS )a9  
        Register *factory* to be used when asked for a *svc_type*.

        Repeated registrations overwrite previous ones, but the
        *on_registry_close* callbacks are run all together when the registry is
        closed.

        Args:
            svc_type: The type of the service to register.

            factory:
                A callable that is used to instantiated *svc_type* if asked. If
                it's a generator or a context manager, a cleanup is registered
                after instantiation.

                Can also be an async callable/generator/context manager.

                If *factory* takes a first argument called ``svcs_container``
                or the first argument (of any name) is annotated as being
                :class:`svcs.Container`, the container instance that is
                instantiating the service is passed into the factory as the
                first positional argument.

                Note:
                    Generally speaking, given the churn and edgecases in the
                    typing ecosystem, we recommend using the name route to
                    detect the container argument because it's most reliable.

            enter:
                Whether to enter context managers if one is returned by
                *factory*. Usually you want that, but there are occasions --
                like database transaction managers -- that you want to enter
                manually.

            ping:
                A callable that marks the service as having a health check.

                See Also:
                    :meth:`Container.get_pings` and :class:`ServicePing`.

            on_registry_close:
                A callable that is called when the
                :meth:`svcs.Registry.close()` method is called.

                Can also be an async callable or an
                :class:`collections.abc.Awaitable`; then
                :meth:`svcs.Registry.aclose()` must be called.

        .. versionchanged:: 25.1.0
            *factory* now may take any amount of arguments and they are ignored.
        ru   z)registered factory %r for service type %s)svcs_service_namesvcs_factory_nameTextra
stack_infoN)_register_factorylogdebugr2   r"   r1   r'   r)   r,   r.   rv   rsr    r    r!   register_factory   s    <
zRegistry.register_factoryFvaluer   c                  s>   | j | fdd|||d}tjd |j|j ddd dS )	a  
        Syntactic sugar for::

           register_factory(
               svc_type,
               lambda: value,
               enter=enter,
               ping=ping,
               on_registry_close=on_registry_close
           )

        Please note that, unlike with :meth:`register_factory`, entering
        context managers is **disabled** by default.

        .. versionchanged:: 23.21.0
           *enter* is now ``False`` by default.
        c                         S r/   r    r    r   r    r!   <lambda>M      z)Registry.register_value.<locals>.<lambda>ru   z'registered value %r for service type %s)rx   
svcs_valueTrz   N)r}   r~   r   r2   )r1   r'   r   r,   r.   rv   r   r    r   r!   register_value1  s   


zRegistry.register_valuer%   c                 C  s^   t |r	t|}nt|rt|}t||t|||}|| j|< |d ur-| j|j	|f |S r/   )
r   r	   r   r   r%   _takes_containerrJ   rK   appendr2   r   r    r    r!   r}   [  s   

zRegistry._register_factoryc                 C  s&   z| j | W S  ty   t|d w r/   )rJ   KeyErrorr   rN   r    r    r!   get_registered_service_forp  s
   
z#Registry.get_registered_service_forc              
   C  s   t | jD ]=\}}t|st|rtjd|ddd qztd| |  td| W q tyB   tj	d|dd	|id
 Y qw | j
  | j  dS )z
        Clear registrations and run synchronous *on_registry_close* callbacks.

        Async callbacks are *not* awaited and a warning is raised

        Errors are logged at warning level, but otherwise ignored.
        Skipped async cleanup for . Use aclose() instead.r   rl   
closing %r	closed %r4Registry's on_registry_close callback failed for %r.Trx   exc_infor{   N)reversedrK   r   r   rp   rq   r~   r   	ExceptionwarningrJ   clearr1   r2   ocr    r    r!   r_   v  s*   


zRegistry.closec              
     s   t | jD ]F\}}z.t|r| }t|r(td| |I dH  td| ntd| |  td| W q tyL   tjd|dd|id	 Y qw | j	  | j	  dS )
z
        Clear registrations and run all *on_registry_close* callbacks.

        Errors are logged at warning level, but otherwise ignored.

        Also works with synchronous services, so in an async application, just
        use this.
        zasync closing %rNzasync closed %rr   r   r   Trx   r   )
r   rK   r   r   r~   r   r   r   rJ   r   r   r    r    r!   rh     s.   	


zRegistry.acloser5   r'   r&   r   r*   )r   rP   )r   rI   rW   rX   rY   rZ   r[   r\   r   rB   rH   r'   r&   r)   r   r,   r*   r.   r-   rv   rw   r   rB   r'   r&   r   r   r,   r*   r.   r-   rv   rw   r   rB   r/   )r'   r&   r)   r   r,   r*   r.   r-   rv   rw   r   r%   )r'   r&   r   r%   )r6   r   r   r7   r9   FactorydictrJ   r8   listrK   r4   rO   rS   rU   ra   rd   ri   rs   r   r   r}   r   r_   rh   r    r    r    r!   rI      s2   
 



	



T0

"rI   r)   r   r*   c                 C  s   zt j| dtidd}W n ty(   zt | }W n ty%   Y Y dS w Y nw ztt|j \}}W n
 ty@   Y dS w |dkpL|j	tddfv S )zP
    Return True if *factory* takes a svcs.Container as its first argument.
    r@   T)localseval_strFr$   zsvcs.Container)
inspect	signaturer@   r   nextrQ   
parametersitemsStopIteration
annotation)r)   sigr2   pr    r    r!   r     s,   

r   T1T2T3T4T5T6T7T8T9T10c                   @  s   e Zd ZU dZded< dZded< eeZ	ded< ee
Zd	ed
< d{ddZd|ddZd}ddZd~ddZd}dd Zd~d!d"Zdd#d$Zdd%d&Zdd'd(Zdd*d+Zdd.d/Zdd0d1Zdd3d4Zd5ddd6dd>d?Zd@ddd6ddCdDZeddGdHZeddMdHZeddQdHZeddUdHZeddYdHZedd]dHZeddadHZeddedHZeddidHZeddmdHZddndHZeddodpZeddqdpZeddrdpZeddsdpZeddtdpZeddudpZeddvdpZeddwdpZeddxdpZeddydpZddzdpZdS )r@   a  
    A per-context container for instantiated services and cleanups.

    The instance of this should live as long as a request or a task.

    Also works as a context manager that runs clean ups on exit:

    .. doctest::

        >>> reg = svcs.Registry()
        >>> def factory() -> str:
        ...     yield "Hello World"
        ...     print("Cleaned up!")
        >>> reg.register_factory(str, factory)

        >>> with svcs.Container(reg) as con:
        ...     _ = con.get(str)
        Cleaned up!

    Warns:
        ResourceWarning:
            If a container with pending cleanups is garbage-collected.

    Attributes:
        registry:
            The :class:`Registry` instance that this container uses for service
            type lookup.

    rI   registryNzRegistry | None_lazy_local_registryzdict[type, object]_instantiatedzFlist[tuple[str, AbstractContextManager | AbstractAsyncContextManager]]rK   r   r   c                 C  s   dt | j dt | j dS )Nz<Container(instantiated=z, cleanups=r3   )rL   r   rK   r0   r    r    r!   r4     s   zContainer.__repr__r'   r&   r*   c                 C  rM   )zS
        Check whether this container has a cached instance of *svc_type*.
        )r   rN   r    r    r!   rO     s   
zContainer.__contains__c                 C  rT   r/   r    r0   r    r    r!   rU     rV   zContainer.__enter__rW   rX   rY   rZ   r[   r\   rB   c                 C  r]   r/   r^   r`   r    r    r!   ra     rb   zContainer.__exit__c                   rc   r/   r    r0   r    r    r!   rd   "  re   zContainer.__aenter__c                   rf   r/   rg   r`   r    r    r!   ri   %  rj   zContainer.__aexit__c                 C  rk   )zE
        Warn if the container is gc'ed before being closed.
        rK   Nz6Container was garbage-collected with pending cleanups.r   rl   rn   r0   r    r    r!   rs   -  rt   zContainer.__del__c              
   C  s   t | jD ]3\}}zt|trtjd|ddd W q|ddd W q ty8   tj	d|dd|id	 Y qw | j
durC| j
  | j  | j  dS )
aA  
        Run all registered *synchronous* cleanups.

        Async closes are *not* awaited and a warning is raised.

        Errors are logged at warning level, but otherwise ignored.

        Hint:
            The Container can be used again after this. Closing it is an
            idempotent way to reset it.
        r   r   r   rl   N!Container clean up failed for %r.Trx   r   )r   rK   
isinstancer   rp   rq   ra   r   r~   r   r   r_   r   r   r1   r2   cmr    r    r!   r_   8  s*   





zContainer.closec              
     s   t | jD ]1\}}zt|tr|ddd n
|dddI dH  W q ty7   tjd|dd|id Y qw | j	durE| j	
 I dH  | j  | j  dS )az  
        Run *all* registered cleanups -- synchronous **and** asynchronous.

        Errors are logged at warning level, but otherwise ignored.

        Also works with synchronous services, so in an async application, just
        use this.

        Hint:
            The container can be used again after this. Closing it is an
            idempotent way to reset it.
        Nr   Trx   r   )r   rK   r   r   ra   ri   r   r~   r   r   rh   r   r   r   r    r    r!   rh   ^  s&   



zContainer.acloselist[ServicePing]c                   s    fdd j j D S )z
        Return all services that have defined a *ping* and bind them to this
        container.

        Returns:
            A list of services that have registered a ping callable.
        c                   s2   g | ]}|j d urt|jt|j |j|j  qS r/   )r.   r<   r2   r   r'   ).0r   r0   r    r!   
<listcomp>  s    
z'Container.get_pings.<locals>.<listcomp>)r   rJ   rR   r0   r    r0   r!   	get_pings  s   

zContainer.get_pings	svc_typesr   c                 G  s
   | j | S )a  
        Like :meth:`get` but is annotated to return :data:`typing.Any` which
        allows it to be used with abstract types like :class:`typing.Protocol`
        or :mod:`abc` classes.

        Note:
             See :doc:`typing-caveats` why this is necessary.
        )rC   r1   r   r    r    r!   get_abstract  s   
	zContainer.get_abstractc                   s   | j | I dH S )z
        Same as :meth:`get_abstract` but instantiates asynchronously, if
        necessary.

        Also works with synchronous services, so in an async application, just
        use this.
        N)rF   r   r    r    r!   aget_abstract  s   zContainer.aget_abstracttuple[bool, object, str, bool]c                 C  s   | j |tj }tjurd|ddfS d}| jdur4tt | j|}W d   n1 s/w   Y  |du r>| j|}|j	rF|
| n|
 }d||j|jfS )z
        Look up svc_type first in our cache, then in the registry.

        If it's cached, only the first two items of the returned tupled are
        meaningful.
        T FN)r   rC   r9   NOTHINGr   r
   r   r   r   r+   r)   r2   r,   )r1   r'   rE   r   r    r    r!   _lookup  s   

zContainer._lookupTru   r)   r   r,   r.   r-   rv   rw   c                C  s,   | j du r	t | _ | j j|||||d dS )a^  
        Same as :meth:`svcs.Registry.register_factory()`, but registers the
        factory only for this container.

        A temporary :class:`svcs.Registry` is transparently created -- and
        closed together with the container it belongs to.

        See Also:
            :ref:`local-registries`

        .. versionadded:: 23.21.0
        N)r'   r)   r,   r.   rv   )r   rI   r   )r1   r'   r)   r,   r.   rv   r    r    r!   register_local_factory  s   

z Container.register_local_factoryFr   r   c                  s    | j | fdd|||d dS )a  
        Syntactic sugar for::

           register_local_factory(
               svc_type,
               lambda: value,
               enter=enter,
               ping=ping,
               on_registry_close=on_registry_close
           )

        Please note that, unlike with :meth:`register_local_factory`, entering
        context managers is **disabled** by default.

        See Also:
            :ref:`local-registries`

        .. versionadded:: 23.21.0
        c                     r   r/   r    r    r   r    r!   r      r   z0Container.register_local_value.<locals>.<lambda>ru   N)r   )r1   r'   r   r,   r.   rv   r    r   r!   register_local_value  s   

zContainer.register_local_valuetype[T1]r   c                C     d S r/   r    rN   r    r    r!   rC     rV   zContainer.get	svc_type1	svc_type2type[T2]tuple[T1, T2]c                C  r   r/   r    r1   r   r   r    r    r!   rC   	     	svc_type3type[T3]tuple[T1, T2, T3]c                C  r   r/   r    r1   r   r   r   r    r    r!   rC     r   	svc_type4type[T4]tuple[T1, T2, T3, T4]c                C  r   r/   r    r1   r   r   r   r   r    r    r!   rC     s   	svc_type5type[T5]tuple[T1, T2, T3, T4, T5]c                C  r   r/   r    r1   r   r   r   r   r   r    r    r!   rC     s   		svc_type6type[T6]tuple[T1, T2, T3, T4, T5, T6]c                C  r   r/   r    r1   r   r   r   r   r   r   r    r    r!   rC   (  s   
	svc_type7type[T7]!tuple[T1, T2, T3, T4, T5, T6, T7]c                C  r   r/   r    r1   r   r   r   r   r   r   r   r    r    r!   rC   4  s   	svc_type8type[T8]%tuple[T1, T2, T3, T4, T5, T6, T7, T8]c	   	       	      C  r   r/   r    	r1   r   r   r   r   r   r   r   r   r    r    r!   rC   A  s   	svc_type9type[T9])tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9]c
   
       
      C  r   r/   r    
r1   r   r   r   r   r   r   r   r   r   r    r    r!   rC   O  s   
svc_type10	type[T10].tuple[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]c                C  r   r/   r    r1   r   r   r   r   r   r   r   r   r   r   r    r    r!   rC   ^  s   c           	      G  s   g }|D ]?}|  |\}}}}|r|| qt|s t|tr&d}t||r9t|tr9| j||f | }|| j	|< || qt
|dkrN|d S |S )aE  
        Get services of *svc_types*.

        Instantiate them if necessary and register their cleanup.

        Returns:
             ``svc_types[0]`` | ``tuple[*svc_types]``: If one service is
             requested, it's returned directly. If multiple are requested, a
             tuple of services is returned.
        z!Use `aget()` for async factories.r   r   )r   r   r   r   r   	TypeErrorr   rK   rU   r   rL   )	r1   r   rvr'   cachedrE   r2   r,   msgr    r    r!   rC   n  s&   


c                     d S r/   r    rN   r    r    r!   rF     re   zContainer.agetc                  r   r/   r    r   r    r    r!   rF        c                  r   r/   r    r   r    r    r!   rF     r   c                  r   r/   r    r   r    r    r!   rF     s   c                  r   r/   r    r   r    r    r!   rF     s   	c                  r   r/   r    r   r    r    r!   rF     s   
c                  r   r/   r    r   r    r    r!   rF     s   c	   	       	        r   r/   r    r   r    r    r!   rF     s   c
   
       
        r   r/   r    r   r    r    r!   rF     s   c                  r   r/   r    r   r    r    r!   rF     s   c                   s  g }|D ]{}|  |\}}}}|r|| q|r/t|tr/| j||f | I dH }nG|rCt|trC| j||f | }n3t|rv|I dH }|rct|trc| j||f | I dH }n|rvt|trv| j||f | }|| j	|< || qt
|dkr|d S |S )a  
        Same as :meth:`get` but instantiates asynchronously, if necessary.

        Also works with synchronous services, so in an async application, just
        use this.

        .. versionchanged:: 25.1.0
           Synchronous context managers are now entered/exited, too.
        Nr   r   )r   r   r   r   rK   rd   r   rU   r   r   rL   )r1   r   r   r'   r   rE   r2   r,   r    r    r!   rF     s4   




r5   r   )r   r@   r   rH   )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   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   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   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   )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   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r&   r   r   )r6   r   r   r7   r8   r   r9   r   r   r   r   rK   r4   rO   rU   ra   rd   ri   rs   r_   rh   r   r   r   r   r   r   r   rC   rF   r    r    r    r!   r@     s   
 









&
!



%$	

%	
r@   )r   r   r   r   )r)   r   r   r*   )3
__future__r   r   loggingrp   collections.abcr   r   r   
contextlibr   r   r   r	   r
   r   r   r   r   r   typesr   typingr   r   r   r9   
exceptionsr   	getLoggerr~   r"   _KEY_REGISTRY_KEY_CONTAINERfrozenr%   r<   definerI   r   r   r   r   r   r   r   r   r   r   r   r@   r    r    r    r!   <module>   sH   

+*  
3