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