Class decorator to capture the creation and deletion of objects

  • Thread starter Sangeeth Saravanaraj
  • Start date

S

Sangeeth Saravanaraj

This question was initially asked in (e-mail address removed); Now I am widening
the audience to gain attention.

I want to create a decorator which should do the following things:
=> When an object of the decorated class is created, the objects name (say
the value of the incoming "id" argument) should be stored as a record in a
table in a database.
=> When an object of the decorated class is deleted, the record with this
deleted objects name (i.e. object.id) should be removed from the table.

Now, for example - consider the following snippet:

@saveme
class A(object):
def __init__(self, id):
self.id = id

@saveme
class B(object):
def __init__(self, id):
self.id = id

"saveme" should do what I have explained earlier.

a1 = A("A1")
a2 = A("A2")
a3 = A("A3")
b1 = B("B1")
b2 = B("B2")

At this point if I query and print all the records in a table, I should get
the following output:
["A1", "A2", "A3", "B1", "B2"]

del a1
del a2
del a3
del b1
del b2

At this point, all entries in the table should be deleted; query should
return an empty list!

And, I want to highlight that the classes that are being decorated with
"saveme" can de derived classes too [which initialises its base classes
using super() method]!

Now the following is what I have tried:

class saveme(object):
def __init__(self, klass):
print "saveme::__init__()"
self._klass = klass

def __call__(self, *args, **kwargs):
print "saveme::__call__()"
obj = self._klass(*args, **kwargs)
# creation of DB record will happen here!
# i.e. something like add_to_db(kwargs.get("id"))
return obj

def __del__(self):
# deletion of DB record will happen here!
# i.e. something like remove_from_db(id)
# TODO: how to retrieve the "id" here?!
print "saveme::__del__()"


class Parent1(object):
def __init__(self):
print "Parent1:: __init__()"
super(Parent1, self).__init__()


class Parent2(object):
def __init__(self):
print "Parent2:: __init__()"
super(Parent2, self).__init__()


@saveme
class A(Parent1, Parent2):
def __init__(self, id):
print "A::__init__()"
self.id = id
#super(A, self).__init__()


#@saveme
#class B(object):
# def __init__(self, id):
# print "B::__init__()"
# self.id = id


def main():
a1 = A(id="A1")
# b1 = B(id="B1")

if __name__ == "__main__":
main()


When executed the above, I ran in to the following:

saveme::__init__()
saveme::__call__()
A::__init__()
Traceback (most recent call last):
File "1.py", line 54, in <module>
main()
File "1.py", line 50, in main
a1 = A(id="A1")
File "1.py", line 10, in __call__
obj = self._klass(*args, **kwargs)
File "1.py", line 39, in __init__
super(A, self).__init__()
TypeError: must be type, not saveme
saveme::__del__()


When I commented "super(A, self).__init__()" in the class A :: __init__()
method, it returned an object of type A and I was able to see the prints in
the __call__ and __del__ methods but the __init__() methods of the base
classes (Parent1 & Parent2) were not called!
From the error message, what I could understand is - the object returned by
saveme::__call__() is not of type A but of type saveme. But when I put a
print in the saveme::__call__() I could see it returns an object of type A
and not saveme.

Now the question is - with this approach to capture the initiation and
deletion events of an object, how do I initialise the base classes using
super()?

Or, is there any other better way to capture the __call__ and __del__
events for an object of a certain class - if so, how?!

Thank you,

Sangeeth


PS:
http://stackoverflow.com/questions/...thod-with-class-decorator-for-a-derived-class
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top