views:

76

answers:

3

Hi,

I have a class Foo with a method isValid. Then I have a method bar() that receives a Foo object and whose behavior depends on whether it is valid or not.

For testing this, I wanted to pass some object to bar whose isValid method returns always False. For other reasons, I cannot create an object of Foo at the time of testing, so I needed an object to fake it. What I first thought of was creating the most general object and adding the attribute isValid to it, for using it as a Foo. But that didn't quite work:

>>> foo = object()
>>> foo.isValid = lambda : False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'isValid'

I found out object doesn't have a __dict__, so you cannot add attributes to it. At this point, the workaround I am using is creating a type on the fly for this purpose and then creating an object of that type:

>>> tmptype = type('tmptype', (), {'isValid' : lambda self : False})
>>> x = tmptype()
>>> x.isValid()
False

But this seems too long a shot. There must be some readily available general type that I could use for this purpose, but which?

+4  A: 

you have the right idea but you can make it more general. Either

 tmptype = type('tmptype', (object,) {})

or

 class tmptype(object):
     pass

Then you can just do

foo = tmptype()
foo.is_valid = lambda: False

like you wanted to do with object. This way, you can use the same class for all of your dynamic, monky-patching needs.

aaronasterling
Well, that is basically the same thing spread across more lines and with a new style class instead. But my question still persists: isn't there some general readily available type to achieve the same purpose? Something like object with a __dict__? Do I really need to create a type just for this?
ricab
@ricab: Here's a rejection of the idea I just pulled off google. You may be able to find others. http://mail.python.org/pipermail/python-bugs-list/2007-January/036866.html
aaronasterling
@aaronasterling: Oh, ok, so there isn't such a type. I though I was probably just missing it... Thanks
ricab
+1  A: 

why do you have to have to make it complex? i think the most simple way (and the 'standard' way) is to do

class FakeFoo(object):
    def is_valid():
        return False

besides, the use of lambda is not good in this context... take a look at this: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html is by the BDFL

and so on...

Ant
Because I don't want to distract the reader with additional classes whose uses might have him boggled and for which he might have to look for. Also, because this way the definition of the type is at the only place its only object is created, for a single purpose you can find right away. The definition is where it is used, which allows the test to be self-contained. When you see the object, you see the type definition, and when you see the type definition, you know its only purpose. The purpose of both the object and the type are clear without having to look elsewhere.
ricab
By the way, I read the article and I don't understand how does it follow that the use of lambda is not good in the context...
ricab
i know it's for a single purpose and so on... but it's not the right way to do that, in my opinion... i can write try: a.next() except StopIterationError: pass intead of for x in a: #pass but it's not the correct way...i know in some case you can use it, but why should you do that? in my opinion, i say...the article was about the use of lambda, and it's written that lambda is not supposed to be used in place of a normal 'def', but only when python requires an expression and not a statement...so, you can do that, but i don't thin k it's the right approach at the problem...
Ant
+1  A: 

Just so that the right answer is stated and people don't have to read all the comments: There is no such type. It has been proposed, discussed, and the idea has been rejected. Here is the link that aaronasterling posted on a comment, where more can be read: http://mail.python.org/pipermail/python-bugs-list/2007-January/036866.html

ricab