Skip to content

Commit 2543f50

Browse files
authored
bpo-30522: Implemented a method to allow setting a logging.StreamHander's stream. (GH-2921)
1 parent 78c18a9 commit 2543f50

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

Doc/library/logging.handlers.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,26 @@ and :meth:`flush` methods).
5959
:meth:`close` method is inherited from :class:`~logging.Handler` and so
6060
does no output, so an explicit :meth:`flush` call may be needed at times.
6161

62+
.. method:: setStream(stream)
63+
64+
Sets the instance's stream to the specified value, if it is different.
65+
The old stream is flushed before the new stream is set.
66+
67+
:param stream: The stream that the handler should use.
68+
69+
:return: the old stream, if the stream was changed, or *None* if it wasn't.
70+
71+
.. versionadded:: 3.7
72+
73+
6274
.. versionchanged:: 3.2
6375
The ``StreamHandler`` class now has a ``terminator`` attribute, default
6476
value ``'\n'``, which is used as the terminator when writing a formatted
6577
record to a stream. If you don't want this newline termination, you can
6678
set the handler instance's ``terminator`` attribute to the empty string.
6779
In earlier versions, the terminator was hardcoded as ``'\n'``.
6880

81+
6982
.. _file-handler:
7083

7184
FileHandler

Lib/logging/__init__.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,26 @@ def emit(self, record):
997997
except Exception:
998998
self.handleError(record)
999999

1000+
def setStream(self, stream):
1001+
"""
1002+
Sets the StreamHandler's stream to the specified value,
1003+
if it is different.
1004+
1005+
Returns the old stream, if the stream was changed, or None
1006+
if it wasn't.
1007+
"""
1008+
if stream is self.stream:
1009+
result = None
1010+
else:
1011+
result = self.stream
1012+
self.acquire()
1013+
try:
1014+
self.flush()
1015+
self.stream = stream
1016+
finally:
1017+
self.release()
1018+
return result
1019+
10001020
def __repr__(self):
10011021
level = getLevelName(self.level)
10021022
name = getattr(self.stream, 'name', '')

Lib/test/test_logging.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,20 @@ def test_error_handling(self):
698698
finally:
699699
logging.raiseExceptions = old_raise
700700

701+
def test_stream_setting(self):
702+
"""
703+
Test setting the handler's stream
704+
"""
705+
h = logging.StreamHandler()
706+
stream = io.StringIO()
707+
old = h.setStream(stream)
708+
self.assertIs(old, sys.stderr)
709+
actual = h.setStream(old)
710+
self.assertIs(actual, stream)
711+
# test that setting to existing value returns None
712+
actual = h.setStream(old)
713+
self.assertIsNone(actual)
714+
701715
# -- The following section could be moved into a server_helper.py module
702716
# -- if it proves to be of wider utility than just test_logging
703717

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Added a ``setStream`` method to ``logging.StreamHandler`` to allow the
2+
stream to be set after creation.

0 commit comments

Comments
 (0)