beartype: [Bug] Unreadable exceptions raised after @beartype erroneously detects uncallable objects as callable (...or something, something)
Discussed in https://github.com/beartype/beartype/discussions/338
<div type='discussions-op-text'>Originally posted by sylvorg March 14, 2024 Hello!
Is it possible to allow partials, C-based callables, etc. when using beartype_this_package
? Iโm writing a function piping class:
class PipeMeta(SlotsMeta):
# wrap = lambda cls, b: lambda a: lambda *args, **kwargs: b(a(*args, **kwargs))
def wrap(cls: "PipeMeta", b: Callable) -> Callable:
def wrapper(a: Callable):
@wraps(a)
def wrapped(*args: Unpack[Any], **kwargs: Unpack[Any]):
return b(a(*args, **kwargs))
return wrapped
return wrapper
class Pipe(metaclass=PipeMeta):
def __init__(self: "Pipe", func: Callable) -> None:
self.func: Callable = func.func if isinstance(func, self.__class__) else func
self.__rshift__ = self.__rlshift__ = self.__or__
self.__rrshift__ = self.__lshift__ = self.__ror__
self.__irshift__ = self.__ior__
def __wrap__(self: "Pipe", b: Callable, a: Callable) -> Callable:
return self.__class__.wrap(b)(a)
def __call__(self: "Pipe", *args: Unpack[Any], **kwargs: Unpack[Any]) -> Any:
return self.func(*args, **kwargs)
def __or__(self: "Pipe", other: Callable) -> "Pipe":
return self.__class__(self.__wrap__(other, self.func))
def __ror__(self: "Pipe", other: Callable) -> "Pipe":
return self.__class__(self.__wrap__(self.func, other))
def __ior__(self: "Pipe", other: Callable) -> "Pipe":
self.func = self.__wrap__(other, self.func)
return self
def __ilshift__(self: "Pipe", other: Callable) -> "Pipe":
self.func = self.__wrap__(self.func, other)
return self
But am getting the following error when trying to test it with a partial function:
beartype.roar._BeartypeUtilCallableException: Functools.partial(<class 'map'>, <class 'str'>) not pure-Python function.
I am assuming that users of the class already know the type hints of the final function.
Thank you kindly for the help, and sorry in advance for a general lack of knowledge regarding Pythonโs internals! ๐ </div>
About this issue
- Original URL
- State: closed
- Created 4 months ago
- Reactions: 1
- Comments: 20 (10 by maintainers)
Sorry for the repeated pings, but, interestingly enough, removing all
Unpack
hints and puttingAny
as the output hint fordef wrapped(*args, **kwargs):
also triggers this when used withfrom pipe import Pipe; list | Pipe(lambda: range(10))
!No, waitโฆ
from pipe import Pipe; list | Pipe(lambda: range(10))
works as well in the repl, despite__ror__
being defined:Oh, youโre much too kind; I just keep chugging along, despite how many math and math-based courses Iโve failed so far. ๐
It turns out like recognizes like; I have Aspergerโs too! Iโd thought you sounded a bit too similar to myself! Or at least, before I started taking medication for it, because things were getting a wee bit out of handโฆ Sighโฆ Ah, well. You live and you learn. ๐น Itโs actually where the visual memory problems come from! โฆ Or not, because correlation is not causation. Guess weโll need more research!
As for the rest, is it possible that using
beartype_this_package
is the problem?This is the entire traceback; in the meantime, Iโll see if I can create a tiny package using
beartype_this_package
and see if I can recreate a mrp / minimal reproducible package ๐น:โฆ In retrospect, I probably shouldโve provided this to begin withโฆ
Superb request. Youโre absolutely right, @sylvorg. Iโm kinda surprised @beartype doesnโt already support
functools.partial
. Thatโs bad.functools.partial
is literally everywhere. Itโs standard and ubiquitous, so @beartype needs to support this ASAP.Let us see what the future brings for everyone. โOh, look! Itโs a double rainbow!โ ๐ ๐
Hah! Glad I could help! ๐ธ
These are for rich, though I donโt yet know if the second one works:
Regarding
wraps
, I always assumed it could take any callable, since classes could also be called, no?And finally, thank you so, so much for sticking with me through this; I very much appreciate it, and Iโll keep your offer in mind! ๐ I am in the currently in the very strange position of both wanting to find issues in
beartype
, just to have this much fun again, and not, because, well, you know. ๐นAgain, thank you kindly for all the help! ๐ป
Ah ha! Thanks to your tremendous gusto, @sylvorg, Iโve isolated this to a minimal reproducible example:
Fascinating. I never even knew you could pass classes to the
@functools.wraps()
decorator. Today I learned. Interestingly, when you pass a class to the@functools.wraps()
, it looks like that decorator internally wraps that class in a new function of the same name. Or something, something.Anywaaaays. I now have much to chew on. Let us chew until the night bleeds into dawn! ๐
And hereโs the link to the repository with the minimal reproducible package; I was able to consistently reproduce the error!
Thank you kindly! ๐ธ To be fair, my not realizing that these were python internals may prove my point. ๐น What makes the situation worse is that Iโm currently pursuing a Computer Science degree, have studied the algorithms and data structures and the related time complexities, but am not very good at math due a visual disability. What fun! ๐ญ
*Ahem.* Moving onโฆ
As it turns out, it was indeed the use of
Unpack
. However! The error message didnโt seem to specify this, instead telling me that the callables were not pure-python functions. โฆ Also, sorry, I just realized I didnโt include thepipe
function, which reduces thePipe
class when given a tuple of functions:Can you trip the error when using
Unpack
for all of them? Because it might be better forbeartype
to specify in these cases thatUnpack
only works withtyping.TypeVarTuple
andtyping.TypeDict
, and / or that it doesnโt support it yet.In the meantime, Iโll study up on the blog post; thanks for the pointer!
Oh โ and would you mind posting your test that uses a partial function? Iโm not quite sure whatโs failing here. The exact code would be a huge help. Thanks so much, @sylvorg! Weโll get this squared away for you or my favorite emoji isnโt a flexing bear. ๐ช ๐ป