Open nolar opened 7 years ago
I already use the partial wrapper approach to break out __call__()
as it caused similar issues early on. Trying to create even more variations and the combinations will get messy, as also have to deal with __hash__()
, __len__()
, __contains__()
and possibly others.
An alternative approach is for a base proxy object not to have any of these special methods which cause problems and have the __init__()
method of the proxy object to only add them into the instance at the time of creation if the wrapped object has them. This means extra checks every time a proxy object is created, but also complicates the C implementation as the proxy object couldn't be in C, only the base proxy object. This is because you can't update the slots of the C object struct to add them in __init__()
.
I'll keep thinking about it and do some tests to see how practical it is for it to handle it more dynamically just for these special methods for which there are special isinstance()
types.
What about creating the wrapping methods or returning the original methods on __getattribute__
/__getattr__
, and escalating the AttributeError if they are absent in the original wrapped object? Consider also the case when the wrapped instance has some magic methods added at runtime, not defined in its class (rare, but possible case).
Another way would be to create specialised wrapper classes, e.g. MyObjectWrapper = creater_wrapper_class(MyObject)
, or via inheritance: class MyObjectWrapper(MetaWrapper): CLS=MyObject
. By default, the wrapper wraps the instances of arbitrary classes as it does now.
Overriding __getattribute__()
is too expensive as impacts every attribute lookup and not just missing ones. Am not sure if overriding __getattr__()
will have desired effect on a C implementation as C methods for some things from memory only look up the slots structure for special methods. Will need to experiment with using it for that.
Problem:
Cause:
This is caused by
collections.Iterable
to actually check the MRO of the instance for the presence of__iter__
in one of the base classes (i.e. not viagetattr()
/hasattr()
), and theObjectProxy
happens to have this and all other magic methods predefined.See the checking logic here:
Suggestions:
I guess, the issue cannot be solved for the generic case. There is no way to intercept such checks in the proxy class or its descendant or in their metaclasses (i.e., no
__instancecheck__
,__subclasscheck__
,__subclasshook__
tricks are possible).But at least, can it be possible to define partial wrappers, similar to how namedtuples are created at runtime? I.e., to create a wrapper base class with the selected set of magic methods enabled/disabled:
Something similar to this: http://code.activestate.com/recipes/496741-object-proxying/ — but with the filtering of the properties.
PS: I really do not want to create yet another wrapper library when there are so many of them, and prefer to use the already used library.