1# Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Deprecation tests.""" 16 17# pylint: disable=unused-import 18import collections 19import enum 20 21import numpy as np 22 23 24from tensorflow.python.eager import context 25from tensorflow.python.framework import constant_op 26from tensorflow.python.framework import ops 27from tensorflow.python.framework import test_util 28from tensorflow.python.ops import variables 29from tensorflow.python.platform import test 30from tensorflow.python.platform import tf_logging as logging 31from tensorflow.python.util import deprecation 32from tensorflow.python.util import tf_inspect 33 34 35class DeprecatedAliasTest(test.TestCase): 36 37 @test.mock.patch.object(logging, "warning", autospec=True) 38 def test_function_alias(self, mock_warning): 39 deprecated_func = deprecation.deprecated_alias("deprecated.func", 40 "real.func", 41 logging.error) 42 43 logging.error("fake error logged") 44 self.assertEqual(0, mock_warning.call_count) 45 deprecated_func("FAKE ERROR!") 46 self.assertEqual(1, mock_warning.call_count) 47 # Make sure the error points to the right file. 48 self.assertRegex(mock_warning.call_args[0][1], r"deprecation_test\.py:") 49 deprecated_func("ANOTHER FAKE ERROR!") 50 self.assertEqual(1, mock_warning.call_count) 51 52 @test.mock.patch.object(logging, "warning", autospec=True) 53 def test_class_alias(self, mock_warning): 54 class MyClass(object): 55 """My docstring.""" 56 57 init_args = [] 58 59 def __init__(self, arg): 60 MyClass.init_args.append(arg) 61 62 deprecated_cls = deprecation.deprecated_alias("deprecated.cls", 63 "real.cls", 64 MyClass) 65 66 print(deprecated_cls.__name__) 67 print(deprecated_cls.__module__) 68 print(deprecated_cls.__doc__) 69 70 MyClass("test") 71 self.assertEqual(0, mock_warning.call_count) 72 deprecated_cls("deprecated") 73 self.assertEqual(1, mock_warning.call_count) 74 # Make sure the error points to the right file. 75 self.assertRegex(mock_warning.call_args[0][1], r"deprecation_test\.py:") 76 deprecated_cls("deprecated again") 77 self.assertEqual(1, mock_warning.call_count) 78 79 self.assertEqual(["test", "deprecated", "deprecated again"], 80 MyClass.init_args) 81 82 # Check __init__ signature matches for doc generation. 83 self.assertEqual( 84 tf_inspect.getfullargspec(MyClass.__init__), 85 tf_inspect.getfullargspec(deprecated_cls.__init__)) 86 87 88class DeprecationTest(test.TestCase): 89 90 @test.mock.patch.object(logging, "warning", autospec=True) 91 def test_deprecated_once(self, mock_warning): 92 date = "2016-07-04" 93 instructions = "This is how you update..." 94 95 @deprecation.deprecated(date, instructions, warn_once=True) 96 def _fn(): 97 pass 98 99 _fn() 100 self.assertEqual(1, mock_warning.call_count) 101 _fn() 102 self.assertEqual(1, mock_warning.call_count) 103 104 @test.mock.patch.object(logging, "warning", autospec=True) 105 def test_deprecated_init_class(self, mock_warning): 106 date = "2016-07-04" 107 instructions = "This is how you update..." 108 109 @deprecation.deprecated(date, instructions, warn_once=True) 110 class MyClass(): 111 """A test class.""" 112 113 def __init__(self, a): 114 pass 115 116 MyClass("") 117 self.assertEqual(1, mock_warning.call_count) 118 MyClass("") 119 self.assertEqual(1, mock_warning.call_count) 120 self.assertIn("IS DEPRECATED", MyClass.__doc__) 121 122 @test.mock.patch.object(logging, "warning", autospec=True) 123 def test_deprecated_new_class(self, mock_warning): 124 date = "2016-07-04" 125 instructions = "This is how you update..." 126 127 @deprecation.deprecated(date, instructions, warn_once=True) 128 class MyStr(str): 129 130 def __new__(cls, value): 131 return str.__new__(cls, value) 132 133 MyStr("abc") 134 self.assertEqual(1, mock_warning.call_count) 135 MyStr("abc") 136 self.assertEqual(1, mock_warning.call_count) 137 self.assertIn("IS DEPRECATED", MyStr.__doc__) 138 139 @test.mock.patch.object(logging, "warning", autospec=True) 140 def test_deprecated_enum(self, mock_warning): 141 date = "2016-07-04" 142 instructions = "This is how you update..." 143 144 @deprecation.deprecated(date, instructions, warn_once=True) 145 class MyEnum(enum.Enum): 146 a = 1 147 b = 2 148 149 self.assertIs(MyEnum(1), MyEnum.a) 150 self.assertEqual(1, mock_warning.call_count) 151 self.assertIs(MyEnum(2), MyEnum.b) 152 self.assertEqual(1, mock_warning.call_count) 153 self.assertIn("IS DEPRECATED", MyEnum.__doc__) 154 155 @test.mock.patch.object(logging, "warning", autospec=True) 156 def test_deprecated_namedtuple(self, mock_warning): 157 date = "2016-07-04" 158 instructions = "This is how you update..." 159 160 mytuple = deprecation.deprecated( 161 date, instructions, warn_once=True)( 162 collections.namedtuple("my_tuple", ["field1", "field2"])) 163 164 mytuple(1, 2) 165 self.assertEqual(1, mock_warning.call_count) 166 mytuple(3, 4) 167 self.assertEqual(1, mock_warning.call_count) 168 self.assertIn("IS DEPRECATED", mytuple.__doc__) 169 170 @test.mock.patch.object(logging, "warning", autospec=True) 171 def test_silence(self, mock_warning): 172 date = "2016-07-04" 173 instructions = "This is how you update..." 174 175 @deprecation.deprecated(date, instructions, warn_once=False) 176 def _fn(): 177 pass 178 179 _fn() 180 self.assertEqual(1, mock_warning.call_count) 181 182 with deprecation.silence(): 183 _fn() 184 self.assertEqual(1, mock_warning.call_count) 185 186 _fn() 187 self.assertEqual(2, mock_warning.call_count) 188 189 def _assert_subset(self, expected_subset, actual_set): 190 self.assertTrue( 191 actual_set.issuperset(expected_subset), 192 msg="%s is not a superset of %s." % (actual_set, expected_subset)) 193 194 def test_deprecated_illegal_args(self): 195 instructions = "This is how you update..." 196 with self.assertRaisesRegex(ValueError, "YYYY-MM-DD"): 197 deprecation.deprecated("", instructions) 198 with self.assertRaisesRegex(ValueError, "YYYY-MM-DD"): 199 deprecation.deprecated("07-04-2016", instructions) 200 date = "2016-07-04" 201 with self.assertRaisesRegex(ValueError, "instructions"): 202 deprecation.deprecated(date, None) 203 with self.assertRaisesRegex(ValueError, "instructions"): 204 deprecation.deprecated(date, "") 205 206 @test.mock.patch.object(logging, "warning", autospec=True) 207 def test_no_date(self, mock_warning): 208 date = None 209 instructions = "This is how you update..." 210 211 @deprecation.deprecated(date, instructions) 212 def _fn(arg0, arg1): 213 """fn doc. 214 215 Args: 216 arg0: Arg 0. 217 arg1: Arg 1. 218 219 Returns: 220 Sum of args. 221 """ 222 return arg0 + arg1 223 224 self.assertEqual( 225 "fn doc. (deprecated)" 226 "\n" 227 "\nDeprecated: THIS FUNCTION IS DEPRECATED. " 228 "It will be removed in a future version." 229 "\nInstructions for updating:\n%s" 230 "\n" 231 "\nArgs:" 232 "\n arg0: Arg 0." 233 "\n arg1: Arg 1." 234 "\n" 235 "\nReturns:" 236 "\n Sum of args." % instructions, _fn.__doc__) 237 238 # Assert calling new fn issues log warning. 239 self.assertEqual(3, _fn(1, 2)) 240 self.assertEqual(1, mock_warning.call_count) 241 (args, _) = mock_warning.call_args 242 self.assertRegex(args[0], r"deprecated and will be removed") 243 self._assert_subset(set(["in a future version", instructions]), 244 set(args[1:])) 245 246 @test.mock.patch.object(logging, "warning", autospec=True) 247 @test_util.run_deprecated_v1 248 def test_static_fn_with_doc(self, mock_warning): 249 date = "2016-07-04" 250 instructions = "This is how you update..." 251 252 @deprecation.deprecated(date, instructions) 253 def _fn(arg0, arg1): 254 """fn doc. 255 256 Args: 257 arg0: Arg 0. 258 arg1: Arg 1. 259 260 Returns: 261 Sum of args. 262 """ 263 return arg0 + arg1 264 265 # Assert function docs are properly updated. 266 self.assertEqual("_fn", _fn.__name__) 267 self.assertEqual( 268 "fn doc. (deprecated)" 269 "\n" 270 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 271 "\nInstructions for updating:\n%s" 272 "\n" 273 "\nArgs:" 274 "\n arg0: Arg 0." 275 "\n arg1: Arg 1." 276 "\n" 277 "\nReturns:" 278 "\n Sum of args." % (date, instructions), _fn.__doc__) 279 280 # Assert calling new fn issues log warning. 281 self.assertEqual(3, _fn(1, 2)) 282 self.assertEqual(1, mock_warning.call_count) 283 (args, _) = mock_warning.call_args 284 self.assertRegex(args[0], r"deprecated and will be removed") 285 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 286 287 @test.mock.patch.object(logging, "warning", autospec=True) 288 @test_util.run_deprecated_v1 289 def test_static_fn_with_one_line_doc(self, mock_warning): 290 date = "2016-07-04" 291 instructions = "This is how you update..." 292 293 @deprecation.deprecated(date, instructions) 294 def _fn(arg0, arg1): 295 """fn doc.""" 296 return arg0 + arg1 297 298 # Assert function docs are properly updated. 299 self.assertEqual("_fn", _fn.__name__) 300 self.assertEqual( 301 "fn doc. (deprecated)" 302 "\n" 303 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 304 "\nInstructions for updating:\n%s" % (date, instructions), _fn.__doc__) 305 306 # Assert calling new fn issues log warning. 307 self.assertEqual(3, _fn(1, 2)) 308 self.assertEqual(1, mock_warning.call_count) 309 (args, _) = mock_warning.call_args 310 self.assertRegex(args[0], r"deprecated and will be removed") 311 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 312 313 @test.mock.patch.object(logging, "warning", autospec=True) 314 @test_util.run_deprecated_v1 315 def test_static_fn_no_doc(self, mock_warning): 316 date = "2016-07-04" 317 instructions = "This is how you update..." 318 319 @deprecation.deprecated(date, instructions) 320 def _fn(arg0, arg1): 321 return arg0 + arg1 322 323 # Assert function docs are properly updated. 324 self.assertEqual("_fn", _fn.__name__) 325 self.assertEqual( 326 "DEPRECATED FUNCTION" 327 "\n" 328 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 329 "\nInstructions for updating:" 330 "\n%s" % (date, instructions), _fn.__doc__) 331 332 # Assert calling new fn issues log warning. 333 self.assertEqual(3, _fn(1, 2)) 334 self.assertEqual(1, mock_warning.call_count) 335 (args, _) = mock_warning.call_args 336 self.assertRegex(args[0], r"deprecated and will be removed") 337 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 338 339 @test.mock.patch.object(logging, "warning", autospec=True) 340 def test_instance_fn_with_doc(self, mock_warning): 341 date = "2016-07-04" 342 instructions = "This is how you update..." 343 344 class _Object(object): 345 346 def __init(self): 347 pass 348 349 @deprecation.deprecated(date, instructions) 350 def _fn(self, arg0, arg1): 351 """fn doc. 352 353 Args: 354 arg0: Arg 0. 355 arg1: Arg 1. 356 357 Returns: 358 Sum of args. 359 """ 360 return arg0 + arg1 361 362 # Assert function docs are properly updated. 363 self.assertEqual( 364 "fn doc. (deprecated)" 365 "\n" 366 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 367 "\nInstructions for updating:\n%s" 368 "\n" 369 "\nArgs:" 370 "\n arg0: Arg 0." 371 "\n arg1: Arg 1." 372 "\n" 373 "\nReturns:" 374 "\n Sum of args." % (date, instructions), 375 getattr(_Object, "_fn").__doc__) 376 377 # Assert calling new fn issues log warning. 378 self.assertEqual(3, _Object()._fn(1, 2)) 379 self.assertEqual(1, mock_warning.call_count) 380 (args, _) = mock_warning.call_args 381 self.assertRegex(args[0], r"deprecated and will be removed") 382 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 383 384 @test.mock.patch.object(logging, "warning", autospec=True) 385 def test_instance_fn_with_one_line_doc(self, mock_warning): 386 date = "2016-07-04" 387 instructions = "This is how you update..." 388 389 class _Object(object): 390 391 def __init(self): 392 pass 393 394 @deprecation.deprecated(date, instructions) 395 def _fn(self, arg0, arg1): 396 """fn doc.""" 397 return arg0 + arg1 398 399 # Assert function docs are properly updated. 400 self.assertEqual( 401 "fn doc. (deprecated)" 402 "\n" 403 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 404 "\nInstructions for updating:\n%s" % (date, instructions), 405 getattr(_Object, "_fn").__doc__) 406 407 # Assert calling new fn issues log warning. 408 self.assertEqual(3, _Object()._fn(1, 2)) 409 self.assertEqual(1, mock_warning.call_count) 410 (args, _) = mock_warning.call_args 411 self.assertRegex(args[0], r"deprecated and will be removed") 412 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 413 414 @test.mock.patch.object(logging, "warning", autospec=True) 415 def test_instance_fn_no_doc(self, mock_warning): 416 date = "2016-07-04" 417 instructions = "This is how you update..." 418 419 class _Object(object): 420 421 def __init(self): 422 pass 423 424 @deprecation.deprecated(date, instructions) 425 def _fn(self, arg0, arg1): 426 return arg0 + arg1 427 428 # Assert function docs are properly updated. 429 self.assertEqual( 430 "DEPRECATED FUNCTION" 431 "\n" 432 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 433 "\nInstructions for updating:" 434 "\n%s" % (date, instructions), 435 getattr(_Object, "_fn").__doc__) 436 437 # Assert calling new fn issues log warning. 438 self.assertEqual(3, _Object()._fn(1, 2)) 439 self.assertEqual(1, mock_warning.call_count) 440 (args, _) = mock_warning.call_args 441 self.assertRegex(args[0], r"deprecated and will be removed") 442 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 443 444 def test_prop_wrong_order(self): 445 with self.assertRaisesRegex( 446 ValueError, 447 "make sure @property appears before @deprecated in your source code"): 448 # pylint: disable=unused-variable 449 450 class _Object(object): 451 452 def __init(self): 453 pass 454 455 @deprecation.deprecated("2016-07-04", "Instructions.") 456 @property 457 def _prop(self): 458 return "prop_wrong_order" 459 460 @test.mock.patch.object(logging, "warning", autospec=True) 461 def test_prop_with_doc(self, mock_warning): 462 date = "2016-07-04" 463 instructions = "This is how you update..." 464 465 class _Object(object): 466 467 def __init(self): 468 pass 469 470 @property 471 @deprecation.deprecated(date, instructions) 472 def _prop(self): 473 """prop doc. 474 475 Returns: 476 String. 477 """ 478 return "prop_with_doc" 479 480 # Assert function docs are properly updated. 481 self.assertEqual( 482 "prop doc. (deprecated)" 483 "\n" 484 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 485 "\nInstructions for updating:" 486 "\n%s" 487 "\n" 488 "\nReturns:" 489 "\n String." % (date, instructions), 490 getattr(_Object, "_prop").__doc__) 491 492 # Assert calling new fn issues log warning. 493 self.assertEqual("prop_with_doc", _Object()._prop) 494 self.assertEqual(1, mock_warning.call_count) 495 (args, _) = mock_warning.call_args 496 self.assertRegex(args[0], r"deprecated and will be removed") 497 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 498 499 @test.mock.patch.object(logging, "warning", autospec=True) 500 def test_prop_no_doc(self, mock_warning): 501 date = "2016-07-04" 502 instructions = "This is how you update..." 503 504 class _Object(object): 505 506 def __init(self): 507 pass 508 509 @property 510 @deprecation.deprecated(date, instructions) 511 def _prop(self): 512 return "prop_no_doc" 513 514 # Assert function docs are properly updated. 515 self.assertEqual( 516 "DEPRECATED FUNCTION" 517 "\n" 518 "\nDeprecated: THIS FUNCTION IS DEPRECATED. It will be removed after %s." 519 "\nInstructions for updating:" 520 "\n%s" % (date, instructions), 521 getattr(_Object, "_prop").__doc__) 522 523 # Assert calling new fn issues log warning. 524 self.assertEqual("prop_no_doc", _Object()._prop) 525 self.assertEqual(1, mock_warning.call_count) 526 (args, _) = mock_warning.call_args 527 self.assertRegex(args[0], r"deprecated and will be removed") 528 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 529 530 531class DeprecatedArgsTest(test.TestCase): 532 533 def _assert_subset(self, expected_subset, actual_set): 534 self.assertTrue( 535 actual_set.issuperset(expected_subset), 536 msg="%s is not a superset of %s." % (actual_set, expected_subset)) 537 538 def test_deprecated_illegal_args(self): 539 instructions = "This is how you update..." 540 date = "2016-07-04" 541 with self.assertRaisesRegex(ValueError, "YYYY-MM-DD"): 542 deprecation.deprecated_args("", instructions, "deprecated") 543 with self.assertRaisesRegex(ValueError, "YYYY-MM-DD"): 544 deprecation.deprecated_args("07-04-2016", instructions, "deprecated") 545 with self.assertRaisesRegex(ValueError, "instructions"): 546 deprecation.deprecated_args(date, None, "deprecated") 547 with self.assertRaisesRegex(ValueError, "instructions"): 548 deprecation.deprecated_args(date, "", "deprecated") 549 with self.assertRaisesRegex(ValueError, "argument"): 550 deprecation.deprecated_args(date, instructions) 551 552 def test_deprecated_missing_args(self): 553 date = "2016-07-04" 554 instructions = "This is how you update..." 555 556 def _fn(arg0, arg1, deprecated=None): 557 return arg0 + arg1 if deprecated else arg1 + arg0 558 559 # Assert calls without the deprecated argument log nothing. 560 with self.assertRaisesRegex(ValueError, "not present.*\\['missing'\\]"): 561 deprecation.deprecated_args(date, instructions, "missing")(_fn) 562 563 @test.mock.patch.object(logging, "warning", autospec=True) 564 @test_util.run_deprecated_v1 565 def test_static_fn_with_doc(self, mock_warning): 566 date = "2016-07-04" 567 instructions = "This is how you update..." 568 569 @deprecation.deprecated_args(date, instructions, "deprecated") 570 def _fn(arg0, arg1, deprecated=True): 571 """fn doc. 572 573 Args: 574 arg0: Arg 0. 575 arg1: Arg 1. 576 deprecated: Deprecated! 577 578 Returns: 579 Sum of args. 580 """ 581 return arg0 + arg1 if deprecated else arg1 + arg0 582 583 # Assert function docs are properly updated. 584 self.assertEqual("_fn", _fn.__name__) 585 self.assertEqual( 586 "fn doc. (deprecated arguments)" 587 "\n" 588 "\nDeprecated: SOME ARGUMENTS ARE DEPRECATED: `(deprecated)`. " 589 "They will be removed after %s." 590 "\nInstructions for updating:\n%s" 591 "\n" 592 "\nArgs:" 593 "\n arg0: Arg 0." 594 "\n arg1: Arg 1." 595 "\n deprecated: Deprecated!" 596 "\n" 597 "\nReturns:" 598 "\n Sum of args." % (date, instructions), _fn.__doc__) 599 600 # Assert calls without the deprecated argument log nothing. 601 self.assertEqual(3, _fn(1, 2)) 602 self.assertEqual(0, mock_warning.call_count) 603 604 # Assert calls with the deprecated argument log a warning. 605 self.assertEqual(3, _fn(1, 2, True)) 606 self.assertEqual(1, mock_warning.call_count) 607 (args, _) = mock_warning.call_args 608 self.assertRegex(args[0], r"deprecated and will be removed") 609 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 610 611 @test.mock.patch.object(logging, "warning", autospec=True) 612 @test_util.run_deprecated_v1 613 def test_static_fn_with_one_line_doc(self, mock_warning): 614 date = "2016-07-04" 615 instructions = "This is how you update..." 616 617 @deprecation.deprecated_args(date, instructions, "deprecated") 618 def _fn(arg0, arg1, deprecated=True): 619 """fn doc.""" 620 return arg0 + arg1 if deprecated else arg1 + arg0 621 622 # Assert function docs are properly updated. 623 self.assertEqual("_fn", _fn.__name__) 624 self.assertEqual( 625 "fn doc. (deprecated arguments)" 626 "\n" 627 "\nDeprecated: SOME ARGUMENTS ARE DEPRECATED: `(deprecated)`. " 628 "They will be removed after %s." 629 "\nInstructions for updating:\n%s" % (date, instructions), _fn.__doc__) 630 631 # Assert calls without the deprecated argument log nothing. 632 self.assertEqual(3, _fn(1, 2)) 633 self.assertEqual(0, mock_warning.call_count) 634 635 # Assert calls with the deprecated argument log a warning. 636 self.assertEqual(3, _fn(1, 2, True)) 637 self.assertEqual(1, mock_warning.call_count) 638 (args, _) = mock_warning.call_args 639 self.assertRegex(args[0], r"deprecated and will be removed") 640 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 641 642 @test.mock.patch.object(logging, "warning", autospec=True) 643 @test_util.run_deprecated_v1 644 def test_static_fn_no_doc(self, mock_warning): 645 date = "2016-07-04" 646 instructions = "This is how you update..." 647 648 @deprecation.deprecated_args(date, instructions, "deprecated") 649 def _fn(arg0, arg1, deprecated=True): 650 return arg0 + arg1 if deprecated else arg1 + arg0 651 652 # Assert function docs are properly updated. 653 self.assertEqual("_fn", _fn.__name__) 654 self.assertEqual( 655 "DEPRECATED FUNCTION ARGUMENTS" 656 "\n" 657 "\nDeprecated: SOME ARGUMENTS ARE DEPRECATED: `(deprecated)`. " 658 "They will be removed after %s." 659 "\nInstructions for updating:" 660 "\n%s" % (date, instructions), _fn.__doc__) 661 662 # Assert calls without the deprecated argument log nothing. 663 self.assertEqual(3, _fn(1, 2)) 664 self.assertEqual(0, mock_warning.call_count) 665 666 # Assert calls with the deprecated argument log a warning. 667 self.assertEqual(3, _fn(1, 2, True)) 668 self.assertEqual(1, mock_warning.call_count) 669 (args, _) = mock_warning.call_args 670 self.assertRegex(args[0], r"deprecated and will be removed") 671 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 672 673 @test.mock.patch.object(logging, "warning", autospec=True) 674 @test_util.run_deprecated_v1 675 def test_varargs(self, mock_warning): 676 date = "2016-07-04" 677 instructions = "This is how you update..." 678 679 @deprecation.deprecated_args(date, instructions, "deprecated") 680 def _fn(arg0, arg1, *deprecated): 681 return arg0 + arg1 if deprecated else arg1 + arg0 682 683 # Assert calls without the deprecated argument log nothing. 684 self.assertEqual(3, _fn(1, 2)) 685 self.assertEqual(0, mock_warning.call_count) 686 687 # Assert calls with the deprecated argument log a warning. 688 self.assertEqual(3, _fn(1, 2, True, False)) 689 self.assertEqual(1, mock_warning.call_count) 690 (args, _) = mock_warning.call_args 691 self.assertRegex(args[0], r"deprecated and will be removed") 692 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 693 694 @test.mock.patch.object(logging, "warning", autospec=True) 695 @test_util.run_deprecated_v1 696 def test_kwargs(self, mock_warning): 697 date = "2016-07-04" 698 instructions = "This is how you update..." 699 700 @deprecation.deprecated_args(date, instructions, "deprecated") 701 def _fn(arg0, arg1, **deprecated): 702 return arg0 + arg1 if deprecated else arg1 + arg0 703 704 # Assert calls without the deprecated argument log nothing. 705 self.assertEqual(3, _fn(1, 2)) 706 self.assertEqual(0, mock_warning.call_count) 707 708 # Assert calls with the deprecated argument log a warning. 709 self.assertEqual(3, _fn(1, 2, a=True, b=False)) 710 self.assertEqual(1, mock_warning.call_count) 711 (args, _) = mock_warning.call_args 712 self.assertRegex(args[0], r"deprecated and will be removed") 713 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 714 715 @test.mock.patch.object(logging, "warning", autospec=True) 716 @test_util.run_deprecated_v1 717 def test_positional_and_named(self, mock_warning): 718 date = "2016-07-04" 719 instructions = "This is how you update..." 720 721 @deprecation.deprecated_args(date, instructions, "d1", "d2") 722 def _fn(arg0, d1=None, arg1=2, d2=None): 723 return arg0 + arg1 if d1 else arg1 + arg0 if d2 else arg0 * arg1 724 725 # Assert calls without the deprecated arguments log nothing. 726 self.assertEqual(2, _fn(1, arg1=2)) 727 self.assertEqual(0, mock_warning.call_count) 728 729 # Assert calls with the deprecated arguments log warnings. 730 self.assertEqual(2, _fn(1, None, 2, d2=False)) 731 self.assertEqual(2, mock_warning.call_count) 732 (args1, _) = mock_warning.call_args_list[0] 733 self.assertRegex(args1[0], r"deprecated and will be removed") 734 self._assert_subset(set(["after " + date, instructions, "d1"]), 735 set(args1[1:])) 736 (args2, _) = mock_warning.call_args_list[1] 737 self.assertRegex(args2[0], r"deprecated and will be removed") 738 self._assert_subset(set(["after " + date, instructions, "d2"]), 739 set(args2[1:])) 740 741 @test.mock.patch.object(logging, "warning", autospec=True) 742 @test_util.run_deprecated_v1 743 def test_positional_and_named_with_ok_vals(self, mock_warning): 744 date = "2016-07-04" 745 instructions = "This is how you update..." 746 747 @deprecation.deprecated_args(date, instructions, ("d1", None), 748 ("d2", "my_ok_val")) 749 def _fn(arg0, d1=None, arg1=2, d2=None): 750 return arg0 + arg1 if d1 else arg1 + arg0 if d2 else arg0 * arg1 751 752 # Assert calls without the deprecated arguments log nothing. 753 self.assertEqual(2, _fn(1, arg1=2)) 754 self.assertEqual(0, mock_warning.call_count) 755 756 # Assert calls with the deprecated arguments log warnings. 757 self.assertEqual(2, _fn(1, False, 2, d2=False)) 758 self.assertEqual(2, mock_warning.call_count) 759 (args1, _) = mock_warning.call_args_list[0] 760 self.assertRegex(args1[0], r"deprecated and will be removed") 761 self._assert_subset(set(["after " + date, instructions, "d1"]), 762 set(args1[1:])) 763 (args2, _) = mock_warning.call_args_list[1] 764 self.assertRegex(args2[0], r"deprecated and will be removed") 765 self._assert_subset(set(["after " + date, instructions, "d2"]), 766 set(args2[1:])) 767 768 # Assert calls with the deprecated arguments don't log warnings if 769 # the value matches the 'ok_val'. 770 mock_warning.reset_mock() 771 self.assertEqual(3, _fn(1, None, 2, d2="my_ok_val")) 772 self.assertEqual(0, mock_warning.call_count) 773 774 @test.mock.patch.object(logging, "warning", autospec=True) 775 @test_util.run_deprecated_v1 776 def test_kwonlyargs(self, mock_warning): 777 date = "2016-07-04" 778 instructions = "This is how you update..." 779 780 @deprecation.deprecated_args(date, instructions, "deprecated") 781 def _fn(*, arg0, arg1, deprecated=None): 782 return arg0 + arg1 if deprecated is not None else arg1 + arg0 783 784 # Assert calls without the deprecated argument log nothing. 785 self.assertEqual(3, _fn(arg0=1, arg1=2)) 786 self.assertEqual(0, mock_warning.call_count) 787 788 # Assert calls with the deprecated argument log a warning. 789 self.assertEqual(3, _fn(arg0=1, arg1=2, deprecated=2)) 790 self.assertEqual(1, mock_warning.call_count) 791 (args, _) = mock_warning.call_args 792 self.assertRegex(args[0], r"deprecated and will be removed") 793 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 794 795 @test.mock.patch.object(logging, "warning", autospec=True) 796 @test_util.run_deprecated_v1 797 def test_kwonlyargs_and_args(self, mock_warning): 798 date = "2016-07-04" 799 instructions = "This is how you update..." 800 801 @deprecation.deprecated_args(date, instructions, 802 ("deprecated_arg1", "deprecated_arg2")) 803 def _fn(arg0, arg1, *, kw1, 804 deprecated_arg1=None, 805 deprecated_arg2=None): 806 res = arg0 + arg1 + kw1 807 if deprecated_arg1 is not None: 808 res += deprecated_arg1 809 if deprecated_arg2 is not None: 810 res += deprecated_arg2 811 return res 812 813 # Assert calls without the deprecated argument log nothing. 814 self.assertEqual(6, _fn(1, 2, kw1=3)) 815 self.assertEqual(0, mock_warning.call_count) 816 817 # Assert calls with the deprecated_arg1 argument log a warning. 818 self.assertEqual(8, _fn(1, 2, kw1=3, deprecated_arg1=2)) 819 self.assertEqual(1, mock_warning.call_count) 820 (args, _) = mock_warning.call_args 821 self.assertRegex(args[0], r"deprecated and will be removed") 822 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 823 824 # Assert calls with the deprecated arguments log a warning. 825 self.assertEqual(12, _fn(1, 2, kw1=3, deprecated_arg1=2, deprecated_arg2=4)) 826 self.assertEqual(1, mock_warning.call_count) 827 (args, _) = mock_warning.call_args 828 self.assertRegex(args[0], r"deprecated and will be removed") 829 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 830 831 @test.mock.patch.object(logging, "warning", autospec=True) 832 @test_util.run_deprecated_v1 833 def test_deprecated_args_once(self, mock_warning): 834 date = "2016-07-04" 835 instructions = "This is how you update..." 836 837 @deprecation.deprecated_args(date, instructions, "arg", warn_once=True) 838 def _fn(arg=0): # pylint: disable=unused-argument 839 pass 840 841 _fn() 842 self.assertEqual(0, mock_warning.call_count) 843 _fn(arg=0) 844 self.assertEqual(1, mock_warning.call_count) 845 _fn(arg=1) 846 self.assertEqual(1, mock_warning.call_count) 847 848 @test.mock.patch.object(logging, "warning", autospec=True) 849 @test_util.run_deprecated_v1 850 def test_deprecated_multiple_args_once_each(self, mock_warning): 851 date = "2016-07-04" 852 instructions = "This is how you update..." 853 854 @deprecation.deprecated_args(date, instructions, "arg0", "arg1", 855 warn_once=True) 856 def _fn(arg0=0, arg1=0): # pylint: disable=unused-argument 857 pass 858 859 _fn(arg0=0) 860 self.assertEqual(1, mock_warning.call_count) 861 _fn(arg0=0) 862 self.assertEqual(1, mock_warning.call_count) 863 _fn(arg1=0) 864 self.assertEqual(2, mock_warning.call_count) 865 _fn(arg0=0) 866 self.assertEqual(2, mock_warning.call_count) 867 _fn(arg1=0) 868 self.assertEqual(2, mock_warning.call_count) 869 870 871class DeprecatedArgValuesTest(test.TestCase): 872 873 def _assert_subset(self, expected_subset, actual_set): 874 self.assertTrue( 875 actual_set.issuperset(expected_subset), 876 msg="%s is not a superset of %s." % (actual_set, expected_subset)) 877 878 def test_deprecated_illegal_args(self): 879 instructions = "This is how you update..." 880 with self.assertRaisesRegex(ValueError, "YYYY-MM-DD"): 881 deprecation.deprecated_arg_values("", instructions, deprecated=True) 882 with self.assertRaisesRegex(ValueError, "YYYY-MM-DD"): 883 deprecation.deprecated_arg_values( 884 "07-04-2016", instructions, deprecated=True) 885 date = "2016-07-04" 886 with self.assertRaisesRegex(ValueError, "instructions"): 887 deprecation.deprecated_arg_values(date, None, deprecated=True) 888 with self.assertRaisesRegex(ValueError, "instructions"): 889 deprecation.deprecated_arg_values(date, "", deprecated=True) 890 with self.assertRaisesRegex(ValueError, "argument"): 891 deprecation.deprecated_arg_values(date, instructions) 892 893 @test.mock.patch.object(logging, "warning", autospec=True) 894 @test_util.run_deprecated_v1 895 def test_static_fn_with_doc(self, mock_warning): 896 date = "2016-07-04" 897 instructions = "This is how you update..." 898 899 @deprecation.deprecated_arg_values(date, instructions, warn_once=False, 900 deprecated=True) 901 def _fn(arg0, arg1, deprecated=True): 902 """fn doc. 903 904 Args: 905 arg0: Arg 0. 906 arg1: Arg 1. 907 deprecated: Deprecated! 908 909 Returns: 910 Sum of args. 911 """ 912 return arg0 + arg1 if deprecated else arg1 + arg0 913 914 # Assert function docs are properly updated. 915 self.assertEqual("_fn", _fn.__name__) 916 self.assertEqual( 917 "fn doc. (deprecated argument values)" 918 "\n" 919 "\nDeprecated: SOME ARGUMENT VALUES ARE DEPRECATED: `(deprecated=True)`. " 920 "They will be removed after %s." 921 "\nInstructions for updating:\n%s" 922 "\n" 923 "\nArgs:" 924 "\n arg0: Arg 0." 925 "\n arg1: Arg 1." 926 "\n deprecated: Deprecated!" 927 "\n" 928 "\nReturns:" 929 "\n Sum of args." % (date, instructions), _fn.__doc__) 930 931 # Assert calling new fn with non-deprecated value logs nothing. 932 self.assertEqual(3, _fn(1, 2, deprecated=False)) 933 self.assertEqual(0, mock_warning.call_count) 934 935 # Assert calling new fn with deprecated value issues log warning. 936 self.assertEqual(3, _fn(1, 2, deprecated=True)) 937 self.assertEqual(1, mock_warning.call_count) 938 (args, _) = mock_warning.call_args 939 self.assertRegex(args[0], r"deprecated and will be removed") 940 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 941 942 # Assert calling new fn with default deprecated value issues log warning. 943 self.assertEqual(3, _fn(1, 2)) 944 self.assertEqual(2, mock_warning.call_count) 945 946 @test.mock.patch.object(logging, "warning", autospec=True) 947 @test_util.run_deprecated_v1 948 def test_static_fn_with_one_line_doc(self, mock_warning): 949 date = "2016-07-04" 950 instructions = "This is how you update..." 951 952 @deprecation.deprecated_arg_values(date, instructions, warn_once=False, 953 deprecated=True) 954 def _fn(arg0, arg1, deprecated=True): 955 """fn doc.""" 956 return arg0 + arg1 if deprecated else arg1 + arg0 957 958 # Assert function docs are properly updated. 959 self.assertEqual("_fn", _fn.__name__) 960 self.assertEqual( 961 "fn doc. (deprecated argument values)" 962 "\n" 963 "\nDeprecated: SOME ARGUMENT VALUES ARE DEPRECATED: `(deprecated=True)`. " 964 "They will be removed after %s." 965 "\nInstructions for updating:\n%s" % (date, instructions), _fn.__doc__) 966 967 # Assert calling new fn with non-deprecated value logs nothing. 968 self.assertEqual(3, _fn(1, 2, deprecated=False)) 969 self.assertEqual(0, mock_warning.call_count) 970 971 # Assert calling new fn with deprecated value issues log warning. 972 self.assertEqual(3, _fn(1, 2, deprecated=True)) 973 self.assertEqual(1, mock_warning.call_count) 974 (args, _) = mock_warning.call_args 975 self.assertRegex(args[0], r"deprecated and will be removed") 976 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 977 978 # Assert calling new fn with default deprecated value issues log warning. 979 self.assertEqual(3, _fn(1, 2)) 980 self.assertEqual(2, mock_warning.call_count) 981 982 @test.mock.patch.object(logging, "warning", autospec=True) 983 @test_util.run_deprecated_v1 984 def test_static_fn_no_doc(self, mock_warning): 985 date = "2016-07-04" 986 instructions = "This is how you update..." 987 988 @deprecation.deprecated_arg_values(date, instructions, warn_once=False, 989 deprecated=True) 990 def _fn(arg0, arg1, deprecated=True): 991 return arg0 + arg1 if deprecated else arg1 + arg0 992 993 # Assert function docs are properly updated. 994 self.assertEqual("_fn", _fn.__name__) 995 self.assertEqual( 996 "DEPRECATED FUNCTION ARGUMENT VALUES" 997 "\n" 998 "\nDeprecated: SOME ARGUMENT VALUES ARE DEPRECATED: `(deprecated=True)`. " 999 "They will be removed after %s." 1000 "\nInstructions for updating:" 1001 "\n%s" % (date, instructions), _fn.__doc__) 1002 1003 # Assert calling new fn with non-deprecated value logs nothing. 1004 self.assertEqual(3, _fn(1, 2, deprecated=False)) 1005 self.assertEqual(0, mock_warning.call_count) 1006 1007 # Assert calling new fn issues log warning. 1008 self.assertEqual(3, _fn(1, 2, deprecated=True)) 1009 self.assertEqual(1, mock_warning.call_count) 1010 (args, _) = mock_warning.call_args 1011 self.assertRegex(args[0], r"deprecated and will be removed") 1012 self._assert_subset(set(["after " + date, instructions]), set(args[1:])) 1013 1014 # Assert calling new fn with default deprecated value issues log warning. 1015 self.assertEqual(3, _fn(1, 2)) 1016 self.assertEqual(2, mock_warning.call_count) 1017 1018 @test.mock.patch.object(logging, "warning", autospec=True) 1019 def test_deprecated_arg_values_once(self, mock_warning): 1020 date = "2016-07-04" 1021 instructions = "This is how you update..." 1022 1023 @deprecation.deprecated_arg_values(date, instructions, warn_once=True, 1024 deprecated=True) 1025 def _fn(deprecated): # pylint: disable=unused-argument 1026 pass 1027 1028 _fn(deprecated=False) 1029 self.assertEqual(0, mock_warning.call_count) 1030 _fn(deprecated=True) 1031 self.assertEqual(1, mock_warning.call_count) 1032 _fn(deprecated=True) 1033 self.assertEqual(1, mock_warning.call_count) 1034 1035 @test.mock.patch.object(logging, "warning", autospec=True) 1036 def test_deprecated_multiple_arg_values_once_each(self, mock_warning): 1037 date = "2016-07-04" 1038 instructions = "This is how you update..." 1039 1040 @deprecation.deprecated_arg_values(date, instructions, warn_once=True, 1041 arg0="forbidden", arg1="disallowed") 1042 def _fn(arg0, arg1): # pylint: disable=unused-argument 1043 pass 1044 1045 _fn(arg0="allowed", arg1="also allowed") 1046 self.assertEqual(0, mock_warning.call_count) 1047 _fn(arg0="forbidden", arg1="disallowed") 1048 self.assertEqual(2, mock_warning.call_count) 1049 _fn(arg0="forbidden", arg1="allowed") 1050 self.assertEqual(2, mock_warning.call_count) 1051 _fn(arg0="forbidden", arg1="disallowed") 1052 self.assertEqual(2, mock_warning.call_count) 1053 1054 @test.mock.patch.object(logging, "warning", autospec=True) 1055 @test_util.run_in_graph_and_eager_modes 1056 def test_deprecated_arg_values_when_value_is_none(self, mock_warning): 1057 1058 @deprecation.deprecated_arg_values("2016-07-04", 1059 "This is how you update...", 1060 warn_once=True, 1061 arg0=None) 1062 def _fn(arg0): # pylint: disable=unused-argument 1063 pass 1064 1065 ops.enable_tensor_equality() 1066 initial_count = mock_warning.call_count 1067 # Check that we avoid error from explicit `var == None` check. 1068 _fn(arg0=variables.Variable(0)) 1069 self.assertEqual(initial_count, mock_warning.call_count) 1070 _fn(arg0=None) 1071 self.assertEqual(initial_count + 1, mock_warning.call_count) 1072 ops.disable_tensor_equality() 1073 1074 1075class DeprecationArgumentsTest(test.TestCase): 1076 1077 def testDeprecatedArgumentLookup(self): 1078 good_value = 3 1079 self.assertEqual( 1080 deprecation.deprecated_argument_lookup("val_new", good_value, "val_old", 1081 None), good_value) 1082 self.assertEqual( 1083 deprecation.deprecated_argument_lookup("val_new", None, "val_old", 1084 good_value), good_value) 1085 with self.assertRaisesRegex(ValueError, 1086 "Cannot specify both 'val_old' and 'val_new'"): 1087 1088 deprecation.deprecated_argument_lookup("val_new", good_value, 1089 "val_old", good_value) 1090 1091 def testRewriteArgumentDocstring(self): 1092 docs = """Add `a` and `b` 1093 1094 Args: 1095 a: first arg 1096 b: second arg 1097 """ 1098 new_docs = deprecation.rewrite_argument_docstring( 1099 deprecation.rewrite_argument_docstring(docs, "a", "left"), "b", "right") 1100 new_docs_ref = """Add `left` and `right` 1101 1102 Args: 1103 left: first arg 1104 right: second arg 1105 """ 1106 self.assertEqual(new_docs, new_docs_ref) 1107 1108 1109class DeprecatedEndpointsTest(test.TestCase): 1110 1111 def testSingleDeprecatedEndpoint(self): 1112 @deprecation.deprecated_endpoints("foo1") 1113 def foo(): 1114 pass 1115 self.assertEqual(("foo1",), foo._tf_deprecated_api_names) 1116 1117 def testMultipleDeprecatedEndpoint(self): 1118 @deprecation.deprecated_endpoints("foo1", "foo2") 1119 def foo(): 1120 pass 1121 self.assertEqual(("foo1", "foo2"), foo._tf_deprecated_api_names) 1122 1123 def testCannotSetDeprecatedEndpointsTwice(self): 1124 with self.assertRaises(deprecation.DeprecatedNamesAlreadySet): 1125 @deprecation.deprecated_endpoints("foo1") 1126 @deprecation.deprecated_endpoints("foo2") 1127 def foo(): # pylint: disable=unused-variable 1128 pass 1129 1130 1131class DeprecateMovedModuleTest(test.TestCase): 1132 1133 @test.mock.patch.object(logging, "warning", autospec=True) 1134 def testCallDeprecatedModule(self, mock_warning): 1135 from tensorflow.python.util import deprecated_module # pylint: disable=g-import-not-at-top 1136 self.assertEqual(0, mock_warning.call_count) 1137 result = deprecated_module.a() 1138 self.assertEqual(1, mock_warning.call_count) 1139 self.assertEqual(1, result) 1140 1141 deprecated_module.a() 1142 self.assertEqual(1, mock_warning.call_count) 1143 1144 1145if __name__ == "__main__": 1146 test.main() 1147