diff --git a/logcall.py b/logcall.py index c0ae43f..3703a73 100644 --- a/logcall.py +++ b/logcall.py @@ -1,6 +1,27 @@ -def logged(func): - print('Adding logging to', func.__name__) - def wrapper(*args, **kwargs): - print('Calling', func.__name__) - return func(*args, **kwargs) - return wrapper +from functools import wraps + + +def logformat(message="Calling {name}"): + def logged(func): + print(f'Adding logging to {func.__name__}') + + @wraps(func) + def wrapper(*args, **kwargs): + fmtargs=dict( + name=func.__name__, + func=func, + ) + print(message.format(**fmtargs)) + return func(*args, **kwargs) + return wrapper + return logged + + +logged = logformat() + + +if __name__ == '__main__': + @logged + def add(x: int, y: int): + """Adds two numbers.""" + return x + y diff --git a/sample.py b/sample.py index 017dfb2..14942f2 100644 --- a/sample.py +++ b/sample.py @@ -1,4 +1,4 @@ -from logcall import logged +from logcall import logformat, logged @logged @@ -9,3 +9,29 @@ def add(x, y): @logged def sub(x, y): return x - y + + +@logformat('{func.__code__.co_filename}:{func.__name__}') +def mult(x, y): + return x * y + + +class Spam: + @logged + def instance_method(self): + pass + + @classmethod + @logged + def class_method(cls): + pass + + @staticmethod + @logged + def static_method(): + pass + + @property + @logged + def property_method(self): + pass diff --git a/validate.py b/validate.py index d7fe4fe..77f3dc7 100644 --- a/validate.py +++ b/validate.py @@ -1,4 +1,5 @@ import inspect +from functools import wraps class Validator: @@ -71,6 +72,7 @@ def validated(func): annotations = dict(func.__annotations__) retcheck = annotations.pop('return', None) + @wraps(func) def wrapper(*args, **kwargs): bound = sig.bind(*args, **kwargs) errors = [] @@ -91,6 +93,34 @@ def validated(func): return wrapper +def enforce(**outerkwargs): + def enforced(func): + sig = inspect.signature(func) + retcheck = outerkwargs.pop('return_', None) + annotations = outerkwargs + + @wraps(func) + def wrapper(*args, **kwargs): + bound = sig.bind(*args, **kwargs) + errors = [] + for name, validator in annotations.items(): + try: + validator.check(bound.arguments[name]) + except Exception as e: + errors.append(f' {name}: {e}') + if errors: + raise TypeError('Bad Arguments\n' + '\n'.join(errors)) + result = func(*args, **kwargs) + if retcheck: + try: + retcheck.check(result) + except Exception as e: + raise TypeError(f'Bad return: {e}') from None + return result + return wrapper + return enforced + + class ValidatedFunction: def __init__(self, func): self.func = func @@ -115,3 +145,7 @@ if __name__ == '__main__': @validated def power(x: Integer, y: Integer): return x ** y + + @enforce(x=Integer, y=Integer, return_=Integer) + def mult(x, y): + return x * y