[Python-ideas] __getattr__ bouncer for modules

Nathaniel Smith njs at pobox.com
Sat Apr 16 23:40:14 EDT 2016


On Sat, Apr 16, 2016 at 7:50 PM, Chris Angelico <rosuav at gmail.com> wrote:
> Every now and then there's been talk of making it easier to subclass
> modules, and the most common use case that I can remember hearing
> about is descriptor protocol requiring code on the type. (For
> instance, you can't change a module-level constant into a property
> without moving away from the default ModuleType.)
>
> How bad would it be for the default ModuleType to have a __getattr__
> function which defers to the instance? Something like this:
>
> def __getattr__(self, name):
>     if '__getattr__' in self.__dict__:
>         return self.__dict__['__getattr__'](name)
>     raise AttributeError
>
> The biggest downside I'm seeing is that module attributes double as
> global names, which might mean this would get checked for every global
> name that ends up being resolved from the builtins (which is going to
> be a LOT). But I'm not sure if that's even true.

It's not true :-). Code executing inside the module has 'globals() is
mod.__dict__', so lookups go directly to mod.__dict__ and skip
mod.__getattr__.

However, starting in 3.5 cpython allows __class__ assignment on
modules, so you can implement custom __getattr__ on a module with:

  class ModuleWithMyGetattr(types.ModuleType):
      def __getattr__(self, name):
          # .. whatever you want ...

  sys.modules[__name__].__class__ = ModuleWithMyGetattr

The advantage of doing it this way is that you can also implement
other things like __dir__ (so tab completion on your new attributes
will work).

This package backports the functionality to earlier versions of CPython:

  https://pypi.python.org/pypi/metamodule
  https://github.com/njsmith/metamodule/

Basically just replace the explicit __class__ assignment with

  import metamodule
  metamodule.install(__name__, ModuleWithMyGetattr)

(See the links above for more details and a worked example.)

-n

-- 
Nathaniel J. Smith -- https://vorpus.org


More information about the Python-ideas mailing list