bpo-30266: support "= None" pattern in AbstractContextManager (#1448) · python/cpython@57161aa (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
1 1 """Utilities for with-statement contexts. See PEP 343."""
2 2 import abc
3 3 import sys
4 +import _collections_abc
4 5 from collections import deque
5 6 from functools import wraps
6 7
@@ -25,9 +26,7 @@ def __exit__(self, exc_type, exc_value, traceback):
25 26 @classmethod
26 27 def __subclasshook__(cls, C):
27 28 if cls is AbstractContextManager:
28 -if (any("__enter__" in B.__dict__ for B in C.__mro__) and
29 -any("__exit__" in B.__dict__ for B in C.__mro__)):
30 -return True
29 +return _collections_abc._check_methods(C, "__enter__", "__exit__")
31 30 return NotImplemented
32 31
33 32
Original file line number Diff line number Diff line change
@@ -44,6 +44,16 @@ def __exit__(self, *args):
44 44
45 45 self.assertTrue(issubclass(DefaultEnter, AbstractContextManager))
46 46
47 +class NoEnter(ManagerFromScratch):
48 +__enter__ = None
49 +
50 +self.assertFalse(issubclass(NoEnter, AbstractContextManager))
51 +
52 +class NoExit(ManagerFromScratch):
53 +__exit__ = None
54 +
55 +self.assertFalse(issubclass(NoExit, AbstractContextManager))
56 +
47 57
48 58 class ContextManagerTestCase(unittest.TestCase):
49 59
Original file line number Diff line number Diff line change
@@ -410,6 +410,10 @@ Library
410 410 - bpo-30048: Fixed ``Task.cancel()`` can be ignored when the task is
411 411 running coroutine and the coroutine returned without any more ``await``.
412 412
413 +- bpo-30266: contextlib.AbstractContextManager now supports anti-registration
414 + by setting __enter__ = None or __exit__ = None, following the pattern
415 + introduced in bpo-25958. Patch by Jelle Zijlstra.
416 +
413 417 - bpo-30340: Enhanced regular expressions optimization. This increased
414 418 the performance of matching some patterns up to 25 times.
415 419