SF.net SVN: docutils:[9873] trunk/docutils/docutils/parsers/__init__.py

aa-turner--- via Docutils-checkins <[email protected]>
Newsgroups gmane.text.docutils.cvs
Message-ID <[email protected]>
Revision: 9873
          http://sourceforge.net/p/docutils/code/9873
Author:   aa-turner
Date:     2024-08-09 06:01:39 +0000 (Fri, 09 Aug 2024)
Log Message:
-----------
Add type hints to ``docutils.parsers``

Modified Paths:
--------------
    trunk/docutils/docutils/parsers/__init__.py

Modified: trunk/docutils/docutils/parsers/__init__.py
===================================================================
--- trunk/docutils/docutils/parsers/__init__.py	2024-08-09 05:36:39 UTC (rev 9872)
+++ trunk/docutils/docutils/parsers/__init__.py	2024-08-09 06:01:39 UTC (rev 9873)
@@ -6,13 +6,31 @@
 This package contains Docutils parser modules.
 """
 
+from __future__ import annotations
+
 __docformat__ = 'reStructuredText'
 
-from importlib import import_module
+import importlib
+from typing import TYPE_CHECKING, overload
 
 from docutils import Component, frontend, transforms
 
+if TYPE_CHECKING:
+    from typing import Final, Literal
 
+    from docutils import nodes
+    from docutils.parsers import (
+        commonmark_wrapper,
+        docutils_xml,
+        null,
+        rst,
+        recommonmark_wrapper,
+    )
+    from docutils.transforms import Transform
+
+    from myst_parser import docutils_ as myst_wrapper
+
+
 class Parser(Component):
     settings_spec = (
         'Generic Parser Options',
@@ -20,7 +38,7 @@
         (('Disable directives that insert the contents of an external file; '
           'replaced with a "warning" system message.',
           ['--no-file-insertion'],
-          {'action': 'store_false', 'default': 1,
+          {'action': 'store_false', 'default': True,
            'dest': 'file_insertion_enabled',
            'validator': frontend.validate_boolean}),
          ('Enable directives that insert the contents '
@@ -30,7 +48,7 @@
          ('Disable the "raw" directive; '
           'replaced with a "warning" system message.',
           ['--no-raw'],
-          {'action': 'store_false', 'default': 1, 'dest': 'raw_enabled',
+          {'action': 'store_false', 'default': True, 'dest': 'raw_enabled',
            'validator': frontend.validate_boolean}),
          ('Enable the "raw" directive. (default)',
           ['--raw-enabled'],
@@ -37,7 +55,7 @@
           {'action': 'store_true'}),
          ('Maximal number of characters in an input line. Default 10 000.',
           ['--line-length-limit'],
-          {'metavar': '<length>', 'type': 'int', 'default': 10000,
+          {'metavar': '<length>', 'type': 'int', 'default': 10_000,
            'validator': frontend.validate_nonnegative_int}),
          ('Validate the document tree after parsing.',
           ['--validate'],
@@ -48,23 +66,23 @@
           {'action': 'store_false', 'dest': 'validate'}),
          )
         )
-    component_type = 'parser'
-    config_section = 'parsers'
+    component_type: Final = 'parser'
+    config_section: Final = 'parsers'
 
-    def get_transforms(self):
+    def get_transforms(self) -> list[type[Transform]]:
         return super().get_transforms() + [transforms.universal.Validate]
 
-    def parse(self, inputstring, document):
+    def parse(self, inputstring: str, document: nodes.document) -> None:
         """Override to parse `inputstring` into document tree `document`."""
         raise NotImplementedError('subclass must override this method')
 
-    def setup_parse(self, inputstring, document) -> None:
+    def setup_parse(self, inputstring: str, document: nodes.document) -> None:
         """Initial parse setup.  Call at start of `self.parse()`."""
         self.inputstring = inputstring
         # provide fallbacks in case the document has only generic settings
         document.settings.setdefault('file_insertion_enabled', False)
         document.settings.setdefault('raw_enabled', False)
-        document.settings.setdefault('line_length_limit', 10000)
+        document.settings.setdefault('line_length_limit', 10_000)
         self.document = document
         document.reporter.attach_observer(document.note_parse_message)
 
@@ -74,32 +92,84 @@
             self.document.note_parse_message)
 
 
-_parser_aliases = {  # short names for known parsers
-                   'null': 'docutils.parsers.null',
-                   # reStructuredText
-                   'rst': 'docutils.parsers.rst',
-                   'restructuredtext': 'docutils.parsers.rst',
-                   'rest': 'docutils.parsers.rst',
-                   'restx': 'docutils.parsers.rst',
-                   'rtxt': 'docutils.parsers.rst',
-                   # Docutils XML
-                   'docutils_xml': 'docutils.parsers.docutils_xml',
-                   'xml': 'docutils.parsers.docutils_xml',
-                   # 3rd-party Markdown parsers
-                   'recommonmark': 'docutils.parsers.recommonmark_wrapper',
-                   'myst': 'myst_parser.docutils_',
-                   # 'pycmark': works out of the box
-                   # dispatcher for 3rd-party Markdown parsers
-                   'commonmark': 'docutils.parsers.commonmark_wrapper',
-                   'markdown': 'docutils.parsers.commonmark_wrapper',
-                  }
+@overload
+def get_parser_class(parser_name: Literal['null']) -> type[null.Parser]:
+    ...
 
 
-def get_parser_class(parser_name):
+@overload
+def get_parser_class(
+    parser_name: Literal['rst', 'restructuredtext']
+) -> type[rst.Parser]:
+    ...
+
+
+@overload
+def get_parser_class(
+    parser_name: Literal['xml', 'docutils_xml']
+) -> type[docutils_xml.Parser]:
+    ...
+
+
+@overload
+def get_parser_class(
+    parser_name: Literal['recommonmark']
+) -> type[recommonmark_wrapper.Parser]:
+    ...
+
+
+@overload
+def get_parser_class(
+    parser_name: Literal['myst']
+) -> type[myst_wrapper.Parser]:
+    ...
+
+
+@overload
+def get_parser_class(
+    parser_name: Literal['commonmark', 'markdown']
+) -> type[commonmark_wrapper.Parser]:
+    ...
+
+
+@overload
+def get_parser_class(parser_name: str) -> type[Parser]:
+    ...
+
+
+def get_parser_class(parser_name: str) -> type[Parser]:
     """Return the Parser class from the `parser_name` module."""
     name = parser_name.lower()
+
+    # short names for known parsers
+    if name == 'null':
+        from docutils.parsers import null
+        return null.Parser
+    if name in {'rst', 'restructuredtext', 'rest', 'restx', 'rtxt'}:
+        from docutils.parsers import rst
+        return rst.Parser
+    if name in {'docutils_xml', 'xml'}:
+        from docutils.parsers import docutils_xml
+        return docutils_xml.Parser
+
     try:
-        module = import_module(_parser_aliases.get(name, name))
+        # 3rd-party Markdown parsers
+        # (pycmark works out of the box)
+        if name == 'recommonmark':
+            from docutils.parsers import recommonmark_wrapper
+            return recommonmark_wrapper.Parser
+        if name == 'myst':
+            from myst_parser import docutils_ as myst_wrapper
+            return myst_wrapper.Parser
+
+        # dispatcher for 3rd-party Markdown parsers
+        if name in {'commonmark', 'markdown'}:
+            from docutils.parsers import commonmark_wrapper
+            return commonmark_wrapper.Parser
+
+        # fallback to importing a fully-qualified name
+        module = importlib.import_module(name)
     except ImportError as err:
         raise ImportError(f'Parser "{parser_name}" not found. {err}')
-    return module.Parser
+    else:
+        return module.Parser

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.