Serhiy's definition sounds recursive (defining __getattr__ to define the behavior of __getattr__) but Mark's suggestion makes his intention unclear since the error message is still the same. Also the word "now" is confusing (does it mean "currently, before the PEP" or "once this PEP is accepted"?)
It would be clearer to first state that Module.__getattribute__ is currently (before the PEP) essentially defined as class Module(object): def __getattribute__(self, name): try: return object.__getattribute__(self, name) except AttributeError: if hasattr(self, '__dict__'): mod_name = self.__dict__.get(name) if isinstance(mod_name, str): raise AttributeError("module '%s' has no attribute '%s'" % (mod_name, name)) raise AttributeError("module has no attribute '%s'" % name) The PEP changes the contents of the except clause to: if hasattr(self, '__dict__'): if '__getattr__' in self.__dict__: getter = self.__dict__['__getattr__'] if not callable(getter): raise TypeError("module __getattr__ must be callable") return getter(name) # Unchanged from here on mod_name = self.__dict__.get(name) if isinstance(mod_name, str): raise AttributeError("module '%s' has no attribute '%s'" % (mod_name, name)) raise AttributeError("module has no attribute '%s'" % name) (However exception chaining makes the equivalency still not perfect. And we ignore threading. But how far do we need to go when specifying "equivalent code" to what every implementation should implement natively?) On Sun, Nov 19, 2017 at 12:48 PM, Mark Shannon <m...@hotpy.org> wrote: > > > On 19/11/17 20:41, Serhiy Storchaka wrote: > >> 19.11.17 22:24, Mark Shannon пише: >> >>> Just one comment. Could the new behaviour of attribute lookup on a >>> module be spelled out more explicitly please? >>> >>> >>> I'm guessing it is now something like: >>> >>> `module.__getattribute__` is now equivalent to: >>> >>> def __getattribute__(mod, name): >>> try: >>> return object.__getattribute__(mod, name) >>> except AttributeError: >>> try: >>> getter = mod.__dict__["__getattr__"] >>> except KeyError: >>> raise AttributeError(f"module has no attribute '{name}'") >>> return getter(name) >>> >> >> I think it is better to describe in the terms of __getattr__. >> >> def ModuleType.__getattr__(mod, name): >> try: >> getter = mod.__dict__["__getattr__"] >> except KeyError: >> raise AttributeError(f"module has no attribute '{name}'") >> return getter(name) >> >> The implementation of ModuleType.__getattribute__ will be not changed (it >> is inherited from the object type). >> > > Not quite, ModuleType overrides object.__getattribute__ in order to > provide a better error message. So with your suggestion, the change would > be to *not* override object.__getattribute__ and provide the above > ModuleType.__getattr__ > > Cheers, > Mark. > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: https://mail.python.org/mailman/options/python-dev/guido% > 40python.org > -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com