Skip to content

Commit 1182135

Browse files
committed
Use lazy import
1 parent 50d5739 commit 1182135

File tree

2 files changed

+42
-31
lines changed

2 files changed

+42
-31
lines changed

Lib/test/test_tomllib/test_misc.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
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 import os_helper
16+
from test.support.script_helper import assert_python_ok
1417

1518
from . import tomllib
1619

@@ -139,3 +142,26 @@ def test_parse_simple_number(self):
139142
self.assertIsNone(parse_simple_number("x123\n", 0))
140143
self.assertIsNone(parse_simple_number("o123\n", 0))
141144
self.assertIsNone(parse_simple_number("b100\n", 0))
145+
146+
def test_lazy_import(self):
147+
# Test that _parse_simple_number() can parse the TOML file without
148+
# importing regular expressions (tomllib._re)
149+
filename = os_helper.TESTFN
150+
self.addCleanup(os_helper.unlink, filename)
151+
toml = textwrap.dedent("""
152+
[metadata]
153+
int = 123
154+
list = [+1, -2, 3]
155+
table = {x=1, y=2}
156+
""")
157+
with open(filename, "w") as fp:
158+
fp.write(toml)
159+
160+
code = textwrap.dedent(f"""
161+
import sys, tomllib
162+
with open({filename!a}, "rb") as fp:
163+
tomllib.load(fp)
164+
print("lazy import?", 'tomllib._re' not in sys.modules)
165+
""")
166+
proc = assert_python_ok('-c', code)
167+
self.assertIn(b'lazy import? True', proc.out)

Lib/tomllib/_parser.py

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,24 @@
66

77
from types import MappingProxyType
88

9+
__lazy_modules__ = ["tomllib._re"]
10+
11+
from ._re import (
12+
RE_DATETIME,
13+
RE_LOCALTIME,
14+
RE_NUMBER,
15+
match_to_datetime,
16+
match_to_localtime,
17+
match_to_number,
18+
)
19+
920
TYPE_CHECKING = False
1021
if TYPE_CHECKING:
1122
from collections.abc import Iterable
1223
from typing import IO, Any, Final
1324

1425
from ._types import Key, ParseFloat, Pos
1526

16-
_REGEX_IMPORTED = True
17-
from ._re import (
18-
RE_DATETIME,
19-
RE_LOCALTIME,
20-
RE_NUMBER,
21-
match_to_datetime,
22-
match_to_localtime,
23-
match_to_number,
24-
)
25-
else:
26-
# Regular expressions are lazy imported to speed up startup time
27-
_REGEX_IMPORTED = False
28-
2927
ASCII_CTRL: Final = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
3028

3129
# Neither of these sets include quotation mark or backslash. They are
@@ -727,24 +725,11 @@ def parse_value(
727725
if char == "{":
728726
return parse_inline_table(src, pos, parse_float)
729727

730-
global _REGEX_IMPORTED, RE_DATETIME, RE_LOCALTIME, RE_NUMBER
731-
global match_to_datetime, match_to_localtime, match_to_number
732-
if not _REGEX_IMPORTED:
733-
# Simple number parser avoiding regex
734-
if char in _DECDIGIT_CHARS:
735-
res = _parse_simple_number(src, pos)
736-
if res is not None:
737-
return res
738-
739-
from ._re import (
740-
RE_DATETIME,
741-
RE_LOCALTIME,
742-
RE_NUMBER,
743-
match_to_datetime,
744-
match_to_localtime,
745-
match_to_number,
746-
)
747-
_REGEX_IMPORTED = True
728+
# Simple number parser avoiding regex
729+
if char in _DECDIGIT_CHARS:
730+
res = _parse_simple_number(src, pos)
731+
if res is not None:
732+
return res
748733

749734
# Dates and times
750735
datetime_match = RE_DATETIME.match(src, pos)

0 commit comments

Comments
 (0)