On Wed, 5 Aug 2009 03:06 pm Nick Daly wrote: > The problem actually lies in the contract. Generally, the PyContract > shouldn't affect the return values or in any way modify the code, which > it doesn't, as long as the function returns a list values (the way the > code had in fact originally been written). However, the contract > mentioned above is actually quite wrong for a generator.
Yes, because you are conflating the items yielded from the generator with the generator object returned from the generator function "find_files". You can't look inside the generator object without using up whichever items you look at. [...] > Correcting the above example involves doing nothing more than > simplifying the contract: > > post: > name in __return__ That can't be right, not unless PyContract is doing something I don't expect. I expect that would be equivalent of: 'fish' in <generator object> which should fail: >>> __return__ = find_files('fish') # a generator object >>> 'fish' in __return__ False >>> >>> __return__ = find_files('fish') >>> __return__ = list(__return__) >>> 'fish' in __return__ False >>> __return__ ['one fish', 'two fish', 'red fish', 'blue fish'] Of course, I may be mistaking what PyContract is doing. ----- No, you're absolutely right, I realized the error in my email moments after sending it, I was just hoping no one was paying enough attention to notice. I'm essentially asking PyContract to operate outside of the generator (it needs to check the return value of a generator, without changing its internal state), which doesn't seem to have an easy solution unless generators have some fantastic reverse_states function that I haven't heard about. I suppose one could be built, saving off the values of all local variables for later restoration, but that would still be dependent on the state of the rest of the machine and could not guarantee giving the same answer twice in a row. So, the moral of the story seems to be that PyContract's post-return value checking doesn't mix with generators at all. Sort of sad, because they're two neat flavors that would go great together but are instead technically incompatible. A decent set of unit-tests would accomplish the same thing much less destructively anyway. Nick -- http://mail.python.org/mailman/listinfo/python-list