deprecated.py 3.6 KB

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