deprecated.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # -*- coding: utf-8 -*-
  2. """Deprecation utilities."""
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import warnings
  5. from vine.utils import wraps
  6. from celery.exceptions import CPendingDeprecationWarning, CDeprecationWarning
  7. __all__ = ['Callable', 'Property', 'warn']
  8. PENDING_DEPRECATION_FMT = """
  9. {description} is scheduled for deprecation in \
  10. version {deprecation} and removal in version v{removal}. \
  11. {alternative}
  12. """
  13. DEPRECATION_FMT = """
  14. {description} is deprecated and scheduled for removal in
  15. version {removal}. {alternative}
  16. """
  17. def warn(description=None, deprecation=None,
  18. removal=None, alternative=None, stacklevel=2):
  19. ctx = {'description': description,
  20. 'deprecation': deprecation, 'removal': removal,
  21. 'alternative': alternative}
  22. if deprecation is not None:
  23. w = CPendingDeprecationWarning(PENDING_DEPRECATION_FMT.format(**ctx))
  24. else:
  25. w = CDeprecationWarning(DEPRECATION_FMT.format(**ctx))
  26. warnings.warn(w, stacklevel=stacklevel)
  27. def Callable(deprecation=None, removal=None,
  28. alternative=None, description=None):
  29. """Decorator for deprecated functions.
  30. A deprecation warning will be emitted when the function is called.
  31. Arguments:
  32. deprecation (str): Version that marks first deprecation, if this
  33. argument is not set a ``PendingDeprecationWarning`` will be
  34. emitted instead.
  35. removal (str): Future version when this feature will be removed.
  36. alternative (str): Instructions for an alternative solution (if any).
  37. description (str): Description of what is being deprecated.
  38. """
  39. def _inner(fun):
  40. @wraps(fun)
  41. def __inner(*args, **kwargs):
  42. from .imports import qualname
  43. warn(description=description or qualname(fun),
  44. deprecation=deprecation,
  45. removal=removal,
  46. alternative=alternative,
  47. stacklevel=3)
  48. return fun(*args, **kwargs)
  49. return __inner
  50. return _inner
  51. def Property(deprecation=None, removal=None,
  52. alternative=None, description=None):
  53. def _inner(fun):
  54. return _deprecated_property(
  55. fun, deprecation=deprecation, removal=removal,
  56. alternative=alternative, description=description or fun.__name__)
  57. return _inner
  58. class _deprecated_property:
  59. def __init__(self, fget=None, fset=None, fdel=None, doc=None, **depreinfo):
  60. self.__get = fget
  61. self.__set = fset
  62. self.__del = fdel
  63. self.__name__, self.__module__, self.__doc__ = (
  64. fget.__name__, fget.__module__, fget.__doc__,
  65. )
  66. self.depreinfo = depreinfo
  67. self.depreinfo.setdefault('stacklevel', 3)
  68. def __get__(self, obj, type=None):
  69. if obj is None:
  70. return self
  71. warn(**self.depreinfo)
  72. return self.__get(obj)
  73. def __set__(self, obj, value):
  74. if obj is None:
  75. return self
  76. if self.__set is None:
  77. raise AttributeError('cannot set attribute')
  78. warn(**self.depreinfo)
  79. self.__set(obj, value)
  80. def __delete__(self, obj):
  81. if obj is None:
  82. return self
  83. if self.__del is None:
  84. raise AttributeError('cannot delete attribute')
  85. warn(**self.depreinfo)
  86. self.__del(obj)
  87. def setter(self, fset):
  88. return self.__class__(self.__get, fset, self.__del, **self.depreinfo)
  89. def deleter(self, fdel):
  90. return self.__class__(self.__get, self.__set, fdel, **self.depreinfo)