Skip to content

Introduce MetaPathFinder.discover and PathEntryFinder.discover #139899

@FFY00

Description

@FFY00

Proposal:

In certain scenarios, such as implementing error suggestions for ModuleNotFoundError, it would be helpful to have the ability to ask the finder to search for possible specs.

I propose adding a new optional discover method to MetaPathFinder and PathEntryFinder, as follows:

   .. method:: discover(parent=None)

      An optional method which searches for possible specs with given *parent*.
      If *parent* is *None*, :meth:`MetaPathFinder.discover` will search for
      top-level modules.

      Returns an iterable of possible specs.
Python 3.15.0a0 free-threading build (heads/main:744ec1d6c39, Oct 10 2025, 06:22:11) [GCC 15.2.1 20250813] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> path_finder = sys.meta_path[-1]
>>> import sysconfig
>>> for spec in path_finder.discover(sysconfig):
...     print(spec)
...
ModuleSpec(name='sysconfig.__init__', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000922c20>, origin='/home/anubis/git/cpython/Lib/sysconfig/__init__.py')
ModuleSpec(name='sysconfig.__main__', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000922ca0>, origin='/home/anubis/git/cpython/Lib/sysconfig/__main__.py')
>>> import urllib
>>> for spec in path_finder.discover(urllib):
...     print(spec)
...
ModuleSpec(name='urllib.robotparser', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000922220>, origin='/home/anubis/git/cpython/Lib/urllib/robotparser.py')
ModuleSpec(name='urllib.response', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000920d20>, origin='/home/anubis/git/cpython/Lib/urllib/response.py')
ModuleSpec(name='urllib.__init__', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000921ba0>, origin='/home/anubis/git/cpython/Lib/urllib/__init__.py')
ModuleSpec(name='urllib.request', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000920520>, origin='/home/anubis/git/cpython/Lib/urllib/request.py')
ModuleSpec(name='urllib.parse', loader=<_frozen_importlib_external.SourceFileLoader object at 0x20000921520>, origin='/home/anubis/git/cpython/Lib/urllib/parse.py')
ModuleSpec(name='urllib.error', loader=<_frozen_importlib_external.SourceFileLoader object at 0x200009214a0>, origin='/home/anubis/git/cpython/Lib/urllib/error.py')

Possibly, we could also add a helper function that searches sys.meta_path, similarly to importlib.util.find_spec. Although I don't think it is strictly necessary.

def discover(parent=None):
    for finder in sys.meta_path:
        try:
            discover = getattr(finder, 'discover')
        except AttributeError:
            continue
        yield from discover(parent)

This allows us to implement suggestions in traceback using the import system abstractions — see https://github.com/FFY00/cpython/tree/ModuleNotFoundError-suggestions.

Python 3.15.0a0 free-threading build (heads/main:744ec1d6c39, Oct 10 2025, 06:22:11) [GCC 15.2.1 20250813] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import asd
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    import asd
ModuleNotFoundError: No module named 'asd'. Did you mean: 'ast'?
>>> import importlib.utill
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    import importlib.utill
ModuleNotFoundError: No module named 'importlib.utill'. Did you mean: 'importlib.util'?

Has this already been discussed elsewhere?

No response given

Links to previous discussion of this feature:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-importlibtype-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions