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. -- Steve
# Extension method helpers and proof of concept. import inspect MODULE_REGISTRY = set() METHOD_REGISTRY = {} def get_execution_scope(): frm = inspect.stack()[2] return inspect.getmodule(frm[0]) def extends(cls): def inner(func): METHOD_REGISTRY.setdefault(cls, set()).add(func) return func return inner def using(): MODULE_REGISTRY.add(get_execution_scope()) class MyObject: # Base class that supports extension methods. def __getattribute__(self, name): try: return super().__getattribute__(name) except AttributeError: mod = get_execution_scope() if mod in MODULE_REGISTRY: xmethods = METHOD_REGISTRY.get(type(self), set()) for func in xmethods: if func.__name__ == name: return func.__get__(self) raise class Demo(MyObject): pass @extends(Demo) def xmethod(self): return "called extension method"
from extmethods import Demo instance = Demo() print('(Module A) has xmethod?', hasattr(instance, 'xmethod')) import B B.main() print('(Module A) has xmethod?', hasattr(instance, 'xmethod'))
from extmethods import using, Demo using() def main(): obj = Demo() print('(Module B) has xmethod?', hasattr(obj, 'xmethod')) print(getattr(obj, 'xmethod')())
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@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/GINVBO2BIJNPSTT65DQ37YQF2PFZQYST/ Code of Conduct: http://python.org/psf/codeofconduct/