Skip to content

Commit a60520d

Browse files
vstinnerhukkinencukou
authored
gh-147991: Speed up tomllib import time (GH-147992)
- Use lazy import for regular expressions. - Use frozendict for string escapes Co-authored-by: Taneli Hukkinen <hukkinen@eurecom.fr> Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent bf42481 commit a60520d

3 files changed

Lines changed: 30 additions & 2 deletions

File tree

Lib/test/test_tomllib/test_misc.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
from pathlib import Path
1010
import sys
1111
import tempfile
12+
import textwrap
1213
import unittest
1314
from test import support
15+
from test.support.script_helper import assert_python_ok
1416

1517
from . import tomllib
1618

@@ -124,3 +126,20 @@ def test_types_import(self):
124126
never imported by tests.
125127
"""
126128
importlib.import_module(f"{tomllib.__name__}._types")
129+
130+
def test_lazy_import(self):
131+
# Test the TOML file can be parsed without importing regular
132+
# expressions (tomllib._re)
133+
code = textwrap.dedent("""
134+
import sys, tomllib, textwrap
135+
document = textwrap.dedent('''
136+
[metadata]
137+
key = "text"
138+
array = ["array", "of", "text"]
139+
booleans = [true, false]
140+
''')
141+
tomllib.loads(document)
142+
print("lazy import?", 'tomllib._re' not in sys.modules)
143+
""")
144+
proc = assert_python_ok("-c", code)
145+
self.assertIn(b"lazy import? True", proc.out)

Lib/tomllib/_parser.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
from __future__ import annotations
66

7-
from types import MappingProxyType
7+
# Defer loading regular expressions until we actually need them in
8+
# parse_value().
9+
__lazy_modules__ = ["tomllib._re"]
10+
11+
import sys
812

913
from ._re import (
1014
RE_DATETIME,
@@ -15,6 +19,9 @@
1519
match_to_number,
1620
)
1721

22+
if sys.version_info < (3, 15):
23+
from types import MappingProxyType as frozendict
24+
1825
TYPE_CHECKING = False
1926
if TYPE_CHECKING:
2027
from collections.abc import Iterable
@@ -42,7 +49,7 @@
4249
KEY_INITIAL_CHARS: Final = BARE_KEY_CHARS | frozenset("\"'")
4350
HEXDIGIT_CHARS: Final = frozenset("abcdef" "ABCDEF" "0123456789")
4451

45-
BASIC_STR_ESCAPE_REPLACEMENTS: Final = MappingProxyType(
52+
BASIC_STR_ESCAPE_REPLACEMENTS: Final = frozendict(
4653
{
4754
"\\b": "\u0008", # backspace
4855
"\\t": "\u0009", # tab
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve :mod:`tomllib` import time (up to 10x faster). Patch by Victor
2+
Stinner.

0 commit comments

Comments
 (0)