# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

from dmi import hw_metrics_mgmt_service_pb2 as dmi_dot_hw__metrics__mgmt__service__pb2
from dmi import hw_pb2 as dmi_dot_hw__pb2


class NativeMetricsManagementServiceStub(object):
    """Missing associated documentation comment in .proto file."""

    def __init__(self, channel):
        """Constructor.

        Args:
            channel: A grpc.Channel.
        """
        self.ListMetrics = channel.unary_unary(
                '/dmi.NativeMetricsManagementService/ListMetrics',
                request_serializer=dmi_dot_hw__pb2.HardwareID.SerializeToString,
                response_deserializer=dmi_dot_hw__metrics__mgmt__service__pb2.ListMetricsResponse.FromString,
                )
        self.UpdateMetricsConfiguration = channel.unary_unary(
                '/dmi.NativeMetricsManagementService/UpdateMetricsConfiguration',
                request_serializer=dmi_dot_hw__metrics__mgmt__service__pb2.MetricsConfigurationRequest.SerializeToString,
                response_deserializer=dmi_dot_hw__metrics__mgmt__service__pb2.MetricsConfigurationResponse.FromString,
                )
        self.GetMetric = channel.unary_unary(
                '/dmi.NativeMetricsManagementService/GetMetric',
                request_serializer=dmi_dot_hw__metrics__mgmt__service__pb2.GetMetricRequest.SerializeToString,
                response_deserializer=dmi_dot_hw__metrics__mgmt__service__pb2.Metric.FromString,
                )


class NativeMetricsManagementServiceServicer(object):
    """Missing associated documentation comment in .proto file."""

    def ListMetrics(self, request, context):
        """List the supported metrics for the passed device.
        This would be the first call that you make to know about the metrics that a particular device supports and
        then use the UpdateMetricsConfiguration API to monitor only the required metrics.
        """
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def UpdateMetricsConfiguration(self, request, context):
        """Updates the configuration of the list of metrics in the request
        Acts upon single metric configuration, collection of a single metric can be started/stopped
        by changing its configuration.
        
        This configuration is persisted across restart of the device or the device manager
        """
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def GetMetric(self, request, context):
        """Get the instantenous value of a metric
        """
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')


def add_NativeMetricsManagementServiceServicer_to_server(servicer, server):
    rpc_method_handlers = {
            'ListMetrics': grpc.unary_unary_rpc_method_handler(
                    servicer.ListMetrics,
                    request_deserializer=dmi_dot_hw__pb2.HardwareID.FromString,
                    response_serializer=dmi_dot_hw__metrics__mgmt__service__pb2.ListMetricsResponse.SerializeToString,
            ),
            'UpdateMetricsConfiguration': grpc.unary_unary_rpc_method_handler(
                    servicer.UpdateMetricsConfiguration,
                    request_deserializer=dmi_dot_hw__metrics__mgmt__service__pb2.MetricsConfigurationRequest.FromString,
                    response_serializer=dmi_dot_hw__metrics__mgmt__service__pb2.MetricsConfigurationResponse.SerializeToString,
            ),
            'GetMetric': grpc.unary_unary_rpc_method_handler(
                    servicer.GetMetric,
                    request_deserializer=dmi_dot_hw__metrics__mgmt__service__pb2.GetMetricRequest.FromString,
                    response_serializer=dmi_dot_hw__metrics__mgmt__service__pb2.Metric.SerializeToString,
            ),
    }
    generic_handler = grpc.method_handlers_generic_handler(
            'dmi.NativeMetricsManagementService', rpc_method_handlers)
    server.add_generic_rpc_handlers((generic_handler,))


 # This class is part of an EXPERIMENTAL API.
class NativeMetricsManagementService(object):
    """Missing associated documentation comment in .proto file."""

    @staticmethod
    def ListMetrics(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/dmi.NativeMetricsManagementService/ListMetrics',
            dmi_dot_hw__pb2.HardwareID.SerializeToString,
            dmi_dot_hw__metrics__mgmt__service__pb2.ListMetricsResponse.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def UpdateMetricsConfiguration(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/dmi.NativeMetricsManagementService/UpdateMetricsConfiguration',
            dmi_dot_hw__metrics__mgmt__service__pb2.MetricsConfigurationRequest.SerializeToString,
            dmi_dot_hw__metrics__mgmt__service__pb2.MetricsConfigurationResponse.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def GetMetric(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/dmi.NativeMetricsManagementService/GetMetric',
            dmi_dot_hw__metrics__mgmt__service__pb2.GetMetricRequest.SerializeToString,
            dmi_dot_hw__metrics__mgmt__service__pb2.Metric.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
