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 > >>> >