On Sun, 23 Feb 2020 at 11:25, Michael Foord <fuzzyman@gmail.com> wrote:
In unittest.mock.MagicMock I solve this problem by having __new__ create a new subclass for every instantiation. Setting any magic method on the instance is promoted to the type via __setattr__. That way every instance can have unique magic methods without affecting other instances.


The other little bit of trickery is that MagicMock gets all the magic methods by default and they're all MagicMock objects. To avoid instantiating MagicMock recursively creating MagicMocks forever the magic methods are descriptors that put a new MagicMock instance onto the subclass on first access via an instance. I could probably have saved a lot of effort by overriding __getattribute__ (which can intercept magic method lookups unlike __getatttr__) instead of the descriptor solution. At the time I didn't know that. There's still a bunch of jiggery-pokery to set valid default return values on a bunch of the methods (some are type checked on the return value and some aren't *sigh*), so maybe it's unavoidable. 

I had fun getting mock to work.

Michael 
 

Michael

On Sun, 23 Feb 2020 at 04:21, Jérôme Carretero <cj-python@zougloub.eu> wrote:
Thanks Josh for your prompt reply. All clear.


Regards,

--
Jérôme

PS: Somehow I had never encountered a situation exacerbating the
subtleties of implicit invocations of special methods, and hadn't read
or integrated that section of the documentation, then when encountering
the “problem” I didn't make my way to the docs.
And now I also see that right when opening § 3.3. Special method
names ¶ 1 it's stated that “`x[i]` is roughly equivalent to
`type(x).__getitem__(x, i)`”. I'll be more careful next time!


On Sun, 23 Feb 2020 02:35:24 +0000
Josh Rosenberg <shadowranger+pythonideas@gmail.com> wrote:

> This is explained in "Special Method Lookup":
> https://docs.python.org/3/reference/datamodel.html#special-method-lookup
>
> Short version: For both correctness and performance, special methods (those
> that begin and end with double underscores) are typically looked up on the
> class, not the instance. If you want to override on a per-instance level,
> have a non-special method that __str__ invokes, that can be overridden on a
> per-instance basis.
>
> On Sun, Feb 23, 2020 at 2:30 AM Jérôme Carretero <cj-python@zougloub.eu>
> wrote:
>
> > Hello,
> >
> >
> > I just noticed that calling `str(x)` is actually doing (in CPython
> > `PyObject_Str`) `type(x).__str__(x)` rather than `x.__str__()`.
> >
> > Context: I wanted to override __str__ for certain objects in order to
> > “see them better”.
> >
> > I'm wondering why not do `x.__str__()`
> >
> >
> > Best regards,
> >
> > --
> > Jérôme
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/G3MW5GD534GNYLE4ARZGE42NHGSSNLGL/
Code of Conduct: http://python.org/psf/codeofconduct/


--
Michael Foord
Python Consultant, Contractor and Trainer
https://agileabstractions.com/


--
Michael Foord
Python Consultant, Contractor and Trainer
https://agileabstractions.com/