From b796178f9b802dff1724164b7d08e16d5ce5f660 Mon Sep 17 00:00:00 2001 From: Harald Husum Date: Fri, 3 Jun 2022 23:25:15 +0200 Subject: [PATCH 1/4] Add covariant mapping type --- src/typing_extensions.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 31d3564e..d5acb773 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,19 @@ def runtime_checkable(cls): runtime = runtime_checkable +# Not yet ported to typing, but who knows +if hasattr(typing, 'MappingAuxiliary'): + MappingAuxiliary = typing.MappingAuxiliary +else: + class MappingAuxiliary(typing.Collection[KT_co], Protocol[KT_co, VT_co]): + """Represents the covariant sub-protocol of the Mapping type. + """ + def items(self) -> ItemsView[KT_co, VT_co]: ... + def keys(self) -> KeysView[KT_co]: ... + def values(self) -> ValuesView[VT_co]: ... + def __contains__(self, __o: object) -> bool: ... + + # 3.8+ if hasattr(typing, 'SupportsIndex'): SupportsIndex = typing.SupportsIndex From cb54adc28f7aecdab0f13757956adf9e23a79d44 Mon Sep 17 00:00:00 2001 From: Harald Husum Date: Sat, 4 Jun 2022 11:17:15 +0200 Subject: [PATCH 2/4] Simplifcation and improved docs --- src/typing_extensions.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index d5acb773..eef091ee 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -610,13 +610,16 @@ def runtime_checkable(cls): 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) -> ItemsView[KT_co, VT_co]: ... - def keys(self) -> KeysView[KT_co]: ... - def values(self) -> ValuesView[VT_co]: ... - def __contains__(self, __o: object) -> bool: ... + 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+ From 1aa540f6ec9d6ca6ea37e6343bbb21fd7f8d889f Mon Sep 17 00:00:00 2001 From: Harald Husum Date: Sat, 4 Jun 2022 14:02:11 +0200 Subject: [PATCH 3/4] Fix test --- src/test_typing_extensions.py | 2 ++ 1 file changed, 2 insertions(+) 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) From b3b8317830ae71e0be6bfef390c4f09a883fc5e5 Mon Sep 17 00:00:00 2001 From: Harald Husum Date: Sat, 4 Jun 2022 20:05:11 +0200 Subject: [PATCH 4/4] Linting --- src/typing_extensions.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index eef091ee..48f98680 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -613,13 +613,18 @@ def runtime_checkable(cls): @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]: ... + 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+