summaryrefslogtreecommitdiffstats
path: root/Lib/typing.py
diff options
context:
space:
mode:
authorMariatta <Mariatta@users.noreply.github.com>2017-06-10 21:41:00 (GMT)
committerGitHub <noreply@github.com>2017-06-10 21:41:00 (GMT)
commit8d15b19be667e30f8d36aefb680859bdf23866cf (patch)
tree6f27d69006fccd5f60922906716cdb72c96d409c /Lib/typing.py
parent964c261dc9a6a901f50d5596d88248bfc4251a55 (diff)
downloadcpython-8d15b19be667e30f8d36aefb680859bdf23866cf.zip
cpython-8d15b19be667e30f8d36aefb680859bdf23866cf.tar.gz
cpython-8d15b19be667e30f8d36aefb680859bdf23866cf.tar.bz2
bpo-28556: Updates to typing module (GH-2076) (GH-2087)
This PR contains two updates to typing module: - Support ContextManager on all versions (original PR by Jelle Zijlstra). - Add generic AsyncContextManager.. (cherry picked from commit 29fda8db16e0edab92841277fa223f844f5a92cc)
Diffstat (limited to 'Lib/typing.py')
-rw-r--r--Lib/typing.py61
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):