[3.9] bpo-40204: Allow pre-Sphinx 3 syntax in the doc (GH-21844) (GH-21901)

* bpo-40204: Allow pre-Sphinx 3 syntax in the doc (GH-21844)

Enable Sphinx 3.2 "c_allow_pre_v3" option and disable the
c_warn_on_allowed_pre_v3 option to make the documentation compatible
with Sphinx 2 and Sphinx 3.

(cherry picked from commit 423e77d6de497931585d1883805a9e3fa4096b0b)

* bpo-40204: Fix Sphinx sytanx in howto/instrumentation.rst (GH-21858)

Use generic '.. object::' to declare markers, rather than abusing
'..  c:function::' which fails on Sphinx 3.

(cherry picked from commit 43577c01a2ab49122db696e9eaec6cb31d11cc81)

* bpo-40204: Fix duplicates in the documentation (GH-21857)

Fix two Sphinx 3 issues:

Doc/c-api/buffer.rst:304: WARNING: Duplicate C declaration, also defined in 'c-api/buffer'.
Declaration is 'PyBUF_ND'.

Doc/c-api/unicode.rst:1603: WARNING: Duplicate C declaration, also defined in 'c-api/unicode'.
Declaration is 'PyObject* PyUnicode_Translate(PyObject *str, PyObject *table, const char *errors)'.

(cherry picked from commit 46d10b1237c67ff8347f533eda6a5468d098f7eb)

* bpo-40204: Add :noindex: in the documentation (GH-21859)

Add :noindex: to duplicated documentation to fix "duplicate object
description" errors.

For example, fix this Sphinx 3 issue:

Doc/library/configparser.rst:1146: WARNING: duplicate object
description of configparser.ConfigParser.optionxform, other instance
in library/configparser, use :noindex: for one of them

(cherry picked from commit d3ded080482beae578faa704b13534a62d066f9f)

* bpo-40204, doc: Fix syntax of C variables (GH-21846)

For example, fix the following Sphinx 3 errors:

Doc/c-api/buffer.rst:102: WARNING: Error in declarator or parameters
Invalid C declaration: Expected identifier in nested name. [error at 5]
  void \*obj
  -----^

Doc/c-api/arg.rst:130: WARNING: Unparseable C cross-reference: 'PyObject*'
Invalid C declaration: Expected end of definition. [error at 8]
  PyObject*
  --------^

The modified documentation is compatible with Sphinx 2 and Sphinx 3.

(cherry picked from commit 474652fe9346382dbf793f20b671eb74668bebde)

* bpo-40204: Fix reference to terms in the doc (GH-21865)

Sphinx 3 requires to refer to terms with the exact case.

For example, fix the Sphinx 3 warning:

Doc/library/pkgutil.rst:71: WARNING: term Loader not found in case
sensitive match.made a reference to loader instead.

(cherry picked from commit bb0b08540cc93e56f3f1bde1b39ce086d9e35fe1)

* bpo-40204: Fix duplicated productionlist names in the doc (GH-21900)

Sphinx 3 disallows having more than one productionlist markup with
the same name. Simply remove names in this case, since names are not
shown anyway. For example, fix the Sphinx 3 warning:

Doc/reference/introduction.rst:96: duplicate token description
of *:name, other instance in reference/expressions

(cherry picked from commit 1abeda80f760134b4233608e2c288790f955b95a)
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst
index 739477f..2e22a54 100644
--- a/Doc/library/configparser.rst
+++ b/Doc/library/configparser.rst
@@ -674,97 +674,98 @@
 
 .. attribute:: ConfigParser.BOOLEAN_STATES
 
-  By default when using :meth:`~ConfigParser.getboolean`, config parsers
-  consider the following values ``True``: ``'1'``, ``'yes'``, ``'true'``,
-  ``'on'`` and the following values ``False``: ``'0'``, ``'no'``, ``'false'``,
-  ``'off'``.  You can override this by specifying a custom dictionary of strings
-  and their Boolean outcomes. For example:
+   By default when using :meth:`~ConfigParser.getboolean`, config parsers
+   consider the following values ``True``: ``'1'``, ``'yes'``, ``'true'``,
+   ``'on'`` and the following values ``False``: ``'0'``, ``'no'``, ``'false'``,
+   ``'off'``.  You can override this by specifying a custom dictionary of strings
+   and their Boolean outcomes. For example:
 
-  .. doctest::
+   .. doctest::
 
-     >>> custom = configparser.ConfigParser()
-     >>> custom['section1'] = {'funky': 'nope'}
-     >>> custom['section1'].getboolean('funky')
-     Traceback (most recent call last):
-     ...
-     ValueError: Not a boolean: nope
-     >>> custom.BOOLEAN_STATES = {'sure': True, 'nope': False}
-     >>> custom['section1'].getboolean('funky')
-     False
+      >>> custom = configparser.ConfigParser()
+      >>> custom['section1'] = {'funky': 'nope'}
+      >>> custom['section1'].getboolean('funky')
+      Traceback (most recent call last):
+      ...
+      ValueError: Not a boolean: nope
+      >>> custom.BOOLEAN_STATES = {'sure': True, 'nope': False}
+      >>> custom['section1'].getboolean('funky')
+      False
 
