Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #67014 > unrolled thread

Re: [Baypiggies] Class decorator to capture the creation and deletion of objects

Started byAlex Martelli <aleax@google.com>
First post2014-02-24 18:24 -0800
Last post2014-02-24 18:24 -0800
Articles 1 — 1 participant

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [Baypiggies] Class decorator to capture the creation and deletion of objects Alex Martelli <aleax@google.com> - 2014-02-24 18:24 -0800

#67014 — Re: [Baypiggies] Class decorator to capture the creation and deletion of objects

FromAlex Martelli <aleax@google.com>
Date2014-02-24 18:24 -0800
SubjectRe: [Baypiggies] Class decorator to capture the creation and deletion of objects
Message-ID<mailman.7336.1393295100.18130.python-list@python.org>

[Multipart message — attachments visible in raw view] — view raw

Off the cuff, I'd make saveme into a function, not a class;
the saveme function would alter the class passed in as its only argument
(saving __init__ and/or __del__ methods it may have and replacing them with
other -- nested -- functions that call them and do the rest of the job) and
return the same class object it received.

No time to actually write the code but this seems a much sounder
architecture.


Alex



On Mon, Feb 24, 2014 at 4:49 PM, Sangeeth Saravanaraj <
sangeeth.saravanaraj@gmail.com> wrote:

> This question was initially asked in tutor@python.org; 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/21826854/typeerror-when-using-super-method-with-class-decorator-for-a-derived-class
>
>
> _______________________________________________
> Baypiggies mailing list
> Baypiggies@python.org
> To change your subscription options or unsubscribe:
> https://mail.python.org/mailman/listinfo/baypiggies
>

[toc] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web