Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_utilities.py221 linesDownload Raw Back to grpc
1# Copyright 2015 gRPC authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Internal utilities for gRPC Python."""
15
16import collections
17import logging
18import threading
19import time
20from typing import Callable, Dict, Optional, Sequence
21
22import grpc
23from grpc import _common
24from grpc._typing import DoneCallbackType
25
26_LOGGER = logging.getLogger(__name__)
27
28_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = (
29    'Exception calling connectivity future "done" callback!'
30)
31
32
33class RpcMethodHandler(
34    collections.namedtuple(
35        "_RpcMethodHandler",
36        (
37            "request_streaming",
38            "response_streaming",
39            "request_deserializer",
40            "response_serializer",
41            "unary_unary",
42            "unary_stream",
43            "stream_unary",
44            "stream_stream",
45        ),
46    ),
47    grpc.RpcMethodHandler,
48):
49    pass
50
51
52class DictionaryGenericHandler(grpc.ServiceRpcHandler):
53    _name: str
54    _method_handlers: Dict[str, grpc.RpcMethodHandler]
55
56    def __init__(
57        self, service: str, method_handlers: Dict[str, grpc.RpcMethodHandler]
58    ):
59        self._name = service
60        self._method_handlers = {
61            _common.fully_qualified_method(service, method): method_handler
62            for method, method_handler in method_handlers.items()
63        }
64
65    def service_name(self) -> str:
66        return self._name
67
68    def service(
69        self, handler_call_details: grpc.HandlerCallDetails
70    ) -> Optional[grpc.RpcMethodHandler]:
71        details_method = handler_call_details.method
72        return self._method_handlers.get(
73            details_method
74        )  # pytype: disable=attribute-error
75
76
77class _ChannelReadyFuture(grpc.Future):
78    _condition: threading.Condition
79    _channel: grpc.Channel
80    _matured: bool
81    _cancelled: bool
82    _done_callbacks: Sequence[Callable]
83
84    def __init__(self, channel: grpc.Channel):
85        self._condition = threading.Condition()
86        self._channel = channel
87
88        self._matured = False
89        self._cancelled = False
90        self._done_callbacks = []
91
92    def _block(self, timeout: Optional[float]) -> None:
93        until = None if timeout is None else time.time() + timeout
94        with self._condition:
95            while True:
96                if self._cancelled:
97                    raise grpc.FutureCancelledError()
98                if self._matured:
99                    return
100                if until is None:
101                    self._condition.wait()
102                else:
103                    remaining = until - time.time()
104                    if remaining < 0:
105                        raise grpc.FutureTimeoutError()
106                    self._condition.wait(timeout=remaining)
107
108    def _update(self, connectivity: Optional[grpc.ChannelConnectivity]) -> None:
109        with self._condition:
110            if (
111                not self._cancelled
112                and connectivity is grpc.ChannelConnectivity.READY
113            ):
114                self._matured = True
115                self._channel.unsubscribe(self._update)
116                self._condition.notify_all()
117                done_callbacks = tuple(self._done_callbacks)
118                self._done_callbacks = None
119            else:
120                return
121
122        for done_callback in done_callbacks:
123            try:
124                done_callback(self)
125            except Exception:  # pylint: disable=broad-except
126                _LOGGER.exception(_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE)
127
128    def cancel(self) -> bool:
129        with self._condition:
130            if not self._matured:
131                self._cancelled = True
132                self._channel.unsubscribe(self._update)
133                self._condition.notify_all()
134                done_callbacks = tuple(self._done_callbacks)
135                self._done_callbacks = None
136            else:
137                return False
138
139        for done_callback in done_callbacks:
140            try:
141                done_callback(self)
142            except Exception:  # pylint: disable=broad-except
143                _LOGGER.exception(_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE)
144
145        return True
146
147    def cancelled(self) -> bool:
148        with self._condition:
149            return self._cancelled
150
151    def running(self) -> bool:
152        with self._condition:
153            return not self._cancelled and not self._matured
154
155    def done(self) -> bool:
156        with self._condition:
157            return self._cancelled or self._matured
158
159    def result(self, timeout: Optional[float] = None) -> None:
160        self._block(timeout)
161
162    def exception(self, timeout: Optional[float] = None) -> None:
163        self._block(timeout)
164
165    def traceback(self, timeout: Optional[float] = None) -> None:
166        self._block(timeout)
167
168    def add_done_callback(self, fn: DoneCallbackType):
169        with self._condition:
170            if not self._cancelled and not self._matured:
171                self._done_callbacks.append(fn)
172                return
173
174        fn(self)
175
176    def start(self):
177        with self._condition:
178            self._channel.subscribe(self._update, try_to_connect=True)
179
180    def __del__(self):
181        with self._condition:
182            if not self._cancelled and not self._matured:
183                self._channel.unsubscribe(self._update)
184
185
186def channel_ready_future(channel: grpc.Channel) -> _ChannelReadyFuture:
187    ready_future = _ChannelReadyFuture(channel)
188    ready_future.start()
189    return ready_future
190
191
192def first_version_is_lower(version1: str, version2: str) -> bool:
193    """
194    Compares two versions in the format '1.60.1' or '1.60.1.dev0'.
195
196    This method will be used in all stubs generated by grpcio-tools to check whether
197    the stub version is compatible with the runtime grpcio.
198
199    Args:
200        version1: The first version string.
201        version2: The second version string.
202
203    Returns:
204        True if version1 is lower, False otherwise.
205    """
206    version1_list = version1.split(".")
207    version2_list = version2.split(".")
208
209    try:
210        for i in range(3):
211            if int(version1_list[i]) < int(version2_list[i]):
212                return True
213            if int(version1_list[i]) > int(version2_list[i]):
214                return False
215    except ValueError:
216        # Return false in case we can't convert version to int.
217        return False
218
219    # The version without dev0 will be considered lower.
220    return len(version1_list) < len(version2_list)
221 
codekingpro/portable-devtools · Team Ai