[Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError

2014-02-24 Thread Sangeeth Saravanaraj
I am trying to capture an object initiation and deletion events using the
__call__() and __del__() methods with the following approach.


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

def __call__(self):
print A::__call__()
return self._klass()

def __del__(self):
print A::__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__()

@A
class B(Parent1, Parent2):
def __init__(self):
print B::__init__()
super(B, self).__init__()

def main():
b = B()

if __name__ == __main__:
main()


I decorate a class, say class B (whose object initiation and deletion I
wanted to capture) with a decorator class A. Please note that the class B
is derived from two classes - Parent1  Parent2 and I want to use super()
method to initialise the parent classes.

When I executed the above code snippet, I ran into the following issue:


A::__init__()
A::__call__()
B::__init__()
Traceback (most recent call last):
  File so.py, line 40, in module
main()
  File so.py, line 36, in main
b = B()
  File so.py, line 10, in __call__
return self._klass()
  File so.py, line 32, in __init__
super(B, self).__init__()
TypeError: must be type, not A
A::__del__()


When I commented super(B, self).__init__() in the class B :: __init__()
method, it returned an object of type B and I was able to see the prints in
the __call__ and __del__ methods but the __init__() methods of the base
classes (Parent1  Parent2) are not called!

From the error message, what I could understand is - the object returned by
A::__call__() is not of type B but of type A. But when I put a print in the
A::__call__() I could see it returns an object of type B and not A.

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
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError

2014-02-24 Thread Sangeeth Saravanaraj
On Mon, Feb 24, 2014 at 10:53 PM, Peter Otten __pete...@web.de wrote:

 Sangeeth Saravanaraj wrote:

  I am trying to capture an object initiation and deletion events using the
  __call__() and __del__() methods with the following approach.

 Note that there is no guarantee that __dell__ will ever be called. Usually
 it is better to introduce a weakref with callback.

  class A(object):
  def __init__(self, klass):
  print A::__init__()
  self._klass = klass
 
  def __call__(self):
  print A::__call__()
  return self._klass()
 
  def __del__(self):
  print A::__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__()
 
  @A
  class B(Parent1, Parent2):
  def __init__(self):
  print B::__init__()
  super(B, self).__init__()
 
  def main():
  b = B()
 
  if __name__ == __main__:
  main()
 
 
  I decorate a class, say class B (whose object initiation and deletion I
  wanted to capture) with a decorator class A. Please note that the class B
  is derived from two classes - Parent1  Parent2 and I want to use super()
  method to initialise the parent classes.
 
  When I executed the above code snippet, I ran into the following issue:
 
 
  A::__init__()
  A::__call__()
  B::__init__()
  Traceback (most recent call last):
File so.py, line 40, in module
  main()
File so.py, line 36, in main
  b = B()
File so.py, line 10, in __call__
  return self._klass()
File so.py, line 32, in __init__
  super(B, self).__init__()
  TypeError: must be type, not A
  A::__del__()
 
 
  When I commented super(B, self).__init__() in the class B :: __init__()
  method, it returned an object of type B and I was able to see the prints
  in the __call__ and __del__ methods but the __init__() methods of the
 base
  classes (Parent1  Parent2) are not called!
 
  From the error message, what I could understand is - the object returned
  by A::__call__() is not of type B but of type A. But when I put a print
 in
  the A::__call__() I could see it returns an object of type B and not A.
 
  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()?

 You'd have to introduce a naming convention or rewrite your class to be
 aware of the wrapping in some way:

 @A
 class B(Parent1, Parent2):
 def __init__(self):
 print B::__init__()
 super(B._klass, self).__init__()

 Not pretty.

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

 Most certainly, but you have to give some details about what you are up to
 first.


Sorry, I should have described what I was trying!

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.

You can safely assume that all the database operations are working fine!

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!

What is the best way to do this?!

Thank you,

Sangeeth




  PS:
  http://stackoverflow.com/questions/21826854/typeerror-when-using-super-
 method-with-class-decorator-for-a-derived-class


 ___
 Tutor maillist  -  Tutor@python.org
 To unsubscribe or change subscription options:
 https://mail.python.org/mailman/listinfo/tutor

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Class decorator on a derived class not initialising the base classes using super - TypeError

2014-02-24 Thread Sangeeth Saravanaraj
Peter, Spir - thanks for your time and effort!

I am posting this query to few more Python mailers.

Thank you,

Sangeeth


On Tue, Feb 25, 2014 at 5:22 AM, spir denis.s...@gmail.com wrote:

 On 02/24/2014 08:19 PM, Sangeeth Saravanaraj wrote:

 Sorry, I should have described what I was trying!

 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.

 You can safely assume that all the database operations are working fine!

 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!

 What is the best way to do this?!

 Thank you,

 Sangeeth


 Your problem looks like a typical crosscutting (transversal) concern
 addressed by AOP (Aspect Oriented Programming). Their usual example is in
 fact logging. Look at the wikipedia page:
 https://en.wikipedia.org/wiki/Aspect-oriented_programming

 Not that it would help you solve it _in python_, but this may serve at
 least to better understand what kind of problem you are actually facing;
 and why it is annoying in programming (with common languages); what may be
 your options.

 [I have no better approach than yours, using magic metamethods, and a
 decorator to wrap it all.]


 d
 ___
 Tutor maillist  -  Tutor@python.org
 To unsubscribe or change subscription options:
 https://mail.python.org/mailman/listinfo/tutor

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor