summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2020-01-01 12:07:31 -0800
committerVinay Sajip <vinay_sajip@yahoo.co.uk>2020-01-01 20:07:31 +0000
commit0e0e4acaabdcf8efb60cf75f08301022ac4422a4 (patch)
treead396194a872dbc2f1850f3704afa6c19f694b32
parent88938e415f4160dbccc3a6826394cf0d460e273c (diff)
downloadcpython-git-0e0e4acaabdcf8efb60cf75f08301022ac4422a4.tar.gz
bpo-39142: Avoid converting namedtuple instances to ConvertingTuple. (GH-17773) (GH-17786)
(cherry picked from commit 46abfc1416ff8e450999611ef8f231ff871ab133)
-rw-r--r--Lib/logging/config.py2
-rw-r--r--Lib/test/test_logging.py31
-rw-r--r--Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst5
3 files changed, 37 insertions, 1 deletions
diff --git a/Lib/logging/config.py b/Lib/logging/config.py
index f58be93089..626aeea7c2 100644
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -447,7 +447,7 @@ class BaseConfigurator(object):
value = ConvertingList(value)
value.configurator = self
elif not isinstance(value, ConvertingTuple) and\
- isinstance(value, tuple):
+ isinstance(value, tuple) and not hasattr(value, '_fields'):
value = ConvertingTuple(value)
value.configurator = self
elif isinstance(value, str): # str for py3k
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index 546cea98c1..c24a302868 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -3223,6 +3223,37 @@ class ConfigDictTest(BaseTest):
self.assertRaises(ValueError, bc.convert, 'cfg://!')
self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]')
+ def test_namedtuple(self):
+ # see bpo-39142
+ from collections import namedtuple
+
+ class MyHandler(logging.StreamHandler):
+ def __init__(self, resource, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.resource: namedtuple = resource
+
+ def emit(self, record):
+ record.msg += f' {self.resource.type}'
+ return super().emit(record)
+
+ Resource = namedtuple('Resource', ['type', 'labels'])
+ resource = Resource(type='my_type', labels=['a'])
+
+ config = {
+ 'version': 1,
+ 'handlers': {
+ 'myhandler': {
+ '()': MyHandler,
+ 'resource': resource
+ }
+ },
+ 'root': {'level': 'INFO', 'handlers': ['myhandler']},
+ }
+ with support.captured_stderr() as stderr:
+ self.apply_config(config)
+ logging.info('some log')
+ self.assertEqual(stderr.getvalue(), 'some log my_type\n')
+
class ManagerTest(BaseTest):
def test_manager_loggerclass(self):
logged = []
diff --git a/Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst b/Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst
new file mode 100644
index 0000000000..508d1338d7
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst
@@ -0,0 +1,5 @@
+A change was made to logging.config.dictConfig to avoid converting instances
+of named tuples to ConvertingTuple. It's assumed that named tuples are too
+specialised to be treated like ordinary tuples; if a user of named tuples
+requires ConvertingTuple functionality, they will have to implement that
+themselves in their named tuple class.