You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Convert importlib.abc to use typing.Protocol #82963
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2019-11-12.22:47:40.242>labels= ['type-feature', 'library', '3.9']
title='Convert importlib.abc to use typing.Protocol'updated_at=<Date2021-10-20.21:07:21.258>user='https://github.com/brettcannon'
Now that typing.Protocol exists we should convert the ABCs in importlib over to protocols as the import system functions off of structural typing and not nominal typing.
Protocols are a better conceptual fit for these classes, but wouldn't this change break backwards compatibility? For example, protocols don't support .register().
Probably, which is why I figured the protocols would be separate since the ABCs also have default implementations that the protocols wouldn't have (I just forgot to update the issue with my latest thinking 😅). I had not decided if they should be in a separate module or just stick them in importlib.abc.
That said however, most type-checkers don't support .register() well (or at all).
It would just be for the legacy ABC support. My expectation is the current ABCs will inherit from the protocols, but that most code will type to the protocols themselves and the type checkers will rely on that. But I would still have to either leave the abstract methods that are already there on the ABCs or use @abc.abstractmethod on the protocol classes themselves. Otherwise the protocols might as well be kept separate, in which case it's a question of where to put them in the importlib namespace.
Since I have not written it down, the protocols/types will be for:
So, for the protocols, do we keep the ABC names? It would be a bit weird to have two different types with the same name, but coming up with new names for the protocols seems silly.
Here are the ABC types that would need a protocol:
MetaPathFinder
PathEntryFinder
Loader
ResourceLoader
InspectLoader
ExecutionLoader
FileLoader
SourceLoader
Here are the new protocols we would need for the rest of the import machinery:
Importer (MetaPathFinder + Loader)
PathHook (Callable[[str], Finder])
That said, ResourceLoader is currently deprecated in favor of TraversableResources. Should we be creating a new protocol for ResourceLoader? If we don't, its subtypes probably also need to be omitted.
ResourceLoader and its subtypes implement a couple APIs that overlap with the new abstractions:
ResourceLoader.get_data -> Traversable
InspectLoader.get_source -> Traversable
InspectLoader.is_package -> Traversable.is_dir
ExecutionLoader.get_filename -> Traversable
SourceLoader.set_data -> Traversable
They could be replaced with a single loader protocol implementing:
InspectLoader.get_code
TraversableResources.files
source_to_code (is static, could be provided standalone)
And extending Traversable with the following APIs:
With the introduction of Traversable, most of the old APIs became redundant.
If we are introducing protocols, I am not sure if it makes sense to keep the old PEP 302 APIs.
I think protocols like FinderLike and LoaderLike makes sense. There can be a type for path hooks if we want. So I agree on new names and I'm personally fond of the "*Like" style of naming (hence os.PathLike 😁).
As for all the PEP 302 protocols, I say skip them.
Activity
brettcannon commentedon Nov 12, 2019
Now that typing.Protocol exists we should convert the ABCs in importlib over to protocols as the import system functions off of structural typing and not nominal typing.
JelleZijlstra commentedon Apr 30, 2022
Protocols are a better conceptual fit for these classes, but wouldn't this change break backwards compatibility? For example, protocols don't support
.register().brettcannon commentedon May 1, 2022
Probably, which is why I figured the protocols would be separate since the ABCs also have default implementations that the protocols wouldn't have (I just forgot to update the issue with my latest thinking 😅). I had not decided if they should be in a separate module or just stick them in
importlib.abc.brettcannon commentedon Jun 6, 2025
Doesn't using
ABCMetagetProtocolsubclasses access toregister()?cpython/Lib/typing.py
Line 2043 in f00512d
cpython/Lib/typing.py
Line 1926 in f00512d
ilevkivskyi commentedon Jun 12, 2025
Yes, IIRC protocols a supposed to be "drop in" replacement for ABCs, in particular
.register()support is tested herecpython/Lib/test/test_typing.py
Line 3765 in f00512d
.register()well (or at all).brettcannon commentedon Jun 12, 2025
It would just be for the legacy ABC support. My expectation is the current ABCs will inherit from the protocols, but that most code will type to the protocols themselves and the type checkers will rely on that. But I would still have to either leave the abstract methods that are already there on the ABCs or use
@abc.abstractmethodon the protocol classes themselves. Otherwise the protocols might as well be kept separate, in which case it's a question of where to put them in the importlib namespace.Since I have not written it down, the protocols/types will be for:
sys.meta_pathfinderssys.pathfinderssys.path_hookcallablesFFY00 commentedon Feb 25, 2026
So, for the protocols, do we keep the ABC names? It would be a bit weird to have two different types with the same name, but coming up with new names for the protocols seems silly.
Here are the ABC types that would need a protocol:
MetaPathFinderPathEntryFinderLoaderResourceLoaderInspectLoaderExecutionLoaderFileLoaderSourceLoaderHere are the new protocols we would need for the rest of the import machinery:
Importer(MetaPathFinder+Loader)PathHook(Callable[[str], Finder])That said,
ResourceLoaderis currently deprecated in favor ofTraversableResources. Should we be creating a new protocol forResourceLoader? If we don't, its subtypes probably also need to be omitted.ResourceLoaderand its subtypes implement a couple APIs that overlap with the new abstractions:ResourceLoader.get_data->TraversableInspectLoader.get_source->TraversableInspectLoader.is_package->Traversable.is_dirExecutionLoader.get_filename->TraversableSourceLoader.set_data->TraversableThey could be replaced with a single loader protocol implementing:
InspectLoader.get_codeTraversableResources.filessource_to_code(is static, could be provided standalone)And extending
Traversablewith the following APIs:SourceLoader.path_statsI guess this issue converges towards GH-89710.
With the introduction of
Traversable, most of the old APIs became redundant.If we are introducing protocols, I am not sure if it makes sense to keep the old PEP 302 APIs.
brettcannon commentedon Feb 25, 2026
I think protocols like
FinderLikeandLoaderLikemakes sense. There can be atypefor path hooks if we want. So I agree on new names and I'm personally fond of the "*Like" style of naming (henceos.PathLike😁).As for all the PEP 302 protocols, I say skip them.