deprecation.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. # -*- coding: utf-8 -*-
  2. """
  3. flaskbb.deprecation
  4. ~~~~~~~~~~~~~~~~~~~
  5. Module used for deprecation handling in FlaskBB
  6. :copyright: (c) 2018 the FlaskBB Team.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. import inspect
  10. import warnings
  11. from abc import abstractproperty
  12. from functools import wraps
  13. from flask_babelplus import gettext as _
  14. from ._compat import ABC
  15. class FlaskBBWarning(Warning):
  16. """
  17. Base class for any warnings that FlaskBB itself needs to issue, provided
  18. for convenient filtering.
  19. """
  20. pass
  21. class FlaskBBDeprecation(DeprecationWarning, FlaskBBWarning, ABC):
  22. """
  23. Base class for deprecations originating from FlaskBB, subclasses must
  24. provide a version attribute that represents when deprecation becomes a
  25. removal::
  26. class RemovedInPluginv3(FlaskBBDeprecation):
  27. version = (3, 0, 0)
  28. """
  29. version = abstractproperty(lambda self: None)
  30. class RemovedInFlaskBB3(FlaskBBDeprecation):
  31. """
  32. warning for features removed in FlaskBB3
  33. """
  34. version = (3, 0, 0)
  35. def deprecated(message="", category=RemovedInFlaskBB3):
  36. """
  37. Flags a function or method as deprecated, should not be used on
  38. classes as it will break inheritance and introspection.
  39. :param message: Optional message to display along with deprecation warning.
  40. :param category: Warning category to use, defaults to RemovedInFlaskBB3,
  41. if provided must be a subclass of FlaskBBDeprecation.
  42. """
  43. def deprecation_decorator(f):
  44. if not issubclass(category, FlaskBBDeprecation):
  45. raise ValueError(
  46. "Expected subclass of FlaskBBDeprecation for category, got {}".format( # noqa
  47. str(category)
  48. )
  49. )
  50. version = ".".join([str(x) for x in category.version])
  51. warning = _(
  52. "%(name)s is deprecated and will be removed in version %(version)s.", # noqa
  53. name=f.__name__,
  54. version=version,
  55. )
  56. if message:
  57. warning = "{} {}".format(warning, message)
  58. docstring = f.__doc__
  59. if docstring:
  60. docstring = "\n".join([docstring, warning])
  61. else:
  62. docstring = warning
  63. f.__doc__ = docstring
  64. @wraps(f)
  65. def wrapper(*a, **k):
  66. frame = inspect.currentframe().f_back
  67. warnings.warn_explicit(
  68. warning,
  69. category=category,
  70. filename=inspect.getfile(frame.f_code),
  71. lineno=frame.f_lineno,
  72. )
  73. return f(*a, **k)
  74. return wrapper
  75. return deprecation_decorator