Skip to content

Commit f301e2b

Browse files
committed
Defer uuid, unicodedata, guarded_eval and latex_symbols in the completer
`IPython.core.completer` is imported at startup, but none of these is needed until a completion is actually requested: `uuid` names a profiler output file, `unicodedata` backs `\GREEK SMALL LETTER ...` completion, `IPython.core.guarded_eval` evaluates expressions for attribute and dict key completion, and `IPython.core.latex_symbols` backs `\alpha` completion. Every use is inside a function body, so they move to their use sites. Note the module's own body is not the cost it can appear to be: a `-X importtime` run over a stale `__pycache__` attributes byte-compilation of the whole file to it (12 ms here); warm it is under 2 ms. Nor is `find_spec("jedi")`, which is 0.05 ms. In a clean interpreter `import IPython.terminal.ipapp` goes from 482 to 479 modules. `unicodedata` and `guarded_eval` remain, now reached via `terminal/ptutils.py` and `terminal/shortcuts/filters.py`.
1 parent 6722272 commit f301e2b

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

IPython/core/completer.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,6 @@
192192
import sys
193193
import tokenize
194194
import time
195-
import unicodedata
196-
import uuid
197195
import warnings
198196
from ast import literal_eval
199197
from collections import defaultdict
@@ -210,18 +208,12 @@
210208
)
211209
from collections.abc import Iterable, Iterator, Sequence, Sized
212210

213-
from IPython.core.guarded_eval import (
214-
guarded_eval,
215-
EvaluationContext,
216-
_validate_policy_overrides,
217-
)
218211
from IPython.core.error import TryNext, UsageError
219212
from IPython.core.inputtransformer2 import (
220213
ESC_MAGIC,
221214
SystemAssign,
222215
make_tokens_by_line,
223216
)
224-
from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
225217
from IPython.testing.skipdoctest import skip_doctest
226218
from IPython.utils import generics
227219
from IPython.utils.PyColorize import theme_table
@@ -1077,12 +1069,16 @@ class Completer(Configurable):
10771069

10781070
@observe("evaluation")
10791071
def _evaluation_changed(self, _change):
1072+
from IPython.core.guarded_eval import _validate_policy_overrides
1073+
10801074
_validate_policy_overrides(
10811075
policy_name=self.evaluation, policy_overrides=self.policy_overrides
10821076
)
10831077

10841078
@observe("policy_overrides")
10851079
def _policy_overrides_changed(self, _change):
1080+
from IPython.core.guarded_eval import _validate_policy_overrides
1081+
10861082
_validate_policy_overrides(
10871083
policy_name=self.evaluation, policy_overrides=self.policy_overrides
10881084
)
@@ -1162,6 +1158,8 @@ def global_matches(self, text: str, context: CompletionContext | None = None):
11621158
defined in self.namespace or self.global_namespace that match.
11631159
11641160
"""
1161+
from IPython.core.guarded_eval import EvaluationContext, guarded_eval
1162+
11651163
matches = []
11661164
match_append = matches.append
11671165
n = len(text)
@@ -1387,6 +1385,8 @@ def _trim_expr(self, code: str) -> str:
13871385
return ""
13881386

13891387
def _evaluate_expr(self, expr):
1388+
from IPython.core.guarded_eval import EvaluationContext, guarded_eval
1389+
13901390
obj = not_found
13911391
done = False
13921392
while not done and expr:
@@ -1779,6 +1779,8 @@ def back_unicode_name_matches(text: str) -> tuple[str, Sequence[str]]:
17791779
- a sequence (of 1), name for the match Unicode character, preceded by
17801780
backslash, or empty if no match.
17811781
"""
1782+
import unicodedata
1783+
17821784
if len(text)<2:
17831785
return '', ()
17841786
maybe_slash = text[-2]
@@ -1804,6 +1806,8 @@ def back_latex_name_matcher(context: CompletionContext) -> SimpleMatcherResult:
18041806
18051807
This does ``\\ℵ`` -> ``\\aleph``
18061808
"""
1809+
from IPython.core.latex_symbols import reverse_latex_symbol
1810+
18071811

18081812
text = context.text_until_cursor
18091813
no_match = {
@@ -3038,6 +3042,7 @@ def dict_key_matches(self, text: str) -> list[str]:
30383042
.. deprecated:: 8.6
30393043
You can use :meth:`dict_key_matcher` instead.
30403044
"""
3045+
from IPython.core.guarded_eval import EvaluationContext, guarded_eval
30413046

30423047
# Short-circuit on closed dictionary (regular expression would
30433048
# not match anyway, but would take quite a while).
@@ -3161,6 +3166,8 @@ def unicode_name_matcher(self, context: CompletionContext) -> SimpleMatcherResul
31613166
Works only on valid python 3 identifier, or on combining characters that
31623167
will combine to form a valid identifier.
31633168
"""
3169+
import unicodedata
3170+
31643171

31653172
text = context.text_until_cursor
31663173

@@ -3202,6 +3209,8 @@ def latex_matches(self, text: str) -> tuple[str, Sequence[str]]:
32023209
.. deprecated:: 8.6
32033210
You can use :meth:`latex_name_matcher` instead.
32043211
"""
3212+
from IPython.core.latex_symbols import latex_symbols
3213+
32053214
slashpos = text.rfind('\\')
32063215
if slashpos > -1:
32073216
s = text[slashpos:]
@@ -3329,6 +3338,8 @@ def completions(self, text: str, offset: int)->Iterator[Completion]:
33293338
completions are coming from different sources this function does not
33303339
ensure that each completion object will only be present once.
33313340
"""
3341+
import uuid
3342+
33323343
warnings.warn("_complete is a provisional API (as of IPython 6.0). "
33333344
"It may change without warnings. "
33343345
"Use in corresponding context manager.",
@@ -3845,6 +3856,8 @@ def unicode_names(self) -> list[str]:
38453856
38463857
The list is lazily initialized on first access.
38473858
"""
3859+
import unicodedata
3860+
38483861
if self._unicode_names is None:
38493862
names = []
38503863
for c in range(0,0x10FFFF + 1):
@@ -3858,6 +3871,8 @@ def unicode_names(self) -> list[str]:
38583871

38593872

38603873
def _unicode_name_compute(ranges: list[tuple[int, int]]) -> list[str]:
3874+
import unicodedata
3875+
38613876
names = []
38623877
for start,stop in ranges:
38633878
for c in range(start, stop) :

0 commit comments

Comments
 (0)