clarete/forbiddenfruit

Exceptions raised in cursed-in dunder methods are not raised to calling code

EZForever opened this issue · 0 comments

Proof of concept:

#!/usr/bin/env python3

from forbiddenfruit import curse

class foo(object):
    def __init__(self): pass

def foo_add(self: foo, other: int) -> foo:
    raise TypeError('This exception should be caught')

curse(foo, '__add__', foo_add)

try:
    print(foo() + 1) # <class '__main__.foo'> (on Windows), __main__ (on Linux)
except TypeError:
    print('TypeError caught') # Not caught (wrong)

Test result:

(venv) C:\dev\test> python bug.py  
Exception ignored on calling ctypes callback function: <function foo_add at 0x0000026EC623FEE0>
Traceback (most recent call last):
  File "E:\src\pytrickz\venv\lib\site-packages\forbiddenfruit\__init__.py", line 328, in wrapper
    return func(*args, **kwargs)
  File "bug.py", line 13, in foo_add
    raise TypeError('This exception should be caught')
TypeError: This exception should be caught
<class '__main__.foo'>

(venv) C:\dev\test> 

The exception is printed to the screen (presumably by ctypes?) but not raised, except TypeError not triggered, print() receives a garbage result that depends on Python version and class structure (for example, if I remove foo.__init__ from code the result becomes None on Windows).