google / sqlcommenter

Apache License 2.0
601 stars 81 forks source link

Django middleware AttributeError exception on "if execute.__self__.__class__ is CursorDebugWrapper" #46

Closed yuval-curv closed 3 years ago

yuval-curv commented 3 years ago
    if execute.__self__.__class__ is CursorDebugWrapper:
AttributeError: 'functools.partial' object has no attribute '__self__

I am using Python3.6 with Django2.2.13.

I also tested a simple code that reproduces this error with a trivial class.

import functools
class ClassA:
    def foo(self):
        pass

functools.partial(ClassA.foo).__self__  # functools.partial(ClassA.foo, ClassA()).__self__ also fails
yuval-curv commented 3 years ago

Django calls the executor from django.db.backends.CursorWrapper._execute_with_wrappers. this function looks like this:

    def _execute_with_wrappers(self, sql, params, many, executor):
        context = {'connection': self.db, 'cursor': self}
        for wrapper in reversed(self.db.execute_wrappers):
            executor = functools.partial(wrapper, executor)
        return executor(sql, params, many, context)

This means that if the sqlcommenter executor is last in the self.db.execute_wrappers list, it will be passed the executor as received by the method (notice that the list is reversed so last becomes first). Only then will execute in the sqlcommenter QueryWrapper method not be a functools.partial instance.

In any other case, the code I opened the issue for will break.

omirho commented 3 years ago

@yuval-curv Thanks for bringing this to our notice. I'll have a fix out soon, and will update here.

omirho commented 3 years ago

@yuval-curv Will you be able to provide me with a sample project which reproduces the error? Will help me with writing tests.

yuval-curv commented 3 years ago

@omirho You can just create a new Django project and add this middleware twice in the settings.py file. This will reproduce the issue (just create a superuser and try logging in to http://127.0.0.1:8000/admin/).

Screen Shot 2021-02-26 at 22 18 17