diff options
author | Ivan Levkivskyi <levkivskyi@gmail.com> | 2017-06-10 19:57:56 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2017-06-10 19:57:56 (GMT) |
commit | 29fda8db16e0edab92841277fa223f844f5a92cc (patch) | |
tree | aac6c5428f6f02488f2e9e8099b9c200496c1018 /Lib/typing.py | |
parent | ca816153445cba3baec15f7e890c71abfe495340 (diff) | |
download | cpython-29fda8db16e0edab92841277fa223f844f5a92cc.zip cpython-29fda8db16e0edab92841277fa223f844f5a92cc.tar.gz cpython-29fda8db16e0edab92841277fa223f844f5a92cc.tar.bz2 |
bpo-28556: Updates to typing module (#2076)
This PR contains two updates to typing module:
- Support ContextManager on all versions (original PR by Jelle Zijlstra).
- Add generic AsyncContextManager.
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 645bc6f..c487afc 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -10,6 +10,8 @@ try: import collections.abc as collections_abc except ImportError: import collections as collections_abc # Fallback for PY3.2. +if sys.version_info[:2] >= (3, 6): + import _collections_abc # Needed for private function _check_methods # noqa try: from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType except ImportError: @@ -37,6 +39,7 @@ __all__ = [ # for 'Generic' and ABCs below. 'ByteString', 'Container', + 'ContextManager', 'Hashable', 'ItemsView', 'Iterable', @@ -57,8 +60,8 @@ __all__ = [ # AsyncIterable, # Coroutine, # Collection, - # ContextManager, # AsyncGenerator, + # AsyncContextManager # Structural checks, a.k.a. protocols. 'Reversible', @@ -1949,7 +1952,61 @@ class ValuesView(MappingView[VT_co], extra=collections_abc.ValuesView): if hasattr(contextlib, 'AbstractContextManager'): class ContextManager(Generic[T_co], extra=contextlib.AbstractContextManager): __slots__ = () - __all__.append('ContextManager') +else: + class ContextManager(Generic[T_co]): + __slots__ = () + + def __enter__(self): + return self + + @abc.abstractmethod + def __exit__(self, exc_type, exc_value, traceback): + return None + + @classmethod + def __subclasshook__(cls, C): + if cls is ContextManager: + # In Python 3.6+, it is possible to set a method to None to + # explicitly indicate that the class does not implement an ABC + # (https://bugs.python.org/issue25958), but we do not support + # that pattern here because this fallback class is only used + # in Python 3.5 and earlier. + if (any("__enter__" in B.__dict__ for B in C.__mro__) and + any("__exit__" in B.__dict__ for B in C.__mro__)): + return True + return NotImplemented + + +if hasattr(contextlib, 'AbstractAsyncContextManager'): + class AsyncContextManager(Generic[T_co], + extra=contextlib.AbstractAsyncContextManager): + __slots__ = () + + __all__.append('AsyncContextManager') +elif sys.version_info[:2] >= (3, 5): + exec(""" +class AsyncContextManager(Generic[T_co]): + __slots__ = () + + async def __aenter__(self): + return self + + @abc.abstractmethod + async def __aexit__(self, exc_type, exc_value, traceback): + return None + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncContextManager: + if sys.version_info[:2] >= (3, 6): + return _collections_abc._check_methods(C, "__aenter__", "__aexit__") + if (any("__aenter__" in B.__dict__ for B in C.__mro__) and + any("__aexit__" in B.__dict__ for B in C.__mro__)): + return True + return NotImplemented + +__all__.append('AsyncContextManager') +""") class Dict(dict, MutableMapping[KT, VT], extra=dict): |