On Fri, Jun 25, 2021 at 3:31 AM Steven D'Aprano firstname.lastname@example.org wrote:
Here's a quick and dirty proof of concept I knocked up in about 20 minutes, demonstrating that no deep compiler magic is needed. It's just a small change to the way `object.__getattribute__` works.
I've emulated it with my own base class, since `object` can't be monkey-patched.
The proof of concept is probably buggy and incomplete. It isn't intended to be a final, polished production-ready implementation. It's not implementation-agnostic: it requires the ability to inspect the call stack. If you're using IronPython, this may not work.
You will notice I didn't need to touch getattr to have it work, let alone hack the interpreter to make it some sort of magical construct. It all works through `__getattribute__`.
The registration system is just the easiest thing that I could throw together. There are surely better designs.
Run A.py to see it in action.
Okay, so you've hidden the magic away a bit, but you have to choose the number  for your stack inspection. That means you have to be sure that that's the correct module, in some way. If you do *anything* to disrupt the exact depth of the call stack, that breaks.
_hasattr = hasattr def hasattr(obj, attr): return _hasattr(obj, attr)
Or any of the other higher level constructs. What if there's a C-level function in there?
This is still magic. It's just that the magic has been buried slightly.