]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-118761: Improve import time of `tomllib` (#128907)
authorTaneli Hukkinen <3275109+hukkin@users.noreply.github.com>
Fri, 17 Jan 2025 02:48:42 +0000 (04:48 +0200)
committerGitHub <noreply@github.com>
Fri, 17 Jan 2025 02:48:42 +0000 (18:48 -0800)
Improve import time of `tomllib`  (in sync with upstream)

Lib/test/test_tomllib/test_misc.py
Lib/tomllib/_parser.py
Lib/tomllib/_re.py
Misc/NEWS.d/next/Library/2025-01-16-10-06-40.gh-issue-118761.z100LC.rst [new file with mode: 0644]

index 9e677a337a2835f459311e9743265dc39c5029d0..59116afa1f36ad10345a9ac2ef67ef8457c82bf4 100644 (file)
@@ -5,6 +5,7 @@
 import copy
 import datetime
 from decimal import Decimal as D
+import importlib
 from pathlib import Path
 import sys
 import tempfile
@@ -113,3 +114,11 @@ class TestMiscellaneous(unittest.TestCase):
                               nest_count=nest_count):
                 recursive_table_toml = nest_count * "key = {" + nest_count * "}"
                 tomllib.loads(recursive_table_toml)
+
+    def test_types_import(self):
+        """Test that `_types` module runs.
+
+        The module is for type annotations only, so it is otherwise
+        never imported by tests.
+        """
+        importlib.import_module(f"{tomllib.__name__}._types")
index 4d208bcfb4a9a679f094410bdc4a8a1faa8c6bf2..0e522c3a69e6fecc32cf5dd415340016cc426dcd 100644 (file)
@@ -4,11 +4,7 @@
 
 from __future__ import annotations
 
-from collections.abc import Iterable
-import string
 from types import MappingProxyType
-from typing import Any, BinaryIO, NamedTuple
-import warnings
 
 from ._re import (
     RE_DATETIME,
@@ -18,7 +14,13 @@ from ._re import (
     match_to_localtime,
     match_to_number,
 )
-from ._types import Key, ParseFloat, Pos
+
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+    from collections.abc import Iterable
+    from typing import IO, Any
+
+    from ._types import Key, ParseFloat, Pos
 
 ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
 
@@ -34,9 +36,11 @@ ILLEGAL_COMMENT_CHARS = ILLEGAL_BASIC_STR_CHARS
 
 TOML_WS = frozenset(" \t")
 TOML_WS_AND_NEWLINE = TOML_WS | frozenset("\n")
-BARE_KEY_CHARS = frozenset(string.ascii_letters + string.digits + "-_")
+BARE_KEY_CHARS = frozenset(
+    "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "-_"
+)
 KEY_INITIAL_CHARS = BARE_KEY_CHARS | frozenset("\"'")
-HEXDIGIT_CHARS = frozenset(string.hexdigits)
+HEXDIGIT_CHARS = frozenset("abcdef" "ABCDEF" "0123456789")
 
 BASIC_STR_ESCAPE_REPLACEMENTS = MappingProxyType(
     {
@@ -80,6 +84,8 @@ class TOMLDecodeError(ValueError):
             or not isinstance(doc, str)
             or not isinstance(pos, int)
         ):
+            import warnings
+
             warnings.warn(
                 "Free-form arguments for TOMLDecodeError are deprecated. "
                 "Please set 'msg' (str), 'doc' (str) and 'pos' (int) arguments only.",
@@ -115,7 +121,7 @@ class TOMLDecodeError(ValueError):
         self.colno = colno
 
 
-def load(fp: BinaryIO, /, *, parse_float: ParseFloat = float) -> dict[str, Any]:
+def load(fp: IO[bytes], /, *, parse_float: ParseFloat = float) -> dict[str, Any]:
     """Parse TOML from a binary file object."""
     b = fp.read()
     try:
@@ -139,7 +145,7 @@ def loads(s: str, /, *, parse_float: ParseFloat = float) -> dict[str, Any]:  # n
             f"Expected str object, not '{type(s).__qualname__}'"
         ) from None
     pos = 0
-    out = Output(NestedDict(), Flags())
+    out = Output()
     header: Key = ()
     parse_float = make_safe_parse_float(parse_float)
 
@@ -290,9 +296,10 @@ class NestedDict:
             cont[last_key] = [{}]
 
 
-class Output(NamedTuple):
-    data: NestedDict
-    flags: Flags
+class Output:
+    def __init__(self) -> None:
+        self.data = NestedDict()
+        self.flags = Flags()
 
 
 def skip_chars(src: str, pos: Pos, chars: Iterable[str]) -> Pos:
index 9eacefc729544e3c8e223eb189be1c16da877da6..1ca6bef77a0b0396cfb821abb3f636494fd3b922 100644 (file)
@@ -7,9 +7,12 @@ from __future__ import annotations
 from datetime import date, datetime, time, timedelta, timezone, tzinfo
 from functools import lru_cache
 import re
-from typing import Any
 
-from ._types import ParseFloat
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+    from typing import Any
+
+    from ._types import ParseFloat
 
 # E.g.
 # - 00:32:00.999999
diff --git a/Misc/NEWS.d/next/Library/2025-01-16-10-06-40.gh-issue-118761.z100LC.rst b/Misc/NEWS.d/next/Library/2025-01-16-10-06-40.gh-issue-118761.z100LC.rst
new file mode 100644 (file)
index 0000000..ea71eca
--- /dev/null
@@ -0,0 +1,2 @@
+Improve import time of :mod:`tomllib` by removing ``typing``, ``string``,
+and ``tomllib._types`` imports. Patch by Taneli Hukkinen.