1616
1717from __future__ import absolute_import
1818
19+ import concurrent .futures
1920import logging
2021import threading
21- import collections .abc
22- import time
23- import random
24- import concurrent .futures
2522
26- _LOGGER = logging .getLogger (__name__ )
2723from google .auth import exceptions
2824from google .auth .transport import _mtls_helper
2925from google .auth .transport import mtls
@@ -293,8 +289,8 @@ def my_client_cert_callback():
293289 "target" : target ,
294290 "ssl_credentials" : None ,
295291 "client_cert_callback" : client_cert_callback ,
296- "_is_retry" : True , # Hidden flag to stop recursion
297- ** kwargs
292+ "_is_retry" : True , # Hidden flag to stop recursion
293+ ** kwargs ,
298294 }
299295 interceptor = _MTLSCallInterceptor ()
300296
@@ -304,6 +300,7 @@ def my_client_cert_callback():
304300 return grpc .intercept_channel (wrapper , interceptor )
305301 return channel
306302
303+
307304class SslCredentials :
308305 """Class for application default SSL credentials.
309306
@@ -380,45 +377,65 @@ class _MTLSCallInterceptor(
380377):
381378 def __init__ (self ):
382379 self ._wrapper = None
383- self ._max_retries = 2 # Set your desired limit here
380+ self ._max_retries = 2 # Set your desired limit here
384381 self ._executor = concurrent .futures .ThreadPoolExecutor (max_workers = 5 )
385382
386383 def _should_retry (self , code , retry_count , attempt_cert ):
387384 if code != grpc .StatusCode .UNAUTHENTICATED or not self ._wrapper :
388385 return False
389386
390387 if retry_count >= self ._max_retries :
391- _LOGGER .debug ("Max retries reached (%d/%d)." , retry_count , self ._max_retries )
388+ _LOGGER .debug (
389+ "Max retries reached (%d/%d)." , retry_count , self ._max_retries
390+ )
392391 return False
393392
394393 # If the wrapper has already rotated to a new cert, we can retry immediately
395394 if attempt_cert != self ._wrapper ._cached_cert :
396395 return True
397396
398397 # Fingerprint check logic
399- _ , _ , cached_fp , current_fp = _mtls_helper .check_parameters_for_unauthorized_response (attempt_cert )
398+ (
399+ _ ,
400+ _ ,
401+ cached_fp ,
402+ current_fp ,
403+ ) = _mtls_helper .check_parameters_for_unauthorized_response (attempt_cert )
400404 return cached_fp != current_fp
401405
402406 def intercept_unary_unary (self , continuation , client_call_details , request ):
403407 return _RetryableUnaryResponseFuture (
404408 continuation , client_call_details , request , self , is_client_stream = False
405409 )
406410
407- def intercept_stream_unary (self , continuation , client_call_details , request_iterator ):
411+ def intercept_stream_unary (
412+ self , continuation , client_call_details , request_iterator
413+ ):
408414 return _RetryableUnaryResponseFuture (
409- continuation , client_call_details , request_iterator , self , is_client_stream = True
415+ continuation ,
416+ client_call_details ,
417+ request_iterator ,
418+ self ,
419+ is_client_stream = True ,
410420 )
411421
412422 def intercept_unary_stream (self , continuation , client_call_details , request ):
413423 return _RetryableStreamResponseIterator (
414424 continuation , client_call_details , request , self , is_client_stream = False
415425 )
416426
417- def intercept_stream_stream (self , continuation , client_call_details , request_iterator ):
427+ def intercept_stream_stream (
428+ self , continuation , client_call_details , request_iterator
429+ ):
418430 return _RetryableStreamResponseIterator (
419- continuation , client_call_details , request_iterator , self , is_client_stream = True
431+ continuation ,
432+ client_call_details ,
433+ request_iterator ,
434+ self ,
435+ is_client_stream = True ,
420436 )
421437
438+
422439class _MTLSRefreshingChannel (grpc .Channel ):
423440 def __init__ (self , target , factory_args , initial_channel , initial_cert ):
424441 self ._target = target
@@ -431,9 +448,18 @@ def __init__(self, target, factory_args, initial_channel, initial_cert):
431448 def refresh_logic (self , count ):
432449 with self ._lock :
433450 # Re-check inside lock to prevent race conditions
434- _ , _ , cached_fp , current_fp = _mtls_helper .check_parameters_for_unauthorized_response (self ._cached_cert )
451+ (
452+ _ ,
453+ _ ,
454+ cached_fp ,
455+ current_fp ,
456+ ) = _mtls_helper .check_parameters_for_unauthorized_response (
457+ self ._cached_cert
458+ )
435459 if cached_fp != current_fp :
436- _LOGGER .debug ("Wrapper: Refreshing mTLS channel. Retry count: %d" , count )
460+ _LOGGER .debug (
461+ "Wrapper: Refreshing mTLS channel. Retry count: %d" , count
462+ )
437463 old_channel = self ._channel
438464 client_cert_callback = self ._factory_args .get ("client_cert_callback" )
439465 if client_cert_callback :
@@ -460,9 +486,14 @@ def unary_unary(self, method, *args, **kwargs):
460486 return self ._channel .unary_unary (method , * args , ** kwargs )
461487
462488 # Mandatory passthroughs
463- def unary_stream (self , method , * args , ** kwargs ): return self ._channel .unary_stream (method , * args , ** kwargs )
464- def stream_unary (self , method , * args , ** kwargs ): return self ._channel .stream_unary (method , * args , ** kwargs )
465- def stream_stream (self , method , * args , ** kwargs ): return self ._channel .stream_stream (method , * args , ** kwargs )
489+ def unary_stream (self , method , * args , ** kwargs ):
490+ return self ._channel .unary_stream (method , * args , ** kwargs )
491+
492+ def stream_unary (self , method , * args , ** kwargs ):
493+ return self ._channel .stream_unary (method , * args , ** kwargs )
494+
495+ def stream_stream (self , method , * args , ** kwargs ):
496+ return self ._channel .stream_stream (method , * args , ** kwargs )
466497
467498 def subscribe (self , callback , try_to_connect = False ):
468499 with self ._lock :
@@ -474,7 +505,8 @@ def unsubscribe(self, callback):
474505 self ._subscribers .discard (callback )
475506 return self ._channel .unsubscribe (callback )
476507
477- def close (self ): self ._channel .close ()
508+ def close (self ):
509+ self ._channel .close ()
478510
479511
480512class _ReplayableIterator (object ):
@@ -550,7 +582,6 @@ def __next__(self):
550582 return val
551583
552584
553-
554585class _RetryableUnaryResponseFuture (grpc .Future , grpc .Call ):
555586 def __init__ (
556587 self ,
@@ -568,9 +599,14 @@ def __init__(
568599
569600 # New Factory Pattern for infinite streaming replays
570601 self ._uses_factory = is_client_stream and callable (request_or_iterator )
571- self ._payload = None if self ._uses_factory else (
572- _ReplayableIterator (request_or_iterator )
573- if is_client_stream else request_or_iterator
602+ self ._payload = (
603+ None
604+ if self ._uses_factory
605+ else (
606+ _ReplayableIterator (request_or_iterator )
607+ if is_client_stream
608+ else request_or_iterator
609+ )
574610 )
575611
576612 self ._retry_count = 0
@@ -592,7 +628,9 @@ def _start_call(self):
592628 if self ._uses_factory :
593629 payload = self ._source_request ()
594630 else :
595- payload = iter (self ._payload ) if self ._is_client_stream else self ._payload
631+ payload = (
632+ iter (self ._payload ) if self ._is_client_stream else self ._payload
633+ )
596634
597635 self ._target_future = self ._continuation (self ._client_call_details , payload )
598636
@@ -607,8 +645,10 @@ def _on_inner_future_done(self, inner_future):
607645 if isinstance (exc , grpc .RpcError ):
608646 status_code = exc .code ()
609647
610- can_replay = True if self ._uses_factory else (
611- self ._payload .can_replay () if self ._is_client_stream else True
648+ can_replay = (
649+ True
650+ if self ._uses_factory
651+ else (self ._payload .can_replay () if self ._is_client_stream else True )
612652 )
613653
614654 if can_replay and self ._interceptor ._should_retry (
@@ -625,9 +665,13 @@ def _on_inner_future_done(self, inner_future):
625665 return
626666
627667 # If zero-retry refresh logic is needed (buffer exhausted, etc)
628- if isinstance (exc , grpc .RpcError ) and getattr (self ._interceptor , "_wrapper" , None ):
629- if self ._interceptor ._should_retry (exc .code (), 0 , getattr (self , "_attempt_cert" , None )):
630- self ._interceptor ._wrapper .refresh_logic (1 )
668+ if isinstance (exc , grpc .RpcError ) and getattr (
669+ self ._interceptor , "_wrapper" , None
670+ ):
671+ if self ._interceptor ._should_retry (
672+ exc .code (), 0 , getattr (self , "_attempt_cert" , None )
673+ ):
674+ self ._interceptor ._wrapper .refresh_logic (1 )
631675
632676 def result (self , timeout = None ):
633677 while True :
@@ -651,6 +695,7 @@ def result(self, timeout=None):
651695
652696 def add_done_callback (self , fn ):
653697 with self ._lock :
698+
654699 def custom_callback (f ):
655700 if not self ._retry_event .is_set ():
656701 return
@@ -666,35 +711,44 @@ def custom_callback(f):
666711 def cancel (self ):
667712 with self ._lock :
668713 return self ._target_future .cancel ()
714+
669715 def cancelled (self ):
670716 with self ._lock :
671717 return self ._target_future .cancelled ()
718+
672719 def running (self ):
673720 with self ._lock :
674721 return self ._target_future .running ()
722+
675723 def done (self ):
676724 with self ._lock :
677725 return self ._target_future .done ()
726+
678727 def exception (self , timeout = None ):
679728 self ._retry_event .wait (timeout )
680729 with self ._lock :
681730 return self ._target_future .exception (timeout = timeout )
731+
682732 def traceback (self , timeout = None ):
683733 self ._retry_event .wait (timeout )
684734 with self ._lock :
685735 return self ._target_future .traceback (timeout = timeout )
736+
686737 def initial_metadata (self ):
687738 self ._retry_event .wait ()
688739 with self ._lock :
689740 return self ._target_future .initial_metadata ()
741+
690742 def trailing_metadata (self ):
691743 self ._retry_event .wait ()
692744 with self ._lock :
693745 return self ._target_future .trailing_metadata ()
746+
694747 def code (self ):
695748 self ._retry_event .wait ()
696749 with self ._lock :
697750 return self ._target_future .code ()
751+
698752 def details (self ):
699753 self ._retry_event .wait ()
700754 with self ._lock :
@@ -717,9 +771,14 @@ def __init__(
717771 self ._interceptor = interceptor
718772
719773 self ._uses_factory = is_client_stream and callable (request_or_iterator )
720- self ._payload = None if self ._uses_factory else (
721- _ReplayableIterator (request_or_iterator )
722- if is_client_stream else request_or_iterator
774+ self ._payload = (
775+ None
776+ if self ._uses_factory
777+ else (
778+ _ReplayableIterator (request_or_iterator )
779+ if is_client_stream
780+ else request_or_iterator
781+ )
723782 )
724783
725784 self ._retry_count = 0
@@ -740,7 +799,9 @@ def _start_call(self):
740799 if self ._uses_factory :
741800 payload = self ._source_request ()
742801 else :
743- payload = iter (self ._payload ) if self ._is_client_stream else self ._payload
802+ payload = (
803+ iter (self ._payload ) if self ._is_client_stream else self ._payload
804+ )
744805
745806 self ._call = self ._continuation (self ._client_call_details , payload )
746807
@@ -766,15 +827,21 @@ def __next__(self):
766827 except grpc .RpcError as e :
767828 status_code = e .code ()
768829
769- can_replay = True if self ._uses_factory else (
770- self ._payload .can_replay () if self ._is_client_stream else True
830+ can_replay = (
831+ True
832+ if self ._uses_factory
833+ else (
834+ self ._payload .can_replay () if self ._is_client_stream else True
835+ )
771836 )
772837
773838 if (
774839 not self ._yielded_any_response
775840 and can_replay
776841 and self ._interceptor ._should_retry (
777- status_code , self ._retry_count , getattr (self , "_attempt_cert" , None )
842+ status_code ,
843+ self ._retry_count ,
844+ getattr (self , "_attempt_cert" , None ),
778845 )
779846 ):
780847 with self ._lock :
@@ -796,6 +863,7 @@ def __next__(self):
796863
797864 def add_done_callback (self , fn ):
798865 with self ._lock :
866+
799867 def custom_callback (c ):
800868 with self ._lock :
801869 if self ._ignore_done_callbacks or self ._call is not c :
@@ -808,28 +876,40 @@ def custom_callback(c):
808876 def cancel (self ):
809877 with self ._lock :
810878 return self ._call .cancel ()
879+
811880 def cancelled (self ):
812881 with self ._lock :
813882 return self ._call .cancelled ()
883+
814884 def running (self ):
815885 with self ._lock :
816886 return self ._call .running ()
887+
817888 def done (self ):
818889 with self ._lock :
819890 return self ._call .done ()
891+
820892 def initial_metadata (self ):
821893 with self ._lock :
822894 return self ._call .initial_metadata ()
895+
823896 def trailing_metadata (self ):
824897 with self ._lock :
825898 return self ._call .trailing_metadata ()
899+
826900 def code (self ):
827901 with self ._lock :
828902 return self ._call .code ()
903+
829904 def details (self ):
830905 with self ._lock :
831906 return self ._call .details ()
832907
833- def is_active (self ): return self ._call .is_active ()
834- def time_remaining (self ): return self ._call .time_remaining ()
835- def add_callback (self , callback ): self ._call .add_callback (callback )
908+ def is_active (self ):
909+ return self ._call .is_active ()
910+
911+ def time_remaining (self ):
912+ return self ._call .time_remaining ()
913+
914+ def add_callback (self , callback ):
915+ self ._call .add_callback (callback )
0 commit comments