##// END OF EJS Templates
Merge pull request #12299 from ssanderson/make-unicode-completions-lazier
Matthias Bussonnier -
r25700:6f352bfa merge
parent child Browse files
Show More
@@ -35,7 +35,7 b' or using unicode completion:'
35 35
36 36 .. code::
37 37
38 \\greek small letter alpha<tab>
38 \\GREEK SMALL LETTER ALPHA<tab>
39 39 α
40 40
41 41
@@ -121,6 +121,7 b' import string'
121 121 import sys
122 122 import time
123 123 import unicodedata
124 import uuid
124 125 import warnings
125 126 from contextlib import contextmanager
126 127 from importlib import import_module
@@ -133,8 +134,9 b' from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol'
133 134 from IPython.core.oinspect import InspectColors
134 135 from IPython.utils import generics
135 136 from IPython.utils.dir2 import dir2, get_real_method
137 from IPython.utils.path import ensure_dir_exists
136 138 from IPython.utils.process import arg_split
137 from traitlets import Bool, Enum, Int, observe
139 from traitlets import Bool, Enum, Int, List as ListTrait, Unicode, default, observe
138 140 from traitlets.config.configurable import Configurable
139 141
140 142 import __main__
@@ -1003,8 +1005,6 b' def _make_signature(completion)-> str:'
1003 1005 class IPCompleter(Completer):
1004 1006 """Extension of the completer class with IPython-specific features"""
1005 1007
1006 _names = None
1007
1008 1008 @observe('greedy')
1009 1009 def _greedy_changed(self, change):
1010 1010 """update the splitter and readline delims when greedy is changed"""
@@ -1049,6 +1049,16 b' class IPCompleter(Completer):'
1049 1049 """,
1050 1050 ).tag(config=True)
1051 1051
1052 profile_completions = Bool(
1053 default_value=False,
1054 help="If True, emit profiling data for completion subsystem using cProfile."
1055 ).tag(config=True)
1056
1057 profiler_output_dir = Unicode(
1058 default_value=".completion_profiles",
1059 help="Template for path at which to output profile data for completions."
1060 ).tag(config=True)
1061
1052 1062 @observe('limit_to__all__')
1053 1063 def _limit_to_all_changed(self, change):
1054 1064 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
@@ -1126,6 +1136,12 b' class IPCompleter(Completer):'
1126 1136 # This is set externally by InteractiveShell
1127 1137 self.custom_completers = None
1128 1138
1139 # This is a list of names of unicode characters that can be completed
1140 # into their corresponding unicode value. The list is large, so we
1141 # laziliy initialize it on first use. Consuming code should access this
1142 # attribute through the `@unicode_names` property.
1143 self._unicode_names = None
1144
1129 1145 @property
1130 1146 def matchers(self):
1131 1147 """All active matcher routines for completion"""
@@ -1824,6 +1840,13 b' class IPCompleter(Completer):'
1824 1840
1825 1841 seen = set()
1826 1842 try:
1843 if self.profile_completions:
1844 import cProfile
1845 profiler = cProfile.Profile()
1846 profiler.enable()
1847 else:
1848 profiler = None
1849
1827 1850 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1828 1851 if c and (c in seen):
1829 1852 continue
@@ -1833,6 +1856,13 b' class IPCompleter(Completer):'
1833 1856 """if completions take too long and users send keyboard interrupt,
1834 1857 do not crash and return ASAP. """
1835 1858 pass
1859 finally:
1860 if profiler is not None:
1861 profiler.disable()
1862 ensure_dir_exists(self.profiler_output_dir)
1863 output_path = os.path.join(self.profiler_output_dir, str(uuid.uuid4()))
1864 print("Writing profiler output to", output_path)
1865 profiler.dump_stats(output_path)
1836 1866
1837 1867 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1838 1868 """
@@ -2078,19 +2108,17 b' class IPCompleter(Completer):'
2078 2108 return text, _matches, origins, completions
2079 2109
2080 2110 def fwd_unicode_match(self, text:str) -> Tuple[str, list]:
2081 if self._names is None:
2082 self._names = []
2083 for c in range(0,0x10FFFF + 1):
2084 try:
2085 self._names.append(unicodedata.name(chr(c)))
2086 except ValueError:
2087 pass
2088 2111
2089 2112 slashpos = text.rfind('\\')
2090 2113 # if text starts with slash
2091 2114 if slashpos > -1:
2115 # PERF: It's important that we don't access self._unicode_names
2116 # until we're inside this if-block. _unicode_names is lazily
2117 # initialized, and it takes a user-noticeable amount of time to
2118 # initialize it, so we don't want to initialize it unless we're
2119 # actually going to use it.
2092 2120 s = text[slashpos+1:]
2093 candidates = [x for x in self._names if x.startswith(s)]
2121 candidates = [x for x in self.unicode_names if x.startswith(s)]
2094 2122 if candidates:
2095 2123 return s, candidates
2096 2124 else:
@@ -2099,3 +2127,20 b' class IPCompleter(Completer):'
2099 2127 # if text does not start with slash
2100 2128 else:
2101 2129 return u'', ()
2130
2131 @property
2132 def unicode_names(self) -> List[str]:
2133 """List of names of unicode code points that can be completed.
2134
2135 The list is lazily initialized on first access.
2136 """
2137 if self._unicode_names is None:
2138 names = []
2139 for c in range(0,0x10FFFF + 1):
2140 try:
2141 names.append(unicodedata.name(chr(c)))
2142 except ValueError:
2143 pass
2144 self._unicode_names = names
2145
2146 return self._unicode_names
General Comments 0
You need to be logged in to leave comments. Login now