[pytest-dev] monkeypatch.setattr of functions and from imports

holger krekel holger at merlinux.eu
Tue Oct 29 06:39:02 CET 2013


On Mon, Oct 28, 2013 at 21:44 +0000, Floris Bruynooghe wrote:
> On 23 October 2013 19:36, holger krekel <holger at merlinux.eu> wrote:
> > As to patching func_code: good idea, i had forgotten about assigning func_code.
> > In earlier Python2.X versions assigning to func_code didn't work but i just
> > checked that it does on py27 and py33.  So it's definitely worthwhile to
> > pursue.  In your example you could do:
> >
> >     monkeypatch.setattr('a.somefunc.func_code', (lambda: 'eh?').func_code)
> >
> > and it works (needs to use __code__ on py3).  I guess we could think about a
> >
> >     monkeypatch.setcode("a.somefunc", lambda: 'eh?')
> >
> > helper.  You could either pass in a function or a code object.
> > We could even think about allowing non-string targets:
> >
> >     monkeypatch.setcode(a.somefunc, lambda: 'eh?')
> >
> > Or would "monkeypatch.setfunc" be a better name?
> 
> Why does it have to be a new method?  Can't setattr simply see if the
> object being patched as well as the object it is being patched with
> has a .func_code or .__code__ attribute and automatically patch the
> code if so?  This would be additional to the current patching it does
> so that it's more obvious in a debugger for the current cases.  It
> would have solved the OPs problem and I can't think of any real
> downside currently.

Wouldn't it violate what you expect from a "setattr" operation?
Anyway, i played with setting __code__ the other day and there is
a bad limitation::

    def test_hello(monkeypatch):
        x = "/tmp"
        def myabs(somepath):
            return x
    >   monkeypatch.setattr("os.path.abspath.__code__", myabs.__code__)
    E   ValueError: abspath() requires a code object with 0 free vars, not 1

This means that setting __code__ with closure-using code does not work. 
This reduces the usefullness of setting code objects for practical
purposes and speaks against introducing any support at this point.
Setting non-closures might still be useful and the example above is
other compatible to py26++ so it's probably good enough.

best,
holger


More information about the Pytest-dev mailing list