__all__ attribute: bug and proposal

Chris Angelico rosuav at gmail.com
Mon Jun 27 18:41:16 EDT 2016


On Tue, Jun 28, 2016 at 8:29 AM, Pavel S <pavel at schon.cz> wrote:
>> but what about integers or strings?
>
> Can you provide example?

Sure. I'll spare you the wall of text that is os.__all__, but here's the types:

>>> import os
>>> {type(getattr(os, x)).__name__ for x in os.__all__}
{'bool', 'module', 'function', 'str', '_Environ', 'NoneType', 'type',
'int', 'dict', 'builtin_function_or_method'}
>>> collections.Counter(hasattr(getattr(os, x), "__name__") for x in os.__all__)
Counter({True: 184, False: 122})

So, roughly 60% of them even have canonical names. And you don't
always want the canonical name, anyway:

>>> os.path.__name__
'posixpath'

(Your results may vary. Specifically. os.path.__name__ will be
'ntpath' if you're on Windows.)

> No matter if __all__ uses names or objects, I think it should be validated not only when importing '*', but always.
>
> Frankly, do you always unit-test if __all__ works?

Frankly, I don't unit test enough. But if you have __all__, it
shouldn't be too hard, nor too unobvious, to test it.

>>> def test_all():
...   exec("from os import *")
...
>>> test_all()
>>> os.__all__.append("asdf")
>>> test_all()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in test_all
  File "<string>", line 1, in <module>
AttributeError: module 'os' has no attribute 'asdf'

ChrisA



More information about the Python-list mailing list