Files
HP_InHand_IG502/APPS_UNCOMPILED/lib/deprecation.py
2025-04-30 08:48:49 -05:00

177 lines
9.1 KiB
Python

# uncompyle6 version 3.9.2
# Python bytecode version base 3.7.0 (3394)
# Decompiled from: Python 3.8.19 (default, Mar 20 2024, 15:27:52)
# [Clang 14.0.6 ]
# Embedded file name: /var/user/app/device_supervisorbak/device_supervisor/lib/deprecation.py
# Compiled at: 2024-04-18 03:12:55
# Size of source mod 2**32: 12895 bytes
import collections, functools, textwrap, warnings
from packaging import version
from datetime import date
__version__ = "2.1.0"
__all__ = [
'deprecated', 'message_location', 'fail_if_not_removed',
'DeprecatedWarning',
'UnsupportedWarning']
message_location = "bottom"
class DeprecatedWarning(DeprecationWarning):
__doc__ = "A warning class for deprecated methods\n\n This is a specialization of the built-in :class:`DeprecationWarning`,\n adding parameters that allow us to get information into the __str__\n that ends up being sent through the :mod:`warnings` system.\n The attributes aren't able to be retrieved after the warning gets\n raised and passed through the system as only the class--not the\n instance--and message are what gets preserved.\n\n :param function: The function being deprecated.\n :param deprecated_in: The version that ``function`` is deprecated in\n :param removed_in: The version or :class:`datetime.date` specifying\n when ``function`` gets removed.\n :param details: Optional details about the deprecation. Most often\n this will include directions on what to use instead\n of the now deprecated code.\n "
def __init__(self, function, deprecated_in, removed_in, details=''):
self.function = function
self.deprecated_in = deprecated_in
self.removed_in = removed_in
self.details = details
super(DeprecatedWarning, self).__init__(function, deprecated_in, removed_in, details)
def __str__(self):
parts = collections.defaultdict(str)
parts["function"] = self.function
if self.deprecated_in:
parts["deprecated"] = " as of %s" % self.deprecated_in
if self.removed_in:
parts["removed"] = " and will be removed {} {}".format("on" if isinstance(self.removed_in, date) else "in", self.removed_in)
if any([self.deprecated_in, self.removed_in, self.details]):
parts["period"] = "."
if self.details:
parts["details"] = " %s" % self.details
return "%(function)s is deprecated%(deprecated)s%(removed)s%(period)s%(details)s" % parts
class UnsupportedWarning(DeprecatedWarning):
__doc__ = "A warning class for methods to be removed\n\n This is a subclass of :class:`~deprecation.DeprecatedWarning` and is used\n to output a proper message about a function being unsupported.\n Additionally, the :func:`~deprecation.fail_if_not_removed` decorator\n will handle this warning and cause any tests to fail if the system\n under test uses code that raises this warning.\n "
def __str__(self):
parts = collections.defaultdict(str)
parts["function"] = self.function
parts["removed"] = self.removed_in
if self.details:
parts["details"] = " %s" % self.details
return "%(function)s is unsupported as of %(removed)s.%(details)s" % parts
def deprecated(deprecated_in=None, removed_in=None, current_version=None, details=''):
"""Decorate a function to signify its deprecation
This function wraps a method that will soon be removed and does two things:
* The docstring of the method will be modified to include a notice
about deprecation, e.g., "Deprecated since 0.9.11. Use foo instead."
* Raises a :class:`~deprecation.DeprecatedWarning`
via the :mod:`warnings` module, which is a subclass of the built-in
:class:`DeprecationWarning`. Note that built-in
:class:`DeprecationWarning`s are ignored by default, so for users
to be informed of said warnings they will need to enable them--see
the :mod:`warnings` module documentation for more details.
:param deprecated_in: The version at which the decorated method is
considered deprecated. This will usually be the
next version to be released when the decorator is
added. The default is **None**, which effectively
means immediate deprecation. If this is not
specified, then the `removed_in` and
`current_version` arguments are ignored.
:param removed_in: The version or :class:`datetime.date` when the decorated
method will be removed. The default is **None**,
specifying that the function is not currently planned
to be removed.
Note: This parameter cannot be set to a value if
`deprecated_in=None`.
:param current_version: The source of version information for the
currently running code. This will usually be
a `__version__` attribute on your library.
The default is `None`.
When `current_version=None` the automation to
determine if the wrapped function is actually
in a period of deprecation or time for removal
does not work, causing a
:class:`~deprecation.DeprecatedWarning`
to be raised in all cases.
:param details: Extra details to be added to the method docstring and
warning. For example, the details may point users to
a replacement method, such as "Use the foo_bar
method instead". By default there are no details.
"""
if deprecated_in is None:
if removed_in is not None:
raise TypeError("Cannot set removed_in to a value without also setting deprecated_in")
else:
is_deprecated = False
is_unsupported = False
if isinstance(removed_in, date):
if date.today() >= removed_in:
is_unsupported = True
else:
is_deprecated = True
else:
if current_version:
current_version = version.parse(current_version)
if removed_in and current_version >= version.parse(removed_in):
is_unsupported = True
elif deprecated_in:
if current_version >= version.parse(deprecated_in):
is_deprecated = True
else:
is_deprecated = True
should_warn = any([is_deprecated, is_unsupported])
def _function_wrapper(function):
if should_warn:
existing_docstring = function.__doc__ or ""
parts = {'deprecated_in':" %s" % deprecated_in if deprecated_in else "",
'removed_in':"\n This will be removed {} {}.".format("on" if isinstance(removed_in, date) else "in", removed_in) if removed_in else "",
'details':" %s" % details if details else ""}
deprecation_note = (".. deprecated::{deprecated_in}{removed_in}{details}".format)(**parts)
loc = 1
string_list = existing_docstring.split("\n", 1)
if len(string_list) > 1:
string_list[1] = textwrap.dedent(string_list[1])
string_list.insert(loc, "\n")
if message_location != "top":
loc = 3
string_list.insert(loc, deprecation_note)
string_list.insert(loc, "\n\n")
function.__doc__ = "".join(string_list)
@functools.wraps(function)
def _inner(*args, **kwargs):
if should_warn:
if is_unsupported:
cls = UnsupportedWarning
else:
cls = DeprecatedWarning
the_warning = cls(function.__name__, deprecated_in, removed_in, details)
warnings.warn(the_warning, category=DeprecationWarning, stacklevel=2)
return function(*args, **kwargs)
return _inner
return _function_wrapper
def fail_if_not_removed(method):
"""Decorate a test method to track removal of deprecated code
This decorator catches :class:`~deprecation.UnsupportedWarning`
warnings that occur during testing and causes unittests to fail,
making it easier to keep track of when code should be removed.
:raises: :class:`AssertionError` if an
:class:`~deprecation.UnsupportedWarning`
is raised while running the test method.
"""
@functools.wraps(method)
def test_inner(*args, **kwargs):
with warnings.catch_warnings(record=True) as caught_warnings:
warnings.simplefilter("always")
rv = method(*args, **kwargs)
for warning in caught_warnings:
if warning.category == UnsupportedWarning:
raise AssertionError("%s uses a function that should be removed: %s" % (
method, str(warning.message)))
return rv
return test_inner