From 7831a9537f1c392d66c04867f1aa5064690f3b54 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Fri, 2 Apr 2021 22:48:18 +0200 Subject: [PATCH 1/2] Get call node in __call__ in preparation for decorator detection --- icecream/icecream.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/icecream/icecream.py b/icecream/icecream.py index a361356..f003671 100644 --- a/icecream/icecream.py +++ b/icecream/icecream.py @@ -176,11 +176,14 @@ def __init__(self, prefix=DEFAULT_PREFIX, def __call__(self, *args): if self.enabled: callFrame = inspect.currentframe().f_back - try: - out = self._format(callFrame, *args) - except NoSourceAvailableError as err: + + callNode = Source.executing(callFrame).node + if callNode is None: prefix = callOrValue(self.prefix) - out = prefix + 'Error: ' + err.infoMessage + out = prefix + 'Error: ' + NoSourceAvailableError.infoMessage + else: + out = self._format(callFrame, callNode, *args) + self.outputFunction(out) if not args: # E.g. ic(). @@ -194,16 +197,17 @@ def __call__(self, *args): def format(self, *args): callFrame = inspect.currentframe().f_back - out = self._format(callFrame, *args) - return out - - def _format(self, callFrame, *args): - prefix = callOrValue(self.prefix) callNode = Source.executing(callFrame).node if callNode is None: raise NoSourceAvailableError() + out = self._format(callFrame, callNode, *args) + return out + + def _format(self, callFrame, callNode, *args): + prefix = callOrValue(self.prefix) + context = self._formatContext(callFrame, callNode) if not args: time = self._formatTime() From 9ffa1d5bde496c7ab144ce7d53751411e00edaef Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sat, 3 Apr 2021 00:14:57 +0200 Subject: [PATCH 2/2] Add decorator functionality --- icecream/icecream.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/icecream/icecream.py b/icecream/icecream.py index f003671..228be33 100644 --- a/icecream/icecream.py +++ b/icecream/icecream.py @@ -19,6 +19,7 @@ import sys from datetime import datetime from contextlib import contextmanager +from functools import wraps from os.path import basename from textwrap import dedent @@ -177,10 +178,13 @@ def __call__(self, *args): if self.enabled: callFrame = inspect.currentframe().f_back - callNode = Source.executing(callFrame).node + ex = Source.executing(callFrame) + callNode = ex.node if callNode is None: prefix = callOrValue(self.prefix) out = prefix + 'Error: ' + NoSourceAvailableError.infoMessage + elif getattr(ex, 'decorator', None): + return self.decorate(args[0]) else: out = self._format(callFrame, callNode, *args) @@ -195,6 +199,24 @@ def __call__(self, *args): return passthrough + def decorate(self, func): + name = func.__name__ + + @wraps(func) + def wrapper(*args, **kwargs): + args_kwargs = ( + [repr(arg) for arg in args] + + ['%s=%r' % pair for pair in kwargs.items()] + ) + self.outputFunction( + '%scalled %s(%s)' % (self.prefix, name, ', '.join(args_kwargs)) + ) + result = func(*args, **kwargs) + self.outputFunction('%s%s returned %r' % (self.prefix, name, result)) + return result + + return wrapper + def format(self, *args): callFrame = inspect.currentframe().f_back