From fa21c6ecc23e660faefc4c0795af5097711ae444 Mon Sep 17 00:00:00 2001 From: ashwin <52176187+aakum03@users.noreply.github.com> Date: Tue, 4 Feb 2020 15:11:21 -0500 Subject: [PATCH] Allow removed_in to be a date (#47) * Allowed removed_in to be a date (datetime.date) * added 9 more test cases(for date); passed local tests * removed TODOs * Fixed errors and formatted lines * removed unecessary condition on ln 168 * made requested changes to docstring --- .gitignore | 3 +++ deprecation.py | 33 +++++++++++++++++++++--------- tests/test_deprecation.py | 43 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 72364f9..0627077 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,6 @@ ENV/ # Rope project settings .ropeproject + +#Pycharm Files +.idea/ diff --git a/deprecation.py b/deprecation.py index ccb7f66..e7903b4 100644 --- a/deprecation.py +++ b/deprecation.py @@ -15,6 +15,7 @@ import warnings from packaging import version +from datetime import date __version__ = "2.0.7" @@ -42,7 +43,8 @@ class DeprecatedWarning(DeprecationWarning): :param function: The function being deprecated. :param deprecated_in: The version that ``function`` is deprecated in - :param removed_in: The version that ``function`` gets removed in + :param removed_in: The version or :class:`datetime.date` specifying + when ``function`` gets removed. :param details: Optional details about the deprecation. Most often this will include directions on what to use instead of the now deprecated code. @@ -68,7 +70,8 @@ def __str__(self): if self.deprecated_in: parts["deprecated"] = " as of %s" % self.deprecated_in if self.removed_in: - parts["removed"] = " and will be removed in %s" % 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: @@ -121,10 +124,11 @@ def deprecated(deprecated_in=None, removed_in=None, current_version=None, means immediate deprecation. If this is not specified, then the `removed_in` and `current_version` arguments are ignored. - :param removed_in: The version when the decorated method will be removed. - The default is **None**, specifying that the function - is not currently planned to be removed. - Note: This cannot be set to a value if + :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 @@ -155,8 +159,14 @@ def deprecated(deprecated_in=None, removed_in=None, current_version=None, is_unsupported = False # StrictVersion won't take a None or a "", so make whatever goes to it - # is at least *something*. - if current_version: + # is at least *something*. Compare versions only if removed_in is not + # of type datetime.date + if isinstance(removed_in, date): + if date.today() >= removed_in: + is_unsupported = True + else: + is_deprecated = True + elif current_version: current_version = version.parse(current_version) if (removed_in @@ -183,12 +193,15 @@ def _function_wrapper(function): # a number of ways the deprecation notice could go. The following # makes for a nicely constructed sentence with or without any # of the parts. + + # If removed_in is a date, use "removed on" + # If removed_in is a version, use "removed in" parts = { "deprecated_in": " %s" % deprecated_in if deprecated_in else "", "removed_in": - "\n This will be removed in %s." % - removed_in if removed_in else "", + "\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 ""} diff --git a/tests/test_deprecation.py b/tests/test_deprecation.py index 4d294ba..0fd29b3 100644 --- a/tests/test_deprecation.py +++ b/tests/test_deprecation.py @@ -16,6 +16,7 @@ import warnings import deprecation +from datetime import date class Test_deprecated(unittest2.TestCase): @@ -41,6 +42,14 @@ def test_docstring(self): "details": "some details"}, "__doc__": "docstring\n\n.. deprecated:: 1.0" "\n This will be removed in 2.0. " + "some details"}, + {"args": {"deprecated_in": "1.0", "removed_in": date(2200, 5, 20)}, + "__doc__": "docstring\n\n.. deprecated:: 1.0" + "\n This will be removed on 2200-05-20."}, + {"args": {"deprecated_in": "1.0", "removed_in": date(2100, 3, 15), + "details": "some details"}, + "__doc__": "docstring\n\n.. deprecated:: 1.0" + "\n This will be removed on 2100-03-15. " "some details"}]: with self.subTest(**test): @deprecation.deprecated(**test["args"]) @@ -62,6 +71,14 @@ def test_multiline_docstring(self): "details": "some details"}, "__doc__": "%s\n\n.. deprecated:: 1.0" "\n This will be removed in 2.0. " + "some details"}, + {"args": {"deprecated_in": "1.0", "removed_in": date(2200, 11, 20)}, + "__doc__": "%s\n\n.. deprecated:: 1.0" + "\n This will be removed on 2200-11-20."}, + {"args": {"deprecated_in": "1.0", "removed_in": date(2100, 3, 15), + "details": "some details"}, + "__doc__": "%s\n\n.. deprecated:: 1.0" + "\n This will be removed on 2100-03-15. " "some details"}]: with self.subTest(**test): @deprecation.deprecated(**test["args"]) @@ -88,6 +105,14 @@ def test_multiline_docstring_top(self): "details": "some details"}, "__doc__": "%s\n\n.. deprecated:: 1.0" "\n This will be removed in 2.0. " + "some details%s"},##### + {"args": {"deprecated_in": "1.0", "removed_in": date(2200, 11, 20)}, + "__doc__": "%s\n\n.. deprecated:: 1.0" + "\n This will be removed on 2200-11-20.%s"}, + {"args": {"deprecated_in": "1.0", "removed_in": date(2100, 3, 15), + "details": "some details"}, + "__doc__": "%s\n\n.. deprecated:: 1.0" + "\n This will be removed on 2100-03-15. " "some details%s"}]: with self.subTest(**test): deprecation.message_location = "top" @@ -150,6 +175,24 @@ def test_warning_raised(self): "details": "do something else."}, "warning": deprecation.UnsupportedWarning, "message": ("method is unsupported as of 2.0. " + "do something else.")}, + {"args": {"deprecated_in": "1.0", + "removed_in": date(2100, 4, 19), + "current_version": "2.0"}, + "warning": deprecation.DeprecatedWarning, + "message": ("method is deprecated as of 1.0 " + "and will be removed on 2100-04-19.")}, + {"args": {"deprecated_in": "1.0", + "removed_in": date.today(), + "current_version": "2.0"}, + "warning": deprecation.UnsupportedWarning, + "message": "method is unsupported as of %s." % date.today()}, + {"args": {"deprecated_in": "1.0", + "removed_in": date(2020, 1, 30), + "current_version": "2.0", + "details": "do something else."}, + "warning": deprecation.UnsupportedWarning, + "message": ("method is unsupported as of 2020-01-30. " "do something else.")}]: with self.subTest(**test): class Test(object):