From 3db7200ab62a8abdd5319167493291379e5b3c11 Mon Sep 17 00:00:00 2001 From: Pavel Boldin Date: Thu, 16 Apr 2015 15:40:43 +0300 Subject: [PATCH] Add function decorator `log_deprecated_args' Add decorator `log_deprecated_args' that issues a message whenever the decorated function is called with deprecated keyword arguments supplied. Message is issued only once or per each call depending on the configuration. Change-Id: Icedf72c40d9255f8d82233ebf640165d4827d53b --- rally/common/utils.py | 33 ++++++++++++++++++++++++++++++++- tests/unit/common/test_utils.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/rally/common/utils.py b/rally/common/utils.py index 5b1fa1280c..1ce65b18bf 100644 --- a/rally/common/utils.py +++ b/rally/common/utils.py @@ -224,7 +224,7 @@ def log_verification_wrapper(log_function, msg, **kw): def log_deprecated(message, rally_version, log_function=None): - """A wrapper marking a certain method as decrecated. + """A wrapper marking a certain method as deprecated. :param message: Message that describes why the method was deprecated :param rally_version: version of Rally when the method was deprecated @@ -243,6 +243,37 @@ def log_deprecated(message, rally_version, log_function=None): return decorator +def log_deprecated_args(message, rally_version, deprecated_args, + log_function=None, once=False): + """A wrapper marking certain arguments as deprecated. + + :param message: Message that describes why the arguments were deprecated + :param rally_version: version of Rally when the arguments were deprecated + :param deprecated_args: List of deprecated args. + :param log_function: Logging method to be used, e.g. LOG.info + :param once: Show only once (default is each) + """ + log_function = log_function or LOG.warning + + def decorator(f): + @functools.wraps(f) + def wrapper(*args, **kwargs): + if (not once) or (not getattr(f, "_warned_dep_args", False)): + deprecated = ", ".join([ + "`%s'" % x for x in deprecated_args if x in kwargs]) + if deprecated: + log_function( + "%(msg)s (args %(args)s deprecated in Rally " + "v%(version)s)" % + {"msg": message, "version": rally_version, + "args": deprecated}) + setattr(f, "_warned_dep_args", once) + result = f(*args, **kwargs) + return result + return wrapper + return decorator + + def load_plugins(directory): if os.path.exists(directory): LOG.info("Loading plugins from directories %s/*" % directory) diff --git a/tests/unit/common/test_utils.py b/tests/unit/common/test_utils.py index 7c7269b4ee..24b138fc82 100644 --- a/tests/unit/common/test_utils.py +++ b/tests/unit/common/test_utils.py @@ -169,6 +169,36 @@ class LogTestCase(test.TestCase): mock_log.assert_called_once_with("Deprecated test " "(deprecated in Rally v0.0.1)") + def test_log_deprecated_args(self): + mock_log = mock.MagicMock() + + @utils.log_deprecated_args("Deprecated test", "0.0.1", ("z",), + mock_log, once=True) + def some_method(x, y, z): + return x + y + z + + self.assertEqual(some_method(2, 2, z=3), 7) + mock_log.assert_called_once_with( + "Deprecated test (args `z' deprecated in Rally v0.0.1)") + + mock_log.reset_mock() + self.assertEqual(some_method(2, 2, z=3), 7) + self.assertFalse(mock_log.called) + + @utils.log_deprecated_args("Deprecated test", "0.0.1", ("z",), + mock_log, once=False) + def some_method(x, y, z): + return x + y + z + + self.assertEqual(some_method(2, 2, z=3), 7) + mock_log.assert_called_once_with( + "Deprecated test (args `z' deprecated in Rally v0.0.1)") + + mock_log.reset_mock() + self.assertEqual(some_method(2, 2, z=3), 7) + mock_log.assert_called_once_with( + "Deprecated test (args `z' deprecated in Rally v0.0.1)") + class LoadExtraModulesTestCase(test.TestCase):