Lichen

tests/methods_unbound.py

338:61776a5a0e16
2016-12-07 Paul Boddie Associate constant name information with references so that structure members such as function instance default members can be generated statically, thus eliminating unnecessary structure initialisation in the translated code. Improved the determination of dynamic functions in the importer to consider only non-constant defaults.
     1 class C:     2      3     "Class providing class and instance attributes."     4      5     def __init__(self):     6         self.a = 1     7      8     def m(self, x):     9         return x    10     11 class D:    12     13     "An alternative class."    14     15     pass    16     17 def getc():    18     19     "Return an instance of C to test object suitability."    20     21     return C()    22     23 def getd():    24     25     "Return an instance of D to test object suitability."    26     27     return D()    28     29 def f(obj, i):    30     31     """    32     Obtain an attribute on 'obj', performing an operation depending on 'i'.    33     This tests attribute access and invocation.    34     """    35     36     if i:    37         return obj.m(i)         # should cause access to an unbound method    38     else:    39         return obj.m    40     41 def g(obj, i):    42     43     """    44     Obtain an attribute on 'obj', performing an operation depending on 'i'.    45     This tests attribute access and invocation, restricting 'obj' using a guard.    46     """    47     48     obj.a                       # only provided by instances of C    49     if i:    50         return obj.m(i)         # should use the method directly since obj is an instance    51     else:    52         return obj.m    53     54 def h(obj, fn):    55     56     """    57     Obtain an attribute on 'obj', performing an operation depending on 'fn'.    58     This tests attribute access and invocation, restricting 'obj' using a guard    59     on a re-assignment of the name.    60     """    61     62     if fn:    63         obj = fn()    64         obj.a                   # only provided by instances of C    65         return obj.m(1)    66     else:    67         return obj.m    68     69 # Main program.    70     71 c = C()    72 d = D()    73     74 try:    75     print f(C, 1)               # fails    76 except UnboundMethodInvocation:    77     print "f(C, 1): Unbound method is not callable."    78     79 print f(c, 1)                   # 1    80     81 try:    82     print f(d, 1)               # should fail with an error caused by a guard    83 except TypeError:    84     print "f(d, 1): d is not a suitable argument."    85     86 fn = f(C, 0)    87     88 try:    89     print fn(2)                 # fails    90 except UnboundMethodInvocation:    91     print "fn(2): Unbound method is not callable."    92     93 print get_using(fn, c)(2)       # 2    94 print get_using(f(C, 0), c)(2)  # 2    95     96 try:    97     print g(C, 1)               # should fail with an error caused by a guard    98 except TypeError:    99     print "g(C, 1): C is not a suitable argument."   100    101 print g(c, 1)                   # 1   102 print g(c, 0)(3)                # 3   103    104 print h(c, getc)                # 1   105 print h(c, 0)(4)                # 4   106    107 try:   108     print h(c, getd)            # should fail with an error caused by a guard   109 except TypeError:   110     print "h(c, getd): getd provides an unsuitable result."   111    112 try:   113     print h(d, 0)(4)            # should fail with an error caused by a test   114 except TypeError:   115     print "h(d, 0): d is not a suitable argument."   116    117 try:   118     print g(c, 1)(5)   119 except TypeError:   120     print "g(c, 1)(5): attempt to invoke an integer result from g."