Django Model classes, Wrapt decorator, and decorator argument

12 views
Skip to first unread message

Utkarsh

unread,
Aug 10, 2015, 3:48:08 PM8/10/15
to Django users

Dear All,

My aim is to obtain all unique call stacks where model classes are accessed. 

To implement it, I thought of overriding save(), delete(), and get_query_set() methods, as follows -

class MyModelClass(CallStackMixin, models.Model) # Mixin to override save, and delete
        objects
= CallStackManager() # Manager which overrides the get_query_set


Overriding those methods as follows -

class CallStackMixin(object):
   
""" A mixin class for getting call stacks when Save() and Delete() methods are called
    """



   
def save(self, *args, **kwargs):
       
"""
        Logs before save and overrides respective model API save()
        """

        capture_call_stack
(type(self))
       
return super(CallStackMixin, self).save(*args, **kwargs)


   
def delete(self, *args, **kwargs):
       
"""
        Logs before delete and overrides respective model API delete()
        """

        capture_call_stack
(type(self))
       
return super(CallStackMixin, self).delete(*args, **kwargs)

class CallStackManager(Manager):
   
""" A Manager class which overrides the default Manager class for getting call stacks
    """

   
def get_query_set(self):
       
"""overriding the default queryset API method
        """

        capture_call_stack
(type(self))
       
return super(CallStackManager, self).get_query_set()

where capture_call_stack is a method which logs call stacks. 

There is also a functionality of @donottrack which is a decorator that avoids logging obvious calls made where we know the call stack.

The @donottrack is as follows -

def donottrack(*classes_not_to_be_tracked):
   
"""function decorator which deals with toggling call stack
    Args:
        classes_not_to_be_tracked: model classes where tracking is undesirable
    Returns:
        wrapped function
    """

   
@wrapt.decorator
   
def real_donottrack(wrapped, instance, args, kwargs):  # pylint: disable=W0613
       
"""takes function to be decorated and returns wrapped function


        Args:
            function - wrapped function i.e. real_donottrack
        """

       
global HALT_TRACKING  # pylint: disable=W0603
        HALT_TRACKING
.append(classes_not_to_be_tracked)
        HALT_TRACKING
[-1] = list(set([x for sublist in HALT_TRACKING for x in sublist]))
        return_value
= wrapped(*args, **kwargs)
        HALT_TRACKING
.pop()
       
return return_value
   
return real_donottrack

Where HALT_TRACKING is a stack which is a global data structure, and it pops wrt to value associated with function.

I am using @wrapt for retaining identity of functions, and ModelBase class. Strangely, HALT_TRACKING.pop() executes first and then wrapped function seems to be in action. However, I desire to execute wrapped first and then pop HALT_TRACKING

Any idea what exactly is going wrong here?



Reply all
Reply to author
Forward
0 new messages