icecream icon indicating copy to clipboard operation
icecream copied to clipboard

ic does not show funtion name, *args or **kwargs inside a wrapper

Open Soif2Sang opened this issue 1 year ago • 3 comments

@decohints
def get_name(func):
    @wraps(func)
    def wrapper(self: object, *args: object, **kwargs: object):
        func_output = ic(func(self, *args, **kwargs))
        return func_output
    return wrapper

returns 'ic| func(self, *args, **kwargs): None'

instead of the actual functio name, args, and kwargs

Soif2Sang avatar Sep 15 '23 19:09 Soif2Sang

I guess this is actually a consequence of it showing the local variable names. They just happen to be not very helpful here. You get the same when doing:

from icecream import ic

def f(*args, **kwargs):
    return args, kwargs

args = 1, 2
kwargs = {"a": 3}
ic(f(*args, **kwargs))
# ic| f(*args, **kwargs): ((1, 2), {'a': 3})

Not sure how one could distinguish this case from the wrapped function case.

graipher avatar Oct 09 '23 06:10 graipher

@graipher

Not sure how one could distinguish this case from the wrapped function case.

I think Microsoft stumbled on a similar issue with Pylance, and they solved it like this (not sure if applicable to ic):

https://github.com/microsoft/pylance-release/issues/4140 (related: https://github.com/microsoft/pylance-release/issues/442 )

Emasoft avatar Dec 23 '23 07:12 Emasoft

I just checked, adding type hints (as alluded to in that first pylance link, to leverage the better type hints introduced by functools.wraps in recent Python versions), does not help:

from icecream import ic
from typing import Callable, TypeVar, ParamSpec

R = TypeVar("R")
P = ParamSpec("P")


def get_name(func: Callable[P, R]) -> Callable[P, R]:
    @wraps(func)
    def wrapper(self: object, *args: P.args, **kwargs: P.kwargs) -> R:
        func_output = ic(func(self, *args, **kwargs))
        return func_output
    return wrapper


class A:
    def a(self, x: str) -> str:
        return x


a = A()
get_name(a.a)("foo")
# ic| func(self, *args, **kwargs): 'foo'

Not unsurprising, since I guess ic only inspects the scope surrounding the call.

graipher avatar Dec 28 '23 13:12 graipher