bpo-39385: Add an assertNoLogs context manager to unittest.TestCase (GH-18067)

Co-authored-by: Rémi Lapeyre <remi.lapeyre@henki.fr>
diff --git a/Lib/unittest/_log.py b/Lib/unittest/_log.py
index 94e7e75..961c448 100644
--- a/Lib/unittest/_log.py
+++ b/Lib/unittest/_log.py
@@ -26,11 +26,11 @@
 
 
 class _AssertLogsContext(_BaseTestCaseContext):
-    """A context manager used to implement TestCase.assertLogs()."""
+    """A context manager for assertLogs() and assertNoLogs() """
 
     LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
 
-    def __init__(self, test_case, logger_name, level):
+    def __init__(self, test_case, logger_name, level, no_logs):
         _BaseTestCaseContext.__init__(self, test_case)
         self.logger_name = logger_name
         if level:
@@ -38,6 +38,7 @@
         else:
             self.level = logging.INFO
         self.msg = None
+        self.no_logs = no_logs
 
     def __enter__(self):
         if isinstance(self.logger_name, logging.Logger):
@@ -54,16 +55,31 @@
         logger.handlers = [handler]
         logger.setLevel(self.level)
         logger.propagate = False
+        if self.no_logs:
+            return
         return handler.watcher
 
     def __exit__(self, exc_type, exc_value, tb):
         self.logger.handlers = self.old_handlers
         self.logger.propagate = self.old_propagate
         self.logger.setLevel(self.old_level)
+
         if exc_type is not None:
             # let unexpected exceptions pass through
             return False
-        if len(self.watcher.records) == 0:
-            self._raiseFailure(
-                "no logs of level {} or higher triggered on {}"
-                .format(logging.getLevelName(self.level), self.logger.name))
+
+        if self.no_logs:
+            # assertNoLogs
+            if len(self.watcher.records) > 0:
+                self._raiseFailure(
+                    "Unexpected logs found: {!r}".format(
+                        self.watcher.output
+                    )
+                )
+
+        else:
+            # assertLogs
+            if len(self.watcher.records) == 0:
+                self._raiseFailure(
+                    "no logs of level {} or higher triggered on {}"
+                    .format(logging.getLevelName(self.level), self.logger.name))