So, the problem exists with both enableMaintenance and cancelMaintenance for 
hosts and with enableMaintenance for storage (not with cancelMaintenance for 
storage).

A bunch of UI scripts use those class methods (I didn't see us trying to use 
the instance methods anywhere).

I believe those class methods exist because the test scripts already have the 
UUIDs of the host or storage and those class methods provide a faster means of 
performing the action in question (when compared to having to retrieve a host 
or storage object from the applicable UUID and then invoke the method on it).

That being the case, I think we should just keep the class methods.
________________________________________
From: Will Stevens <williamstev...@gmail.com>
Sent: Sunday, May 1, 2016 12:15 PM
To: dev@cloudstack.apache.org
Subject: Re: Python Question (with regards to Marvin)

Ya. Let's see how prevalent the class method is to start with and we will
cross that bridge after.
On May 1, 2016 2:07 PM, "Tutkowski, Mike" <mike.tutkow...@netapp.com> wrote:

> I was just "concerned" that those who have their own Marvin tests that are
> not checked in might be broken if I don't keep the class method.
> ________________________________________
> From: Will Stevens <williamstev...@gmail.com>
> Sent: Sunday, May 1, 2016 12:03 PM
> To: dev@cloudstack.apache.org
> Subject: Re: Python Question (with regards to Marvin)
>
> It will be easy to grep if there class methods, so we should start there.
> If not, then I agree that an instance method is probably the best way to
> go.
> On May 1, 2016 12:41 PM, "Tutkowski, Mike" <mike.tutkow...@netapp.com>
> wrote:
>
> > However, from a design standpoint, I prefer the instance method here as
> it
> > would be nice to ask the object itself to place itself in maintenance
> mode.
> >
> > So, it's really a question of just staying backward compatible (the class
> > method) or a possibly better design (the instance method).
> > ________________________________________
> > From: Tutkowski, Mike <mike.tutkow...@netapp.com>
> > Sent: Sunday, May 1, 2016 10:18 AM
> > To: dev@cloudstack.apache.org
> > Subject: Re: Python Question (with regards to Marvin)
> >
> > The question then becomes, do we want to keep the instance or the class
> > method?
> >
> > There exists the same problem for at least one other pair of methods.
> >
> > Since the class method is listed second in the file currently, it is the
> > only one of the two that can be utilized. That being the case, we might
> > just want to keep the class method and remove the instance method.
> >
> > > On May 1, 2016, at 5:43 AM, Will Stevens <williamstev...@gmail.com>
> > wrote:
> > >
> > > Yep. Looking like there is a bug in that file. Thanks for testing. :)
> > >> On May 1, 2016 1:40 AM, "Tutkowski, Mike" <mike.tutkow...@netapp.com>
> > wrote:
> > >>
> > >> Here are my tests (run from http://ideone.com/).
> > >>
> > >> The short story is that having multiple methods with the same name
> (even
> > >> if one is an instance method and one is a class method) should
> probably
> > not
> > >> be done.
> > >>
> > >> If you try to invoke the instance method (ex. test.run()), the last
> > method
> > >> by that name in the source file is invoked (which could be the class
> > >> method). If the number of parameters don't match, that's an error.
> > >>
> > >> If you try to invoke the class method (ex. Test.run()), the last
> method
> > by
> > >> that name in the source file is invoked. If this is not a class method
> > or
> > >> if the number of parameters don't match, that's an error.
> > >>
> > >> class Test:
> > >>    @classmethod
> > >>    def run(cls):
> > >>        print "class hi"
> > >>
> > >>    def run(self):
> > >>        print "instance hi"
> > >>
> > >> test = Test()
> > >>
> > >> test.run()
> > >>
> > >> What gets printed:
> > >> instance hi
> > >>
> > >> class Test:
> > >>    def run(self):
> > >>        print "instance hi"
> > >>
> > >>    @classmethod
> > >>    def run(cls):
> > >>        print "class hi"
> > >>
> > >> test = Test()
> > >>
> > >> test.run()
> > >>
> > >> What gets printed:
> > >> class hi
> > >>
> > >> class Test:
> > >>    @classmethod
> > >>    def run(cls):
> > >>        print "class hi"
> > >>
> > >>    def run(self):
> > >>        print "instance hi"
> > >>
> > >> # test = Test()
> > >>
> > >> Test.run()
> > >>
> > >> Runtime error
> > >>
> > >> class Test:
> > >>    @classmethod
> > >>    def run(cls):
> > >>        print "class hi"
> > >>
> > >> # test = Test()
> > >>
> > >> Test.run()
> > >>
> > >> What gets printed:
> > >> class hi
> > >>
> > >> class Test:
> > >>    def run(self):
> > >>        print "instance hi"
> > >>
> > >>    @classmethod
> > >>    def run(cls):
> > >>        print "class hi"
> > >>
> > >> # test = Test()
> > >>
> > >> Test.run()
> > >>
> > >> What gets printed:
> > >> class hi
> > >>
> > >> class Test:
> > >>    @classmethod
> > >>    def run(cls):
> > >>        print "class hi"
> > >>
> > >> # test = Test()
> > >>
> > >> Test.run()
> > >>
> > >> What gets printed:
> > >> class hi
> > >> ________________________________________
> > >> From: Tutkowski, Mike
> > >> Sent: Saturday, April 30, 2016 6:58 PM
> > >> To: dev@cloudstack.apache.org
> > >> Subject: Re: Python Question (with regards to Marvin)
> > >>
> > >> I can play around with it later tonight. I'm not home at the moment.
> > >>
> > >> When I did invoke it as Test.run(), it invoked the class method (the
> > class
> > >> method was listed after the instance method for that test, so I wasn't
> > >> surprised that the class method did, in fact, get executed there).
> > >>
> > >> What I did not try was to list the class method first, then list the
> > >> instance method, and then try to invoke the class method.
> > >>
> > >> As mentioned in my prior e-mail, when I did try to invoke the instance
> > >> version of run, it was only successful if the instance version was the
> > >> second one declared in the file. If the class method was declared
> > second,
> > >> then it was invoked even when I was trying to invoke the instance one.
> > >>
> > >>>> On Apr 30, 2016, at 6:06 PM, Will Stevens <williamstev...@gmail.com
> >
> > >>> wrote:
> > >>>
> > >>> That's strange. That means the @classmethod decorator is not working.
> > You
> > >>> should have gotten the instance method in both cases.
> > >>>
> > >>> What if you don't instantiate Test and only do the following.
> > >>>
> > >>> Test.run()
> > >>>
> > >>> In both cases.
> > >>> On Apr 30, 2016 6:04 PM, "Tutkowski, Mike" <
> mike.tutkow...@netapp.com>
> > >>> wrote:
> > >>>
> > >>>> I ran this with an online Python tool and it calls the class method:
> > >>>>
> > >>>> 1       class Test:
> > >>>> 2         def run(self):
> > >>>> 3             print 'instance hi'
> > >>>> 4
> > >>>> 5         @classmethod
> > >>>> 6         def run(cls):
> > >>>> 7             print 'class hi'
> > >>>> 8
> > >>>> 9       test = Test()
> > >>>> 10
> > >>>> 11      test.run()
> > >>>>
> > >>>> If I reverse the order of the methods, the instance method is
> invoked:
> > >>>>
> > >>>> 1       class Test:
> > >>>> 2         @classmethod
> > >>>> 3         def run(cls):
> > >>>> 4             print 'class hi'
> > >>>> 5
> > >>>> 6         def run(self):
> > >>>> 7             print 'instance hi'
> > >>>> 8
> > >>>> 9       test = Test()
> > >>>> 10
> > >>>> 11      test.run()
> > >>>>
> > >>>> As I suspected, I think this means we have a problem in base.py.
> > >>>> ________________________________________
> > >>>> From: Will Stevens <williamstev...@gmail.com>
> > >>>> Sent: Saturday, April 30, 2016 1:46 PM
> > >>>> To: dev@cloudstack.apache.org
> > >>>> Subject: Re: Python Question (with regards to Marvin)
> > >>>>
> > >>>> I am on my phone so I have not been able to research this for you. I
> > >> think
> > >>>> you are right for the most part.  Instead of multiple methods,
> python
> > >> kind
> > >>>> of fakes overloading by being to have named function arguments which
> > can
> > >>>> have default values, so you can call the method with a dynamic
> number
> > of
> > >>>> arguments making it appear like you are overloading, but you are
> > >> actually
> > >>>> calling the same function.
> > >>>>
> > >>>> I think in this case the two methods are actually in different
> scopes
> > >> (even
> > >>>> though they are next to each other).  The decorator actually wraps
> the
> > >>>> method, so I believe in the actual runtime the to methods are in
> > >> different
> > >>>> scopes.
> > >>>>
> > >>>> I would have to look into this more to know for sure. I am taking a
> > few
> > >>>> minute break from building garden boxes right now. :)
> > >>>> On Apr 30, 2016 3:31 PM, "Tutkowski, Mike" <
> mike.tutkow...@netapp.com
> > >
> > >>>> wrote:
> > >>>>
> > >>>>> Will - You can override a method in Python, but can you overload
> it?
> > >>
> >
> http://stackoverflow.com/questions/10202938/how-do-i-use-method-overloading-in-python
> > >>>>>
> > >>>>>>> On Apr 30, 2016, at 6:23 AM, Will Stevens <
> > williamstev...@gmail.com>
> > >>>>>> wrote:
> > >>>>>>
> > >>>>>> Here is a pretty good explanation.
> > >>
> >
> http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
> > >>>>>>
> > >>>>>> I am guessing that both exist because the function is called both
> > with
> > >>>> a
> > >>>>>> host instance and with the class itself.
> > >>>>>>
> > >>>>>> Class instance example: `h.enableMaintenance(client)`
> > >>>>>>
> > >>>>>> Class example: `Host.enableMaintenance(client, 1)`
> > >>>>>>
> > >>>>>> In both cases the first parameter is implicitly `h` and `Host`
> > >>>>>> respectively.
> > >>>>>>
> > >>>>>> I am not sure why we need both (because I am not familiar with how
> > >> this
> > >>>>>> code is called), but method overloading is definitely valid in
> > python.
> > >>>>>>
> > >>>>>> On Apr 30, 2016 1:08 AM, "Tutkowski, Mike" <
> > mike.tutkow...@netapp.com
> > >>>
> > >>>>>> wrote:
> > >>>>>>>
> > >>>>>>> Hi everyone,
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> I received an error when trying to invoke the instance version of
> > >>>>>> enableMaintenance (below).
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> 'TypeError: enableMaintenance() takes exactly 3 arguments (2
> > >>>> given)\n']
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> I looked at base.py and it has the following with regards to
> > >>>> maintenance
> > >>>>>> mode for hosts:
> > >>>>>>>
> > >>>>>>>
> > >>>>>>>  def enableMaintenance(self, apiclient):
> > >>>>>>>
> > >>>>>>>      """enables maintenance mode Host"""
> > >>>>>>>
> > >>>>>>>
> > >>>>>>>      cmd =
> prepareHostForMaintenance.prepareHostForMaintenanceCmd()
> > >>>>>>>
> > >>>>>>>      cmd.id = self.id
> > >>>>>>>
> > >>>>>>>      return apiclient.prepareHostForMaintenance(cmd)
> > >>>>>>>
> > >>>>>>>
> > >>>>>>>  @classmethod
> > >>>>>>>
> > >>>>>>>  def enableMaintenance(cls, apiclient, id):
> > >>>>>>>
> > >>>>>>>      """enables maintenance mode Host"""
> > >>>>>>>
> > >>>>>>>
> > >>>>>>>      cmd =
> prepareHostForMaintenance.prepareHostForMaintenanceCmd()
> > >>>>>>>
> > >>>>>>>      cmd.id = id
> > >>>>>>>
> > >>>>>>>      return apiclient.prepareHostForMaintenance(cmd)
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> Now, I definitely have a lot more Java experience than Python,
> but
> > -
> > >>>> as
> > >>>>>> far as I know - having two methods with the same name such as this
> > >>>> (even
> > >>>>> if
> > >>>>>> one is an instance method and the other is a class method) is not
> > >>>> really
> > >>>>>> "permitted" in Python.
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> I mean, technically it's permitted, but the second one will
> > override
> > >>>> the
> > >>>>>> first one.
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> Can any of our Python people comment on this?
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> I was thinking I'd remove the class method (assuming my knowledge
> > >> here
> > >>>>>> regarding this topic is correct).
> > >>>>>>>
> > >>>>>>>
> > >>>>>>> Thanks!
> > >>>>>>>
> > >>>>>>> Mike
> > >>
> >
>

Reply via email to