Home | History | Annotate | Download | only in util
      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
     18 from __future__ import absolute_import
     19 from __future__ import division
     20 from __future__ import print_function
     21 
     22 import inspect
     23 
     24 from tensorflow.python.platform import test
     25 from tensorflow.python.platform import tf_logging as logging
     26 from tensorflow.python.util import tf_decorator
     27 from tensorflow.python.util import tf_inspect
     28 
     29 
     30 def test_decorator(decorator_name, decorator_doc=None):
     31 
     32   def make_tf_decorator(target):
     33     return tf_decorator.TFDecorator(decorator_name, target, decorator_doc)
     34 
     35   return make_tf_decorator
     36 
     37 
     38 def test_undecorated_function():
     39   pass
     40 
     41 
     42 @test_decorator('decorator 1')
     43 @test_decorator('decorator 2')
     44 @test_decorator('decorator 3')
     45 def test_decorated_function(x):
     46   """Test Decorated Function Docstring."""
     47   return x * 2
     48 
     49 
     50 @test_decorator('decorator')
     51 def test_decorated_function_with_defaults(a, b=2, c='Hello'):
     52   """Test Decorated Function With Defaults Docstring."""
     53   return [a, b, c]
     54 
     55 
     56 @test_decorator('decorator')
     57 class TestDecoratedClass(object):
     58   """Test Decorated Class."""
     59 
     60   def __init__(self):
     61     pass
     62 
     63   def two(self):
     64     return 2
     65 
     66 
     67 class TfInspectTest(test.TestCase):
     68 
     69   def testCurrentFrame(self):
     70     self.assertEqual(inspect.currentframe(), tf_inspect.currentframe())
     71 
     72   def testGetArgSpecOnDecoratorsThatDontProvideArgspec(self):
     73     argspec = tf_inspect.getargspec(test_decorated_function_with_defaults)
     74     self.assertEqual(['a', 'b', 'c'], argspec.args)
     75     self.assertEqual((2, 'Hello'), argspec.defaults)
     76 
     77   def testGetArgSpecOnDecoratorThatChangesArgspec(self):
     78     argspec = tf_inspect.ArgSpec(
     79         args=['a', 'b', 'c'],
     80         varargs=None,
     81         keywords=None,
     82         defaults=(1, 'hello'))
     83 
     84     decorator = tf_decorator.TFDecorator('', test_undecorated_function, '',
     85                                          argspec)
     86     self.assertEqual(argspec, tf_inspect.getargspec(decorator))
     87 
     88   def testGetArgSpecIgnoresDecoratorsThatDontProvideArgspec(self):
     89     argspec = tf_inspect.ArgSpec(
     90         args=['a', 'b', 'c'],
     91         varargs=None,
     92         keywords=None,
     93         defaults=(1, 'hello'))
     94 
     95     inner_decorator = tf_decorator.TFDecorator('', test_undecorated_function,
     96                                                '', argspec)
     97     outer_decorator = tf_decorator.TFDecorator('', inner_decorator)
     98     self.assertEqual(argspec, tf_inspect.getargspec(outer_decorator))
     99 
    100   def testGetArgSpecReturnsOutermostDecoratorThatChangesArgspec(self):
    101     outer_argspec = tf_inspect.ArgSpec(
    102         args=['a'], varargs=None, keywords=None, defaults=None)
    103     inner_argspec = tf_inspect.ArgSpec(
    104         args=['b'], varargs=None, keywords=None, defaults=None)
    105 
    106     inner_decorator = tf_decorator.TFDecorator('', test_undecorated_function,
    107                                                '', inner_argspec)
    108     outer_decorator = tf_decorator.TFDecorator('', inner_decorator, '',
    109                                                outer_argspec)
    110     self.assertEqual(outer_argspec, tf_inspect.getargspec(outer_decorator))
    111 
    112   def testGetDoc(self):
    113     self.assertEqual('Test Decorated Function With Defaults Docstring.',
    114                      tf_inspect.getdoc(test_decorated_function_with_defaults))
    115 
    116   def testGetFile(self):
    117     self.assertTrue('tf_inspect_test.py' in tf_inspect.getfile(
    118         test_decorated_function_with_defaults))
    119     self.assertTrue('tf_decorator.py' in tf_inspect.getfile(
    120         test_decorator('decorator')(tf_decorator.unwrap)))
    121 
    122   def testGetMembers(self):
    123     self.assertEqual(
    124         inspect.getmembers(TestDecoratedClass),
    125         tf_inspect.getmembers(TestDecoratedClass))
    126 
    127   def testGetModule(self):
    128     self.assertEqual(
    129         inspect.getmodule(TestDecoratedClass),
    130         tf_inspect.getmodule(TestDecoratedClass))
    131     self.assertEqual(
    132         inspect.getmodule(test_decorated_function),
    133         tf_inspect.getmodule(test_decorated_function))
    134     self.assertEqual(
    135         inspect.getmodule(test_undecorated_function),
    136         tf_inspect.getmodule(test_undecorated_function))
    137 
    138   def testGetSource(self):
    139     expected = '''@test_decorator('decorator')
    140 def test_decorated_function_with_defaults(a, b=2, c='Hello'):
    141   """Test Decorated Function With Defaults Docstring."""
    142   return [a, b, c]
    143 '''
    144     self.assertEqual(
    145         expected, tf_inspect.getsource(test_decorated_function_with_defaults))
    146 
    147   def testIsClass(self):
    148     self.assertTrue(tf_inspect.isclass(TestDecoratedClass))
    149     self.assertFalse(tf_inspect.isclass(test_decorated_function))
    150 
    151   def testIsFunction(self):
    152     self.assertTrue(tf_inspect.isfunction(test_decorated_function))
    153     self.assertFalse(tf_inspect.isfunction(TestDecoratedClass))
    154 
    155   def testIsMethod(self):
    156     self.assertTrue(tf_inspect.ismethod(TestDecoratedClass().two))
    157     self.assertFalse(tf_inspect.ismethod(test_decorated_function))
    158 
    159   def testIsModule(self):
    160     self.assertTrue(
    161         tf_inspect.ismodule(inspect.getmodule(inspect.currentframe())))
    162     self.assertFalse(tf_inspect.ismodule(test_decorated_function))
    163 
    164   def testIsRoutine(self):
    165     self.assertTrue(tf_inspect.isroutine(len))
    166     self.assertFalse(tf_inspect.isroutine(TestDecoratedClass))
    167 
    168   def testStack(self):
    169     expected_stack = inspect.stack()
    170     actual_stack = tf_inspect.stack()
    171     self.assertEqual(len(expected_stack), len(actual_stack))
    172     self.assertEqual(expected_stack[0][0], actual_stack[0][0])  # Frame object
    173     self.assertEqual(expected_stack[0][1], actual_stack[0][1])  # Filename
    174     self.assertEqual(expected_stack[0][2],
    175                      actual_stack[0][2] - 1)  # Line number
    176     self.assertEqual(expected_stack[0][3], actual_stack[0][3])  # Function name
    177     self.assertEqual(expected_stack[1:], actual_stack[1:])
    178 
    179 
    180 class TfInspectGetCallArgsTest(test.TestCase):
    181 
    182   def testReturnsEmptyWhenUnboundFuncHasNoParameters(self):
    183 
    184     def empty():
    185       pass
    186 
    187     self.assertEqual({}, tf_inspect.getcallargs(empty))
    188 
    189   def testUnboundFuncWithOneParamPositional(self):
    190 
    191     def func(a):
    192       return a
    193 
    194     self.assertEqual({'a': 5}, tf_inspect.getcallargs(func, 5))
    195 
    196   def testUnboundFuncWithTwoParamsPositional(self):
    197 
    198     def func(a, b):
    199       return (a, b)
    200 
    201     self.assertEqual({'a': 10, 'b': 20}, tf_inspect.getcallargs(func, 10, 20))
    202 
    203   def testUnboundFuncWithOneParamKeyword(self):
    204 
    205     def func(a):
    206       return a
    207 
    208     self.assertEqual({'a': 5}, tf_inspect.getcallargs(func, a=5))
    209 
    210   def testUnboundFuncWithTwoParamsKeyword(self):
    211 
    212     def func(a, b):
    213       return (a, b)
    214 
    215     self.assertEqual({'a': 6, 'b': 7}, tf_inspect.getcallargs(func, a=6, b=7))
    216 
    217   def testUnboundFuncWithOneParamDefault(self):
    218 
    219     def func(a=13):
    220       return a
    221 
    222     self.assertEqual({'a': 13}, tf_inspect.getcallargs(func))
    223 
    224   def testUnboundFuncWithOneParamDefaultOnePositional(self):
    225 
    226     def func(a=0):
    227       return a
    228 
    229     self.assertEqual({'a': 1}, tf_inspect.getcallargs(func, 1))
    230 
    231   def testUnboundFuncWithTwoParamsDefaultOnePositional(self):
    232 
    233     def func(a=1, b=2):
    234       return (a, b)
    235 
    236     self.assertEqual({'a': 5, 'b': 2}, tf_inspect.getcallargs(func, 5))
    237 
    238   def testUnboundFuncWithTwoParamsDefaultTwoPositional(self):
    239 
    240     def func(a=1, b=2):
    241       return (a, b)
    242 
    243     self.assertEqual({'a': 3, 'b': 4}, tf_inspect.getcallargs(func, 3, 4))
    244 
    245   def testUnboundFuncWithOneParamDefaultOneKeyword(self):
    246 
    247     def func(a=1):
    248       return a
    249 
    250     self.assertEqual({'a': 3}, tf_inspect.getcallargs(func, a=3))
    251 
    252   def testUnboundFuncWithTwoParamsDefaultOneKeywordFirst(self):
    253 
    254     def func(a=1, b=2):
    255       return (a, b)
    256 
    257     self.assertEqual({'a': 3, 'b': 2}, tf_inspect.getcallargs(func, a=3))
    258 
    259   def testUnboundFuncWithTwoParamsDefaultOneKeywordSecond(self):
    260 
    261     def func(a=1, b=2):
    262       return (a, b)
    263 
    264     self.assertEqual({'a': 1, 'b': 4}, tf_inspect.getcallargs(func, b=4))
    265 
    266   def testUnboundFuncWithTwoParamsDefaultTwoKeywords(self):
    267 
    268     def func(a=1, b=2):
    269       return (a, b)
    270 
    271     self.assertEqual({'a': 3, 'b': 4}, tf_inspect.getcallargs(func, a=3, b=4))
    272 
    273   def testBoundFuncWithOneParam(self):
    274 
    275     class Test(object):
    276 
    277       def bound(self):
    278         pass
    279 
    280     t = Test()
    281     self.assertEqual({'self': t}, tf_inspect.getcallargs(t.bound))
    282 
    283   def testBoundFuncWithManyParamsAndDefaults(self):
    284 
    285     class Test(object):
    286 
    287       def bound(self, a, b=2, c='Hello'):
    288         return (a, b, c)
    289 
    290     t = Test()
    291     self.assertEqual({
    292         'self': t,
    293         'a': 3,
    294         'b': 2,
    295         'c': 'Goodbye'
    296     }, tf_inspect.getcallargs(t.bound, 3, c='Goodbye'))
    297 
    298   def testClassMethod(self):
    299 
    300     class Test(object):
    301 
    302       @classmethod
    303       def test(cls, a, b=3, c='hello'):
    304         return (a, b, c)
    305 
    306     self.assertEqual({
    307         'cls': Test,
    308         'a': 5,
    309         'b': 3,
    310         'c': 'goodbye'
    311     }, tf_inspect.getcallargs(Test.test, 5, c='goodbye'))
    312 
    313   def testUsesOutermostDecoratorsArgSpec(self):
    314 
    315     def func():
    316       pass
    317 
    318     def wrapper(*args, **kwargs):
    319       return func(*args, **kwargs)
    320 
    321     decorated = tf_decorator.make_decorator(
    322         func,
    323         wrapper,
    324         decorator_argspec=tf_inspect.ArgSpec(
    325             args=['a', 'b', 'c'],
    326             varargs=None,
    327             keywords=None,
    328             defaults=(3, 'hello')))
    329 
    330     self.assertEqual({
    331         'a': 4,
    332         'b': 3,
    333         'c': 'goodbye'
    334     }, tf_inspect.getcallargs(decorated, 4, c='goodbye'))
    335 
    336 
    337 if __name__ == '__main__':
    338   test.main()
    339