TBH, I don’t think it’s really meaningful to compare the proposals like this given that they have different goals. PEP 842 seeks to address 3 concerns:
- Functions/classes/variables that aren’t supposed to be used but are still visible in the namespace
- Imports leaking into the namespace of packages that import them
- This idea that the underscore prefix convention isn’t enough and that we need something more aggressive
(Concern 2 is the only one that gains any traction for me personally, and mostly only for single file modules where the import sys as _sys workaround is quite annoying.)
843 focuses only on 2 but only for packages[1] and only handling __all__[2]. requests.urllib3 is still there and still looks like public API to anyone using completion to explore a library.
Incidentally, if you compare the contents of the numpy namespace with numpy.__all__, there’s nothing in there that would have been exported without __all__.
>>> set(dir(numpy)) - set(numpy.__all__)
{'_NoValue', '_array_api_info', '__all__', '__getattr__', '__config__', '__cached__', '__future_scalars__', '__spec__', '_specific_msg', '__builtins__', '_core', '_expired_attrs_2_0', '_utils', '__package__', '__dir__', '__doc__', '__expired_attributes__', '__loader__', '_pyinstaller_hooks_dir', '__NUMPY_SETUP__', '_type_info', '_int_extended_msg', '__file__', '_distributor_init', '__numpy_submodules__', '_msg', '__path__', '_CopyMode', '__name__', '_typing', '_globals', '_pytesttester', '_mat', '__array_api_version__', '__former_attrs__'}
So numpy is actually a perfect example of going to great lengths to define __all__ when you could just delete it and your problem is solved.
Whilst I’m not completely dismissing your arguments for still defining __all__ even when you’ve already taken advantage of the __init__.py to create a clean, curated namespace, I don’t find them nearly compelling enough to justify a language change.