''' require_decorator1.py
creating a general safe decorator
a safe decorator can be combined with other decorators
py2 and py3 tested 
'''

def require(expr):
    """a general decorator checking args requirement"""
    def decorator(func):
        def wrapper(*__args,**__kw):
            message = "failed precondition %s" % expr
            assert eval(expr), message
            return func(*__args,**__kw)
        # optional next 3 lines make decorator safe
        wrapper.__name__ = func.__name__
        wrapper.__dict__ = func.__dict__
        wrapper.__doc__ = func.__doc__
        return wrapper
    return decorator

# allows only 1 argument here
@require("len(__args)==1")
def test(*args):
    print(args[0])

# no problem, prints Hello world!
test("Hello world!")

print('-'*50)

# has 2 arguments and will fail showing 
# AssertionError: failed precondition len(__args)==1
test("Hello", "World")