File: LP6E/Chapter39/_QuizAnswers/Question3/argtest_testfunc.py

"Test the argtest decorator on function calls"

import sys
from argtest import rangetest, typetest, valuetest

def fails(test):
    try:    result = test()
    except: print('[%r]' % sys.exception())
    else:   print('?%s?' % result)

print('--------------------------------------------------------------------')

# Canned use cases: ranges, types

@rangetest(m=(1, 12), d=(1, 31), y=(1900, 2013))
def date(m, d, y):
    print(f'date = {m}/{d}/{y}')

date(1, 2, 1960)
fails(lambda: date(1, 2, 3))

@typetest(a=int, c=float)
def sum(a, b, c, d):
    print(a + b + c + d)

sum(1, 2, 3.0, 4)
sum(1, d=4, b=2, c=3.0)
fails(lambda: sum('hack', 2, 99, 4))
fails(lambda: sum(1, d=4, b=2, c=99))

print('--------------------------------------------------------------------')

# Arbitrary/mixed tests

@valuetest(word1=str.islower, word2=(lambda x: x[0].isupper()))
def msg(word1='sixth', word2='Edition', label='The'):
    print('%s %s %s' % (label, word1, word2))

msg()  # word1 and word2 defaulted
msg('code', 'Hack')
fails(lambda: msg('Python', 'Decorators'))
fails(lambda: msg('python', word2='decorators'))

print('--------------------------------------------------------------------')

# Manual type and range tests

@valuetest(A=lambda x: isinstance(x, int), B=lambda x: x > 0 and x < 10)
def manual(A, B):
    print(A + B)

manual(100, 2)
fails(lambda: manual(1.99, 2))
fails(lambda: manual(100, 20))

print('--------------------------------------------------------------------')

# Nesting: runs both, by nesting proxies on original.
# Open issue: outer levels do not validate positionals due
# to call proxy function's differing argument signature;
# when trace=True, in all but the last of these "X" is
# classified as defaulted due to the proxy's signature.

@rangetest(X=(1, 10))
@typetest(Z=str)                      # Only innermost validates positional args
def nester(X, Y, Z):
    return('%s-%s-%s' % (X, Y, Z))

print(nester(1, 2, 'lp6e'))                # Original function runs properly
fails(lambda: nester(1, 2, 3))             # Nested typetest is run:  positional
fails(lambda: nester(1, 2, Z=3))           # Nested typetest is run:  keyword
fails(lambda: nester(0, 2, 'lp6e'))        # <==Outer rangetest not run: posit.
fails(lambda: nester(X=0, Y=2, Z='lp6e'))  # Outer rangetest is run:  keyword



[Home page] Books Code Blog Python Author Train Find ©M.Lutz