https://github.com/python/cpython/commit/e1d48237973f0257f84cb5682014b38d18f3d76d
commit: e1d48237973f0257f84cb5682014b38d18f3d76d
branch: main
author: Jack Danger <[email protected]>
committer: vsajip <[email protected]>
date: 2026-03-26T12:41:14Z
summary:

gh-145650: Add `logging.{Formatter,Filter}.__repr__` (GH-145652)

files:
A Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst
M Lib/logging/__init__.py
M Lib/test/test_logging.py

diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
index 39689a57e6ecd6..6eef90ae5cd914 100644
--- a/Lib/logging/__init__.py
+++ b/Lib/logging/__init__.py
@@ -622,6 +622,9 @@ def __init__(self, fmt=None, datefmt=None, style='%', 
validate=True, *,
         self._fmt = self._style._fmt
         self.datefmt = datefmt
 
+    def __repr__(self):
+        return '<%s (%s)>' % (self.__class__.__name__, self._fmt)
+
     default_time_format = '%Y-%m-%d %H:%M:%S'
     default_msec_format = '%s,%03d'
 
@@ -794,6 +797,9 @@ def __init__(self, name=''):
         self.name = name
         self.nlen = len(name)
 
+    def __repr__(self):
+        return '<%s (%s)>' % (self.__class__.__name__, self.name)
+
     def filter(self, record):
         """
         Determine if the specified record is to be logged.
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 05dcea6ce0e98a..1a76c2173a3011 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -404,6 +404,20 @@ def test_empty_filter(self):
         r = logging.makeLogRecord({'name': 'spam.eggs'})
         self.assertTrue(f.filter(r))
 
+    def test_filter_repr(self):
+        f = logging.Filter('myapp')
+        self.assertEqual(repr(f), '<Filter (myapp)>')
+
+    def test_filter_repr_empty(self):
+        f = logging.Filter()
+        self.assertEqual(repr(f), '<Filter ()>')
+
+    def test_filter_repr_subclass(self):
+        class MyFilter(logging.Filter):
+            pass
+        f = MyFilter('myapp')
+        self.assertEqual(repr(f), '<MyFilter (myapp)>')
+
 #
 #   First, we define our levels. There can be as many as you want - the only
 #     limitations are that they should be integers, the lowest should be > 0 
and
@@ -4914,6 +4928,20 @@ def test_relativeCreated_has_higher_precision(self):
                 # After PR gh-102412, precision (places) increases from 3 to 7
                 self.assertAlmostEqual(relativeCreated, offset_ns / 1e6, 
places=7)
 
+    def test_formatter_repr(self):
+        f = logging.Formatter('%(message)s')
+        self.assertEqual(repr(f), '<Formatter (%(message)s)>')
+
+    def test_formatter_repr_default(self):
+        f = logging.Formatter()
+        self.assertEqual(repr(f), '<Formatter (%(message)s)>')
+
+    def test_formatter_repr_subclass(self):
+        class MyFormatter(logging.Formatter):
+            pass
+        f = MyFormatter('%(message)s')
+        self.assertEqual(repr(f), '<MyFormatter (%(message)s)>')
+
 
 class TestBufferingFormatter(logging.BufferingFormatter):
     def formatHeader(self, records):
diff --git 
a/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst 
b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst
new file mode 100644
index 00000000000000..243834d0bbd564
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst
@@ -0,0 +1,3 @@
+Add :meth:`~object.__repr__` support to :class:`logging.Formatter` and
+:class:`logging.Filter`, showing the format string and filter name
+respectively.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to