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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/GINVBO2BIJNPSTT65DQ37YQF2PFZQYST/
Code of Conduct: http://python.org/psf/codeofconduct/