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

I meant that a bunch of test scripts use those methods (not UI scripts).

> On May 1, 2016, at 5:24 PM, Tutkowski, Mike <mike.tutkow...@netapp.com> wrote:
> 
> 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