1# Copyright 2017 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"""Unit tests for tf_inspect.""" 16 17# pylint: disable=unused-import 18from __future__ import absolute_import 19from __future__ import division 20from __future__ import print_function 21 22import functools 23import inspect 24 25from tensorflow.python.platform import test 26from tensorflow.python.platform import tf_logging as logging 27from tensorflow.python.util import tf_decorator 28from tensorflow.python.util import tf_inspect 29 30 31def test_decorator(decorator_name, decorator_doc=None): 32 33 def make_tf_decorator(target): 34 return tf_decorator.TFDecorator(decorator_name, target, decorator_doc) 35 36 return make_tf_decorator 37 38 39def test_undecorated_function(): 40 pass 41 42 43@test_decorator('decorator 1') 44@test_decorator('decorator 2') 45@test_decorator('decorator 3') 46def test_decorated_function(x): 47 """Test Decorated Function Docstring.""" 48 return x * 2 49 50 51@test_decorator('decorator') 52def test_decorated_function_with_defaults(a, b=2, c='Hello'): 53 """Test Decorated Function With Defaults Docstring.""" 54 return [a, b, c] 55 56 57@test_decorator('decorator') 58class TestDecoratedClass(object): 59 """Test Decorated Class.""" 60 61 def __init__(self): 62 pass 63 64 def two(self): 65 return 2 66 67 68class TfInspectTest(test.TestCase): 69 70 def testCurrentFrame(self): 71 self.assertEqual(inspect.currentframe(), tf_inspect.currentframe()) 72 73 def testGetArgSpecOnDecoratorsThatDontProvideArgspec(self): 74 argspec = tf_inspect.getargspec(test_decorated_function_with_defaults) 75 self.assertEqual(['a', 'b', 'c'], argspec.args) 76 self.assertEqual((2, 'Hello'), argspec.defaults) 77 78 def testGetArgSpecOnDecoratorThatChangesArgspec(self): 79 argspec = tf_inspect.ArgSpec( 80 args=['a', 'b', 'c'], 81 varargs=None, 82 keywords=None, 83 defaults=(1, 'hello')) 84 85 decorator = tf_decorator.TFDecorator('', test_undecorated_function, '', 86 argspec) 87 self.assertEqual(argspec, tf_inspect.getargspec(decorator)) 88 89 def testGetArgSpecIgnoresDecoratorsThatDontProvideArgspec(self): 90 argspec = tf_inspect.ArgSpec( 91 args=['a', 'b', 'c'], 92 varargs=None, 93 keywords=None, 94 defaults=(1, 'hello')) 95 96 inner_decorator = tf_decorator.TFDecorator('', test_undecorated_function, 97 '', argspec) 98 outer_decorator = tf_decorator.TFDecorator('', inner_decorator) 99 self.assertEqual(argspec, tf_inspect.getargspec(outer_decorator)) 100 101 def testGetArgSpecReturnsOutermostDecoratorThatChangesArgspec(self): 102 outer_argspec = tf_inspect.ArgSpec( 103 args=['a'], varargs=None, keywords=None, defaults=None) 104 inner_argspec = tf_inspect.ArgSpec( 105 args=['b'], varargs=None, keywords=None, defaults=None) 106 107 inner_decorator = tf_decorator.TFDecorator('', test_undecorated_function, 108 '', inner_argspec) 109 outer_decorator = tf_decorator.TFDecorator('', inner_decorator, '', 110 outer_argspec) 111 self.assertEqual(outer_argspec, tf_inspect.getargspec(outer_decorator)) 112 113 def testGetArgSpecOnPartialPositionalArgumentOnly(self): 114 """Tests getargspec on partial function with only positional arguments.""" 115 116 def func(m, n): 117 return 2 * m + n 118 119 partial_func = functools.partial(func, 7) 120 argspec = tf_inspect.ArgSpec( 121 args=['n'], varargs=None, keywords=None, defaults=None) 122 123 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 124 125 def testGetArgSpecOnPartialArgumentWithConvertibleToFalse(self): 126 """Tests getargspec on partial function with args that convert to False.""" 127 128 def func(m, n): 129 return 2 * m + n 130 131 partial_func = functools.partial(func, m=0) 132 133 exception_message = (r"Some arguments \['n'\] do not have default value, " 134 "but they are positioned after those with default " 135 "values. This can not be expressed with ArgSpec.") 136 with self.assertRaisesRegex(ValueError, exception_message): 137 tf_inspect.getargspec(partial_func) 138 139 def testGetArgSpecOnPartialInvalidArgspec(self): 140 """Tests getargspec on partial function that doesn't have valid argspec.""" 141 142 def func(m, n, l, k=4): 143 return 2 * m + l + n * k 144 145 partial_func = functools.partial(func, n=7) 146 147 exception_message = (r"Some arguments \['l'\] do not have default value, " 148 "but they are positioned after those with default " 149 "values. This can not be expressed with ArgSpec.") 150 with self.assertRaisesRegex(ValueError, exception_message): 151 tf_inspect.getargspec(partial_func) 152 153 def testGetArgSpecOnPartialValidArgspec(self): 154 """Tests getargspec on partial function with valid argspec.""" 155 156 def func(m, n, l, k=4): 157 return 2 * m + l + n * k 158 159 partial_func = functools.partial(func, n=7, l=2) 160 argspec = tf_inspect.ArgSpec( 161 args=['m', 'n', 'l', 'k'], 162 varargs=None, 163 keywords=None, 164 defaults=(7, 2, 4)) 165 166 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 167 168 def testGetArgSpecOnPartialNoArgumentsLeft(self): 169 """Tests getargspec on partial function that prunes all arguments.""" 170 171 def func(m, n): 172 return 2 * m + n 173 174 partial_func = functools.partial(func, 7, 10) 175 argspec = tf_inspect.ArgSpec( 176 args=[], varargs=None, keywords=None, defaults=None) 177 178 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 179 180 def testGetArgSpecOnPartialKeywordArgument(self): 181 """Tests getargspec on partial function that prunes some arguments.""" 182 183 def func(m, n): 184 return 2 * m + n 185 186 partial_func = functools.partial(func, n=7) 187 argspec = tf_inspect.ArgSpec( 188 args=['m', 'n'], varargs=None, keywords=None, defaults=(7,)) 189 190 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 191 192 def testGetArgSpecOnPartialKeywordArgumentWithDefaultValue(self): 193 """Tests getargspec on partial function that prunes argument by keyword.""" 194 195 def func(m=1, n=2): 196 return 2 * m + n 197 198 partial_func = functools.partial(func, n=7) 199 argspec = tf_inspect.ArgSpec( 200 args=['m', 'n'], varargs=None, keywords=None, defaults=(1, 7)) 201 202 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 203 204 def testGetArgSpecOnPartialWithVarargs(self): 205 """Tests getargspec on partial function with variable arguments.""" 206 207 def func(m, *arg): 208 return m + len(arg) 209 210 partial_func = functools.partial(func, 7, 8) 211 argspec = tf_inspect.ArgSpec( 212 args=[], varargs='arg', keywords=None, defaults=None) 213 214 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 215 216 def testGetArgSpecOnPartialWithVarkwargs(self): 217 """Tests getargspec on partial function with variable keyword arguments.""" 218 219 def func(m, n, **kwarg): 220 return m * n + len(kwarg) 221 222 partial_func = functools.partial(func, 7) 223 argspec = tf_inspect.ArgSpec( 224 args=['n'], varargs=None, keywords='kwarg', defaults=None) 225 226 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 227 228 def testGetArgSpecOnPartialWithDecorator(self): 229 """Tests getargspec on decorated partial function.""" 230 231 @test_decorator('decorator') 232 def func(m=1, n=2): 233 return 2 * m + n 234 235 partial_func = functools.partial(func, n=7) 236 argspec = tf_inspect.ArgSpec( 237 args=['m', 'n'], varargs=None, keywords=None, defaults=(1, 7)) 238 239 self.assertEqual(argspec, tf_inspect.getargspec(partial_func)) 240 241 def testGetArgSpecOnPartialWithDecoratorThatChangesArgspec(self): 242 """Tests getargspec on partial function with decorated argspec.""" 243 244 argspec = tf_inspect.ArgSpec( 245 args=['a', 'b', 'c'], 246 varargs=None, 247 keywords=None, 248 defaults=(1, 'hello')) 249 decorator = tf_decorator.TFDecorator('', test_undecorated_function, '', 250 argspec) 251 partial_argspec = tf_inspect.ArgSpec( 252 args=['a', 'b', 'c'], 253 varargs=None, 254 keywords=None, 255 defaults=(2, 1, 'hello')) 256 partial_with_decorator = functools.partial(decorator, a=2) 257 258 self.assertEqual(argspec, tf_inspect.getargspec(decorator)) 259 self.assertEqual(partial_argspec, 260 tf_inspect.getargspec(partial_with_decorator)) 261 262 def testGetArgSpecOnCallableObject(self): 263 264 class Callable(object): 265 266 def __call__(self, a, b=1, c='hello'): 267 pass 268 269 argspec = tf_inspect.ArgSpec( 270 args=['self', 'a', 'b', 'c'], 271 varargs=None, 272 keywords=None, 273 defaults=(1, 'hello')) 274 275 test_obj = Callable() 276 self.assertEqual(argspec, tf_inspect.getargspec(test_obj)) 277 278 def testGetArgSpecOnInitClass(self): 279 280 class InitClass(object): 281 282 def __init__(self, a, b=1, c='hello'): 283 pass 284 285 argspec = tf_inspect.ArgSpec( 286 args=['self', 'a', 'b', 'c'], 287 varargs=None, 288 keywords=None, 289 defaults=(1, 'hello')) 290 291 self.assertEqual(argspec, tf_inspect.getargspec(InitClass)) 292 293 def testGetArgSpecOnNewClass(self): 294 295 class NewClass(object): 296 297 def __new__(cls, a, b=1, c='hello'): 298 pass 299 300 argspec = tf_inspect.ArgSpec( 301 args=['cls', 'a', 'b', 'c'], 302 varargs=None, 303 keywords=None, 304 defaults=(1, 'hello')) 305 306 self.assertEqual(argspec, tf_inspect.getargspec(NewClass)) 307 308 def testGetFullArgSpecOnDecoratorsThatDontProvideFullArgSpec(self): 309 argspec = tf_inspect.getfullargspec(test_decorated_function_with_defaults) 310 self.assertEqual(['a', 'b', 'c'], argspec.args) 311 self.assertEqual((2, 'Hello'), argspec.defaults) 312 313 def testGetFullArgSpecOnDecoratorThatChangesFullArgSpec(self): 314 argspec = tf_inspect.FullArgSpec( 315 args=['a', 'b', 'c'], 316 varargs=None, 317 varkw=None, 318 defaults=(1, 'hello'), 319 kwonlyargs=[], 320 kwonlydefaults=None, 321 annotations={}) 322 323 decorator = tf_decorator.TFDecorator('', test_undecorated_function, '', 324 argspec) 325 self.assertEqual(argspec, tf_inspect.getfullargspec(decorator)) 326 327 def testGetFullArgSpecIgnoresDecoratorsThatDontProvideFullArgSpec(self): 328 argspec = tf_inspect.FullArgSpec( 329 args=['a', 'b', 'c'], 330 varargs=None, 331 varkw=None, 332 defaults=(1, 'hello'), 333 kwonlyargs=[], 334 kwonlydefaults=None, 335 annotations={}) 336 337 inner_decorator = tf_decorator.TFDecorator('', test_undecorated_function, 338 '', argspec) 339 outer_decorator = tf_decorator.TFDecorator('', inner_decorator) 340 self.assertEqual(argspec, tf_inspect.getfullargspec(outer_decorator)) 341 342 def testGetFullArgSpecReturnsOutermostDecoratorThatChangesFullArgSpec(self): 343 outer_argspec = tf_inspect.FullArgSpec( 344 args=['a'], 345 varargs=None, 346 varkw=None, 347 defaults=None, 348 kwonlyargs=[], 349 kwonlydefaults=None, 350 annotations={}) 351 inner_argspec = tf_inspect.FullArgSpec( 352 args=['b'], 353 varargs=None, 354 varkw=None, 355 defaults=None, 356 kwonlyargs=[], 357 kwonlydefaults=None, 358 annotations={}) 359 360 inner_decorator = tf_decorator.TFDecorator('', test_undecorated_function, 361 '', inner_argspec) 362 outer_decorator = tf_decorator.TFDecorator('', inner_decorator, '', 363 outer_argspec) 364 self.assertEqual(outer_argspec, tf_inspect.getfullargspec(outer_decorator)) 365 366 def testGetFullArgsSpecForPartial(self): 367 368 def func(a, b): 369 del a, b 370 371 partial_function = functools.partial(func, 1) 372 argspec = tf_inspect.FullArgSpec( 373 args=['b'], 374 varargs=None, 375 varkw=None, 376 defaults=None, 377 kwonlyargs=[], 378 kwonlydefaults=None, 379 annotations={}) 380 381 self.assertEqual(argspec, tf_inspect.getfullargspec(partial_function)) 382 383 def testGetFullArgSpecOnPartialNoArgumentsLeft(self): 384 """Tests getfullargspec on partial function that prunes all arguments.""" 385 386 def func(m, n): 387 return 2 * m + n 388 389 partial_func = functools.partial(func, 7, 10) 390 argspec = tf_inspect.FullArgSpec( 391 args=[], 392 varargs=None, 393 varkw=None, 394 defaults=None, 395 kwonlyargs=[], 396 kwonlydefaults=None, 397 annotations={}) 398 399 self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) 400 401 def testGetFullArgSpecOnPartialWithVarargs(self): 402 """Tests getfullargspec on partial function with variable arguments.""" 403 404 def func(m, *arg): 405 return m + len(arg) 406 407 partial_func = functools.partial(func, 7, 8) 408 argspec = tf_inspect.FullArgSpec( 409 args=[], 410 varargs='arg', 411 varkw=None, 412 defaults=None, 413 kwonlyargs=[], 414 kwonlydefaults=None, 415 annotations={}) 416 417 self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) 418 419 def testGetFullArgSpecOnPartialWithVarkwargs(self): 420 """Tests getfullargspec. 421 422 Tests on partial function with variable keyword arguments. 423 """ 424 425 def func(m, n, **kwarg): 426 return m * n + len(kwarg) 427 428 partial_func = functools.partial(func, 7) 429 argspec = tf_inspect.FullArgSpec( 430 args=['n'], 431 varargs=None, 432 varkw='kwarg', 433 defaults=None, 434 kwonlyargs=[], 435 kwonlydefaults=None, 436 annotations={}) 437 438 self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) 439 440 def testGetFullArgSpecOnCallableObject(self): 441 442 class Callable(object): 443 444 def __call__(self, a, b=1, c='hello'): 445 pass 446 447 argspec = tf_inspect.FullArgSpec( 448 args=['self', 'a', 'b', 'c'], 449 varargs=None, 450 varkw=None, 451 defaults=(1, 'hello'), 452 kwonlyargs=[], 453 kwonlydefaults=None, 454 annotations={}) 455 456 test_obj = Callable() 457 self.assertEqual(argspec, tf_inspect.getfullargspec(test_obj)) 458 459 def testGetFullArgSpecOnInitClass(self): 460 461 class InitClass(object): 462 463 def __init__(self, a, b=1, c='hello'): 464 pass 465 466 argspec = tf_inspect.FullArgSpec( 467 args=['self', 'a', 'b', 'c'], 468 varargs=None, 469 varkw=None, 470 defaults=(1, 'hello'), 471 kwonlyargs=[], 472 kwonlydefaults=None, 473 annotations={}) 474 475 self.assertEqual(argspec, tf_inspect.getfullargspec(InitClass)) 476 477 def testGetFullArgSpecOnNewClass(self): 478 479 class NewClass(object): 480 481 def __new__(cls, a, b=1, c='hello'): 482 pass 483 484 argspec = tf_inspect.FullArgSpec( 485 args=['cls', 'a', 'b', 'c'], 486 varargs=None, 487 varkw=None, 488 defaults=(1, 'hello'), 489 kwonlyargs=[], 490 kwonlydefaults=None, 491 annotations={}) 492 493 self.assertEqual(argspec, tf_inspect.getfullargspec(NewClass)) 494 495 def testSignatureOnDecoratorsThatDontProvideFullArgSpec(self): 496 signature = tf_inspect.signature(test_decorated_function_with_defaults) 497 498 self.assertEqual([ 499 tf_inspect.Parameter('a', tf_inspect.Parameter.POSITIONAL_OR_KEYWORD), 500 tf_inspect.Parameter( 501 'b', tf_inspect.Parameter.POSITIONAL_OR_KEYWORD, default=2), 502 tf_inspect.Parameter( 503 'c', tf_inspect.Parameter.POSITIONAL_OR_KEYWORD, default='Hello') 504 ], list(signature.parameters.values())) 505 506 def testSignatureFollowsNestedDecorators(self): 507 signature = tf_inspect.signature(test_decorated_function) 508 509 self.assertEqual( 510 [tf_inspect.Parameter('x', tf_inspect.Parameter.POSITIONAL_OR_KEYWORD)], 511 list(signature.parameters.values())) 512 513 def testGetDoc(self): 514 self.assertEqual('Test Decorated Function With Defaults Docstring.', 515 tf_inspect.getdoc(test_decorated_function_with_defaults)) 516 517 def testGetFile(self): 518 self.assertTrue('tf_inspect_test.py' in tf_inspect.getfile( 519 test_decorated_function_with_defaults)) 520 self.assertTrue('tf_decorator.py' in tf_inspect.getfile( 521 test_decorator('decorator')(tf_decorator.unwrap))) 522 523 def testGetMembers(self): 524 self.assertEqual( 525 inspect.getmembers(TestDecoratedClass), 526 tf_inspect.getmembers(TestDecoratedClass)) 527 528 def testGetModule(self): 529 self.assertEqual( 530 inspect.getmodule(TestDecoratedClass), 531 tf_inspect.getmodule(TestDecoratedClass)) 532 self.assertEqual( 533 inspect.getmodule(test_decorated_function), 534 tf_inspect.getmodule(test_decorated_function)) 535 self.assertEqual( 536 inspect.getmodule(test_undecorated_function), 537 tf_inspect.getmodule(test_undecorated_function)) 538 539 def testGetSource(self): 540 expected = '''@test_decorator('decorator') 541def test_decorated_function_with_defaults(a, b=2, c='Hello'): 542 """Test Decorated Function With Defaults Docstring.""" 543 return [a, b, c] 544''' 545 self.assertEqual( 546 expected, tf_inspect.getsource(test_decorated_function_with_defaults)) 547 548 def testGetSourceFile(self): 549 self.assertEqual( 550 __file__, 551 tf_inspect.getsourcefile(test_decorated_function_with_defaults)) 552 553 def testGetSourceLines(self): 554 expected = inspect.getsourcelines( 555 test_decorated_function_with_defaults.decorated_target) 556 self.assertEqual( 557 expected, 558 tf_inspect.getsourcelines(test_decorated_function_with_defaults)) 559 560 def testIsBuiltin(self): 561 self.assertEqual( 562 tf_inspect.isbuiltin(TestDecoratedClass), 563 inspect.isbuiltin(TestDecoratedClass)) 564 self.assertEqual( 565 tf_inspect.isbuiltin(test_decorated_function), 566 inspect.isbuiltin(test_decorated_function)) 567 self.assertEqual( 568 tf_inspect.isbuiltin(test_undecorated_function), 569 inspect.isbuiltin(test_undecorated_function)) 570 self.assertEqual(tf_inspect.isbuiltin(range), inspect.isbuiltin(range)) 571 self.assertEqual(tf_inspect.isbuiltin(max), inspect.isbuiltin(max)) 572 573 def testIsClass(self): 574 self.assertTrue(tf_inspect.isclass(TestDecoratedClass)) 575 self.assertFalse(tf_inspect.isclass(test_decorated_function)) 576 577 def testIsFunction(self): 578 self.assertTrue(tf_inspect.isfunction(test_decorated_function)) 579 self.assertFalse(tf_inspect.isfunction(TestDecoratedClass)) 580 581 def testIsMethod(self): 582 self.assertTrue(tf_inspect.ismethod(TestDecoratedClass().two)) 583 self.assertFalse(tf_inspect.ismethod(test_decorated_function)) 584 585 def testIsModule(self): 586 self.assertTrue( 587 tf_inspect.ismodule(inspect.getmodule(inspect.currentframe()))) 588 self.assertFalse(tf_inspect.ismodule(test_decorated_function)) 589 590 def testIsRoutine(self): 591 self.assertTrue(tf_inspect.isroutine(len)) 592 self.assertFalse(tf_inspect.isroutine(TestDecoratedClass)) 593 594 def testStack(self): 595 expected_stack = inspect.stack() 596 actual_stack = tf_inspect.stack() 597 self.assertEqual(len(expected_stack), len(actual_stack)) 598 self.assertEqual(expected_stack[0][0], actual_stack[0][0]) # Frame object 599 self.assertEqual(expected_stack[0][1], actual_stack[0][1]) # Filename 600 self.assertEqual(expected_stack[0][2], 601 actual_stack[0][2] - 1) # Line number 602 self.assertEqual(expected_stack[0][3], actual_stack[0][3]) # Function name 603 self.assertEqual(expected_stack[1:], actual_stack[1:]) 604 605 606class TfInspectGetCallArgsTest(test.TestCase): 607 608 def testReturnsEmptyWhenUnboundFuncHasNoParameters(self): 609 610 def empty(): 611 pass 612 613 self.assertEqual({}, tf_inspect.getcallargs(empty)) 614 615 def testClashingParameterNames(self): 616 617 def func(positional, func=1, func_and_positional=2, kwargs=3): 618 return positional, func, func_and_positional, kwargs 619 620 kwargs = {} 621 self.assertEqual( 622 tf_inspect.getcallargs(func, 0, **kwargs), { 623 'positional': 0, 624 'func': 1, 625 'func_and_positional': 2, 626 'kwargs': 3 627 }) 628 kwargs = dict(func=4, func_and_positional=5, kwargs=6) 629 self.assertEqual( 630 tf_inspect.getcallargs(func, 0, **kwargs), { 631 'positional': 0, 632 'func': 4, 633 'func_and_positional': 5, 634 'kwargs': 6 635 }) 636 637 def testUnboundFuncWithOneParamPositional(self): 638 639 def func(a): 640 return a 641 642 self.assertEqual({'a': 5}, tf_inspect.getcallargs(func, 5)) 643 644 def testUnboundFuncWithTwoParamsPositional(self): 645 646 def func(a, b): 647 return (a, b) 648 649 self.assertEqual({'a': 10, 'b': 20}, tf_inspect.getcallargs(func, 10, 20)) 650 651 def testUnboundFuncWithOneParamKeyword(self): 652 653 def func(a): 654 return a 655 656 self.assertEqual({'a': 5}, tf_inspect.getcallargs(func, a=5)) 657 658 def testUnboundFuncWithTwoParamsKeyword(self): 659 660 def func(a, b): 661 return (a, b) 662 663 self.assertEqual({'a': 6, 'b': 7}, tf_inspect.getcallargs(func, a=6, b=7)) 664 665 def testUnboundFuncWithOneParamDefault(self): 666 667 def func(a=13): 668 return a 669 670 self.assertEqual({'a': 13}, tf_inspect.getcallargs(func)) 671 672 def testUnboundFuncWithOneParamDefaultOnePositional(self): 673 674 def func(a=0): 675 return a 676 677 self.assertEqual({'a': 1}, tf_inspect.getcallargs(func, 1)) 678 679 def testUnboundFuncWithTwoParamsDefaultOnePositional(self): 680 681 def func(a=1, b=2): 682 return (a, b) 683 684 self.assertEqual({'a': 5, 'b': 2}, tf_inspect.getcallargs(func, 5)) 685 686 def testUnboundFuncWithTwoParamsDefaultTwoPositional(self): 687 688 def func(a=1, b=2): 689 return (a, b) 690 691 self.assertEqual({'a': 3, 'b': 4}, tf_inspect.getcallargs(func, 3, 4)) 692 693 def testUnboundFuncWithOneParamDefaultOneKeyword(self): 694 695 def func(a=1): 696 return a 697 698 self.assertEqual({'a': 3}, tf_inspect.getcallargs(func, a=3)) 699 700 def testUnboundFuncWithTwoParamsDefaultOneKeywordFirst(self): 701 702 def func(a=1, b=2): 703 return (a, b) 704 705 self.assertEqual({'a': 3, 'b': 2}, tf_inspect.getcallargs(func, a=3)) 706 707 def testUnboundFuncWithTwoParamsDefaultOneKeywordSecond(self): 708 709 def func(a=1, b=2): 710 return (a, b) 711 712 self.assertEqual({'a': 1, 'b': 4}, tf_inspect.getcallargs(func, b=4)) 713 714 def testUnboundFuncWithTwoParamsDefaultTwoKeywords(self): 715 716 def func(a=1, b=2): 717 return (a, b) 718 719 self.assertEqual({'a': 3, 'b': 4}, tf_inspect.getcallargs(func, a=3, b=4)) 720 721 def testBoundFuncWithOneParam(self): 722 723 class Test(object): 724 725 def bound(self): 726 pass 727 728 t = Test() 729 self.assertEqual({'self': t}, tf_inspect.getcallargs(t.bound)) 730 731 def testBoundFuncWithManyParamsAndDefaults(self): 732 733 class Test(object): 734 735 def bound(self, a, b=2, c='Hello'): 736 return (a, b, c) 737 738 t = Test() 739 self.assertEqual({ 740 'self': t, 741 'a': 3, 742 'b': 2, 743 'c': 'Goodbye' 744 }, tf_inspect.getcallargs(t.bound, 3, c='Goodbye')) 745 746 def testClassMethod(self): 747 748 class Test(object): 749 750 @classmethod 751 def test(cls, a, b=3, c='hello'): 752 return (a, b, c) 753 754 self.assertEqual({ 755 'cls': Test, 756 'a': 5, 757 'b': 3, 758 'c': 'goodbye' 759 }, tf_inspect.getcallargs(Test.test, 5, c='goodbye')) 760 761 def testUsesOutermostDecoratorsArgSpec(self): 762 763 def func(): 764 pass 765 766 def wrapper(*args, **kwargs): 767 return func(*args, **kwargs) 768 769 decorated = tf_decorator.make_decorator( 770 func, 771 wrapper, 772 decorator_argspec=tf_inspect.ArgSpec( 773 args=['a', 'b', 'c'], 774 varargs=None, 775 keywords=None, 776 defaults=(3, 'hello'))) 777 778 self.assertEqual({ 779 'a': 4, 780 'b': 3, 781 'c': 'goodbye' 782 }, tf_inspect.getcallargs(decorated, 4, c='goodbye')) 783 784 785if __name__ == '__main__': 786 test.main() 787