From bdf6ee7404cedfb3df5ffa365924e0ed334c703a Mon Sep 17 00:00:00 2001 From: Jack Danger Date: Sun, 8 Mar 2026 16:46:51 -0700 Subject: [PATCH 1/5] gh-145650: Add __repr__ to logging.Formatter and logging.Filter --- Lib/logging/__init__.py | 6 ++++++ Lib/test/test_logging.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 39689a57e6ecd6..79cd9f3de53c3b 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' @@ -809,6 +812,9 @@ def filter(self, record): return False return (record.name[self.nlen] == ".") + def __repr__(self): + return '<%s (%s)>' % (self.__class__.__name__, self.name) + class Filterer(object): """ A base class for loggers and handlers which allows them to share diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 05dcea6ce0e98a..b7bbfd6e9a2551 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), '') + + def test_filter_repr_empty(self): + f = logging.Filter() + self.assertEqual(repr(f), '') + + def test_filter_repr_subclass(self): + class MyFilter(logging.Filter): + pass + f = MyFilter('myapp') + self.assertEqual(repr(f), '') + # # 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 @@ -4915,6 +4929,21 @@ def test_relativeCreated_has_higher_precision(self): self.assertAlmostEqual(relativeCreated, offset_ns / 1e6, places=7) + def test_formatter_repr(self): + f = logging.Formatter('%(message)s') + self.assertEqual(repr(f), '') + + def test_formatter_repr_default(self): + f = logging.Formatter() + self.assertEqual(repr(f), '') + + def test_formatter_repr_subclass(self): + class MyFormatter(logging.Formatter): + pass + f = MyFormatter('%(message)s') + self.assertEqual(repr(f), '') + + class TestBufferingFormatter(logging.BufferingFormatter): def formatHeader(self, records): return '[(%d)' % len(records) From 151b1f94a825b5064379ce5c7784e3482c92ccdb Mon Sep 17 00:00:00 2001 From: Jack Danger Date: Sun, 8 Mar 2026 17:33:54 -0700 Subject: [PATCH 2/5] gh-145650: Add NEWS entry for logging repr changes --- .../Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst 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..a269682194a919 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst @@ -0,0 +1,3 @@ +Add :func:`repr` support to :class:`logging.Formatter` and +:class:`logging.Filter`, showing the format string and filter name +respectively. From fffd05ac801edcd59bb5eb8ba388cc84a2037cc8 Mon Sep 17 00:00:00 2001 From: Jack Danger Date: Sun, 8 Mar 2026 17:34:00 -0700 Subject: [PATCH 3/5] gh-145651: Add NEWS entry for http.client repr changes --- .../Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst diff --git a/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst new file mode 100644 index 00000000000000..23af6c195307ff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst @@ -0,0 +1,3 @@ +Add :func:`repr` support to :class:`http.client.HTTPConnection` and +:class:`http.client.HTTPResponse`, showing host/port and status/reason +respectively. From 5f848b303b61e0627c7d9047712959dff5a2fcfc Mon Sep 17 00:00:00 2001 From: Jack Danger Date: Sun, 8 Mar 2026 17:58:40 -0700 Subject: [PATCH 4/5] Update Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../next/Library/2026-03-08-00-00-00.gh-issue-145650.LgRepr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index a269682194a919..243834d0bbd564 100644 --- 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 @@ -1,3 +1,3 @@ -Add :func:`repr` support to :class:`logging.Formatter` and +Add :meth:`~object.__repr__` support to :class:`logging.Formatter` and :class:`logging.Filter`, showing the format string and filter name respectively. From d77de37c8eaf6cb8bf4ae782078ac21d277af085 Mon Sep 17 00:00:00 2001 From: Jack Danger Date: Sun, 8 Mar 2026 18:05:19 -0700 Subject: [PATCH 5/5] Address review feedback from picnixz --- Lib/logging/__init__.py | 6 +++--- Lib/test/test_logging.py | 1 - .../Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 79cd9f3de53c3b..6eef90ae5cd914 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -797,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. @@ -812,9 +815,6 @@ def filter(self, record): return False return (record.name[self.nlen] == ".") - def __repr__(self): - return '<%s (%s)>' % (self.__class__.__name__, self.name) - class Filterer(object): """ A base class for loggers and handlers which allows them to share diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index b7bbfd6e9a2551..1a76c2173a3011 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4928,7 +4928,6 @@ 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), '') diff --git a/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst b/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst deleted file mode 100644 index 23af6c195307ff..00000000000000 --- a/Misc/NEWS.d/next/Library/2026-03-08-00-00-00.gh-issue-145651.HtRepr.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :func:`repr` support to :class:`http.client.HTTPConnection` and -:class:`http.client.HTTPResponse`, showing host/port and status/reason -respectively.