text: #!/usr/bin/python
  # -*- coding: utf-8 -*-
  
  # Hive Appier Framework
  # Copyright (c) 2008-2020 Hive Solutions Lda.
  #
  # This file is part of Hive Appier Framework.
  #
  # Hive Appier Framework is free software: you can redistribute it and/or modify
  # it under the terms of the Apache License as published by the Apache
  # Foundation, either version 2.0 of the License, or (at your option) any
  # later version.
  #
  # Hive Appier Framework is distributed in the hope that it will be useful,
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  # Apache License for more details.
  #
  # You should have received a copy of the Apache License along with
  # Hive Appier Framework. If not, see <http://www.apache.org/licenses/>.
  
  __author__ = "João Magalhães <joamag@hive.pt>"
  """ The author(s) of the module """
  
  __version__ = "1.0.0"
  """ The version of the module """
  
  __revision__ = "$LastChangedRevision$"
  """ The revision number of the module """
  
  __date__ = "$LastChangedDate$"
  """ The last change date of the module """
  
  __copyright__ = "Copyright (c) 2008-2020 Hive Solutions Lda."
  """ The copyright for the module """
  
  __license__ = "Apache License, Version 2.0"
  """ The license for the module """
  
  import inspect
  
  from . import legacy
  from . import async_old
  
  class AwaitWrapper(object):
  
      _is_generator = True
  
      def __init__(self, generator, generate = False):
          if generate: generator = self.generate(generator)
          self.generator = generator
          self.is_generator = legacy.is_generator(generator)
  
      def __await__(self):
          if self.is_generator: return self._await_generator()
          else: return self._await_basic()
  
      def __iter__(self):
          return self
  
      def __next__(self):
          return next(self.generator)
  
      def next(self):
          return self.__next__()
  
      def generate(self, value):
          yield value
  
      def _await_generator(self):
          value = yield from self.generator
          return value
  
      def _await_basic(self):
          return self.generator
          yield
  
  class CoroutineWrapper(object):
  
      def __init__(self, coroutine):
          self.coroutine = coroutine
          self._buffer = None
  
      def __iter__(self):
          return self
  
      def __next__(self):
          if self._buffer: return self._buffer.pop(0)
          return self.coroutine.send(None)
  
      def next(self):
          return self.__next__()
  
      def restore(self, value):
          if self._buffer == None: self._buffer = []
          self._buffer.append(value)
  
  class AyncgenWrapper(object):
  
      def __init__(self, async_iter):
          self.async_iter = async_iter
          self.current = None
          self._buffer = None
  
      def __iter__(self):
          return self
  
      def __next__(self):
          if self._buffer: return self._buffer.pop(0)
          try:
              if self.current == None:
                  self.current = self.async_iter.asend(None)
              try:
                  return next(self.current)
              except StopIteration as exception:
                  self.current = None
                  if not exception.args: return None
                  return exception.args[0]
          except StopAsyncIteration: #@UndefinedVariable
              raise StopIteration()
  
      def next(self):
          return self.__next__()
  
      def restore(self, value):
          if self._buffer == None: self._buffer = []
          self._buffer.append(value)
  
  def await_wrap(generator):
      return AwaitWrapper(generator)
  
  def await_yield(value):
      return AwaitWrapper(value, generate = True)
  
  def ensure_generator(value):
      if legacy.is_generator(value):
          return True, value
  
      if hasattr(value, "_generator"):
          return True, value
  
      if hasattr(inspect, "iscoroutine") and\
          inspect.iscoroutine(value): #@UndefinedVariable
          return True, CoroutineWrapper(value)
  
      if hasattr(inspect, "isasyncgen") and\
          inspect.isasyncgen(value): #@UndefinedVariable
          return True, AyncgenWrapper(value)
  
      return False, value
  
  def is_coroutine(callable):
      if hasattr(callable, "_is_coroutine"):
          return True
  
      if hasattr(inspect, "iscoroutinefunction") and\
          inspect.iscoroutinefunction(callable): #@UndefinedVariable
          return True
  
      return False
  
  def is_coroutine_object(generator):
      if legacy.is_generator(generator):
          return True
  
      if hasattr(inspect, "iscoroutine") and\
          inspect.iscoroutine(generator): #@UndefinedVariable
          return True
  
      return False
  
  def is_coroutine_native(generator):
      if hasattr(inspect, "iscoroutine") and\
          inspect.iscoroutine(generator): #@UndefinedVariable
          return True
  
      return False
  
  def to_coroutine(callable, *args, **kwargs):
      # sets the original reference to the future variable, this
      # should never be the final result, otherwise error occurs
      future = None
  
      # yields the complete set of values from the generator created
      # by the call to the to coroutine converter of the callable
      for value in async_old.to_coroutine(callable, *args, **kwargs):
          yield value
          future = value
  
      # returns the final result, retrieving it from the future object
      # that has been returned from the coroutine generator function
      return future.result()
  