Lichen

tests/methods_unbound.py

303:c07a749f5bd0
2016-12-02 Paul Boddie Use __data__ attributes with native functions apart from when __data__ needs replacing (such as in the list append and concatenation functions).
     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."