paul@230 | 1 | class C: |
paul@239 | 2 | |
paul@239 | 3 | "Class providing class and instance attributes." |
paul@239 | 4 | |
paul@234 | 5 | def __init__(self): |
paul@234 | 6 | self.a = 1 |
paul@239 | 7 | |
paul@230 | 8 | def m(self, x): |
paul@230 | 9 | return x |
paul@230 | 10 | |
paul@238 | 11 | class D: |
paul@239 | 12 | |
paul@239 | 13 | "An alternative class." |
paul@239 | 14 | |
paul@238 | 15 | pass |
paul@238 | 16 | |
paul@238 | 17 | def getc(): |
paul@239 | 18 | |
paul@239 | 19 | "Return an instance of C to test object suitability." |
paul@239 | 20 | |
paul@238 | 21 | return C() |
paul@238 | 22 | |
paul@238 | 23 | def getd(): |
paul@239 | 24 | |
paul@239 | 25 | "Return an instance of D to test object suitability." |
paul@239 | 26 | |
paul@238 | 27 | return D() |
paul@238 | 28 | |
paul@230 | 29 | def f(obj, i): |
paul@239 | 30 | |
paul@239 | 31 | """ |
paul@239 | 32 | Obtain an attribute on 'obj', performing an operation depending on 'i'. |
paul@239 | 33 | This tests attribute access and invocation. |
paul@239 | 34 | """ |
paul@239 | 35 | |
paul@230 | 36 | if i: |
paul@234 | 37 | return obj.m(i) # should cause access to an unbound method |
paul@234 | 38 | else: |
paul@234 | 39 | return obj.m |
paul@234 | 40 | |
paul@234 | 41 | def g(obj, i): |
paul@239 | 42 | |
paul@239 | 43 | """ |
paul@239 | 44 | Obtain an attribute on 'obj', performing an operation depending on 'i'. |
paul@239 | 45 | This tests attribute access and invocation, restricting 'obj' using a guard. |
paul@239 | 46 | """ |
paul@239 | 47 | |
paul@234 | 48 | obj.a # only provided by instances of C |
paul@234 | 49 | if i: |
paul@234 | 50 | return obj.m(i) # should use the method directly since obj is an instance |
paul@230 | 51 | else: |
paul@230 | 52 | return obj.m |
paul@230 | 53 | |
paul@238 | 54 | def h(obj, fn): |
paul@239 | 55 | |
paul@239 | 56 | """ |
paul@239 | 57 | Obtain an attribute on 'obj', performing an operation depending on 'fn'. |
paul@239 | 58 | This tests attribute access and invocation, restricting 'obj' using a guard |
paul@239 | 59 | on a re-assignment of the name. |
paul@239 | 60 | """ |
paul@239 | 61 | |
paul@238 | 62 | if fn: |
paul@238 | 63 | obj = fn() |
paul@238 | 64 | obj.a # only provided by instances of C |
paul@238 | 65 | return obj.m(1) |
paul@238 | 66 | else: |
paul@238 | 67 | return obj.m |
paul@238 | 68 | |
paul@239 | 69 | # Main program. |
paul@239 | 70 | |
paul@230 | 71 | c = C() |
paul@241 | 72 | d = D() |
paul@234 | 73 | |
paul@234 | 74 | try: |
paul@234 | 75 | print f(C, 1) # fails |
paul@234 | 76 | except UnboundMethodInvocation: |
paul@234 | 77 | print "f(C, 1): Unbound method is not callable." |
paul@234 | 78 | |
paul@244 | 79 | print f(c, 1) # 1 |
paul@245 | 80 | |
paul@245 | 81 | try: |
paul@245 | 82 | print f(d, 1) # should fail with an error caused by a guard |
paul@245 | 83 | except TypeError: |
paul@245 | 84 | print "f(d, 1): d is not a suitable argument." |
paul@245 | 85 | |
paul@503 | 86 | # Get an unbound method, C.m. |
paul@503 | 87 | |
paul@230 | 88 | fn = f(C, 0) |
paul@234 | 89 | |
paul@234 | 90 | try: |
paul@234 | 91 | print fn(2) # fails |
paul@234 | 92 | except UnboundMethodInvocation: |
paul@234 | 93 | print "fn(2): Unbound method is not callable." |
paul@234 | 94 | |
paul@234 | 95 | print get_using(fn, c)(2) # 2 |
paul@503 | 96 | |
paul@503 | 97 | # Repeat with fn re-evaluated. |
paul@503 | 98 | |
paul@234 | 99 | print get_using(f(C, 0), c)(2) # 2 |
paul@234 | 100 | |
paul@237 | 101 | try: |
paul@237 | 102 | print g(C, 1) # should fail with an error caused by a guard |
paul@237 | 103 | except TypeError: |
paul@237 | 104 | print "g(C, 1): C is not a suitable argument." |
paul@237 | 105 | |
paul@234 | 106 | print g(c, 1) # 1 |
paul@234 | 107 | print g(c, 0)(3) # 3 |
paul@238 | 108 | |
paul@238 | 109 | print h(c, getc) # 1 |
paul@238 | 110 | print h(c, 0)(4) # 4 |
paul@238 | 111 | |
paul@238 | 112 | try: |
paul@238 | 113 | print h(c, getd) # should fail with an error caused by a guard |
paul@238 | 114 | except TypeError: |
paul@238 | 115 | print "h(c, getd): getd provides an unsuitable result." |
paul@241 | 116 | |
paul@241 | 117 | try: |
paul@241 | 118 | print h(d, 0)(4) # should fail with an error caused by a test |
paul@241 | 119 | except TypeError: |
paul@241 | 120 | print "h(d, 0): d is not a suitable argument." |
paul@241 | 121 | |
paul@241 | 122 | try: |
paul@241 | 123 | print g(c, 1)(5) |
paul@241 | 124 | except TypeError: |
paul@241 | 125 | print "g(c, 1)(5): attempt to invoke an integer result from g." |