Initially this feels like it's "by design". But there's a few alternatives we should consider:
>>> lazy from json import noway
>>> import json
>>> dir(json)
['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'noway', 'scanner']
>>> json.noway
Traceback (most recent call last):
File "<frozen importlib._bootstrap>", line 1319, in _find_and_load_unlocked
ImportError: deferred import of 'json.noway' raised an exception during resolution
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<python-input-3>", line 1, in <module>
json.noway
ImportError: cannot import name 'noway' from 'json' (/home/dinoviehland/cpython_upstream/Lib/json/__init__.py)
>>> dir(json)
['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__doc__', '__file__', '__getattr__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'noway', 'scanner']
>>>```
### CPython versions tested on:
3.15
### Operating systems tested on:
Linux
<!-- gh-linked-prs -->
### Linked PRs
* gh-150054
* gh-150055
<!-- /gh-linked-prs -->
Bug description:
@pablogsal brought this up at the sprints today. When doing "from .. import .." we track the "from" values to publish when on the module when it finally gets imported. We have no way to distinguish whether the values actually exist, if they're values within the package we're importing from, or if they're subpackages. When the module is imported we publish these values as
LazyImportObjects on the module. Because we don't know if they exist or if they're subpackages they all get published as long as they don't already exist in the module potentially leaving some cruft around.Initially this feels like it's "by design". But there's a few alternatives we should consider:
LazyImportObjectfrom the module if the value is attempted to be resolved but doesn't exist_Py_module_getattro_implto return these values. This is maybe more in the spirit of the changes we've made to push things into the module object in general. We'd publish nothing into the module but it would magically become available if we resolve it and then presumably we'd publish it into the module.