util.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. # Copyright (c) 2009 Denis Bilenko. See LICENSE for details.
  2. """
  3. Low-level utilities.
  4. """
  5. from __future__ import absolute_import
  6. import functools
  7. __all__ = ['wrap_errors']
  8. class wrap_errors(object):
  9. """
  10. Helper to make function return an exception, rather than raise it.
  11. Because every exception that is unhandled by greenlet will be logged,
  12. it is desirable to prevent non-error exceptions from leaving a greenlet.
  13. This can done with a simple ``try/except`` construct::
  14. def wrapped_func(*args, **kwargs):
  15. try:
  16. return func(*args, **kwargs)
  17. except (TypeError, ValueError, AttributeError) as ex:
  18. return ex
  19. This class provides a shortcut to write that in one line::
  20. wrapped_func = wrap_errors((TypeError, ValueError, AttributeError), func)
  21. It also preserves ``__str__`` and ``__repr__`` of the original function.
  22. """
  23. # QQQ could also support using wrap_errors as a decorator
  24. def __init__(self, errors, func):
  25. """
  26. Calling this makes a new function from *func*, such that it catches *errors* (an
  27. :exc:`BaseException` subclass, or a tuple of :exc:`BaseException` subclasses) and
  28. return it as a value.
  29. """
  30. self.__errors = errors
  31. self.__func = func
  32. # Set __doc__, __wrapped__, etc, especially useful on Python 3.
  33. functools.update_wrapper(self, func)
  34. def __call__(self, *args, **kwargs):
  35. func = self.__func
  36. try:
  37. return func(*args, **kwargs)
  38. except self.__errors as ex:
  39. return ex
  40. def __str__(self):
  41. return str(self.__func)
  42. def __repr__(self):
  43. return repr(self.__func)
  44. def __getattr__(self, name):
  45. return getattr(self.__func, name)