Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #14987 > unrolled thread
| Started by | Fabio Zadrozny <fabiofz@gmail.com> |
|---|---|
| First post | 2011-10-25 20:59 -0200 |
| Last post | 2011-10-25 20:59 -0200 |
| Articles | 1 — 1 participant |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Strange classmethod mock behavior Fabio Zadrozny <fabiofz@gmail.com> - 2011-10-25 20:59 -0200
| From | Fabio Zadrozny <fabiofz@gmail.com> |
|---|---|
| Date | 2011-10-25 20:59 -0200 |
| Subject | Re: Strange classmethod mock behavior |
| Message-ID | <mailman.2218.1319583589.27778.python-list@python.org> |
On Tue, Oct 25, 2011 at 10:08 AM, Peter Otten <__peter__@web.de> wrote: > Fabio Zadrozny wrote: > >> I'm trying to mock a classmethod in a superclass but when restoring it >> a strange behavior happens in subclasses (tested on Python 2.5) >> >> Anyone knows why this happens? (see test case below for details) >> Is there any way to restore that original method to have the original >> behavior? >> >> import unittest >> >> class Test(unittest.TestCase): >> >> def testClassmethod(self): >> class Super(): >> @classmethod >> def GetCls(cls): >> return cls >> >> class Sub(Super): >> pass >> >> self.assertEqual(Sub.GetCls(), Sub) >> >> original = Super.GetCls >> #Mock Super.GetCls, and do tests... >> Super.GetCls = original #Restore the original classmethod >> self.assertEqual(Sub.GetCls(), Sub) #The call to the >> classmethod subclass returns the cls as Super and not Sub as expected! >> >> if __name__ == '__main__': >> unittest.main() > > [Not related to your problem] When working with descriptors it's a good idea > to use newstyle classes, i. e. have Super inherit from object. > > The Super.GetCls attribute access is roughly equivalent to > > Super.__dict___["GetCls"].__get__(classmethod_instance, None, Super) > > and returns an object that knows about its class. So when you think you are > restoring the original method you are actually setting the GetCls attribute > to something else. You can avoid the problem by accessing the attribute > explicitly: > >>>> class Super(object): > ... @classmethod > ... def m(cls): return cls > ... >>>> bad = Super.m >>>> good = Super.__dict__["m"] >>>> class Sub(Super): pass > ... >>>> Sub.m() > <class '__main__.Sub'> >>>> Super.m = bad >>>> Sub.m() > <class '__main__.Super'> >>>> Super.m = good >>>> Sub.m() > <class '__main__.Sub'> > Hi Peter, thanks for the explanation. Printing it helped me understand it even better... print(Super.__dict__['GetCls']) print(Super.GetCls) <classmethod object at 0x022AF210> <bound method type.GetCls of <class '__main__.Super'>> Cheers, Fabio
Back to top | Article view | comp.lang.python
csiph-web