Lichen

Annotated tests/methods_unbound.py

893:a13fc2cc28f0
2019-02-04 Paul Boddie Optimised __BOOL to test for integers and to return int values directly. For other value types, __VALUE need not be called once integers have been excluded, and so the attrvalue member can be accessed directly.
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."