Skip to content Skip to sidebar Skip to footer

Override Attribute Access Precedence Having A Data Descriptor

I have a bunch of instances of a MongoEngine model. And the profiler shows that a lot of time is spent in __get__ method of MongoEngine model fields: ncalls tottime percall c

Solution 1:

Here is my solution which seems to work:

def_mock_me_instance(self, obj):
    """Patch a MongoEngine model instance to not use descriptors
    to access field values.
    """# copy class
    Model = type(obj.__class__.__name__, obj.__class__.__bases__,
                 dict(obj.__class__.__dict__))
    # add the original model to the base classes, so that isinstance() can work
    Model.__bases__ = (self.__class__,) + Model.__bases__
    # replace descriptor so that values from __dict__ can be seenfor field_name in obj._fields:
        setattr(Model, field_name, None)

    obj.__dict__.update(obj.__dict__['_data'])
    obj.__class__ = Model  # replace the classreturn obj

How it works

  1. I create a copy of the class whose instance the object is.
  2. Put the original model in the base classes, so that isinstance and issubclass can work.
  3. I copy the data into the object's __dict__. The values are ignored for now, because we have data descriptors with the same name which override access to the data.
  4. I assign None to the descriptors in the class (MongoEngine model fields in my case). None is not a descriptor, so values from __dict__ of the object are seen now.
  5. I replace object's class

The speed gain is ~600% (was 17 seconds, now it's 3).

Post a Comment for "Override Attribute Access Precedence Having A Data Descriptor"