clarete / forbiddenfruit

Patch built-in python objects

Home Page:https://clarete.li/forbiddenfruit/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[request] patch the `__bases__` of builtin types

alexchandel opened this issue · comments

commented

I need to monkeypatch the base class of builtin types. No fancy magic methods, I just need to inherit normal method like this (contrived example):

class Iterator:
    def map(self, f):
        return map(f, self)

Naturally, this fails:

>>> list.__bases__ = (Iterator,)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'list'

But forbiddenfruit also fails:

>>> ff.curse(list, '__bases__', (Iterator,))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/forbiddenfruit/__init__.py", line 412, in curse
    _curse_special(klass, attr, value)
  File "/usr/local/lib/python3.7/site-packages/forbiddenfruit/__init__.py", line 327, in _curse_special
    assert isinstance(func, FunctionType)
AssertionError

Could you please add this to forbiddenfruit?

commented

For simple static classes, which aren't supposed to have multiple bases (but sometimes do, e.g. numpy dtypes), this means swapping out tp_base, ensuring to test for tp_bases to handle multi-parent static or dynamic classes and to (throw NotImplementedError or) patch those instead.

We'd also want checks like type_set_bases has for circular inheritance, valid assignments, etc.

On the other hand, adding Py_TPFLAGS_HEAPTYPE to the PyTypeObject's tp_flags simply disables the rejection in check_set_special_type_attr. But compatible_for_assignment still rejects assigning list.__bases__ with new types, as newto->tp_free != oldto->tp_free, since PyBaseObject_Type->tp_free == PyObject_Del instead of PyObject_GC_Del. But object's lack of explicit GC support may not be an issue…