From fb27885fcc50cfebd13865a8267e05daee7bb933 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Wed, 3 May 2017 20:41:14 -0700 Subject: [PATCH 1/2] bpo-30266: support "= None" pattern in AbstractContextManager --- Lib/contextlib.py | 5 ++--- Lib/test/test_contextlib.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/contextlib.py b/Lib/contextlib.py index c53b35e8d5adaa..962cedab490eb2 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -1,6 +1,7 @@ """Utilities for with-statement contexts. See PEP 343.""" import abc import sys +import _collections_abc from collections import deque from functools import wraps @@ -25,9 +26,7 @@ def __exit__(self, exc_type, exc_value, traceback): @classmethod def __subclasshook__(cls, C): if cls is AbstractContextManager: - 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 _collections_abc._check_methods(C, "__enter__", "__exit__") return NotImplemented diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index b1a467d952da0f..2301f759d80858 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -44,6 +44,16 @@ def __exit__(self, *args): self.assertTrue(issubclass(DefaultEnter, AbstractContextManager)) + class NoEnter(ManagerFromScratch): + __enter__ = None + + self.assertFalse(issubclass(NoEnter, AbstractContextManager)) + + class NoExit(ManagerFromScratch): + __exit__ = None + + self.assertFalse(issubclass(NoExit, AbstractContextManager)) + class ContextManagerTestCase(unittest.TestCase): From 47262826c9c64e3deaa58df359b275955028c69c Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 4 May 2017 21:20:50 -0700 Subject: [PATCH 2/2] add Misc/NEWS entry --- Misc/NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index 4e85c0fbf2abb9..56cd993b4dbbeb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -317,6 +317,10 @@ Extension Modules Library ------- +- bpo-30266: contextlib.AbstractContextManager now supports anti-registration + by setting __enter__ = None or __exit__ = None, following the pattern + introduced in bpo-25958. Patch by Jelle Zijlstra. + - bpo-30103: binascii.b2a_uu() and uu.encode() now support using ``'`'`` as zero instead of space.