summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/logging.config.rst3
-rw-r--r--Lib/logging/config.py2
-rw-r--r--Lib/test/test_logging.py48
-rw-r--r--Misc/NEWS.d/next/Library/2023-04-09-05-30-41.gh-issue-103384.zAV7iB.rst1
4 files changed, 51 insertions, 3 deletions
diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst
index 448978f..53fbd07 100644
--- a/Doc/library/logging.config.rst
+++ b/Doc/library/logging.config.rst
@@ -685,7 +685,8 @@ resolve to ``'dev_team@domain.tld'`` and the string
``'support_team@domain.tld'``. The ``subject`` value could be accessed
using either ``'cfg://handlers.email.subject'`` or, equivalently,
``'cfg://handlers.email[subject]'``. The latter form only needs to be
-used if the key contains spaces or non-alphanumeric characters. If an
+used if the key contains spaces or non-alphanumeric characters. Please note
+that the characters ``[`` and ``]`` are not allowed in the keys. If an
index value consists only of decimal digits, access will be attempted
using the corresponding integer value, falling back to the string
value if needed.
diff --git a/Lib/logging/config.py b/Lib/logging/config.py
index a68281d..41283f4 100644
--- a/Lib/logging/config.py
+++ b/Lib/logging/config.py
@@ -378,7 +378,7 @@ class BaseConfigurator(object):
WORD_PATTERN = re.compile(r'^\s*(\w+)\s*')
DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*')
- INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*')
+ INDEX_PATTERN = re.compile(r'^\[([^\[\]]*)\]\s*')
DIGIT_PATTERN = re.compile(r'^\d+$')
value_converters = {
diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
index f26846f..c2e8ff5 100644
--- a/Lib/test/test_logging.py
+++ b/Lib/test/test_logging.py
@@ -3662,7 +3662,28 @@ class ConfigDictTest(BaseTest):
d = {
'atuple': (1, 2, 3),
'alist': ['a', 'b', 'c'],
- 'adict': {'d': 'e', 'f': 3 },
+ 'adict': {
+ 'd': 'e', 'f': 3 ,
+ 'alpha numeric 1 with spaces' : 5,
+ 'aplha numeric 1 %( - © ©ß¯' : 9,
+ 'alpha numeric ] 1 with spaces' : 15,
+ 'aplha ]] numeric 1 %( - © ©ß¯]' : 19,
+ ' aplha [ numeric 1 %( - © ©ß¯] ' : 11,
+ ' aplha ' : 32,
+ '' : 10,
+ 'nest4' : {
+ 'd': 'e', 'f': 3 ,
+ 'alpha numeric 1 with spaces' : 5,
+ 'aplha numeric 1 %( - © ©ß¯' : 9,
+ '' : 10,
+ 'somelist' : ('g', ('h', 'i'), 'j'),
+ 'somedict' : {
+ 'a' : 1,
+ 'a with 1 and space' : 3,
+ 'a with ( and space' : 4,
+ }
+ }
+ },
'nest1': ('g', ('h', 'i'), 'j'),
'nest2': ['k', ['l', 'm'], 'n'],
'nest3': ['o', 'cfg://alist', 'p'],
@@ -3674,11 +3695,36 @@ class ConfigDictTest(BaseTest):
self.assertEqual(bc.convert('cfg://nest2[1][1]'), 'm')
self.assertEqual(bc.convert('cfg://adict.d'), 'e')
self.assertEqual(bc.convert('cfg://adict[f]'), 3)
+ self.assertEqual(bc.convert('cfg://adict[alpha numeric 1 with spaces]'), 5)
+ self.assertEqual(bc.convert('cfg://adict[aplha numeric 1 %( - © ©ß¯]'), 9)
+ self.assertEqual(bc.convert('cfg://adict[]'), 10)
+ self.assertEqual(bc.convert('cfg://adict.nest4.d'), 'e')
+ self.assertEqual(bc.convert('cfg://adict.nest4[d]'), 'e')
+ self.assertEqual(bc.convert('cfg://adict[nest4].d'), 'e')
+ self.assertEqual(bc.convert('cfg://adict[nest4][f]'), 3)
+ self.assertEqual(bc.convert('cfg://adict[nest4][alpha numeric 1 with spaces]'), 5)
+ self.assertEqual(bc.convert('cfg://adict[nest4][aplha numeric 1 %( - © ©ß¯]'), 9)
+ self.assertEqual(bc.convert('cfg://adict[nest4][]'), 10)
+ self.assertEqual(bc.convert('cfg://adict[nest4][somelist][0]'), 'g')
+ self.assertEqual(bc.convert('cfg://adict[nest4][somelist][1][0]'), 'h')
+ self.assertEqual(bc.convert('cfg://adict[nest4][somelist][1][1]'), 'i')
+ self.assertEqual(bc.convert('cfg://adict[nest4][somelist][2]'), 'j')
+ self.assertEqual(bc.convert('cfg://adict[nest4].somedict.a'), 1)
+ self.assertEqual(bc.convert('cfg://adict[nest4].somedict[a]'), 1)
+ self.assertEqual(bc.convert('cfg://adict[nest4].somedict[a with 1 and space]'), 3)
+ self.assertEqual(bc.convert('cfg://adict[nest4].somedict[a with ( and space]'), 4)
+ self.assertEqual(bc.convert('cfg://adict.nest4.somelist[1][1]'), 'i')
+ self.assertEqual(bc.convert('cfg://adict.nest4.somelist[2]'), 'j')
+ self.assertEqual(bc.convert('cfg://adict.nest4.somedict.a'), 1)
+ self.assertEqual(bc.convert('cfg://adict.nest4.somedict[a]'), 1)
v = bc.convert('cfg://nest3')
self.assertEqual(v.pop(1), ['a', 'b', 'c'])
self.assertRaises(KeyError, bc.convert, 'cfg://nosuch')
self.assertRaises(ValueError, bc.convert, 'cfg://!')
self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]')
+ self.assertRaises(KeyError, bc.convert, 'cfg://adict[alpha numeric ] 1 with spaces]')
+ self.assertRaises(ValueError, bc.convert, 'cfg://adict[ aplha ]] numeric 1 %( - © ©ß¯] ]')
+ self.assertRaises(ValueError, bc.convert, 'cfg://adict[ aplha [ numeric 1 %( - © ©ß¯] ]')
def test_namedtuple(self):
# see bpo-39142
diff --git a/Misc/NEWS.d/next/Library/2023-04-09-05-30-41.gh-issue-103384.zAV7iB.rst b/Misc/NEWS.d/next/Library/2023-04-09-05-30-41.gh-issue-103384.zAV7iB.rst
new file mode 100644
index 0000000..3e9d3cf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-04-09-05-30-41.gh-issue-103384.zAV7iB.rst
@@ -0,0 +1 @@
+Generalize the regex pattern ``BaseConfigurator.INDEX_PATTERN`` to allow spaces and non-alphanumeric characters in keys.