
    ZThu                        d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZ  ej                  e      Zd Z G d d      Z G d	 d
      Zy)zTransport layer for gRPC communication.

This module provides a simple wrapper around sift_py/grpc/transport.py for making gRPC API calls.
It just stores the channel and the stubs, without any additional functionality.
    )annotationsN)Any)SiftChannelConfiguse_sift_async_channelc                j    |j                  d      }t        |t              ry| j                  |       y)a  Suppress benign BlockingIOError from gRPC's PollerCompletionQueue.

    gRPC's internal poller uses non-blocking I/O. When no events are ready,
    it raises BlockingIOError (EAGAIN), which is expected and safe to ignore.
    Swallowing these prevents noisy, spurious error logs.
    	exceptionN)get
isinstanceBlockingIOErrordefault_exception_handler)loopcontextexcs      i/home/www/backend.miabetepe.com/venv/lib/python3.12/site-packages/sift_client/transport/grpc_transport.py_suppress_blocking_ior      s-     ++k
"C#'""7+    c                  :    e Zd ZdZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZddZy)
GrpcConfigz#Configuration for gRPC API clients.Nc                R    || _         || _        || _        || _        |xs i | _        y)a  Initialize the gRPC configuration.

        Args:
            url: The URI of the gRPC server.
            api_key: The API key for authentication.
            use_ssl: Whether to use SSL/TLS.
            cert_via_openssl: Whether to use OpenSSL for SSL/TLS.
            use_async: Whether to use async gRPC client.
            metadata: Additional metadata to include in all requests.
        N)uriapi_keyuse_sslcert_via_opensslmetadata)selfurlr   r   r   r   s         r   __init__zGrpcConfig.__init__(   s,    $  0 Br   c                `    | j                   | j                  | j                  | j                  dS )z[Convert to a SiftChannelConfig.

        Returns:
            A SiftChannelConfig.
        )r   apikeyr   r   )r   r   r   r   r   s    r   _to_sift_channel_configz"GrpcConfig._to_sift_channel_config@   s,     88ll|| $ 5 5	
 	
r   )TFN)
r   strr   r"   r   boolr   r#   r   dict[str, str] | None)returnr   )__name__
__module____qualname____doc__r   r!    r   r   r   r   %   sJ    - !&*.'' ' 	'
 ' ('0
r   r   c                  j    e Zd ZdZddZedd       ZddZd Zd Z	d Z
d Zd	 Zd
 Z	 	 	 	 	 	 ddZy)
GrpcClientzA simple wrapper around sift_py/grpc/transport.py for making gRPC API calls.

    This class just stores the channel and the stubs, without any additional functionality.
    c                l    | _         i  _        i  _        t        j                          _        t        j                   j                          j
                  j                  t                fd}t        j                  |d       _         j                  j                          |j                         }t        j                    j#                  ||j$                         j
                        }|j'                         }| j                   j
                  <   i  j                   j
                  <   y)zfInitialize the gRPC client.

        Args:
            config: The gRPC client configuration.
        c                 x    t        j                   j                          j                  j                          y N)asyncioset_event_loop_default_looprun_foreverr    s   r   _run_default_loopz.GrpcClient.__init__.<locals>._run_default_loope   s)    ""4#5#56**,r   T)targetdaemonN)_config_channels_async_stubs_async_mapr0   new_event_loopr2   atexitregister
close_syncset_exception_handlerr   	threadingThread_default_loop_threadstartr!   run_coroutine_threadsafe_create_async_channelr   result)r   configr4   cfgfuturechannels   `     r   r   zGrpcClient.__init__T   s     EGWY$335(001FG	- %.$4$4$%
! 	!!''),,.11&&sFOO<d>P>P
 --/3:T//046d001r   c                    | j                   S )zReturn the default event loop used for synchronous API operations.

        Returns:
            The default asyncio event loop.
        )r2   r    s    r   default_loopzGrpcClient.default_loopw   s     !!!r   c                   	 t        j                         }|j                  t               || j                  vrVt        | j                  j                         | j                  j                        }|| j                  |<   i | j                  |<   | j                  |   }||vr || j                  |         ||<   ||   S # t        $ r | j
                  }Y w xY w)zwGet an async stub bound to the current event loop.
        Creates a channel and stub for this loop if needed.
        )r0   get_running_loopr>   r   RuntimeErrorr2   r8   r   r7   r!   r   r9   )r   
stub_classr   rI   stubss        r   get_stubzGrpcClient.get_stub   s    	&++-D&&'<= t+++,4468M8MG *1D  &*,D!!$'%%d+U" *4+?+?+E FE*Z    	&%%D	&s   )B? ?CCc                p   	 | j                   j                         D ]>  }t        j                  |j	                         | j
                        j                          @ | j
                  j                  | j
                  j                         | j                  j                  d       y# t        $ r Y yw xY w)z.Close the sync channel and all async channels.      ?timeoutN)r8   valuesr0   rC   closer2   rE   call_soon_threadsafestoprA   join
ValueErrorr   chs     r   r=   zGrpcClient.close_sync   s    	**113 Z00T=O=OPWWYZ33D4F4F4K4KL%%**3*7 		s   B&B) )	B54B5c                  K   | j                   j                         D ]  }|j                          d{     | j                  j	                  | j                  j
                         | j                  j                  d       y7 Rw)z8Close sync and async channels and stop the default loop.NrS   rT   )r8   rV   rW   r2   rX   rY   rA   rZ   r\   s     r   rW   zGrpcClient.close   so     &&--/ 	B((*	//0B0B0G0GH!!&&s&3 s   1BBABc                   K   | S wr/   r*   r    s    r   
__aenter__zGrpcClient.__aenter__   s     s   c                @   K   | j                          d {    y 7 wr/   )rW   r   exc_typeexc_valexc_tbs       r   	__aexit__zGrpcClient.__aexit__   s     jjls   c                    | S r/   r*   r    s    r   	__enter__zGrpcClient.__enter__   s    r   c                $    | j                          y r/   )r=   rb   s       r   __exit__zGrpcClient.__exit__   s    r   c                "   K   t        ||      S w)z/Helper to create async channel on default loop.)r   )r   rG   r   s      r   rD   z GrpcClient._create_async_channel   s      &c844s   N)rF   r   )r%   zasyncio.AbstractEventLoop)rO   z	type[Any]r%   r   )rG   r   r   r$   r%   r   )r&   r'   r(   r)   r   propertyrK   rQ   r=   rW   r`   rf   rh   rj   rD   r*   r   r   r,   r,   N   sa    
!7F " "!.45$50E5	5r   r,   )r)   
__future__r   r0   r;   loggingr?   typingr   sift_py.grpc.transportr   r   	getLoggerr&   loggerr   r   r,   r*   r   r   <module>rs      sS    #      
		8	$
,&
 &
Rj5 j5r   