diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index ee498e56..9d763511 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -2985,11 +2985,13 @@ def test_all_names_in___all__(self): exclude = { 'GenericMeta', 'KT', + 'KT_co', 'PEP_560', 'T', 'T_co', 'T_contra', 'VT', + 'VT_co', } actual_names = { name for name in dir(typing_extensions) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 31d3564e..48f98680 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -42,6 +42,7 @@ 'TypedDict', # Structural checks, a.k.a. protocols. + 'MappingAuxiliary', 'SupportsIndex', # One-off things. @@ -145,7 +146,9 @@ def _collect_type_vars(types, typevar_types=None): # (These are not for export.) T = typing.TypeVar('T') # Any type. KT = typing.TypeVar('KT') # Key type. +KT_co = typing.TypeVar('KT', covariant=True) # Covariant key type. VT = typing.TypeVar('VT') # Value type. +VT_co = typing.TypeVar('VT', covariant=True) # Value type. T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers. T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant. @@ -603,6 +606,27 @@ def runtime_checkable(cls): runtime = runtime_checkable +# Not yet ported to typing, but who knows +if hasattr(typing, 'MappingAuxiliary'): + MappingAuxiliary = typing.MappingAuxiliary +else: + @runtime_checkable + class MappingAuxiliary(typing.Collection[KT_co], Protocol[KT_co, VT_co]): + """Represents the covariant sub-protocol of the Mapping type. + + This is useful for annotating function parameters where you really want a + Mapping, but only interact with it covariantly with regards to keys. + """ + def items(self) -> typing.ItemsView[KT_co, VT_co]: + ... + + def keys(self) -> typing.KeysView[KT_co]: + ... + + def values(self) -> typing.ValuesView[VT_co]: + ... + + # 3.8+ if hasattr(typing, 'SupportsIndex'): SupportsIndex = typing.SupportsIndex