Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 3D01D2009C6 for ; Sun, 1 May 2016 18:41:52 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 3B8C91609AA; Sun, 1 May 2016 18:41:52 +0200 (CEST) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 344CF16010A for ; Sun, 1 May 2016 18:41:51 +0200 (CEST) Received: (qmail 83996 invoked by uid 500); 1 May 2016 16:41:50 -0000 Mailing-List: contact dev-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list dev@cloudstack.apache.org Received: (qmail 83985 invoked by uid 99); 1 May 2016 16:41:50 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 01 May 2016 16:41:50 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 80167C00A4 for ; Sun, 1 May 2016 16:41:49 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.202 X-Spam-Level: X-Spam-Status: No, score=-4.202 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=disabled Received: from mx2-lw-us.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id XM6fZGBpgfOg for ; Sun, 1 May 2016 16:41:45 +0000 (UTC) Received: from mx143.netapp.com (mx143.netapp.com [216.240.21.24]) by mx2-lw-us.apache.org (ASF Mail Server at mx2-lw-us.apache.org) with ESMTPS id B646D5F23C for ; Sun, 1 May 2016 16:41:44 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.24,562,1455004800"; d="scan'208";a="112008966" Received: from hioexcmbx06-prd.hq.netapp.com ([10.122.105.39]) by mx143-out.netapp.com with ESMTP; 01 May 2016 09:41:37 -0700 Received: from HIOEXCMBX05-PRD.hq.netapp.com (10.122.105.38) by hioexcmbx06-prd.hq.netapp.com (10.122.105.39) with Microsoft SMTP Server (TLS) id 15.0.1156.6; Sun, 1 May 2016 09:41:32 -0700 Received: from HIOEXCMBX05-PRD.hq.netapp.com ([::1]) by hioexcmbx05-prd.hq.netapp.com ([fe80::dd75:c5fa:b5a0:23a7%21]) with mapi id 15.00.1156.000; Sun, 1 May 2016 09:41:38 -0700 From: "Tutkowski, Mike" To: "dev@cloudstack.apache.org" Subject: Re: Python Question (with regards to Marvin) Thread-Topic: Python Question (with regards to Marvin) Thread-Index: AQHRop1L0/Y4TEMUkUWj+q7EuNNrI5+i5kcAgAACREmAAHmMAP//r69hgACYwID//5mIQoAATOFrgADciQD//9efnwAAuy8i Date: Sun, 1 May 2016 16:41:37 +0000 Message-ID: <1462120896532.34221@netapp.com> References: <1461992897090.81293@netapp.com> <8FAB73AE-A9F6-4BE2-9912-D3B70B6E7651@netapp.com> <1462053829729.78518@netapp.com> <55CCF01C-BEAB-40C7-A0A0-7AAE37AE9A0A@netapp.com> <1462081223172.93482@netapp.com>,, In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [10.120.60.36] Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 archived-at: Sun, 01 May 2016 16:41:52 -0000 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.= =0A= =0A= So, it's really a question of just staying backward compatible (the class m= ethod) or a possibly better design (the instance method).=0A= ________________________________________=0A= From: Tutkowski, Mike =0A= Sent: Sunday, May 1, 2016 10:18 AM=0A= To: dev@cloudstack.apache.org=0A= Subject: Re: Python Question (with regards to Marvin)=0A= =0A= The question then becomes, do we want to keep the instance or the class met= hod?=0A= =0A= There exists the same problem for at least one other pair of methods.=0A= =0A= Since the class method is listed second in the file currently, it is the on= ly 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.=0A= =0A= > On May 1, 2016, at 5:43 AM, Will Stevens wrote= :=0A= >=0A= > Yep. Looking like there is a bug in that file. Thanks for testing. :)=0A= >> On May 1, 2016 1:40 AM, "Tutkowski, Mike" wr= ote:=0A= >>=0A= >> Here are my tests (run from http://ideone.com/).=0A= >>=0A= >> The short story is that having multiple methods with the same name (even= =0A= >> if one is an instance method and one is a class method) should probably = not=0A= >> be done.=0A= >>=0A= >> If you try to invoke the instance method (ex. test.run()), the last meth= od=0A= >> by that name in the source file is invoked (which could be the class=0A= >> method). If the number of parameters don't match, that's an error.=0A= >>=0A= >> If you try to invoke the class method (ex. Test.run()), the last method = by=0A= >> that name in the source file is invoked. If this is not a class method o= r=0A= >> if the number of parameters don't match, that's an error.=0A= >>=0A= >> class Test:=0A= >> @classmethod=0A= >> def run(cls):=0A= >> print "class hi"=0A= >>=0A= >> def run(self):=0A= >> print "instance hi"=0A= >>=0A= >> test =3D Test()=0A= >>=0A= >> test.run()=0A= >>=0A= >> What gets printed:=0A= >> instance hi=0A= >>=0A= >> class Test:=0A= >> def run(self):=0A= >> print "instance hi"=0A= >>=0A= >> @classmethod=0A= >> def run(cls):=0A= >> print "class hi"=0A= >>=0A= >> test =3D Test()=0A= >>=0A= >> test.run()=0A= >>=0A= >> What gets printed:=0A= >> class hi=0A= >>=0A= >> class Test:=0A= >> @classmethod=0A= >> def run(cls):=0A= >> print "class hi"=0A= >>=0A= >> def run(self):=0A= >> print "instance hi"=0A= >>=0A= >> # test =3D Test()=0A= >>=0A= >> Test.run()=0A= >>=0A= >> Runtime error=0A= >>=0A= >> class Test:=0A= >> @classmethod=0A= >> def run(cls):=0A= >> print "class hi"=0A= >>=0A= >> # test =3D Test()=0A= >>=0A= >> Test.run()=0A= >>=0A= >> What gets printed:=0A= >> class hi=0A= >>=0A= >> class Test:=0A= >> def run(self):=0A= >> print "instance hi"=0A= >>=0A= >> @classmethod=0A= >> def run(cls):=0A= >> print "class hi"=0A= >>=0A= >> # test =3D Test()=0A= >>=0A= >> Test.run()=0A= >>=0A= >> What gets printed:=0A= >> class hi=0A= >>=0A= >> class Test:=0A= >> @classmethod=0A= >> def run(cls):=0A= >> print "class hi"=0A= >>=0A= >> # test =3D Test()=0A= >>=0A= >> Test.run()=0A= >>=0A= >> What gets printed:=0A= >> class hi=0A= >> ________________________________________=0A= >> From: Tutkowski, Mike=0A= >> Sent: Saturday, April 30, 2016 6:58 PM=0A= >> To: dev@cloudstack.apache.org=0A= >> Subject: Re: Python Question (with regards to Marvin)=0A= >>=0A= >> I can play around with it later tonight. I'm not home at the moment.=0A= >>=0A= >> When I did invoke it as Test.run(), it invoked the class method (the cla= ss=0A= >> method was listed after the instance method for that test, so I wasn't= =0A= >> surprised that the class method did, in fact, get executed there).=0A= >>=0A= >> What I did not try was to list the class method first, then list the=0A= >> instance method, and then try to invoke the class method.=0A= >>=0A= >> As mentioned in my prior e-mail, when I did try to invoke the instance= =0A= >> version of run, it was only successful if the instance version was the= =0A= >> second one declared in the file. If the class method was declared second= ,=0A= >> then it was invoked even when I was trying to invoke the instance one.= =0A= >>=0A= >>>> On Apr 30, 2016, at 6:06 PM, Will Stevens = =0A= >>> wrote:=0A= >>>=0A= >>> That's strange. That means the @classmethod decorator is not working. Y= ou=0A= >>> should have gotten the instance method in both cases.=0A= >>>=0A= >>> What if you don't instantiate Test and only do the following.=0A= >>>=0A= >>> Test.run()=0A= >>>=0A= >>> In both cases.=0A= >>> On Apr 30, 2016 6:04 PM, "Tutkowski, Mike" = =0A= >>> wrote:=0A= >>>=0A= >>>> I ran this with an online Python tool and it calls the class method:= =0A= >>>>=0A= >>>> 1 class Test:=0A= >>>> 2 def run(self):=0A= >>>> 3 print 'instance hi'=0A= >>>> 4=0A= >>>> 5 @classmethod=0A= >>>> 6 def run(cls):=0A= >>>> 7 print 'class hi'=0A= >>>> 8=0A= >>>> 9 test =3D Test()=0A= >>>> 10=0A= >>>> 11 test.run()=0A= >>>>=0A= >>>> If I reverse the order of the methods, the instance method is invoked:= =0A= >>>>=0A= >>>> 1 class Test:=0A= >>>> 2 @classmethod=0A= >>>> 3 def run(cls):=0A= >>>> 4 print 'class hi'=0A= >>>> 5=0A= >>>> 6 def run(self):=0A= >>>> 7 print 'instance hi'=0A= >>>> 8=0A= >>>> 9 test =3D Test()=0A= >>>> 10=0A= >>>> 11 test.run()=0A= >>>>=0A= >>>> As I suspected, I think this means we have a problem in base.py.=0A= >>>> ________________________________________=0A= >>>> From: Will Stevens =0A= >>>> Sent: Saturday, April 30, 2016 1:46 PM=0A= >>>> To: dev@cloudstack.apache.org=0A= >>>> Subject: Re: Python Question (with regards to Marvin)=0A= >>>>=0A= >>>> I am on my phone so I have not been able to research this for you. I= =0A= >> think=0A= >>>> you are right for the most part. Instead of multiple methods, python= =0A= >> kind=0A= >>>> of fakes overloading by being to have named function arguments which c= an=0A= >>>> have default values, so you can call the method with a dynamic number = of=0A= >>>> arguments making it appear like you are overloading, but you are=0A= >> actually=0A= >>>> calling the same function.=0A= >>>>=0A= >>>> I think in this case the two methods are actually in different scopes= =0A= >> (even=0A= >>>> though they are next to each other). The decorator actually wraps the= =0A= >>>> method, so I believe in the actual runtime the to methods are in=0A= >> different=0A= >>>> scopes.=0A= >>>>=0A= >>>> I would have to look into this more to know for sure. I am taking a fe= w=0A= >>>> minute break from building garden boxes right now. :)=0A= >>>> On Apr 30, 2016 3:31 PM, "Tutkowski, Mike" = =0A= >>>> wrote:=0A= >>>>=0A= >>>>> Will - You can override a method in Python, but can you overload it?= =0A= >> http://stackoverflow.com/questions/10202938/how-do-i-use-method-overload= ing-in-python=0A= >>>>>=0A= >>>>>>> On Apr 30, 2016, at 6:23 AM, Will Stevens =0A= >>>>>> wrote:=0A= >>>>>>=0A= >>>>>> Here is a pretty good explanation.=0A= >> http://stackoverflow.com/questions/136097/what-is-the-difference-between= -staticmethod-and-classmethod-in-python=0A= >>>>>>=0A= >>>>>> I am guessing that both exist because the function is called both wi= th=0A= >>>> a=0A= >>>>>> host instance and with the class itself.=0A= >>>>>>=0A= >>>>>> Class instance example: `h.enableMaintenance(client)`=0A= >>>>>>=0A= >>>>>> Class example: `Host.enableMaintenance(client, 1)`=0A= >>>>>>=0A= >>>>>> In both cases the first parameter is implicitly `h` and `Host`=0A= >>>>>> respectively.=0A= >>>>>>=0A= >>>>>> I am not sure why we need both (because I am not familiar with how= =0A= >> this=0A= >>>>>> code is called), but method overloading is definitely valid in pytho= n.=0A= >>>>>>=0A= >>>>>> On Apr 30, 2016 1:08 AM, "Tutkowski, Mike" >>=0A= >>>>>> wrote:=0A= >>>>>>>=0A= >>>>>>> Hi everyone,=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> I received an error when trying to invoke the instance version of= =0A= >>>>>> enableMaintenance (below).=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> 'TypeError: enableMaintenance() takes exactly 3 arguments (2=0A= >>>> given)\n']=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> I looked at base.py and it has the following with regards to=0A= >>>> maintenance=0A= >>>>>> mode for hosts:=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> def enableMaintenance(self, apiclient):=0A= >>>>>>>=0A= >>>>>>> """enables maintenance mode Host"""=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> cmd =3D prepareHostForMaintenance.prepareHostForMaintenanceCmd= ()=0A= >>>>>>>=0A= >>>>>>> cmd.id =3D self.id=0A= >>>>>>>=0A= >>>>>>> return apiclient.prepareHostForMaintenance(cmd)=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> @classmethod=0A= >>>>>>>=0A= >>>>>>> def enableMaintenance(cls, apiclient, id):=0A= >>>>>>>=0A= >>>>>>> """enables maintenance mode Host"""=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> cmd =3D prepareHostForMaintenance.prepareHostForMaintenanceCmd= ()=0A= >>>>>>>=0A= >>>>>>> cmd.id =3D id=0A= >>>>>>>=0A= >>>>>>> return apiclient.prepareHostForMaintenance(cmd)=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> Now, I definitely have a lot more Java experience than Python, but = -=0A= >>>> as=0A= >>>>>> far as I know - having two methods with the same name such as this= =0A= >>>> (even=0A= >>>>> if=0A= >>>>>> one is an instance method and the other is a class method) is not=0A= >>>> really=0A= >>>>>> "permitted" in Python.=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> I mean, technically it's permitted, but the second one will overrid= e=0A= >>>> the=0A= >>>>>> first one.=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> Can any of our Python people comment on this?=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> I was thinking I'd remove the class method (assuming my knowledge= =0A= >> here=0A= >>>>>> regarding this topic is correct).=0A= >>>>>>>=0A= >>>>>>>=0A= >>>>>>> Thanks!=0A= >>>>>>>=0A= >>>>>>> Mike=0A= >>=0A=