1# Copyright 2018 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"""gRPC's experimental APIs. 
    15 
    16These APIs are subject to be removed during any minor version release. 
    17""" 
    18 
    19import copy 
    20import functools 
    21import sys 
    22import warnings 
    23 
    24import grpc 
    25from grpc._cython import cygrpc as _cygrpc 
    26 
    27_EXPERIMENTAL_APIS_USED = set() 
    28 
    29 
    30class ChannelOptions(object): 
    31    """Indicates a channel option unique to gRPC Python. 
    32 
    33    This enumeration is part of an EXPERIMENTAL API. 
    34 
    35    Attributes: 
    36      SingleThreadedUnaryStream: Perform unary-stream RPCs on a single thread. 
    37    """ 
    38 
    39    SingleThreadedUnaryStream = "SingleThreadedUnaryStream" 
    40 
    41 
    42class UsageError(Exception): 
    43    """Raised by the gRPC library to indicate usage not allowed by the API.""" 
    44 
    45 
    46# It's important that there be a single insecure credentials object so that its 
    47# hash is deterministic and can be used for indexing in the simple stubs cache. 
    48_insecure_channel_credentials = grpc.ChannelCredentials( 
    49    _cygrpc.channel_credentials_insecure() 
    50) 
    51 
    52 
    53def insecure_channel_credentials(): 
    54    """Creates a ChannelCredentials for use with an insecure channel. 
    55 
    56    THIS IS AN EXPERIMENTAL API. 
    57    """ 
    58    return _insecure_channel_credentials 
    59 
    60 
    61class ExperimentalApiWarning(Warning): 
    62    """A warning that an API is experimental.""" 
    63 
    64 
    65def _warn_experimental(api_name, stack_offset): 
    66    if api_name not in _EXPERIMENTAL_APIS_USED: 
    67        _EXPERIMENTAL_APIS_USED.add(api_name) 
    68        msg = ( 
    69            "'{}' is an experimental API. It is subject to change or ".format( 
    70                api_name 
    71            ) 
    72            + "removal between minor releases. Proceed with caution." 
    73        ) 
    74        warnings.warn(msg, ExperimentalApiWarning, stacklevel=2 + stack_offset) 
    75 
    76 
    77def experimental_api(f): 
    78    @functools.wraps(f) 
    79    def _wrapper(*args, **kwargs): 
    80        _warn_experimental(f.__name__, 1) 
    81        return f(*args, **kwargs) 
    82 
    83    return _wrapper 
    84 
    85 
    86def wrap_server_method_handler(wrapper, handler): 
    87    """Wraps the server method handler function. 
    88 
    89    The server implementation requires all server handlers being wrapped as 
    90    RpcMethodHandler objects. This helper function ease the pain of writing 
    91    server handler wrappers. 
    92 
    93    Args: 
    94        wrapper: A wrapper function that takes in a method handler behavior 
    95          (the actual function) and returns a wrapped function. 
    96        handler: A RpcMethodHandler object to be wrapped. 
    97 
    98    Returns: 
    99        A newly created RpcMethodHandler. 
    100    """ 
    101    if not handler: 
    102        return None 
    103 
    104    if not handler.request_streaming: 
    105        if not handler.response_streaming: 
    106            # NOTE(lidiz) _replace is a public API: 
    107            #   https://docs.python.org/dev/library/collections.html 
    108            return handler._replace(unary_unary=wrapper(handler.unary_unary)) 
    109        return handler._replace(unary_stream=wrapper(handler.unary_stream)) 
    110    if not handler.response_streaming: 
    111        return handler._replace(stream_unary=wrapper(handler.stream_unary)) 
    112    return handler._replace(stream_stream=wrapper(handler.stream_stream)) 
    113 
    114 
    115__all__ = ( 
    116    "ChannelOptions", 
    117    "ExperimentalApiWarning", 
    118    "UsageError", 
    119    "insecure_channel_credentials", 
    120    "wrap_server_method_handler", 
    121) 
    122 
    123if sys.version_info > (3, 6): 
    124    from grpc._simple_stubs import stream_stream 
    125    from grpc._simple_stubs import stream_unary 
    126    from grpc._simple_stubs import unary_stream 
    127    from grpc._simple_stubs import unary_unary 
    128 
    129    __all__ += ( 
    130        "unary_unary", 
    131        "unary_stream", 
    132        "stream_unary", 
    133        "stream_stream", 
    134    )