''' 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")
JycnIHJlcXVpcmVfZGVjb3JhdG9yMS5weQpjcmVhdGluZyBhIGdlbmVyYWwgc2FmZSBkZWNvcmF0b3IKYSBzYWZlIGRlY29yYXRvciBjYW4gYmUgY29tYmluZWQgd2l0aCBvdGhlciBkZWNvcmF0b3JzCnB5MiBhbmQgcHkzIHRlc3RlZCAKJycnCgpkZWYgcmVxdWlyZShleHByKToKICAgICIiImEgZ2VuZXJhbCBkZWNvcmF0b3IgY2hlY2tpbmcgYXJncyByZXF1aXJlbWVudCIiIgogICAgZGVmIGRlY29yYXRvcihmdW5jKToKICAgICAgICBkZWYgd3JhcHBlcigqX19hcmdzLCoqX19rdyk6CiAgICAgICAgICAgIG1lc3NhZ2UgPSAiZmFpbGVkIHByZWNvbmRpdGlvbiAlcyIgJSBleHByCiAgICAgICAgICAgIGFzc2VydCBldmFsKGV4cHIpLCBtZXNzYWdlCiAgICAgICAgICAgIHJldHVybiBmdW5jKCpfX2FyZ3MsKipfX2t3KQogICAgICAgICMgb3B0aW9uYWwgbmV4dCAzIGxpbmVzIG1ha2UgZGVjb3JhdG9yIHNhZmUKICAgICAgICB3cmFwcGVyLl9fbmFtZV9fID0gZnVuYy5fX25hbWVfXwogICAgICAgIHdyYXBwZXIuX19kaWN0X18gPSBmdW5jLl9fZGljdF9fCiAgICAgICAgd3JhcHBlci5fX2RvY19fID0gZnVuYy5fX2RvY19fCiAgICAgICAgcmV0dXJuIHdyYXBwZXIKICAgIHJldHVybiBkZWNvcmF0b3IKCiMgYWxsb3dzIG9ubHkgMSBhcmd1bWVudCBoZXJlCkByZXF1aXJlKCJsZW4oX19hcmdzKT09MSIpCmRlZiB0ZXN0KCphcmdzKToKICAgIHByaW50KGFyZ3NbMF0pCgojIG5vIHByb2JsZW0sIHByaW50cyBIZWxsbyB3b3JsZCEKdGVzdCgiSGVsbG8gd29ybGQhIikKCnByaW50KCctJyo1MCkKCiMgaGFzIDIgYXJndW1lbnRzIGFuZCB3aWxsIGZhaWwgc2hvd2luZyAKIyBBc3NlcnRpb25FcnJvcjogZmFpbGVkIHByZWNvbmRpdGlvbiBsZW4oX19hcmdzKT09MQp0ZXN0KCJIZWxsbyIsICJXb3JsZCIp