text: #
  # Copyright 2008 Google LLC. All Rights Reserved.
  #
  # 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.
  
  """Base class for implementing RPC of API proxy stubs."""
  
  
  # WARNING: This file is externally viewable by our users.  All comments from
  # this file will be stripped.  The docstrings will NOT.  Do not put sensitive
  # information in docstrings.  If you must communicate internal information in
  # this source file, please use comments.
  
  
  from __future__ import absolute_import
  
  
  import sys
  
  from googlecloudsdk.third_party.appengine._internal import six_subset
  
  
  class RPC(object):
    """Base class for implementing RPC of API proxy stubs.
  
    To implement a RPC to make real asynchronous API call:
      - Extend this class.
      - Override _MakeCallImpl and/or _WaitImpl to do a real asynchronous call.
    """
  
    IDLE = 0
    RUNNING = 1
    FINISHING = 2
  
    def __init__(self, package=None, call=None, request=None, response=None,
                 callback=None, deadline=None, stub=None):
      """Constructor for the RPC object.
  
      All arguments are optional, and simply set members on the class.
      These data members will be overriden by values passed to MakeCall.
  
      Args:
        package: string, the package for the call
        call: string, the call within the package
        request: ProtocolMessage instance, appropriate for the arguments
        response: ProtocolMessage instance, appropriate for the response
        callback: callable, called when call is complete
        deadline: A double specifying the deadline for this call as the number of
                  seconds from the current time. Ignored if non-positive.
        stub: APIProxyStub instance, used in default _WaitImpl to do real call
      """
      self._exception = None
      self._state = RPC.IDLE
      self._traceback = None
  
      self.package = package
      self.call = call
      self.request = request
      self.response = response
      self.callback = callback
      self.deadline = deadline
      self.stub = stub
      self.cpu_usage_mcycles = 0
  
    def Clone(self):
      """Make a shallow copy of this instances attributes, excluding methods.
  
      This is usually used when an RPC has been specified with some configuration
      options and is being used as a template for multiple RPCs outside of a
      developer's easy control.
      """
      if self.state != RPC.IDLE:
        raise AssertionError('Cannot clone a call already in progress')
  
      clone = self.__class__()
      for k, v in self.__dict__.items():
        setattr(clone, k, v)
      return clone
  
    def MakeCall(self, package=None, call=None, request=None, response=None,
                 callback=None, deadline=None):
      """Makes an asynchronous (i.e. non-blocking) API call within the
      specified package for the specified call method.
  
      It will call the _MakeRealCall to do the real job.
  
      Args:
        Same as constructor; see __init__.
  
      Raises:
        TypeError or AssertionError if an argument is of an invalid type.
        AssertionError or RuntimeError is an RPC is already in use.
      """
      self.callback = callback or self.callback
      self.package = package or self.package
      self.call = call or self.call
      self.request = request or self.request
      self.response = response or self.response
      self.deadline = deadline or self.deadline
  
      assert self._state is RPC.IDLE, ('RPC for %s.%s has already been started' %
                                        (self.package, self.call))
      assert self.callback is None or callable(self.callback)
      self._MakeCallImpl()
  
    def Wait(self):
      """Waits on the API call associated with this RPC."""
      rpc_completed = self._WaitImpl()
  
      assert rpc_completed, ('RPC for %s.%s was not completed, and no other '
                             'exception was raised ' % (self.package, self.call))
  
    def CheckSuccess(self):
      """If there was an exception, raise it now.
  
      Raises:
        Exception of the API call or the callback, if any.
      """
      if self.exception and self._traceback:
        six_subset.reraise(self.exception.__class__, self.exception,
                           self._traceback)
      elif self.exception:
        raise self.exception
  
    @property
    def exception(self):
      return self._exception
  
    @property
    def state(self):
      return self._state
  
    def _MakeCallImpl(self):
      """Override this method to implement a real asynchronous call rpc."""
      self._state = RPC.RUNNING
  
    def _WaitImpl(self):
      """Override this method to implement a real asynchronous call rpc.
  
      Returns:
        True if the async call was completed successfully.
      """
      try:
        try:
          self.stub.MakeSyncCall(self.package, self.call,
                                 self.request, self.response)
        except Exception:
          _, self._exception, self._traceback = sys.exc_info()
      finally:
        self._state = RPC.FINISHING
        self._Callback()
  
      return True
  
    def _Callback(self):
      if self.callback:
        try:
          self.callback()
        except:
          _, self._exception, self._traceback = sys.exc_info()
          self._exception._appengine_apiproxy_rpc = self
          raise
  