##// 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 .. code::
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 import sys
121 import sys
122 import time
122 import time
123 import unicodedata
123 import unicodedata
124 import uuid
124 import warnings
125 import warnings
125 from contextlib import contextmanager
126 from contextlib import contextmanager
126 from importlib import import_module
127 from importlib import import_module
@@ -133,8 +134,9 b' from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol'
133 from IPython.core.oinspect import InspectColors
134 from IPython.core.oinspect import InspectColors
134 from IPython.utils import generics
135 from IPython.utils import generics
135 from IPython.utils.dir2 import dir2, get_real_method
136 from IPython.utils.dir2 import dir2, get_real_method
137 from IPython.utils.path import ensure_dir_exists
136 from IPython.utils.process import arg_split
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 from traitlets.config.configurable import Configurable
140 from traitlets.config.configurable import Configurable
139
141
140 import __main__
142 import __main__
@@ -1003,8 +1005,6 b' def _make_signature(completion)-> str:'
1003 class IPCompleter(Completer):
1005 class IPCompleter(Completer):
1004 """Extension of the completer class with IPython-specific features"""
1006 """Extension of the completer class with IPython-specific features"""
1005
1007
1006 _names = None
1007
1008 @observe('greedy')
1008 @observe('greedy')
1009 def _greedy_changed(self, change):
1009 def _greedy_changed(self, change):
1010 """update the splitter and readline delims when greedy is changed"""
1010 """update the splitter and readline delims when greedy is changed"""
@@ -1049,6 +1049,16 b' class IPCompleter(Completer):'
1049 """,
1049 """,
1050 ).tag(config=True)
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 @observe('limit_to__all__')
1062 @observe('limit_to__all__')
1053 def _limit_to_all_changed(self, change):
1063 def _limit_to_all_changed(self, change):
1054 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1064 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
@@ -1126,6 +1136,12 b' class IPCompleter(Completer):'
1126 # This is set externally by InteractiveShell
1136 # This is set externally by InteractiveShell
1127 self.custom_completers = None
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 @property
1145 @property
1130 def matchers(self):
1146 def matchers(self):
1131 """All active matcher routines for completion"""
1147 """All active matcher routines for completion"""
@@ -1824,6 +1840,13 b' class IPCompleter(Completer):'
1824
1840
1825 seen = set()
1841 seen = set()
1826 try:
1842 try:
1843 if self.profile_completions:
1844 import cProfile
1845 profiler = cProfile.Profile()
1846 profiler.enable()
1847 else:
1848 profiler = None
1849
1827 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1850 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1828 if c and (c in seen):
1851 if c and (c in seen):
1829 continue
1852 continue
@@ -1833,6 +1856,13 b' class IPCompleter(Completer):'
1833 """if completions take too long and users send keyboard interrupt,
1856 """if completions take too long and users send keyboard interrupt,
1834 do not crash and return ASAP. """
1857 do not crash and return ASAP. """
1835 pass
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 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1867 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1838 """
1868 """
@@ -2078,19 +2108,17 b' class IPCompleter(Completer):'
2078 return text, _matches, origins, completions
2108 return text, _matches, origins, completions
2079
2109
2080 def fwd_unicode_match(self, text:str) -> Tuple[str, list]:
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 slashpos = text.rfind('\\')
2112 slashpos = text.rfind('\\')
2090 # if text starts with slash
2113 # if text starts with slash
2091 if slashpos > -1:
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 s = text[slashpos+1:]
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 if candidates:
2122 if candidates:
2095 return s, candidates
2123 return s, candidates
2096 else:
2124 else:
@@ -2099,3 +2127,20 b' class IPCompleter(Completer):'
2099 # if text does not start with slash
2127 # if text does not start with slash
2100 else:
2128 else:
2101 return u'', ()
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