text: #    Copyright 2015-2016 Mirantis, Inc.
  #
  #    Licensed under the Apache License, Version 2.0 (the "License"); you may
  #    not use this file except in compliance with the License. You may obtain
  #    a copy of the License at
  #
  #         http://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing, software
  #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  #    License for the specific language governing permissions and limitations
  #    under the License.
  
  import abc
  import logging
  import uuid
  
  import six
  
  from oslo_messaging._drivers.zmq_driver import zmq_async
  from oslo_messaging._drivers.zmq_driver import zmq_names
  from oslo_messaging._drivers.zmq_driver import zmq_version
  from oslo_messaging._i18n import _LE
  
  LOG = logging.getLogger(__name__)
  
  zmq = zmq_async.import_zmq()
  
  
  @six.add_metaclass(abc.ABCMeta)
  class Request(object):
  
      """Zmq request abstract class
  
      Represents socket (publisher) independent data object to publish.
      Request object should contain all needed information for a publisher
      to publish it, for instance: message payload, target, timeout
      and retries etc.
      """
  
      def __init__(self, target, context=None, message=None, retry=None):
  
          """Construct request object
  
          :param target: Message destination target
          :type target: oslo_messaging.Target
          :param context: Message context
          :type context: dict
          :param message: Message payload to pass
          :type message: dict
          :param retry: an optional default connection retries configuration
                        None or -1 means to retry forever
                        0 means no retry
                        N means N retries
          :type retry: int
          """
  
          if self.msg_type not in zmq_names.REQUEST_TYPES:
              raise RuntimeError("Unknown request type!")
  
          self.target = target
          self.context = context
          self.message = message
  
          self.retry = retry
          if not isinstance(retry, int) and retry is not None:
              raise ValueError(
                  "retry must be an integer, not {0}".format(type(retry)))
  
          self.message_id = str(uuid.uuid1())
  
      @abc.abstractproperty
      def msg_type(self):
          """ZMQ request type"""
  
      @property
      def message_version(self):
          return zmq_version.MESSAGE_VERSION
  
  
  class RpcRequest(Request):
  
      def __init__(self, *args, **kwargs):
          message = kwargs.get("message")
          if message['method'] is None:
              errmsg = _LE("No method specified for RPC call")
              LOG.error(_LE("No method specified for RPC call"))
              raise KeyError(errmsg)
  
          super(RpcRequest, self).__init__(*args, **kwargs)
  
  
  class CallRequest(RpcRequest):
  
      msg_type = zmq_names.CALL_TYPE
  
      def __init__(self, *args, **kwargs):
          self.allowed_remote_exmods = kwargs.pop("allowed_remote_exmods")
  
          self.timeout = kwargs.pop("timeout")
          if self.timeout is None:
              raise ValueError("Timeout should be specified for a RPC call!")
          elif not isinstance(self.timeout, int):
              raise ValueError(
                  "timeout must be an integer, not {0}"
                  .format(type(self.timeout)))
  
          super(CallRequest, self).__init__(*args, **kwargs)
  
  
  class CastRequest(RpcRequest):
  
      msg_type = zmq_names.CAST_TYPE
  
  
  class FanoutRequest(RpcRequest):
  
      msg_type = zmq_names.CAST_FANOUT_TYPE
  
  
  class NotificationRequest(Request):
  
      msg_type = zmq_names.NOTIFY_TYPE
  
      def __init__(self, *args, **kwargs):
          self.version = kwargs.pop("version")
          super(NotificationRequest, self).__init__(*args, **kwargs)
  