[Python-ideas] __getattr__ bouncer for modules
Random832
random832 at fastmail.com
Sun Apr 17 00:06:30 EDT 2016
On Sat, Apr 16, 2016, at 23:42, Chris Angelico wrote:
> It's not as clean as actually supporting @property, but it could be
> done without the "bootstrap problem" of trying to have a module
> contain the class that it's to be an instance of. All you have to do
> is define __getattr__ as a regular top-level function, and it'll get
> called. You can then dispatch to property functions if you wish (eg
> """return globals()['_property_'+name]()"""), or just put all the code
> straight into __getattr__.
Or you could have ModuleType.__getattr(ibute?)__ search through some
object other than the module itself for descriptors.
from types import ModuleType, SimpleNamespace
import sys
# __magic__ could simply be a class, but just to prove it doesn't have
to be:
@property
def foo(self):
return eval(input("get foo?"))
@foo.setter
def foo(self, value):
print("set foo=" + repr(value))
def __call__(self, v1, v2):
print("modcall" + repr((v1, v2)))
__magic__ = SimpleNamespace()
for name in 'foo __call__'.split():
setattr(__magic__, name, globals()[name])
del globals()[name]
class MagicModule(ModuleType):
def __getattr__(self, name):
descriptor = getattr(self.__magic__, name)
return descriptor.__get__(self, None)
def __setattr__(self, name, value):
try:
descriptor = getattr(self.__magic__, name)
except AttributeError:
return super().__setattr__(name, value)
return descriptor.__set__(self, value)
def __call__(self, *args, **kwargs):
# Because why not?
try:
call = self.__magic__.__call__
except AttributeError:
raise TypeError("Could not access " + self.__name__ +
"__magic__.__call__ method.")
return call(self, *args, **kwargs)
sys.modules[__name__].__class__ = MagicModule
More information about the Python-ideas
mailing list