watch this The wheels are turning, slowly turning. home
Evil returns 2004-02-20

After months of having no good ideas for bad things to write, PEAK’s NOT_GIVEN inspired me to write this little tidbit:

import gc, sys, struct, opcode, inspect

class NotGiven:
    pass

def notGiven(param):
    caller = sys._getframe(1)
    for potentialFunction in gc.get_referrers(caller.f_code):
        if getattr(potentialFunction, 'func_code', None) == caller.f_code:
            break
        elif getattr(getattr(potentialFunction, 'im_func', None), 'func_code', None) == caller.f_code:
            potentialFunction = caller.im_func
            break
    else:
        raise Exception("You're insane.")

    argspec = inspect.getargspec(potentialFunction)
    bytes = caller.f_code.co_code
    lasti = caller.f_lasti
    varStart = bytes.rindex(chr(opcode.opmap['LOAD_FAST']), 0, lasti)
    (varIndex,) = struct.unpack('H', bytes[varStart+1:lasti])

    value = argspec[3][varIndex]
    return value is param

def foo(x = NotGiven(), y = NotGiven(), z = NotGiven()):
    print 'x given?', not notGiven(x)
    print 'y given?', not notGiven(y)
    print 'z given?', not notGiven(z)

if __name__ == '__main__':
    for args in ('', 'x', 'y', 'z', 'xy', 'xz', 'yz', 'xyz'):
        print 'Passing', ' '.join(args) or 'nothing'
        foo(**dict.fromkeys(args))



Thanks to teratorn for bringing NOT_GIVEN to my attention. :)