PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Windows/Python3.8/WPy64-3830/WPy64-3830/python-3.8.3.amd64/Lib/site-packages/sqlalchemy/util/deprecations.py

https://gitlab.com/abhi1tb/build
Python | 259 lines | 236 code | 11 blank | 12 comment | 2 complexity | 0034a02e7c57e45abb91bcae13fed7c8 MD5 | raw file
  1. # util/deprecations.py
  2. # Copyright (C) 2005-2020 the SQLAlchemy authors and contributors
  3. # <see AUTHORS file>
  4. #
  5. # This module is part of SQLAlchemy and is released under
  6. # the MIT License: http://www.opensource.org/licenses/mit-license.php
  7. """Helpers related to deprecation of functions, methods, classes, other
  8. functionality."""
  9. import re
  10. import warnings
  11. from . import compat
  12. from .langhelpers import _hash_limit_string
  13. from .langhelpers import decorator
  14. from .langhelpers import inject_docstring_text
  15. from .langhelpers import inject_param_text
  16. from .. import exc
  17. def warn_deprecated(msg, stacklevel=3):
  18. warnings.warn(msg, exc.SADeprecationWarning, stacklevel=stacklevel)
  19. def warn_deprecated_limited(msg, args, stacklevel=3):
  20. """Issue a deprecation warning with a parameterized string,
  21. limiting the number of registrations.
  22. """
  23. if args:
  24. msg = _hash_limit_string(msg, 10, args)
  25. warnings.warn(msg, exc.SADeprecationWarning, stacklevel)
  26. def warn_pending_deprecation(msg, stacklevel=3):
  27. warnings.warn(msg, exc.SAPendingDeprecationWarning, stacklevel=stacklevel)
  28. def deprecated_cls(version, message, constructor="__init__"):
  29. header = ".. deprecated:: %s %s" % (version, (message or ""))
  30. def decorate(cls):
  31. return _decorate_cls_with_warning(
  32. cls,
  33. constructor,
  34. exc.SADeprecationWarning,
  35. message % dict(func=constructor),
  36. header,
  37. )
  38. return decorate
  39. def deprecated(version, message=None, add_deprecation_to_docstring=True):
  40. """Decorates a function and issues a deprecation warning on use.
  41. :param version:
  42. Issue version in the warning.
  43. :param message:
  44. If provided, issue message in the warning. A sensible default
  45. is used if not provided.
  46. :param add_deprecation_to_docstring:
  47. Default True. If False, the wrapped function's __doc__ is left
  48. as-is. If True, the 'message' is prepended to the docs if
  49. provided, or sensible default if message is omitted.
  50. """
  51. if add_deprecation_to_docstring:
  52. header = ".. deprecated:: %s %s" % (version, (message or ""))
  53. else:
  54. header = None
  55. if message is None:
  56. message = "Call to deprecated function %(func)s"
  57. def decorate(fn):
  58. return _decorate_with_warning(
  59. fn,
  60. exc.SADeprecationWarning,
  61. message % dict(func=fn.__name__),
  62. header,
  63. )
  64. return decorate
  65. def deprecated_params(**specs):
  66. """Decorates a function to warn on use of certain parameters.
  67. e.g. ::
  68. @deprecated_params(
  69. weak_identity_map=(
  70. "0.7",
  71. "the :paramref:`.Session.weak_identity_map parameter "
  72. "is deprecated."
  73. )
  74. )
  75. """
  76. messages = {}
  77. for param, (version, message) in specs.items():
  78. messages[param] = _sanitize_restructured_text(message)
  79. def decorate(fn):
  80. spec = compat.inspect_getfullargspec(fn)
  81. if spec.defaults is not None:
  82. defaults = dict(
  83. zip(
  84. spec.args[(len(spec.args) - len(spec.defaults)) :],
  85. spec.defaults,
  86. )
  87. )
  88. check_defaults = set(defaults).intersection(messages)
  89. check_kw = set(messages).difference(defaults)
  90. else:
  91. check_defaults = ()
  92. check_kw = set(messages)
  93. @decorator
  94. def warned(fn, *args, **kwargs):
  95. for m in check_defaults:
  96. if kwargs[m] != defaults[m]:
  97. warnings.warn(
  98. messages[m], exc.SADeprecationWarning, stacklevel=3
  99. )
  100. for m in check_kw:
  101. if m in kwargs:
  102. warnings.warn(
  103. messages[m], exc.SADeprecationWarning, stacklevel=3
  104. )
  105. return fn(*args, **kwargs)
  106. doc = fn.__doc__ is not None and fn.__doc__ or ""
  107. if doc:
  108. doc = inject_param_text(
  109. doc,
  110. {
  111. param: ".. deprecated:: %s %s" % (version, (message or ""))
  112. for param, (version, message) in specs.items()
  113. },
  114. )
  115. decorated = warned(fn)
  116. decorated.__doc__ = doc
  117. return decorated
  118. return decorate
  119. def pending_deprecation(
  120. version, message=None, add_deprecation_to_docstring=True
  121. ):
  122. """Decorates a function and issues a pending deprecation warning on use.
  123. :param version:
  124. An approximate future version at which point the pending deprecation
  125. will become deprecated. Not used in messaging.
  126. :param message:
  127. If provided, issue message in the warning. A sensible default
  128. is used if not provided.
  129. :param add_deprecation_to_docstring:
  130. Default True. If False, the wrapped function's __doc__ is left
  131. as-is. If True, the 'message' is prepended to the docs if
  132. provided, or sensible default if message is omitted.
  133. """
  134. if add_deprecation_to_docstring:
  135. header = ".. deprecated:: %s (pending) %s" % (version, (message or ""))
  136. else:
  137. header = None
  138. if message is None:
  139. message = "Call to deprecated function %(func)s"
  140. def decorate(fn):
  141. return _decorate_with_warning(
  142. fn,
  143. exc.SAPendingDeprecationWarning,
  144. message % dict(func=fn.__name__),
  145. header,
  146. )
  147. return decorate
  148. def deprecated_option_value(parameter_value, default_value, warning_text):
  149. if parameter_value is None:
  150. return default_value
  151. else:
  152. warn_deprecated(warning_text)
  153. return parameter_value
  154. def _sanitize_restructured_text(text):
  155. def repl(m):
  156. type_, name = m.group(1, 2)
  157. if type_ in ("func", "meth"):
  158. name += "()"
  159. return name
  160. return re.sub(r"\:(\w+)\:`~?(?:_\w+)?\.?(.+?)`", repl, text)
  161. def _decorate_cls_with_warning(
  162. cls, constructor, wtype, message, docstring_header=None
  163. ):
  164. doc = cls.__doc__ is not None and cls.__doc__ or ""
  165. if docstring_header is not None:
  166. docstring_header %= dict(func=constructor)
  167. doc = inject_docstring_text(doc, docstring_header, 1)
  168. if type(cls) is type:
  169. clsdict = dict(cls.__dict__)
  170. clsdict["__doc__"] = doc
  171. cls = type(cls.__name__, cls.__bases__, clsdict)
  172. constructor_fn = clsdict[constructor]
  173. else:
  174. cls.__doc__ = doc
  175. constructor_fn = getattr(cls, constructor)
  176. setattr(
  177. cls,
  178. constructor,
  179. _decorate_with_warning(constructor_fn, wtype, message, None),
  180. )
  181. return cls
  182. def _decorate_with_warning(func, wtype, message, docstring_header=None):
  183. """Wrap a function with a warnings.warn and augmented docstring."""
  184. message = _sanitize_restructured_text(message)
  185. @decorator
  186. def warned(fn, *args, **kwargs):
  187. warnings.warn(message, wtype, stacklevel=3)
  188. return fn(*args, **kwargs)
  189. doc = func.__doc__ is not None and func.__doc__ or ""
  190. if docstring_header is not None:
  191. docstring_header %= dict(func=func.__name__)
  192. doc = inject_docstring_text(doc, docstring_header, 1)
  193. decorated = warned(func)
  194. decorated.__doc__ = doc
  195. decorated._sa_warn = lambda: warnings.warn(message, wtype, stacklevel=3)
  196. return decorated