Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Object Wrapper

Tags:

python

I am trying to create a wrapper class that behaves almost like the wrapped object. So far, I have come up with the following code:

import functools
import types

method_wrapper = type((None).__str__)

class Box:

    def __new__(cls, obj):
        attrs = {}
        attr_names = dir(obj)

        for attr_name in attr_names:
            attr = obj.__getattribute__(attr_name)

            if isinstance(attr, (types.MethodType, method_wrapper)):
                "Attr is a bound method, ignore self"
                @functools.wraps(attr)
                def wrapped_attr(self, *args, **kwargs):
                    return attr(*args, **kwargs)
                attrs[attr_name] = wrapped_attr

            elif isinstance(attr, types.FunctionType):
                "attr is a static method"
                attrs[attr_name] = staticmethod(attr)

            else:
                "attr is a property"
                attrs[attr_name] = attr

        cls = type(type(obj).__name__,
                   (cls, type(obj)),
                   attrs)

        return object.__new__(cls)

I tried testing it with:

if __name__ == '__main__':
    x=Box(object())

However it comes up with the following error message:

TypeError: __init__() should return None, not 'NotImplementedType'

__init__ is being properly dispatched by isinstance(attr, (types.MethodType, method_wrapper)), and wrapped_attr seems to be executed. Do you have any idea why this is happening?

like image 504
Joshua Avatar asked Nov 11 '22 08:11

Joshua


1 Answers

The problem is here:

for ...:
    attr = ...
    ...
    def wrapped_attr(...):
        ..attr..

This doesn't work as expected, because attr is rebound to various values by the for loop. All subfunctions will see the last value bound, not the value it had in that iteration of the loop. In this case, the last value bound, in alphabetical order, is __subclasshook__, which tends to return NotImplemented when called with random arguments.

like image 129
Armin Rigo Avatar answered Nov 15 '22 06:11

Armin Rigo