
On Sat, Jul 20, 2019 at 06:03:39AM -0000, Kyle Stanley wrote:
Rather than it being on a case-by-case basis, would it be reasonable to establish a universal standard across stdlib for defining modules as public to apply to older modules as well?
No, I don't think so. That would require code churn to "fix" modules which aren't currently broken, and may never be. It also requires meeting a standard that doesn't universally apply: 1. __all__ is optional, not mandatory. 2. __all__ is a list of names to import during star imports, not a list of public names; while there is some overlap, we should not assume that the two will always match. 3. Imported modules are considered private, regardless of whether they are named with a leading underscore or not; 4. Unless they are considered public, such as os.path. 5. While I don't know of any top-level examples of this, there are cases in the std lib where single-underscore names are considered public, such as the namedtuple interface. So in principle at least, a module might include a single-underscore name in its __all__. 6. Dunder names are not private, and could appear in __all__.
There would be some overhead cost associated with ensuring that every non-public function is is proceeded by an underscore, but adding public functions to __all__ could safely be automated with something like this (https://bugs.python.org/issue29446#msg287049):
__all__ = [name for name, obj in globals().items() if not name.startswith('_') and not isinstance(obj, types.ModuleType)]
And you've just broken about a million scripts and applications that use os.path. As well as any modules which export public dunder names, for example sys.__stdout__ and friends, since your test for a private name may be overzealous. -- Steven