[py-dev] Advanced monkeypatching?

Floris Bruynooghe flub at devork.be
Mon Dec 20 14:47:59 CET 2010

On 20 December 2010 09:56, Virgil Dupras <hsoft at hardcoded.net> wrote:
> On 2010-12-20, at 10:41 AM, Ronny Pfannschmidt wrote:
>> On Mon, 2010-12-20 at 09:22 +0100, Virgil Dupras wrote:
>>> On 2010-12-19, at 3:38 PM, Floris Bruynooghe wrote:
>>>> Looking at the patch_osstat() it seems to me that it just fakes
>>>> os.stat() for one specific path but uses the original in place
>>>> otherwise.  This sounds like it could be just a specialised object
>>>> used to patch with.  I can imagine the monkeypatch plugin to provide a
>>>> funcarg which provides this functionality, e.g.:
>>>> def test_foo(monkeypatch, monkey_osstat):
>>>>   monkeypatch.setattr(monkey_ossstat('/tmp/some_file'))
>>>>   ...
>>> This would kind of work, but it would become complicated to patch os.stat() for two or more files, wouldn't it?
>> there could be a monkey_stat object that controlls the set of
>> files/subtrees under control
> Yes, of course, but keeping the proposed API would make it unintuitive for multiple files. Example:
> monkeypatch.setattr(os, 'stat', monkey_osstat('some_file'))
> monkeypatch.setattr(os, 'stat', monkey_osstat('some_other_file'))
> We're not sure what happens there, as os.stat is patched twice. Are we overwriting our old monkeypatch, or is there some magic caching inside monkey_osstat() making it work for both files? That's the kind of question the developer will wonder about.

I was thinking of something slightly different when I said this:

def test_foo(monkeypatch, monkey_osstat):
    stat = monkey_ossstat('file1', 'file2')
    monkeypatch.setattr(os, 'stat', stat)
    stat.add_file('file4', st_size=123)

That makes it very clear what happens (at least to me).

But as Ronny said it's probably best to try out the various approaches
in an external plugin to get past the bikeshedding.  If that results
in a stable api which is getting used it could be merged with the
core.  This is what is happening to the capturelog plugin too I think.

As for the patch_time() I've never needed it but I understand now why
you want it.  Doing this via a funcarg which you then use in one of
the normal monkeypatch methods will probably be very cumbersome so a
funcarg that does the patching directly is probably the way to go
(which could eventually become something like
"monkeypatch.patch_time(...)" I guess)


PS: I speak with no authority to the development of py.test, I'm just
another user.

Debian GNU/Linux -- The Power of Freedom
www.debian.org | www.gnu.org | www.kernel.org

More information about the Pytest-dev mailing list