bpo-35168: Make shlex.punctuation_chars read-only (#11631)

* bpo-35168: Documentation about shlex.punctuation_chars now states that it should be set in __init__.py

* bpo-35168: Convert shlex.punctuation_chars to read-only property

* Add NEWS.d entry
diff --git a/Lib/shlex.py b/Lib/shlex.py
index edea077..ae0f5dd 100644
--- a/Lib/shlex.py
+++ b/Lib/shlex.py
@@ -55,7 +55,7 @@
             punctuation_chars = ''
         elif punctuation_chars is True:
             punctuation_chars = '();<>|&'
-        self.punctuation_chars = punctuation_chars
+        self._punctuation_chars = punctuation_chars
         if punctuation_chars:
             # _pushback_chars is a push back queue used by lookahead logic
             self._pushback_chars = deque()
@@ -65,6 +65,10 @@
             t = self.wordchars.maketrans(dict.fromkeys(punctuation_chars))
             self.wordchars = self.wordchars.translate(t)
 
+    @property
+    def punctuation_chars(self):
+        return self._punctuation_chars
+
     def push_token(self, tok):
         "Push a token onto the stack popped by the get_token method"
         if self.debug >= 1:
diff --git a/Lib/test/test_shlex.py b/Lib/test/test_shlex.py
index 376c5e8..a21ccd2 100644
--- a/Lib/test/test_shlex.py
+++ b/Lib/test/test_shlex.py
@@ -353,6 +353,13 @@
                 resplit = shlex.split(joined)
                 self.assertEqual(split_command, resplit)
 
+    def testPunctuationCharsReadOnly(self):
+        punctuation_chars = "/|$%^"
+        shlex_instance = shlex.shlex(punctuation_chars=punctuation_chars)
+        self.assertEqual(shlex_instance.punctuation_chars, punctuation_chars)
+        with self.assertRaises(AttributeError):
+            shlex_instance.punctuation_chars = False
+
 
 # Allow this test to be used with old shlex.py
 if not getattr(shlex, "split", None):