qin / pymox

Automatically exported from code.google.com/p/pymox
Apache License 2.0
0 stars 0 forks source link

Stubs are not unset properly for classmethods #5

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Stub out a classmethod (method) of a base class (Foo) with one child (Bar)
    Note that Bar.method.im_self == Bar at this point
2. Execute stub
3. Unset stubs
4. Check Bar.method.im_self.  Note that it is now equivalent to Foo

  See attached test case for complete example

What is the expected output? What do you see instead?
  Bar.method.im_self should revert to it's original value (e.g. Bar, not Foo)

What version of the product are you using? On what operating system?
mox 0.5, OS X

Original issue reported on code.google.com by agora...@gmail.com on 5 Mar 2009 at 8:11

Attachments:

GoogleCodeExporter commented 9 years ago
The basic problem is demonstrated by the snippet below.  Obviously the bug is a
result of Python behavior and not mox itself.  Anyone have ideas for a 
workaround?

class Foo(object):
  @classmethod
  def b(self):
    pass

class Bar(Foo):
  pass

print Foo.b.im_self
print Bar.b.im_self

Foo.b = Foo.b

print Foo.b.im_self
print Bar.b.im_self

Original comment by agora...@gmail.com on 5 Mar 2009 at 9:35

GoogleCodeExporter commented 9 years ago
Attached is a patch that solves the problem.  For those interested in an 
explanation...

In the simple example above Foo.b needs to be reassigned to itself as a 
classmethod.
Otherwise it gets rebound to Foo normally.  That was very confusing to me but 
the
demonstration below cleared it up for me.

>>> print Foo.__dict__
{... 'b': <classmethod object at 0x6b850> ...}
>>> Foo.b = Foo.b
>>> print Foo.__dict__
{... 'b': <bound method type.b of <class '__main__.Foo'>> ...}

The proper behavior is actually already implemented for staticmethods in
mox/stubout.py but not for classmethods.  In our simple example the following 
solves
the problem.

Foo.b = classmethod(Foo.b)

The attached diff does just that for stubbing out classmethods.

Original comment by agora...@gmail.com on 6 Mar 2009 at 1:11

Attachments:

GoogleCodeExporter commented 9 years ago
Sadly, this isn't the whole solution...

>>> Foo.b = classmethod(Foo.b)
>>> Foo.b()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: b() takes exactly 1 argument (2 given)

Python passes Foo to b twice...  Will update if I can find a proper solution.  
My
guess is this is why only the staticmethod fix is in the core code.

Original comment by agora...@gmail.com on 6 Mar 2009 at 1:43

GoogleCodeExporter commented 9 years ago
Thought that was going to take longer.

Foo.b = classmethod(Foo.b.im_func)

Revised diff attached.

Original comment by agora...@gmail.com on 6 Mar 2009 at 1:54

Attachments:

GoogleCodeExporter commented 9 years ago
David, can you handle this patch?  

Sorry for the huge delay!  I'm swamped with work and I am talking a month long
vacation soon, so I'm extra swamped getting everything in order.

Original comment by smidd...@gmail.com on 18 Mar 2009 at 7:08

GoogleCodeExporter commented 9 years ago
I just submitted your patch.

Original comment by smidd...@gmail.com on 20 Mar 2009 at 5:04