diff --git a/tensorflow/python/util/deprecation.py b/tensorflow/python/util/deprecation.py index d09476a680d..60b559b5f4e 100644 --- a/tensorflow/python/util/deprecation.py +++ b/tensorflow/python/util/deprecation.py @@ -33,7 +33,8 @@ def _add_deprecated_function_notice_to_docstring(doc, date, instructions): doc, instructions, 'DEPRECATED FUNCTION', '(deprecated)', [ - 'THIS FUNCTION IS DEPRECATED. It will be removed after %s.' % date, + 'THIS FUNCTION IS DEPRECATED. It will be removed %s.' % ( + 'in a future version' if date is None else ('after %s' % date)), 'Instructions for updating:']) @@ -44,14 +45,13 @@ def _add_deprecated_arg_notice_to_docstring(doc, date, instructions): 'DEPRECATED FUNCTION ARGUMENTS', '(deprecated arguments)', [ 'SOME ARGUMENTS ARE DEPRECATED. ' - 'They will be removed after %s.' % date, + 'They will be removed %s.' % ( + 'in a future version' if date is None else ('after %s' % date)), 'Instructions for updating:']) def _validate_deprecation_args(date, instructions): - if not date: - raise ValueError('Tell us what date this will be deprecated!') - if not re.match(r'20\d\d-[01]\d-[0123]\d', date): + if date is not None and not re.match(r'20\d\d-[01]\d-[0123]\d', date): raise ValueError('Date must be YYYY-MM-DD.') if not instructions: raise ValueError('Don\'t deprecate things without conversion instructions!') @@ -84,6 +84,7 @@ def deprecated(date, instructions): Instructions for updating: + If `date` is None, 'after ' is replaced with 'in a future version'. will include the class name if it is a method. It also edits the docstring of the function: ' (deprecated)' is appended @@ -91,8 +92,8 @@ def deprecated(date, instructions): to the rest of the docstring. Args: - date: String. The date the function is scheduled to be removed. Must be - ISO 8601 (YYYY-MM-DD). + date: String or None. The date the function is scheduled to be removed. + Must be ISO 8601 (YYYY-MM-DD), or None. instructions: String. Instructions on how to update code using the deprecated function. @@ -100,7 +101,8 @@ def deprecated(date, instructions): Decorated function or method. Raises: - ValueError: If date is not in ISO 8601 format, or instructions are empty. + ValueError: If date is not None or in ISO 8601 format, or instructions are + empty. """ _validate_deprecation_args(date, instructions) @@ -110,11 +112,12 @@ def deprecated(date, instructions): @functools.wraps(func) def new_func(*args, **kwargs): logging.warning( - 'From %s: %s (from %s) is deprecated and will be removed ' - 'after %s.\n' + 'From %s: %s (from %s) is deprecated and will be removed %s.\n' 'Instructions for updating:\n%s', _call_location(), decorator_utils.get_qualified_name(func), - func.__module__, date, instructions) + func.__module__, + 'in a future version' if date is None else ('after %s' % date), + instructions) return func(*args, **kwargs) new_func.__doc__ = _add_deprecated_function_notice_to_docstring( func.__doc__, date, instructions) @@ -136,15 +139,16 @@ def deprecated_args(date, instructions, *deprecated_arg_names_or_tuples): removed after . Instructions for updating: - will include the class name if it is a method. + If `date` is None, 'after ' is replaced with 'in a future version'. + includes the class name if it is a method. It also edits the docstring of the function: ' (deprecated arguments)' is appended to the first line of the docstring and a deprecation notice is prepended to the rest of the docstring. Args: - date: String. The date the function is scheduled to be removed. Must be - ISO 8601 (YYYY-MM-DD). + date: String or None. The date the function is scheduled to be removed. + Must be ISO 8601 (YYYY-MM-DD), or None. instructions: String. Instructions on how to update code using the deprecated function. *deprecated_arg_names_or_tuples: String. or 2-Tuple(String, @@ -156,7 +160,7 @@ def deprecated_args(date, instructions, *deprecated_arg_names_or_tuples): Decorated function or method. Raises: - ValueError: If date is not in ISO 8601 format, instructions are + ValueError: If date is not None or in ISO 8601 format, instructions are empty, the deprecated arguments are not present in the function signature, or the second element of a deprecated_tuple is not a list. @@ -275,9 +279,11 @@ def deprecated_args(date, instructions, *deprecated_arg_names_or_tuples): for arg_name in invalid_args: logging.warning( 'From %s: calling %s (from %s) with %s is deprecated and will ' - 'be removed after %s.\nInstructions for updating:\n%s', + 'be removed %s.\nInstructions for updating:\n%s', _call_location(), decorator_utils.get_qualified_name(func), - func.__module__, arg_name, date, instructions) + func.__module__, arg_name, + 'in a future version' if date is None else ('after %s' % date), + instructions) return func(*args, **kwargs) new_func.__doc__ = _add_deprecated_arg_notice_to_docstring( func.__doc__, date, instructions) @@ -295,6 +301,7 @@ def deprecated_arg_values(date, instructions, **deprecated_kwargs): will be removed after . Instructions for updating: + If `date` is None, 'after ' is replaced with 'in a future version'. will include the class name if it is a method. It also edits the docstring of the function: ' (deprecated arguments)' is @@ -302,8 +309,8 @@ def deprecated_arg_values(date, instructions, **deprecated_kwargs): prepended to the rest of the docstring. Args: - date: String. The date the function is scheduled to be removed. Must be - ISO 8601 (YYYY-MM-DD). + date: String or None. The date the function is scheduled to be removed. + Must be ISO 8601 (YYYY-MM-DD), or None instructions: String. Instructions on how to update code using the deprecated function. **deprecated_kwargs: The deprecated argument values. @@ -312,7 +319,8 @@ def deprecated_arg_values(date, instructions, **deprecated_kwargs): Decorated function or method. Raises: - ValueError: If date is not in ISO 8601 format, or instructions are empty. + ValueError: If date is not None or in ISO 8601 format, or instructions are + empty. """ _validate_deprecation_args(date, instructions) if not deprecated_kwargs: @@ -329,9 +337,11 @@ def deprecated_arg_values(date, instructions, **deprecated_kwargs): if arg_name in named_args and named_args[arg_name] == arg_value: logging.warning( 'From %s: calling %s (from %s) with %s=%s is deprecated and will ' - 'be removed after %s.\nInstructions for updating:\n%s', + 'be removed %s.\nInstructions for updating:\n%s', _call_location(), decorator_utils.get_qualified_name(func), - func.__module__, arg_name, arg_value, date, instructions) + func.__module__, arg_name, arg_value, + 'in a future version' if date is None else ('after %s' % date), + instructions) return func(*args, **kwargs) new_func.__doc__ = _add_deprecated_arg_notice_to_docstring( func.__doc__, date, instructions) diff --git a/tensorflow/python/util/deprecation_test.py b/tensorflow/python/util/deprecation_test.py index 07d6bd6a48f..cce0bb1b4ee 100644 --- a/tensorflow/python/util/deprecation_test.py +++ b/tensorflow/python/util/deprecation_test.py @@ -33,9 +33,7 @@ class DeprecationTest(test.TestCase): def test_deprecated_illegal_args(self): instructions = "This is how you update..." - with self.assertRaisesRegexp(ValueError, "date"): - deprecation.deprecated(None, instructions) - with self.assertRaisesRegexp(ValueError, "date"): + with self.assertRaisesRegexp(ValueError, "YYYY-MM-DD"): deprecation.deprecated("", instructions) with self.assertRaisesRegexp(ValueError, "YYYY-MM-DD"): deprecation.deprecated("07-04-2016", instructions) @@ -45,6 +43,46 @@ class DeprecationTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "instructions"): deprecation.deprecated(date, "") + @test.mock.patch.object(logging, "warning", autospec=True) + def test_no_date(self, mock_warning): + date = None + instructions = "This is how you update..." + + @deprecation.deprecated(date, instructions) + def _fn(arg0, arg1): + """fn doc. + + Args: + arg0: Arg 0. + arg1: Arg 1. + + Returns: + Sum of args. + """ + return arg0 + arg1 + + self.assertEqual( + "fn doc. (deprecated)" + "\n" + "\nTHIS FUNCTION IS DEPRECATED. It will be removed in a future version." + "\nInstructions for updating:\n%s" + "\n" + "\nArgs:" + "\n arg0: Arg 0." + "\n arg1: Arg 1." + "\n" + "\nReturns:" + "\n Sum of args." % instructions, _fn.__doc__) + + # Assert calling new fn issues log warning. + self.assertEqual(3, _fn(1, 2)) + self.assertEqual(1, mock_warning.call_count) + (args, _) = mock_warning.call_args + self.assertRegexpMatches( + args[0], r"deprecated and will be removed") + self._assert_subset(set(["in a future version", instructions]), + set(args[1:])) + @test.mock.patch.object(logging, "warning", autospec=True) def test_static_fn_with_doc(self, mock_warning): date = "2016-07-04" @@ -82,8 +120,8 @@ class DeprecationTest(test.TestCase): self.assertEqual(3, _fn(1, 2)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_static_fn_with_one_line_doc(self, mock_warning): @@ -107,8 +145,8 @@ class DeprecationTest(test.TestCase): self.assertEqual(3, _fn(1, 2)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_static_fn_no_doc(self, mock_warning): @@ -132,8 +170,8 @@ class DeprecationTest(test.TestCase): self.assertEqual(3, _fn(1, 2)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_instance_fn_with_doc(self, mock_warning): @@ -177,8 +215,8 @@ class DeprecationTest(test.TestCase): self.assertEqual(3, _Object()._fn(1, 2)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_instance_fn_with_one_line_doc(self, mock_warning): @@ -207,8 +245,8 @@ class DeprecationTest(test.TestCase): self.assertEqual(3, _Object()._fn(1, 2)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_instance_fn_no_doc(self, mock_warning): @@ -236,8 +274,8 @@ class DeprecationTest(test.TestCase): self.assertEqual(3, _Object()._fn(1, 2)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) def test_prop_wrong_order(self): with self.assertRaisesRegexp( @@ -290,8 +328,8 @@ class DeprecationTest(test.TestCase): self.assertEqual("prop_with_doc", _Object()._prop) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_prop_no_doc(self, mock_warning): @@ -320,8 +358,8 @@ class DeprecationTest(test.TestCase): self.assertEqual("prop_no_doc", _Object()._prop) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) class DeprecatedArgsTest(test.TestCase): @@ -334,9 +372,7 @@ class DeprecatedArgsTest(test.TestCase): def test_deprecated_illegal_args(self): instructions = "This is how you update..." date = "2016-07-04" - with self.assertRaisesRegexp(ValueError, "date"): - deprecation.deprecated_args(None, instructions, "deprecated") - with self.assertRaisesRegexp(ValueError, "date"): + with self.assertRaisesRegexp(ValueError, "YYYY-MM-DD"): deprecation.deprecated_args("", instructions, "deprecated") with self.assertRaisesRegexp(ValueError, "YYYY-MM-DD"): deprecation.deprecated_args("07-04-2016", instructions, "deprecated") @@ -401,8 +437,8 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(3, _fn(1, 2, True)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_static_fn_with_one_line_doc(self, mock_warning): @@ -430,8 +466,8 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(3, _fn(1, 2, True)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_static_fn_no_doc(self, mock_warning): @@ -459,8 +495,8 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(3, _fn(1, 2, True)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_varargs(self, mock_warning): @@ -479,8 +515,8 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(3, _fn(1, 2, True, False)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_kwargs(self, mock_warning): @@ -499,8 +535,8 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(3, _fn(1, 2, a=True, b=False)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_positional_and_named(self, mock_warning): @@ -519,11 +555,13 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(2, _fn(1, None, 2, d2=False)) self.assertEqual(2, mock_warning.call_count) (args1, _) = mock_warning.call_args_list[0] - self.assertRegexpMatches(args1[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions, "d1"]), set(args1[1:])) + self.assertRegexpMatches(args1[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions, "d1"]), + set(args1[1:])) (args2, _) = mock_warning.call_args_list[1] - self.assertRegexpMatches(args1[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions, "d2"]), set(args2[1:])) + self.assertRegexpMatches(args2[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions, "d2"]), + set(args2[1:])) @test.mock.patch.object(logging, "warning", autospec=True) def test_positional_and_named_with_ok_vals(self, mock_warning): @@ -543,11 +581,13 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(2, _fn(1, False, 2, d2=False)) self.assertEqual(2, mock_warning.call_count) (args1, _) = mock_warning.call_args_list[0] - self.assertRegexpMatches(args1[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions, "d1"]), set(args1[1:])) + self.assertRegexpMatches(args1[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions, "d1"]), + set(args1[1:])) (args2, _) = mock_warning.call_args_list[1] - self.assertRegexpMatches(args1[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions, "d2"]), set(args2[1:])) + self.assertRegexpMatches(args2[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions, "d2"]), + set(args2[1:])) # Assert calls with the deprecated arguments dont log warnings if # the value matches the 'ok_val'. @@ -565,9 +605,7 @@ class DeprecatedArgValuesTest(test.TestCase): def test_deprecated_illegal_args(self): instructions = "This is how you update..." - with self.assertRaisesRegexp(ValueError, "date"): - deprecation.deprecated_arg_values(None, instructions, deprecated=True) - with self.assertRaisesRegexp(ValueError, "date"): + with self.assertRaisesRegexp(ValueError, "YYYY-MM-DD"): deprecation.deprecated_arg_values("", instructions, deprecated=True) with self.assertRaisesRegexp(ValueError, "YYYY-MM-DD"): deprecation.deprecated_arg_values( @@ -623,8 +661,8 @@ class DeprecatedArgValuesTest(test.TestCase): self.assertEqual(3, _fn(1, 2, deprecated=True)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) # Assert calling new fn with default deprecated value issues log warning. self.assertEqual(3, _fn(1, 2)) @@ -656,8 +694,8 @@ class DeprecatedArgValuesTest(test.TestCase): self.assertEqual(3, _fn(1, 2, deprecated=True)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) # Assert calling new fn with default deprecated value issues log warning. self.assertEqual(3, _fn(1, 2)) @@ -689,8 +727,8 @@ class DeprecatedArgValuesTest(test.TestCase): self.assertEqual(3, _fn(1, 2, deprecated=True)) self.assertEqual(1, mock_warning.call_count) (args, _) = mock_warning.call_args - self.assertRegexpMatches(args[0], r"deprecated and will be removed after") - self._assert_subset(set([date, instructions]), set(args[1:])) + self.assertRegexpMatches(args[0], r"deprecated and will be removed") + self._assert_subset(set(["after " + date, instructions]), set(args[1:])) # Assert calling new fn with default deprecated value issues log warning. self.assertEqual(3, _fn(1, 2))