Monday, August 10, 2015

Django Model classes, Wrapt decorator, and decorator argument


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?



--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/b386f27f-bea1-4d0f-a4e2-ee0ddbf71625%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment