diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2020-01-01 12:07:31 -0800 |
---|---|---|
committer | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2020-01-01 20:07:31 +0000 |
commit | 0e0e4acaabdcf8efb60cf75f08301022ac4422a4 (patch) | |
tree | ad396194a872dbc2f1850f3704afa6c19f694b32 | |
parent | 88938e415f4160dbccc3a6826394cf0d460e273c (diff) | |
download | cpython-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.py | 2 | ||||
-rw-r--r-- | Lib/test/test_logging.py | 31 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst | 5 |
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. |