@@ -42,6 +42,24 @@ class _MethodDefault(enum.Enum):
4242so the default should be used."""
4343
4444
45+ def _is_not_none_or_false (value ):
46+ return value is not None and value is not False
47+
48+
49+ def _apply_decorators (func , decorators ):
50+ """Apply a list of decorators to a given function.
51+
52+ ``decorators`` may contain items that are ``None`` or ``False`` which will
53+ be ignored.
54+ """
55+ filtered_decorators = filter (_is_not_none_or_false , reversed (decorators ))
56+
57+ for decorator in filtered_decorators :
58+ func = decorator (func )
59+
60+ return func
61+
62+
4563class _GapicCallable (object ):
4664 """Callable that applies retry, timeout, and metadata logic.
4765
@@ -73,8 +91,6 @@ def __init__(
7391 ):
7492 self ._target = target
7593 self ._retry = retry
76- if isinstance (timeout , (int , float )):
77- timeout = TimeToDeadlineTimeout (timeout = timeout )
7894 self ._timeout = timeout
7995 self ._compression = compression
8096 self ._metadata = metadata
@@ -84,42 +100,35 @@ def __call__(
84100 ):
85101 """Invoke the low-level RPC with retry, timeout, compression, and metadata."""
86102
87- if compression is DEFAULT :
88- compression = self ._compression
89- if compression is not None :
90- kwargs ["compression" ] = compression
103+ if retry is DEFAULT :
104+ retry = self ._retry
91105
92- # Add the user agent metadata to the call.
93- if self ._metadata is not None :
94- try :
95- # attempt to concatenate default metadata with user-provided metadata
96- kwargs ["metadata" ] = (* kwargs ["metadata" ], * self ._metadata )
97- except (KeyError , TypeError ):
98- # if metadata is not provided, use just the default metadata
99- kwargs ["metadata" ] = self ._metadata
100-
101- call = self ._build_wrapped_call (timeout , retry )
102- return call (* args , ** kwargs )
103-
104- @functools .lru_cache (maxsize = 4 )
105- def _build_wrapped_call (self , timeout , retry ):
106- """
107- Build a wrapped callable that applies retry, timeout, and metadata logic.
108- """
109- wrapped_func = self ._target
110106 if timeout is DEFAULT :
111107 timeout = self ._timeout
112- elif isinstance (timeout , (int , float )):
108+
109+ if compression is DEFAULT :
110+ compression = self ._compression
111+
112+ if isinstance (timeout , (int , float )):
113113 timeout = TimeToDeadlineTimeout (timeout = timeout )
114- if timeout is not None :
115- wrapped_func = timeout (wrapped_func )
116114
117- if retry is DEFAULT :
118- retry = self ._retry
119- if retry is not None :
120- wrapped_func = retry (wrapped_func )
115+ # Apply all applicable decorators.
116+ wrapped_func = _apply_decorators (self ._target , [retry , timeout ])
117+
118+ # Add the user agent metadata to the call.
119+ if self ._metadata is not None :
120+ metadata = kwargs .get ("metadata" , [])
121+ # Due to the nature of invocation, None should be treated the same
122+ # as not specified.
123+ if metadata is None :
124+ metadata = []
125+ metadata = list (metadata )
126+ metadata .extend (self ._metadata )
127+ kwargs ["metadata" ] = metadata
128+ if self ._compression is not None :
129+ kwargs ["compression" ] = compression
121130
122- return wrapped_func
131+ return wrapped_func ( * args , ** kwargs )
123132
124133
125134def wrap_method (
0 commit comments