-  Other typical Boolean pairs include ``accept``/``reject`` or
-  ``enabled``/``disabled``.
+   Other typical Boolean pairs include ``accept``/``reject`` or
+   ``enabled``/``disabled``.
 
 .. method:: ConfigParser.optionxform(option)
+   :noindex:
 
-  This method transforms option names on every read, get, or set
-  operation.  The default converts the name to lowercase.  This also
-  means that when a configuration file gets written, all keys will be
-  lowercase.  Override this method if that's unsuitable.
-  For example:
+   This method transforms option names on every read, get, or set
+   operation.  The default converts the name to lowercase.  This also
+   means that when a configuration file gets written, all keys will be
+   lowercase.  Override this method if that's unsuitable.
+   For example:
 
-  .. doctest::
+   .. doctest::
 
-     >>> config = """
-     ... [Section1]
-     ... Key = Value
-     ...
-     ... [Section2]
-     ... AnotherKey = Value
-     ... """
-     >>> typical = configparser.ConfigParser()
-     >>> typical.read_string(config)
-     >>> list(typical['Section1'].keys())
-     ['key']
-     >>> list(typical['Section2'].keys())
-     ['anotherkey']
-     >>> custom = configparser.RawConfigParser()
-     >>> custom.optionxform = lambda option: option
-     >>> custom.read_string(config)
-     >>> list(custom['Section1'].keys())
-     ['Key']
-     >>> list(custom['Section2'].keys())
-     ['AnotherKey']
+      >>> config = """
+      ... [Section1]
+      ... Key = Value
+      ...
+      ... [Section2]
+      ... AnotherKey = Value
+      ... """
+      >>> typical = configparser.ConfigParser()
+      >>> typical.read_string(config)
+      >>> list(typical['Section1'].keys())
+      ['key']
+      >>> list(typical['Section2'].keys())
+      ['anotherkey']
+      >>> custom = configparser.RawConfigParser()
+      >>> custom.optionxform = lambda option: option
+      >>> custom.read_string(config)
+      >>> list(custom['Section1'].keys())
+      ['Key']
+      >>> list(custom['Section2'].keys())
+      ['AnotherKey']
 
-  .. note::
-     The optionxform function transforms option names to a canonical form.
-     This should be an idempotent function: if the name is already in
-     canonical form, it should be returned unchanged.
+   .. note::
+      The optionxform function transforms option names to a canonical form.
+      This should be an idempotent function: if the name is already in
+      canonical form, it should be returned unchanged.
 
 
 .. attribute:: ConfigParser.SECTCRE
 
-  A compiled regular expression used to parse section headers.  The default
-  matches ``[section]`` to the name ``"section"``.  Whitespace is considered
-  part of the section name, thus ``[  larch  ]`` will be read as a section of
-  name ``"  larch  "``.  Override this attribute if that's unsuitable.  For
-  example:
+   A compiled regular expression used to parse section headers.  The default
+   matches ``[section]`` to the name ``"section"``.  Whitespace is considered
+   part of the section name, thus ``[  larch  ]`` will be read as a section of
+   name ``"  larch  "``.  Override this attribute if that's unsuitable.  For
+   example:
 
-  .. doctest::
+   .. doctest::
 
-     >>> import re
-     >>> config = """
-     ... [Section 1]
-     ... option = value
-     ...
-     ... [  Section 2  ]
-     ... another = val
-     ... """
-     >>> typical = configparser.ConfigParser()
-     >>> typical.read_string(config)
-     >>> typical.sections()
-     ['Section 1', '  Section 2  ']
-     >>> custom = configparser.ConfigParser()
-     >>> custom.SECTCRE = re.compile(r"\[ *(?P<header>[^]]+?) *\]")
-     >>> custom.read_string(config)
-     >>> custom.sections()
-     ['Section 1', 'Section 2']
+      >>> import re
+      >>> config = """
+      ... [Section 1]
+      ... option = value
+      ...
+      ... [  Section 2  ]
+      ... another = val
+      ... """
+      >>> typical = configparser.ConfigParser()
+      >>> typical.read_string(config)
+      >>> typical.sections()
+      ['Section 1', '  Section 2  ']
+      >>> custom = configparser.ConfigParser()
+      >>> custom.SECTCRE = re.compile(r"\[ *(?P<header>[^]]+?) *\]")
+      >>> custom.read_string(config)
+      >>> custom.sections()
+      ['Section 1', 'Section 2']
 
-  .. note::
+   .. note::
 
-     While ConfigParser objects also use an ``OPTCRE`` attribute for recognizing
-     option lines, it's not recommended to override it because that would
-     interfere with constructor options *allow_no_value* and *delimiters*.
+      While ConfigParser objects also use an ``OPTCRE`` attribute for recognizing
+      option lines, it's not recommended to override it because that would
+      interfere with constructor options *allow_no_value* and *delimiters*.
 
 
 Legacy API Examples